I am trying to figure out why I am unable to remove multiple neighboring elements on a successful ajax DELETE. When I had $(".file-preview").filter("a[href='" + fileLink + "']").remove(); by itself in the code below, I was able to remove the first link and when I add $(".remove-file").data("file-link", fileLink).remove(); after it, it breaks the first .remove() statement and removes all of the present .remove-file disregarding the value being passed to the data-file-link attribute in the link.
1) Why would the first remove be broken by this second remove?
2) Is there a better approach to what I'm trying to achieve which is to remove both neighboring elements on the click of .remove-file?
Here is an example of what the HTML looks like:
<div class="file-section>
<div class=" file-preview ">
https://test-bucket.s3.amazonaws.com/1/2017-01-30/screen-shot-2017-01-08-at-12.23.39-pm.png
<span class="glyphicon glyphicon-remove "></span>
</div>
<div class=" file-preview ">
https://test-bucket.s3.amazonaws.com/1/2017-01-30/screen-shot-2017-01-08-at-12.23.39-pm.png
<span class="glyphicon glyphicon-remove "></span>
</div>
</div>
jQuery:
$(document).on('click', '.remove-file', function(){
console.log('Delete Triggered');
var fileLink = $(this).data('file-link');
function pathExtract(url){
var fullUrl = url;
var delimiter = '/';
var start = 3;
var tokens = fullUrl.split(delimiter).slice(start);
var path = tokens.join(delimiter);
return path;
}
$.ajax({
url: '/app/sign?' + $.param({"file": pathExtract(fileLink)}),
type: 'DELETE',
success: function(){
console.log('This is the file link ' + fileLink);
$(".file-preview").filter("a[href='" + fileLink + "']").remove();
$(".remove-file").data("file-link", fileLink).remove();
},
error: function(error){
console.log('error ' + JSON.stringify(error));
}
});
});
.data("file-link", fileLink) isn't a filter, it sets the data of the elements selected. It simply returns the same collection it was called on, so when you call .remove() on the result it removes all the elements with the remove-file class.
If you want to remove just the elements with that data value, use .filter():
$(".remove-file").filter(function() {
return $(this).data("file-link") == fileLink;
}).remove();
This code:
$(".file-preview").filter("a[href='" + fileLink + "']").remove();
doesn't work because the a element is inside the .file-preview DIV, but .filter() tests if the element itself matches the filter. You should write:
$(".file-preview:has(a[href='" + fileLink + "'])").remove();
to test the contents.
Related
I'm using ajax to get an results from code behind, when I Get those results I'm creating an a divs. And this works fine, adding a div dynamically.
Now I Want to add on each div onclick event which should raise some method when it's clicked, so here is my full code:
<script>
function onSelectGroup(Id) {
$.ajax({
method: "GET",
url: "Product/GetProductsByGroupId",
data: { groupId: Id }
})
.done(function (response) {
$(".products").html("");
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
}})};
function addProduct(product) {
console.log(product.Title);
}
</script>
But when I click on any of my generated divs I get an following error:
Uncaught SyntaxError: Unexpected identifier
I'm looking for issue for 3h allready, and I'm really stucked here..
Any kind of help would be great.
Thanks
P.S
CODE BEHIND - C # METHOD:
public ActionResult GetProductsByGroupId(int groupId)
{
var products = ProductController.GetProductsByGroupId(groupId);
if(products)
{
List<Product> productlist = new List<Product>();
foreach (var item in products)
{
Product product = new Product();
product.ProductId = Convert.ToInt32(item.Id);
product.Price = Convert.ToDecimal(item.Price);
product.Title = item.Title;
productlist.Add(product);
}
return Json(productlist, JsonRequestBehavior.AllowGet);
}
return Json(products, JsonRequestBehavior.AllowGet);
}
Remove the onclick and use delegate, you are passing an object to a function which convert response[i] to text [Object object], use data-* attributes to hold data for each object and attach an event to the div with the class product, on click of the div we'll use $(this) to reference the current clicked div and access its data attributes.
$(".products").html("");
var response = [{ProductId:4, Title:"Doe", Price: 34.89}, {ProductId:6, Title:"Jane", Price: 20.99}];
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder product" data-price="'+ response[i].Price +'" data-title="' + response[i].Title + '" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
//console.log(item);
};
$(document).on('click', '.product', function(){
var product = {Title: $(this).data('title'), ProductId: $(this).attr('id'), Price: $(this).data('price')};
console.log(product);
// here use ajax to add this product
});
body {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="products"></div>
Take a look at the Delegate jquery method!
Description: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
So you basically need to bind the onClick event to the parent div, and pass a selector that will appear later on the child divs.
<script>
function onSelectGroup(Id) {
$.ajax(
//Do your ajax call here
).done(function (response) {
for (var i = 0; i < response.length; i++) {
let item = '<div class="event-target"></div>'
$(".products").append(item);
}})};
// Here's where the magic happens.
// We bind the event to the elements that have the 'event-target' class
//inside the element that have the 'products' class.
$('.products').on('click', '.event-target', function(){
console.log(this);
})
</script>
Warning: take care using delegate, if you use the wrong selector you can end up triggering the event for each element on the page, or even recursivelly (belive me, have made it a lot...)
Use data attributes to store any data & on click retrieve the data attribute.The code is not tested but hopefully it will work
let item = '<div class="col-md-3">' +
' <div class="Product-holder" ' +
'onclick="addProduct(this)"' +
' data-title="'+response[i].Title+'"' +
' id=' + response[i].ProductId + '>' +
'<img class="img-responsive" src="images/maxresdefault.jpg">' +
'<p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p>' +
'</div>' +
'</div>';
$(".products").append(item);
function addProduct(product) {
console.log($(product).data('title'));
}
Also you need to delegate the event since they are dynamically created element
$("body").on("click",".Product-holder",function(){
console.log($(product).data('title'));
})
In this case the inline event handler that is onclick function will be redundant
Let me going to explant your code.
for (var i = 0; i < response.length; i++) {
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
$(".products").append(item);
}})};
On these line of code, I saw that you have added strings to a variable.
but more exception response[i].ProductId seem like response[i] was an object.
but in Javascript you can't add an object to String by + operator, it will be return "string [object] string". What is solution for that??
Convert your object to JSON String like {"id": 123, "name": "Product name"}, that will show in html code like this onclick='addProduct({"id": 123, "name": "Product name"})' remember that onclick = ' not "
I am trying to get all span elements inside the form. The span elements are turning into input text fields and become editable. When you click away they are turning back into span elements. I will attached fiddle live example.
I gave it a go but the problem is that I am getting both ids but only value of the first span element.
Here is my html:
<span name="inputEditableTest" class="pztest" id="inputEditableTest" data-editable="">First Element</span>
<span name="inputEditableTest2" class="pztest" id="inputEditableTest2" data-editable="">Second Element</span>
<input id="test" type="submit" class="btn btn-primary" value="Submit">
And here is JavaScript with jQuery:
$('body').on('click', '[data-editable]', function () {
var $el = $(this);
var name = $($el).attr('name');
var value = $($el).text();
console.log(name);
var $input = $('<input name="' + name + '" id="' + name + '" value="' + value + '"/>').val($el.text());
$el.replaceWith($input);
var save = function () {
var $p = $('<span data-editable class="pztest" name="' + name + '" id="' + name + '" />').text($input.val());
$input.replaceWith($p);
};
$input.one('blur', save).focus();
});
$("#test").on('click', function(){
var ok = $("span")
.map(function () {
return this.id;
})
.get()
.join();
var ok2 = $("#" + ok).text();
alert(ok);
alert(ok2);
//return [ok, ok2];
});
Here is the fiddle https://jsfiddle.net/v427zbo1/3/
I would like to return the results as an array example:
{element id : element value}
How can I read ids and values only inside specific form so something like:
<form id = "editableForm">
<span id="test1">Need these details</span>
<span id="test2">Need these details</span>
<input type="submit">
</form>
<span id="test3">Don't need details of this span</span>
Lets say I have got more than 1 form on the page and I want JavaScript to detect which form has been submitted and grab values of these span elements inside the form
I will be grateful for any help
$("#test").on('click', function(){
var result = {};
$("span").each(function (k, v) {
result[v.id] = v.innerHTML;
});
alert(JSON.stringify(result));
//return [ok, ok2];
});
Here is an example: https://jsfiddle.net/v427zbo1/4/
Container issue:
You should use this selector: #editableForm span if you want to get all the divs inside this container.
$("#editableForm span").each(function (k, v) {
result[v.id] = v.innerHTML;
});
But if you want to get only first-level children elements then you should use this selector: #editableForm > span
Example with getting all the spans inside #editableForm container: https://jsfiddle.net/v427zbo1/9/
If you want to have several forms, then you can do like this:
$('form').on('submit', function(e){
e.preventDefault();
var result = {};
$(this).find('span').each(function (k, v) {
result[v.id] = v.innerHTML;
});
alert(JSON.stringify(result));
//return [ok, ok2];
});
Example with two forms: https://jsfiddle.net/v427zbo1/10/
You can't use .text to return the value of multiple elements. It doesn't matter how many elements are selected, .text will only return the value of the first one.
Virtually all jQuery methods that return a value behave this way.
If you want to get an array of values for an array of matched elements, you need another map. You also need to join the strings with , # as you're producing something along the lines of #id1id2id3 instead of #id1, #id2, #id3:
var ok = $("span").map(function () {
return this.id;
}).join(', #')
var ok2 = $("#" + ok).map(function () {
return $(this).text();
});
That said, you're already selecting the right set of elements in your first map. You pass over each element to get its ID, you already have the element. There is no reason to throw it away and reselect the same thing by its ID.
If I got you right following code will do the job
var ok = $("span")
.map(function () {
return {id: $(this).attr('id') , value: $(this).text()};
}).get();
Check this fiddle.
What is the optimize way to append this element to my specific DIV Class using JQUERY. This will generate dynamic elements. I use .AppendTo then display dynamically the element inside <div class='parent-list-workorder'>.
Here's my code so far but it doesn't work:
$(document).ready(function(){
var ListOfWorkOrders = [];
$("#button").click(function(){
//var _WOID = $('.list-workorder-id').text();
var _WOID = $('#txtWOID').val();
//alert(_WOID);
$.ajax({
url:'getWorkOrders.php',
type:'POST',
data:{id:_WOID},
dataType:'json',
success:function(output){
for (var key in output) {
if (output.hasOwnProperty(key)) {
$("<div class='child-list-workorder'>
<div class='list-workorder'>
<div class='list-workorder-header'>
<h3 class='list-workorder-id'>" + output[key] + "</h3>
</div>
<p>" + Sample + ":" + key + "</p>
</div>
</div>").appendTo("<div class='parent-list-workorder'>");
//alert(output[key]);
}
}
console.log(output);
}
});
});
});
Am I missing something?
Your problem is in the code below:
.appendTo("<div class='parent-list-workorder'>");
The parameter of appendTo() should also be a valid selector.
you can try this instead:
.appendTo("div.parent-list-workorder");
granting that div.parent-list-workorder already exists.
You have two problems. First, you need to use a selector as an argument to .appendTo(), not an HTML string. Second, you need to remove or escape the newlines in the HTML string.
$("<div class='child-list-workorder'>\
<div class='list-workorder'>\
<div class='list-workorder-header'>\
<h3 class='list-workorder-id'>" + output[key] + "</h3>\
</div>\
<p>" + Sample + ":" + key + "</p>\
</div>\
</div>").appendTo("div.parent-list-workorder");
I have created one html which contains search box. After searching, I'm getting the data in list. But when I click on that I'm getting the value of all list item by using this
var text = $(this).text(); method
In my app, if I click on one item only it should give me only that value of list item not other. I'm making a mistake somewhere, but I don't know where.
Here is my code:
HTML
<ul data-role="listview" class="ui-li-icon">
<li id="list"></li>
</ul>
And here is my JavaScript code:
function successCallback(responseObj)
{
// alert(JSON.stringify(responseObj));
form.reset();
dataj=JSON.stringify(responseObj);
len=dataj.length;
for(i=0;i<len;i++)
{
var output = "<ul>" + responseObj.merchants[i].imageFileName+ " " + "<font size=3 color=green>" + responseObj.merchants[i].merchantName + "</font>" +"</ul>";
$('#list').append(output);
}
$('#list').click(function() {
var index = $(this).index();
var text = $(this).text();
alert('Index is: ' + index + ' and text is ' + text);
});
}
So when I'm searching for some a item. I'm getting list of:
ab
abc
But when I clicked on it. I get value of both ab and abc. I just want only one value where I have clicked.
//replace your click event by below code
$('.ui-li-icon li').click(function() {
var index = $(this).index();
var text = $(this).text();
alert('Index is: ' + index + ' and text is ' + text);
});
$('#list').append(output);
I believer list is the id you are giving to list items i.e.
Now, this will confuse the browser because id should be UNIQUE and here you are giving this id to all the list items.
If you fix this, your problem should be resolved!
Or you could simply attach click event using this
$('.ui-li-icon li').click //Your click event handler
It's very difficult to understand what you are asking. From what I can tell you're looking for something like this:
$('#list li').on('click', function(){
alert("index: "+$(this).index() + " value: "+ $(this).text());
});
Here's a fiddle http://jsfiddle.net/Jw8qz/
I have one question. Is possible delete <span> element added with javascript append?
When i try remove added span then nothing happens.
Like this:
<script type="text/javascript">
$(document).ready(function(){
$('#SelectBoxData span').click(function(){
var StatusID = this.id;
var StatusIDSplit = StatusID.split("_");
var StatusText = $('#SelectBoxData #' + StatusID).text();
$("#SelectBox").append('<span id=' + StatusID + '>' + StatusText + '</span>');
$("#SelectBoxData #" + StatusID).remove();
InputValue = $("#StatusID").val();
if(InputValue == ""){
$("#StatusID").val(StatusIDSplit[1]);
}
else{
$("#StatusID").val($("#StatusID").val() + ',' + StatusIDSplit[1]);
}
});
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
});
</script>
<div id="SelectBoxBG">
<div id="SelectBox"><div class="SelectBoxBtn"></div></div>
<div id="SelectBoxData">
<span id="StatusData_1">Admin</span>
<span id="StatusData_2">Editor</span>
<span id="StatusData_4">Test 1</span>
<span id="StatusData_6">Test 2</span>
</div>
<input type="hidden" id="StatusID" />
</div>
Please help me.
Thanks.
Yes, you can delete them. However, you can't add click event handlers to them before they exist. This code:
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
will only add a click event handler to <span> elements inside of #SelectBox at the time the code is run (so, based on your provided HTML, zero elements). If you want the event handler to react to dynamically added elements then you need to use a technique called event delegation, using the .on() function:
$('#SelectBox').on('click', 'span', function() {
$(this).remove(); // equivalent to the code you had before
});