Remove html elements added dynamically with JQuery - javascript

In my html page, I have a select with some options.
When selecting an option, an ajax call is fired passing the option's value to a php script, which returns an html fragment (another select) with a certain id that is appended to the page.
When the user selects another option from the first select, the event is fired again, the ajax call is executed and another html fragment (with the same id) gets appended to the page.
I want that, if the event is fired a second time, the appended element is removed form the page before appending the new one.
At the moment I'm using this code:
$(document).ready(function() {
$("#id_serie").change(function() { //#id_serie is the if of the first select
if ($("#id_subserie_label")) { //#id_subserie_label is the id of the html element returned by the ajax call
console.log("Removing");
$("#id_subserie_label").empty().remove();
}
var url = 'myscript.php';
var id_s = $(this).val();
$.post(url, {id_serie: id_s}, function(data) {
$("#id_serie").parent().after(data);
});
});
});
This is not working though, the html element returned by the second ajax call is appended after the element returned from the first call (because the element with id #id_subserie_label is not in the page when the script is loaded?).
How can I achieve what I need?

You're very close.
Just change if ($("#id_subserie_label")) to if ($("#id_subserie_label").length):
$(document).ready(function() {
$("#id_serie").change(function() {
if ($("#id_subserie_label").length) { // <=== change this line
console.log("Removing");
$("#id_subserie_label").empty().remove();
}
var url = 'myscript.php';
var id_s = $(this).val();
$.post(url, {id_serie: id_s}, function(data) {
$("#id_serie").parent().after(data);
});
});
});
See The jQuery FAQ: How do I test whether an element exists?.
This is because, as Ivo points out:
$("#id_subserie_label") is an object, and objects always evaluate to true.
As per Andy E's comment, you can simplify your code to this, if you don't need the console.log() call:
$(document).ready(function() {
$("#id_serie").change(function() {
$("#id_subserie_label").empty().remove();
var url = 'myscript.php';
var id_s = $(this).val();
$.post(url, {id_serie: id_s}, function(data) {
$("#id_serie").parent().after(data);
});
});
});

Related

How do I make the ajax run?

When I add the ajax it only runs once.
I try that when I enter a letter in the search engine or change a select field, it sends me the new search to display it on the screen.
formMenu is a form containing a select and an imput text.
$('#formMenu').on('keyup change',function() {
$.ajax(
{
url: '/calendar',
success: function( data ) {
$('body').html(data);
}
}
);
});
You can Try using the below.
$(document).on('keyup change', '#formMenu', function() {
// Your Ajax Call here
})
You instance of #formMenu is not existing after you replace the body even if the same element exists in the new body its still a different instance.
You have to register the listener on the highest parent that is not replaced (in this case the body):
$("body").on("keyup change", "#formMenu", function() {
//ajax call
});

Add ajax request to element appended with previous ajax request

I have a list of categories and when the client selects one from the list a new list is created below it with the children of that category, now i need to add another level (another list) but i'm not sure how.
This should work but i guess the script can't know if the element is there or not.
So far my JS looks like this:
<script>
// when the user clicks on a drop down item from the list it adds a new drop down list
$('#cat_select_1').on('change', function() {
// fetch second list from the other script
var fetchUrl = 'http://localhost/includes/ajax/list-of-cats.php?catid=';
var fetchCatId = $( "#cat_select_1" ).val();
// if the second list is there
if ($("#cat_select_2").length){
// replace it with the new one
$.get(fetchUrl.concat(fetchCatId)).done(function(data) { $("#cat_select_2").html(data); });
}
else {
// otherwise append this one
$.get(fetchUrl.concat(fetchCatId)).done(function(data) { $("#jumbocats").append(data); });
}
});
//list #2 (not working)
$('#cat_select_2').on('change', function() {
// fetch third list from the other script
var fetchUrl = 'http://localhost/includes/ajax/list-of-cats.php?catid=';
var fetchCatId = $( "#cat_select_2" ).val();
// if the third list is there
if ($("#cat_select_3").length){
// replace it with the new one
$.get(fetchUrl.concat(fetchCatId)).done(function(data) { $("#cat_select_3").html(data); });
}
else {
// otherwise append this one
$.get(fetchUrl.concat(fetchCatId)).done(function(data) { $("#jumbocats").append(data); });
}
});
</script>
It works for the first list but it doesn't work for the second list.
What am I missing?
You can't use direct events with elements that doesn't exist. You need to use delegated events to solve this
$(document).on('change', '#cat_select_2' function() { ... }
Where document can be replaced by any parent element that exist at that time.
Check on documentation for more details (section "Direct and delegated events")

What is jQuery focus() Method doing in this code?

I want to know if the line below is needed in this script, and if so, what purpose it serves.
$("#quantity-0").focus();
If I do not have a form field with id "quantity-0" what other elements could I focus (if required)? Can I focus a hidden form element?
Here's my code. It comes from this blog.
<script type="text/javascript" charset="utf-8">
//<![CDATA[
// Including jQuery conditionnally.
if (typeof jQuery === 'undefined') {
document.write({{ "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" | script_tag | json }});
document.write('<script type="text/javascript">jQuery.noConflict();<\/script>');
}
//]]>
</script>
<script>
$(document).ready(function () {
$("#quantity-0").focus();
var length = $("#linklist-length").val();
$("#submit-table").click(function(e) {
e.preventDefault();
//array for Variant Titles
var toAdd = new Array();
var qty;
for(i=0; i < length; i++){
toAdd.push({
variant_id: $("#variant-"+i).val(),
quantity_id: $("#quantity-"+i).val() || 0
});
}
function moveAlong(){
if (toAdd.length) {
var request = toAdd.shift();
var tempId= request.variant_id;
var tempQty = request.quantity_id;
var params = {
type: 'POST',
url: '/cart/add.js',
data: 'quantity='+tempQty+'&id='+tempId,
dataType: 'json',
success: function(line_item) {
//console.log("success!");
moveAlong();
},
error: function() {
//console.log("fail");
moveAlong();
}
};
$.ajax(params);
}
else {
document.location.href = '/cart';
}
};
moveAlong();
});
});
</script>
I want to know if the line below is needed in this script, and if so, what purpose it serves.
Calling the jQuery .focus() method with no arguments sets focus to the specified element. That line is the first line inside the document ready handler. So its purpose is to set focus to that particular field when the page first opens/loads.
As to whether it is needed, that's really up to the page designer. Setting focus to the field the user will most likely want to interact with first is generally helpful to them. If you didn't have that it wouldn't stop the page from working or anything.
If I do not have a form field with id "quantity-0" what other elements could I focus (if required)?
You can set focus to whatever element you like. Normally this would be either a form element of some kind (input, button, etc.) or a hyperlink. Whichever one makes most sense for a user to interact with first upon page load.
Can I focus a hidden form element?
Why would you want to do that? It doesn't make sense for a user to interact with a hidden element. I believe attempting to set focus to a hidden element may give an error in some browsers.

jQuery not appending title

On my page I want the user to be able to mouseover a td element, have the page make an Ajax call to the server, and then append a title attribute to the td to serve as a tooltip for the remainder of the time the user is on the page.
The information the page needs to retrieve is very basic so there's nothing too complicated about this... however I cannot get the code to append the data I receive from the Ajax call onto the td element.
Jquery/Ajax
$('.ChannelCodeDesc').mouseover(function () {
//Only append if we don't have a title
if (!$(this).attr('title')) {
//Let me know when we're about to make Ajax call
console.log('ajax');
$.ajax({
type: 'GET',
url: '#Url.Action("GetDesc", "ZipCodeTerritory")',
data: { channel: $.trim($(this).text()) },
success: function (data) {
//Append to td
$(this).attr('title', data);
//Display what we got back
console.log(data);
}
});
}
//What does the title look like when we're done?
console.log($(this).attr('title'));
});
Unfortunately I can see, in the console, the 'ajax' entry, followed by the exact value I'm expecting for the data object, but undefined appears as the value for the td title attribute from the final console.log statement (end of the mouseover).
HTML/Razor
<td class="ChannelCodeDesc">
#Html.DisplayFor(model => model.displayForPaging[i].ChannelCode)
#Html.HiddenFor(model => model.displayForPaging[i].ChannelCode)
</td>
Ajax Controller Method
public JsonResult GetDesc(string channel)
{
var description = (from c in db.Channel
where c.ChannelCode.Equals(channel)
select c.ChannelLongDescription).FirstOrDefault();
return Json(description, JsonRequestBehavior.AllowGet);
}
The problem is that the this object in the success function is not the td element. By default the context of the jquery ajax callbacks is set as an object representing the ajax options. However you can change that using the context option:
$('.ChannelCodeDesc').mouseover(function () {
//Only append if we don't have a title
if (!$(this).attr('title')) {
//Let me know when we're about to make Ajax call
console.log('ajax');
$.ajax({
type: 'GET',
url: '#Url.Action("GetDesc", "ZipCodeTerritory")',
data: { channel: $.trim($(this).text()) },
context: this, //make sure "this" inside the success callback is the td element
success: function (data) {
//Append to td
$(this).attr('title', data);
//Display what we got back
console.log(data);
}
});
}
//What does the title look like when we're done?
console.log($(this).attr('title')); });
I am assuming that the data returned by Ajax is valid....
the $(this) within success does not refer to the td anymore.
do this outside the ajax call:
var me = $(this);
Then in your success code do this:
me.attr('title', data);
The final console.log statement shows undefined because it occurs before the AJAX request is complete (because AJAX requests are Asynchronous).
Also, a td can't have a title attribute, might need to look at a different option:
how to apply style to 'title' attribute of 'td' tag
And others have stated, can't use $this inside the ajax success function like that.

setInterval() not updating data during multiple calls

I am using following JavaScript code inside a page. The problem is that the code gets executed for the first time and fetches data from from elements.
During the subsequent calls, the changed data in the form elements is not available to this function as it uses data from its maiden call.
$(document).ready(function() {
$('<textarea id="message-clone"></textarea>').insertAfter("#form-message-compose");
var saveDraft = function () {
var originalStriped = $("#wysiwyg").val().replace(/(<([^>]+)>)/ig,"");
if((originalStriped.length) > 10) {
var input = $("<input>").attr("type", "hidden").attr("id", "savedraft")
.attr("name", "submit").val("savedraft");
$.ajax({
type: "POST",
url: $("#form-message-compose").attr("action"),
data: $("#form-message-compose").append(input).serialize(),
success: function(result){
var result = JSON.parse(result);
$("#subject").val(result.message_subject);
$('input[name="draft"]').val(1);
$("#id").val(result.message_id);
var flash = '<div id="flash" class="alert alert-success"><a data-dismiss="alert" class="close">×</a><strong>Yay!</strong> Message Auto saved to drafts!</div>';
$("#page-title").append(flash);
$("#flash").fadeOut(3000, function() { $(this).remove(); });
$("#savedraft").remove();
$("#message-clone").val($("#wysiwyg").val().replace(/(<([^>]+)>)/ig,""));
}
});
}
}
setInterval(saveDraft(), 2000);
});
The problem here is that for the first time, the function fetches correct data from input element #wysiwyg but during the subsequent, it doesnot update the data from the call $('#wysiwyg').val() which results in single execution of the code inside if block.
Kindly guide, where I am doing wrong.
setInterval(saveDraft(), 2000);
should be
setInterval(saveDraft, 2000);
The first argument of setInterval should be a function. You are not passing a function, what you're doing is executing saveDraft and passing the result as an argument.
The issue was with the Tiny MCE I was using. So instead of trying to get the value of texte area by
var originalStriped = $("#wysiwyg").val().replace(/(<([^>]+)>)/ig,"");
I had to use the tinyMCE method to fetch the text
var originalStriped = tinyMCE.get("wysiwyg").getContent({format : "text"});
Another problem with TinyMCE is that it doesnot update the data in textarea on an AJAX call, which otherwise, it does on form submit. So I had to call the trigger the save on tinyMCE manually by calling
tinyMCE.triggerSave();
And then firing the AJAX request with form data.

Categories