My excuses: First off all, I would like to explain that I've been searching for an answer a long time. I found so many similar questions, but none with a solution for my scenario.
The Problem: After an Ajax call, where I dinamicaly add HTML code, the code added looses its styles and action responses (on click, for example).
HTML : The HTML that is loaded with page loading. It renders the collection of the user's images correctly. I mean... the style is ok and the JS functions bind to the classes 'visualizaImagem' and 'deletaImagem' works fine.
<div class="row">
<div class="col-sm-12" id='imagens'>
<?php
if(isset($imagens)){
if(count($imagens) > 0){
foreach($imagens as $imagem){
echo "
<div class='file-box' data-path='" . $imagem['path'] . "' id='" . $imagem['nome'] . "'>
<div class='file'>
<a class='visualizaImagem' data-path='". $imagem['path'] ."'>
<div class='icon'>
<img src='../" . $imagem['path'] . "' style='height:100%'>
<a class='deletaImagem' data-path='". $imagem['path'] ."' data-divid='" . $imagem['nome'] . "'>
<i class='fa fa-trash' style='position:absolute;top:10px;left:10px;font-size:18px;'></i>
</a>
</div>
<div class='file-name'> " . $imagem['nome'] . "</div>
</a>
</div>
</div>";
}
}
}
?>
</div>
</div>
JS : When I click to the upload button (that is not part of this code), the image data is passed through "data: dados", read by "salvaImagem" in the specific controller and than appended to the page. The image is actually appended, but with no css style and no response to the functions that should have been bind to the same classes presented above.
jQuery.ajax({
type: "POST",
url: "salvaImagem",
data: dados,
dataType: "json"}).done(function(response)
{
if(response.sucesso){
toastr['success'](response.msg);
var img = "" +
"<div class='file-box' id='" + response.nome + "' data-path='" + response.path + "'>" +
" <div class='file'>" +
" <a class='visualizaImagem' data-path='"+response.path+"'>" +
" <div class='icon'>" +
" <img src='../"+response.path+"' style='height:100%'>" +
" <a class='deletaImagem' data-path='"+response.path+"' data-divid='"+response.nome+"'>" +
" <i class='fa fa-trash' style='position:absolute;top:10px;left:10px;font-size:18px;'>" +
" </a>" +
" </div>" +
" <div class='file-name'> "+response.nome+"</div>" +
" </a>" +
" </div>" +
"</div>";
$('#imagens').append(img);
}
else{
toastr['error'](response.msg);
}
});
I think I should give a little bit more about the code. Here is an example of how I bind functions to those classes. Actually as I wrote the function inside the bind, I was expecting that would't be necessary to rebind.
$('.deletaImagem').on('click', function (){
var path = $(this).data('path');
var div_id = $(this).data('divid');
jQuery.ajax({
type: "POST",
url: "deletaImagem",
data: {'path':path},
dataType: "json"}).done(function(response)
{
if(response.sucesso){
toastr['success'](response.msg);
$('#'+div_id).remove();
}
else{
toastr['error'](response.msg);
}
});
return false;
});
Trying to use some of the tips friends gave me here, I tried the following, but no success either.
jQuery.ajax({
type: "POST",
url: "salvaImagem",
data: dados,
dataType: "json"}).done(function(response)
{
if(response.sucesso){
toastr['success'](response.msg);
var img = <HTML original code here>
$(img).appendTo('#imagens').find('.deletaImagem').on('click', deletaImagem);
$('.visualizaImagem').on('click', visualizaImagem);
}
else{
toastr['error'](response.msg);
}
});
function deletaImagem(){
var path = $(this).data('path');
var div_id = $(this).data('divid');
jQuery.ajax({
type: "POST",
url: "deletaImagem",
data: {'path':path},
dataType: "json"}).done(function(response)
{
if(response.sucesso){
$('#'+div_id).remove();
toastr['success'](response.msg);
}
else{
toastr['error'](response.msg);
}
});
return false;
}
Since I assume you are binding events (click etc... ) on document.ready, any new items added later will not have those events.
After adding the the new items, just add the events again.
$('#something').append("<div class='somethingWithClicklistener'>a</div>"); // It won't have the event, you have to add it
$('.somethingWithClicklistener').click(function(){ etc..
Though that approach might double the event handlers on pre-existing classes but you get the point
As for styles it shouldn't happen unless you use jquery animation etc...
if you get an ajax response as html, you have to write your javascript code relatively to your root element in witch you input your html (received from ajax).
1.
<div class="some-root-div">
// the place where you put your html from response
</div>
And you should append the html like this: $('#imagens').append($(img));
3.
(function($){
"use strict";
$('.some-root-div', '.deletaImagem').on('click', function(){
// your logic on `.deletaImagem` link click
})
})(jQuery);
Your problem is that event handlers are not being attached to the new elements. It is pretty simple to do so while you attach the element to the DOM.
Change this
$('#imagens').append(img);
to
$(img).appendTo('#imagens').find('.deletaImagem').on('click', function (){
var path = $(this).data('path');
var div_id = $(this).data('divid');
jQuery.ajax({
type: "POST",
url: "deletaImagem",
data: {'path':path},
dataType: "json"}).done(function(response)
{
if(response.sucesso){
toastr['success'](response.msg);
$('#'+div_id).remove();
}
else{
toastr['error'](response.msg);
}
});
return false;
});
I've been here. My solution and understanding is that AJAX comes at the end/during javascript, javascript coming way after CSS. I ended up setting the styles that need to be the most dynamic in javascript with a function that takes an element as a parameter. works like a charm!
function styleElement(elem){
elem.style.visibility = "hidden";
}
Related
I'm trying to make two Ajax calls in one page using jQuery. The first Ajax runs successfully and produces results. Second Ajax is supposed to fire up on button click and show the result, but it runs twice every time I click on the button. And initially on the first time clicking on the button, I have to click twice before it produces a result. Here's what I'm trying to do:
function showPicture() {
$("button").click(function() {
var id = this.id;
$.ajax({
type: 'POST',
url: 'displaySearch.php',
data: {'getTile': $(this).val()},
success: function(data) {
console.log(id);
$("#" + id).replaceWith("<img src=" + data + " />");
}
});
});
}
Here's my button:
<button id=" . $count . " onclick=showPicture() value=" . htmlentities($result['Poster']) . ">Click Me!</button>
I have seen similar questions on Google but I cannot figure out what the problem is. Any help would be greatly appreciated.
You have 2 onClick handlers, somewhat:
onClick
$("button").click()
Remove one of the handlers.
Example
function showPicture(id) {
$.ajax({
type: 'POST',
url: 'displaySearch.php',
data: {'getTile': $(this).val()},
success: function(data) {
console.log(id);
$("#" + id).replaceWith("<img src=" + data + " />");
}
});
}
<button id=" . $count . " onclick=showPicture(" . $count . ") value=" . htmlentities($result['Poster']) . ">Click Me!</button>
Your function 'showPicture' which you are calling from the html attribute below
<button id=" . $count . " onclick=showPicture()
is calling your function as you would expect.
but the function showPicture() itself is then binding a onclick event
function showPicture() {
$("button").click(function() { <------- this
......
So it is being hit twice as you have the attribute onclick and the even binding onclick.
The event click is on all html buttons.
What you should do: Remove the binding in the function to all buttons
function showPicture(caller) {
var id = $(caller).attr("id");
var val = $(caller).val();
console.log(id);
console.log(val);
$.ajax({
type: 'POST',
url: 'displaySearch.php',
data: {'getTile': val },
success: function(res) {
--you are replacing the button with an image... or something like that
$("#" + id).replaceWith("<img src=" + res+ " />");
}
});
}
html
<button id=".$count." onclick="showPicture(this)" value=".htmlentities($result['Poster']).">Click Me!</button>
I am new to Coding and I got stuck for hours solving this problem:
The response from AJAX is a Json two-dimesional array jqXHR[][] the first index
describes each product id, the second one holds product details like prices etc.
So all i want to is to iterate through the first index by using the button "New_Suggestion" and to update the html content in the "result_wrapper".
The response works fine, but updating the html content doesn't work at all.
Thank you for your help.
$.ajax({
type: "POST",
url: "productsuggestion.php",
data: "criteria1=" + crit1 + "&criteria2=" + crit2 + "&criteria3=" + crit3 + "&criteria4=" + crit4 + "&criteria5=" + crit5,
dataType: "json",
success: function(jqXHR) {
var sug = 0;
$('#New_Suggestion').on('click', function() {
sug = sug + 1
});
$("#result_wrapper").html(
'<div id="prod_name">' + jqXHR[sug][0] + '</div> <br>' +
'<img id="prod_pic" src="' + jqXHR[sug][4] + '">' +
'<div id="prod_price">' + jqXHR[sug][2] + '</div> <br>'
);
}
});
Firstly, your "click" handler just increments a variable when it's clicked. It doesn't touch the output at all.
Secondly, every time the ajax runs, you add another click event handler to the button, without removing the previous one(s). It's easier to declare this outside the ajax context, and set a global variable for the suggestion count.
Something like this, I think (untested):
var sugCount = 0;
var sugData = null;
$.ajax({
type : "POST",
url : "productsuggestion.php",
data : "criteria1="+crit1+"&criteria2="+crit2+"&criteria3="+crit3+"&criteria4="+crit4+"&criteria5="+crit5,
dataType: "json",
success: function(data){
//reset global data after each ajax call
sugCount = 0;
sugData = data;
writeSuggestions(sugCount, sugData); //output the initial set of suggestions
}
});
$('#New_Suggestion').on('click',function(){
sugCount = sugCount + 1;
writeSuggestions(sugCount, sugData); //output updated suggestions
});
function writeSuggestions(count, data)
{
$("#result_wrapper").html('<div id="prod_name">'+data[count][0]+'</div> <br>'+
'<img id="prod_pic" src="'+data[count][4]+'">'+
'<div id="prod_price">'+data[count][2]+'</div> <br>');
}
I have been working on a e-commerce web application. There is a wishlist module which I'm trying to implement. I'm adding the products into wishlist using ajax calls and also removing it with ajax. The adding part works fine but I have a problem in removing part . What I'm trying to do is, making an ajax call to fetch the wishlist items from the database and adding a remove button dynamically using jquery. Although I know that I have to use a .live function to attach an event to it which I did but when i click on the button all the items which are present in the wishlist are removed . I see multiple ajax request was made in console under network tab and I don't get it why , although I clicked it only once. The following is a snippet of my code
$.ajax({
type: "POST",
url: "fetchdata1",
data: "cat=" + cat,
success: function(data) {
productContainer.innerHTML = "";
var $productContainer = $('#productContainer');
$.each(data, function(key, value) {
if (value['newVar'] === 1) {
$productContainer.append("<div id='productBox' class='grid_3'>\n\
<a href='product.jsp?id=" + value['id'] + "'><img src='" + value["image"] + "'/></a><br/>\n\
<a href='product.jsp?id=" + value['id'] + "'><span class='black'>" + value['name'] + "</span></a><br/>\n\
<span class='black'>By " + value['company'] + "</span><br/><span class='red'>RS." + value['price'] + "</span>\n\
<br/><br/><a id='remove' href='#'>REMOVE</a></div>");
foo(value['id']);
} else {
$productContainer.append("<div id='productBox' class='grid_3'>\n\
<a href='product.jsp?id=" + value['id'] + "'><img src='" + value["image"] + "'/></a><br/>\n\
<a href='product.jsp?id=" + value['id'] + "'><span class='black'>" + value['name'] + "</span></a><br/>\n\
<span class='black'>By " + value['company'] + "</span><br/><span class='red'>RS." + value['price'] + "</span></div>");
}
});
}
});
function foo(value) {
var pid = value;
$('#remove').live("click", function() {
$.ajax({
type: "POST",
url: "removeFromWishlist",
data: "pid=" + pid,
success: function(response) {
}
});
});
In the first ajax request I'm fetching products from the database then adding remove button to it dynamically then calling function foo which attach the click event using .live function and then make call to database to remove it.
Hey guys I'm not pro at web, so go easy on me if I made some silly mistake.
Thanks!
Problem:
You have same id for multiple hyperlink and you are using .live function on "id based" selector. It is applying click function again & again on first element.
Solution:
Update your hyperlink
<a href='#' onclick="foo(this)" pid=value['id']>REMOVE</a>
Then in foo() function
function foo(obj) {
var pid = $(obj).attr("pid");
$(obj).bind("click", function() {
$.ajax({
type: "POST",
url: "removeFromWishlist",
data: "pid=" + pid,
success: function(response) {
}
});
});
i don't get why you using same id multiple times.
and afaik, jQuery.live already deprecated.
you can use this if you want to get live behavior:
$(document).on('click', 'element-selector', function(){
...
});
with your code, it can rewriten to:
$(document).on('click', '[id=remove]', function(){
...ajax call...
});
now the problem with your fetch data function is this:
$.each(data, function(key, value) {
if (value['newVar'] === 1) {
...append element...
**foo(value['id']);**
} else {
...append element...
}
});
as we know foo() are your function that bind remove behavior.
based on your code, whenever that fetch data has newVar = 1, it will directly call foo. which mean binding remove behavior multiple times, as many as newVar = 1 was.
solution:
you can put pid as a attribute on your a element
maybe something like remove
and within remove click function, you can use $(this).attr('pid') to get that value.
and remove that foo() content to outside the function, since $(element).live(...) or $(document).on(event, element, ...) will listen the element, even the element dynamicly added to the page.
The issue happened because you register listener multiple times in each loop. So to resolve, you need to register once after all button has been populated. I also change selector to class ".remove" because you going to have multiple remove button so using id is will be duplicated, and using jquery .on() instead of .live() (deprecated)
$.ajax({
type: "POST",
url: "fetchdata1",
data: "cat=" + cat,
success: function(data) {
productContainer.innerHTML = "";
var $productContainer = $('#productContainer');
$.each(data, function(key, value) {
if (value['newVar'] === 1) {
$productContainer.append("<div id='productBox' class='grid_3'>\n\
<a href='product.jsp?id=" + value['id'] + "'><img src='" + value["image"] + "'/></a><br/>\n\
<a href='product.jsp?id=" + value['id'] + "'><span class='black'>" + value['name'] + "</span></a><br/>\n\
<span class='black'>By " + value['company'] + "</span><br/><span class='red'>RS." + value['price'] + "</span>\n\
<br/><br/><a class='remove' id='remove' data-pid='" + value['id'] + "' href='#'>REMOVE</a></div>");
} else {
$productContainer.append("<div id='productBox' class='grid_3'>\n\
<a href='product.jsp?id=" + value['id'] + "'><img src='" + value["image"] + "'/></a><br/>\n\
<a href='product.jsp?id=" + value['id'] + "'><span class='black'>" + value['name'] + "</span></a><br/>\n\
<span class='black'>By " + value['company'] + "</span><br/><span class='red'>RS." + value['price'] + "</span></div>");
}
});
foo();
}
});
function foo() {
$('.remove').on("click", function() {
var pid = $(this).data("pid");
$.ajax({
type: "POST",
url: "removeFromWishlist",
data: "pid=" + pid,
success: function(response) {
}
});
});
I am making some application that it loads data from an xml file. it works file if there is one corresponding div structure and one xml path. But I want to have multiple copies of my div structure, but each one will load different xml content.
I tired to do it by loop but it does copy each data in both content.
JSFIDDLE: https://goo.gl/8XwMYz
HTML:
<div class="data" data-xml="https://dl.dropboxusercontent.com/u/33538012/file1.xml">
</div>
<div class="data" data-xml="https://dl.dropboxusercontent.com/u/33538012/file2.xml">
</div>
jQuery:
$(".data").each(function() {
var path = $(this).attr("data-xml");
$.ajax({
url: path,
dataType: "xml",
success: parse,
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document) {
$(document).find("person").each(function() {
$(".data").append(
"<div class='name'>Name: " +
$(document).find("name").text() +
"</div><div class='title'>Title: " +
$(document).find("title").text() + "</div>")
//$(document).find("name").text();
});
}
As you can see in the HTML I have exactly the same structure but each one are linked to a different xml file paths., an in my code I want to load the corresponding data based on the xml file they are linked to.
UPDATE:
Based on the answer #charlietfl has provided, the code seems better now, but still does not provide the intended result. I have been testing on the below code, and realised that it does not pass the xml instance to the parse function.
$(".data").each(function() {
// store element instance
var elem = $(this);
var path = $(this).attr("data-xml");
//console.log($el);
$.ajax({
url: path,
dataType: "xml",
success: function(xml){
parse(document, elem);
},
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document, elem) {
console.log($(document).find("name").text());
$(document).find("person").each(function() {
//alert($el);
var $person = $(this);
elem.append(
"<div class='name'>Name: " +
$person.find("name").text() +
"</div><div class='title'>Title: " +
$person.find("title").text() + "</div>")
});
}
Any idea?
This should do it. You need to store the instance of element outside the ajax and pass that into the success handling
$(".data").each(function() {
// store element instance
var $el = $(this),
path = $(this).attr("data-xml");
$.ajax({
url: path,
dataType: "xml",
success: function(xml) {
parse(document, $el);
},
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document, $el) {
$(document).find("person").each(function() {
var $person = $(this);
$el.append(
"<div class='name'>Name: " +
$person.find("name").text() +
"</div><div class='title'>Title: " +
$person.find("title").text() + "</div>")
});
}
Here's a simple question:
On the page there are two javascript.
The first script gets JSON and used it to build multiple forms with buttons:
$.getJSON("http://api.server.com/my/?callback=?",
function(data){
var results = [];
$.each(data['results'], function(i, result) {
results.push("<div class='accordion-group span4'><div class='accordion-heading'>Video Frame<blockquote><a href='http://server.com/video/?my=" + result.File + "' target='_blank'><img src='http://jpg.server.com/" + result.File + ".jpg' class='img-polaroid'/></a><p>" + result.ListId + "</p><small>" + result.OwnerId + "</small><small>" + result.updatedAt + "</small> </blockquote><a class='accordion-toggle' data-toggle='collapse' data-parent='#accordion2' href='#" + result.File + "'>Share video</a></div><div id='" + result.File + "' class='accordion-body collapse'><div class='accordion-inner'><form class='share_file_form'>Set list<input name='nd' id='user_id' type='hidden'><input name='file' value = '" + result.File + "' type='hidden'><div class='list'></div><input type='text' placeholder='New list'><div class='modal-footer'><button class='share_file_submit'>Share video</button></div></form><div id='user_info_result'></div></div></div></div>");
});
$('#mytile').html(results.join(""));
}
);
The second script is a response by pressing a button on the form of constructing the first script:
$(document).on('click', '.share_file_form', function(event) {
$(this).validate({
submitHandler: function(form) {
$.ajax({
type: "GET",
url: "http://api.server.com/set/",
timeout: 20000,
data: $(form).serialize(),
beforeSend: function() {
$(".share_file_submit").attr("disabled", true);
$(".share_file_submit").html("Send <img src='http://src.server.com/loadr.gif' border='0'/>");
},
success: function(msg){
console.log("Data Saved: " + msg);
$("#share_file_submit").attr('disabled', false);
$("#share_file_submit").html("Share video");
$("#user_info_result_2").html(msg);
},
error: function(msg){
//////////////// $('#user_info_result_2').html("<div class='alert alert-error span3'>Failed from timeout. Please try again later. <span id='timer'></span> sec.</div>");
}
});
}
});
});
Everything works, but at the time of the second script, the inscription appears on the buttons of all forms, and I need only one button, which I click.
The problem is this line:
$(".share_file_submit").html("Send <img src='http://src.server.com/loadr.gif' border='0'/>");
It sets the html for all elements with the "share_file_submit" class on the entire page. You can fix it by adding a context to the selector:
$(".share_file_submit", $(form)).html("Send <img src='http://src.server.com/loadr.gif' border='0'/>");
If you really want to use validate plugin properly you shouldn't initialize it within a click handler.
Should be initializing right after the form building code.
Within $.getJSON
$('#mytile').html(results.join(""));
$('.share_file_form').validate(/* options*/);
The submitHandler will over ride the default submit event of the form and validation will be active while user fills out form.
To fix button issue:
submitHandler: function(form) {// form is current form elemnt
$.ajax({
beforeSend:function(){
/* look within form for button*/
$(form).find(".share_file_submit").prop('disabled',true);
})
});
Now if user uses Enter key you aren't relying on a click event to prevent submittal by browser default