How do I rebind jquery calls after ajax load? - javascript

Okay so I use a masonry script for arranging images in a grid, I placed it in a function arange_images() in an external script.
In my main script i call
$(document).ready(function(){
arange_images(); //<- Works lovely
});
Then i decide to load some other images with ajax. After that, my images stop being arranged.
function get_img(section_id) {
$.ajax({
type: 'GET',
url: './db/get_img.php',
data: {
section_id: section_id
},
success: function (data) {
var data_parsed = JSON.parse(data);
var images = '<div class="grid-sizer"></div><div class="gutter-sizer"></div>';
$.each(data_parsed, function (i, picture) {
images += '<div class="member">';
images += ' <img src="img/pictures/' + picture.path + '" alt="' + picture.alt + '"/>';
images += '</div>';
});
$('.grid').html(images);
arange_images(); //<- Does not work
}
});
}
$('.section_selector').click(function () {
get_img($(this).attr('data-section_id'));
arange_images(); //<- Does not work either
});
Searching similar errors did not help me.
Most of the problems with jquery after ajax are .click replaced with .on('click').
I read that I need to rebind jquery calls, but I don't really understand how to do it in this situation.

Your .click() handler will only bind elements that exist within the DOM at the time the document is ready. Since you need to bind to the elements after the ajax call, use .on().
Keep Calm and Call .on
$(document).on('click', '.section_selector'), function () {
get_img($(this).attr('data-section_id'));
});

Related

jQuery getting id with [id^=''] when i using ajax and fill and create table after that

in jQuery i'm using ajax and after getting data from that i create simple table with this data, for example
$.ajax({
method: 'GET',
url: '/analyzePage/searchTag/' + tagName,
contentType: false,
processData: false,
success: function (data) {
console.log(data);
setTimeout(function () {
if (data.state == 'error') {
...
}
else {
let table = '<div class="table-responsive pre-scrollable">';
...
$.each(data.tags, function (key, value) {
...
table = table + '<button type="button" class="btn btn-warning btn-icon btn-rounded legitRipple" id="searchTag-' + value.name + '">';
table = table + '<i class="icon-file-plus"></i>';
table = table + '</button>';
table = table + '</td>';
table = table + '</tr>';
});
...
$('.data').html(table);
}
}, 800);
},
error: function (data) {
console.log(data);
}
});
in this code and into $.each i add simple <button> with this id id="searchTag-"' + value.name + '.
now my question is how can i get this id with jquery? parent .data class is div with searchHashTag id as:
my below jquery code doesn't work and i can't get id from added buttons
$("[id^='searchTag']").on('click', function () {
alert($(this).attr("id").split("-")[1]);
});
Your buttons are loaded dynamically. Most likely, you are declaring the click event handler before the elements actually exist on the page, therefore, it does not find them. You can solve this in two ways.
Method 1
Add the click handler only when the elements exist:
// Inside your ajax callback (every time new buttons are added)
$('.data').html(table);
$("[id^='searchTag']").on('click', function () {/*...*/});
Method 2 (I would recommend this one)
Use event delegation. It will bind the click event on an existing ancestor element, and work on any button you add later:
// Anywhere you want, but it needs to be executed only once
$(document).on('click', "[id^='searchTag']", function(){/*...*/});
Method 2 is preferred, because with method 1, for example if you have a Load more button which adds new buttons while keeping the ones loaded before, the latter ones will execute the click handler multiple times.
Note that using document as the ancestor element is safe because we know it always exist when your code is executed, but it would be better (perfomance wise) if you used a more precise container which already exists in your HTML. If that is the case for your .data container, then you should use $('.data').on('click', '[id^.... (Again, only execute this once).

jQuery event fires once, then never again

I've been wrestling with a simple JQuery event handler for hours.
My event handler fires exactly once, when the page loads, and never again no matter the event or the interaction with the select box.
When deferred, the alert (when I have one) shows the first select option. When not, the alert is blank.
All I want is for the select box to load from AJAX and for a user choice to trigger another AJAX call.
HTML:
<select id="connection" name="Connection"></select>
<div id="testme" style="background: #CCC; width:100%; height:50px;position:relative;color:red">testing</div>
Javascript:
$(document).ready(function () {
// Event handler. Tried as a separate function and as a parameter to $.on(...)
function connectionSelected() {
var str = $('#connection option:selected').text();
alert(str);
$("#testme").text(str);
}
var $connectionSelect = $('#connection');
//$connectionSelect.selectmenu(); // Tried enabling/disabling
// Tried this and all JS code inside and outside of $(document).ready(...)
$.when(
$.ajax({
dataType: "JSON",
url: '#Url.Content("~/API/ConnectionHint")', // The AJAX call (using ASP Razor) works fine
success: function(data) {
// This function is always called and works
var items = [];
$.each(data, function(key, val) {
items.push("<option value='" + key + "'>" + val + "</option>");
});
$connectionSelect.append(items.join(""));
// Tried setting up the event handler here
},
error: function() {
$connectionSelect.html('<option id="-1">none available</option>');
}
})
).then(function() {
//$("#connection option").blur(connectionSelected()).change();
$("#connection").on("change", connectionSelected());
});
});
Tried dozens of variations of the event handler, several events, inside and outside of a deferred.done and deferred.then, etc.. E.g.:
$connectionSelect.selectmenu({
change: function (event, data) {
$('#connection').change(function () {
var str = "";
$('#connection').each(function () {
str += $(this).text() + "<br>";
});
$("#testme").text(str);
});
}
});
I usually write back-end code and am familiar only with portions of JQuery, and this is driving me crazy. I've looked more than 30 related question on SO and elsewhere, e.g.
Jquery event fires once
Jquery .change() function not working with dynamically populated SELECT list
http://jqueryui.com/selectmenu/#product-selection
Any ideas are appreciated.
Instead of
$("#connection").on("change", connectionSelected());
try
$("#connection").on("change", connectionSelected);
Note that in the second one I'm passing your function handler by reference, instead of invoking it.

Dynamically added elements don't wrap

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

How to call JavaScript function during Pageload?

I have a Html page contains several pages whose data-role = page as page1,page2 etc.
I am trying to call a JS method during pageload of page1 using the following code
$("#page1").on("load",function () {
alert("hi")
$.ajax({
type: "GET",
url: "",
data: "{}",
contentType: "application/json",
dataType:"json",
success: function (msg) {
var BPRList = '';
$.each(msg, function(i,v){
BPRList += '<li onClick="GetBprDetails('+ v.BPRNo +')"><p class="title">' + v.BPRNo + '</p><p class="bodyEle">' + v.BPR_Product +'</p><p class="bodyEle">' + v.BPR_Details+ '</p><br/><p class="bodyEle">' + v.BPR_Status + ':</p></li>'
})
$("#BPRListTable").html(BPRList)
$('[data-role=listview]').listview('refresh');
},
error: function () {
alert("BPR List Error");
}
}); });
During the execution of above function I am unable to get the output during the formload
where as if I call the above method as button click event am able to get the output.
What might be the mistake made in above code..
I am more worried in following code.
$("#page1").on("load",function () {
--statements
})
$(window).load(function () {
alert("hi")
});
If you want the results on page load,then try this instead.Write this code outside $(document).ready(function(){});
Try to put 'page:load' instead of 'load' it might work better :
$("#page1").on("page:load",function () {
- - - -
- - - -
- - - -
});
Found solution Myself
$(document).ready(function(){
$(document).on('pagebeforeshow','#page1',function () {
--statements
}); });
i think using pageinit would be ok
$(document).on('pageinit', '#page1', function() {...})
In this manner, you avoid using document.ready, which is also not recommended by jquery mobile.

jQuery elements inside a jQuery dialog stop working after ajax call

<div id="divItems"><div id="divItemsContent"></div></div>
I think i know what the problem is, just don't know how to solve it. Here is the code:
function SplitOrder() {
var SplitTable = $.ajax({
url: 'AjaxActions/SplitTable.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1],
async: false
}).responseText;
var dialog = $('#divItems').dialog({
autoOpen: false,
height: 500,
width: 600,
title: 'פיצול שולחן'
});
var content = $("#divItemsContent");
content.html("");
content.html(SplitTable);
dialog.dialog("open");
//הפעולות על החשבונות
/************************************************/
$('#imgLeftArrow').click(
function() {
$(this).css("background-color", "white");
//AJAX הבאת נתוני רשומת ההזמנה מהשרת ב
var SplitTable = $.ajax({
url: 'AjaxActions/SplitUpdate.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1] + '&ItemID=' + $('#hidItemID').val() + '&ItemAmount=' + $('#hidItemAmount').val(),
async: false
}).responseText;
content.html("");
content.html(SplitTable);
});
$('#imgRightArrow').click(
function() {
//AJAX הבאת נתוני רשומת ההזמנה מהשרת ב
var SplitUpdate = $.ajax({
url: 'AjaxActions/SplitUpdate.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1] + '&ItemID=' + $('#hidItemID').val() + '&ItemAmount=' + $('#hidItemAmountTo').val(),
async: false
}).responseText;
});
/************************************************/
$('div[id^="Item_"]').hover(
function(e) {
$(this).css("cursor", "pointer");
$(this).css("background-color", "blue");
},
//כשיוצאים מהשולחן DIVהעלמת ה
function() {
$(this).css("background-color", "white");
});
/************************************************/
//טיפול בבחירת פריט להוספה/הורדה מהחשבון
$('div[id^="Item_"]').click(
function() {
$('#imgLeftArrow').css("background-color", "yellow");
//הוספת הפריט לשדה הנסתר
$('#hidItemID').val($(this).children().html());
$('#hidItemName').val($(this).children().next().html());
$('#hidItemAmount').val($(this).children().next().next().html());
});
}​
I am trying to display one page using the ajax call and put the result in the dialog...This is working great!!!
Next, if someone choses an item and press the left arrow pic, I am doing another ajax call that updates the database and returns the new HTML (using XML/SXL) and I am getting the right result from that also.
I am getting the first hover and click working great, but after I'm updating the data and getting the result the hover stops working and also the click event on the arrow. I think it is because i'm rendering the data inside the click event function but I don't know how to solve it.
If you are returning HTML and you expect to have click events and hover events happen on elements within the new returned html then you need to use the .live() jQuery keyword.
Update: As of jQuery 1.7, the .live() method is deprecated (and no longer exists starting in 1.9!). Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
I think I understand what you're trying to do...
If any of the HTML is in these statements:
$('#hidItemID').val($(this).children().html());
$('#hidItemName').val($(this).children().next().html());
$('#hidItemAmount').val($(this).children().next().next().html());
Contains jQuery, it will be rendered as plain HTML because they are being added to the DOM after event binding. What Griegs suggested willwork.
You'll need something similar to:
$('div[id^="Item_"]').live('hover', function(event) {
// do something on hover
});
$('#imgLeftArrow').live('click', function(event) {
// do something on click
});
$('#imgRightArrow').live('click', function(event) {
// do something on click
});
This way new elements will also trigger the handlers.

Categories