Using jQuery and JavaScript I am trying to write some code that setups up one or more widgets. The widget accepts text in an input and adds it to a ul when a button is clicked.
Then items are added to the ul, a click listener is a setup to remove a specific item when clicked.
The code looks like this:
function WidgetThing(className) {
var items = [];
function removeItem(e) {
var idx = parseInt($(e.target).attr('data-index'));
items.splice(idx, 1);
updateItems();
}
function updateItems() {
var ul = $('.' + className + ' .items ul');
ul.html('');
items.forEach(function(item, idx) {
ul.append('<li data-index="' + idx + '">' + item + '</li>');
});
ul.on('click', 'li', removeItem);
}
$('.' + className + ' .add-button').click(function(e) {
var input = $('.' + className + ' input');
items.push(input.val());
input.val('');
updateItems();
});
}
$(document).ready(function() {
WidgetThing('widget1');
WidgetThing('widget2');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Widget1
<div class="widget1">
<div class="controls">
<input type="text" />
<button class='add-button'>Add Item</button>
</div>
<div class="items">
<ul></ul>
</div>
</div>
Widget2
<div class="widget2">
<div class="controls">
<input type="text" />
<button class='add-button'>Add Item</button>
</div>
<div class="items">
<ul></ul>
</div>
</div>
This works fine for adding items.
However, if I click the item to remove it, it also removes all items below the one selected.
How can I get this code to work? Am I taking the wrong approach?
Update Note: In the real app my updateItems() function has some side effects, so I need to take this approach to removing items from the array.
Working fiddle.
That could be achieved with less code than this, you could attach two events one to the buttons and another to the li elements for the remove :
$(document).ready(function() {
$('.add-button').click(function() {
var items = $(this).closest('.controls').next('.items');
$('ul', items).append('<li>' + $(this).prev('input').val() + '</li>');
});
$('ul').on('click', 'li', function() {
$(this).remove();
});
});
Here is a working snippet :
$(document).ready(function() {
$('.add-button').click(function() {
var items = $(this).closest('.controls').next('.items');
$('ul', items).append('<li>' + $(this).prev('input').val() + '</li>');
});
$('ul').on('click', 'li', function() {
$(this).remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Widget1
<div class="widget1">
<div class="controls">
<input type="text" />
<button class='add-button'>Add Item</button>
</div>
<div class="items">
<ul></ul>
</div>
</div>
Widget2
<div class="widget2">
<div class="controls">
<input type="text" />
<button class='add-button'>Add Item</button>
</div>
<div class="items">
<ul></ul>
</div>
</div>
Related
I'm creating a project in ASP.NET MVC and jQuery. When a user click on addSentence button, I want to duplicate a div called copythis with all events and insert it in another div called myform.
in copythis I have two div: in the first there is a span called sentence where I insert the text in the input in the second the user can add more then one field with different text.
When the user clicks the button called save I want to read all copythis in myform and create a structure to send to a webapi.
I have a problem is the javascript because I can read properly each div.
$("#addSentence").on("click", function (event) {
if ($("#inputSentence").val() == "")
alert("Sentence must have a value");
else {
event.preventDefault();
var theContainer = $("#copythis");
if (theContainer != null) {
var clonedSection = $(theContainer).clone(true);
if (clonedSection != null) {
$(clonedSection).find("#sentence")
.text($("#inputSentence").val());
$(clonedSection).appendTo("#myform");
}
}
}
});
$("#save").on("click", function (event) {
$("#myform #copythis").children().each(function (index, element) {
var elm = $(this);
var sentence = elm.find('.row span#sentence').val();
if (sentence != '') {
console.log('Sentence: ' + sentence);
$("input").children().each(function (m, l) {
var txt = $(this).val();
if (txt != '') {
console.log('Example: ' + txt);
}
});
}
});
});
function makeRepeater(sectionsSelector, addClass, removeClass, AYSMsg) {
$(sectionsSelector + " " + addClass + "," + sectionsSelector +
" " + removeClass).on("click", function (event) {
// Avoiding the link to do the default behavior.
event.preventDefault();
// Get the container to be removed/cloned
var theContainer = $(this).parents(sectionsSelector);
if ($(this).is(addClass)) {
// Cloning the container with events
var clonedSection = $(theContainer).clone(true);
// And appending it just after the current container
$(clonedSection).insertAfter(theContainer);
} else {
// If the user confirm the "Are You Sure" message
// we can remove the current container
if (confirm(AYSMsg)) {
// Making fade out, hide and remove element a sequence
// to provide a nice UX when removing element.
$(theContainer).fadeOut('normal',
function () {
$(this).hide('fast',
function () { $(this).remove(); }
);
}
);
}
}
});
}
makeRepeater(
'.my-repeated-section-form', /* The container selector */
'.addform', /* The add action selector */
'.removeform', /* The remove action selector */
'Are you sure you want to remove this section?' /* The AYS message. */
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="row">
<div class="row">
<div class="col-lg-10">
<div class="input-group">
<input id="inputSentence" type="text"
class="form-control" placeholder="Sentence...">
<span class="input-group-btn">
<button class="btn btn-secondary"
type="button" id="addSentence">Add</button>
</span>
</div>
</div>
</div>
<div class="col-lg-12">
<div style="display: inline;">
<div class="group-of-repeated-sections" style="display: none;">
<div class="my-repeated-section">
<div id="copythis">
<div class="row">
<div class="col-lg-10">
<span id="sentence"></span>
</div>
<div class="col-lg-2">
<span>
+
-
</span>
</div>
</div>
<div class="my-repeated-section-form">
<div class="row">
<div class="col-lg-12">
<input type="text" />
<span>
+
-
</span>
</div>
</div>
</div>
<div style="height:25px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="myform"></div>
<button id="save">Save</button>
I have multiple .note and I want to be able to click on .remove (which is in each .note) and it will remove the .note that the .remove that I clicked was in. I've used .closest() to do that, but it will only work for the first note, and not the other ones after that. Thanks in advance!
Here is the code:
The code that removes the .note:
$('.remove').click(function () {
$(this).closest('.note').remove(".note");
});
HTML:
<body>
<div id="wrapper">
<div id="wrp">
<h1>Click to make a new note!!!</h1>
<hr>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item"></textarea>
<div class="saved"><span class="msg"></span>
</div>
</div>
</body>
JS:
$('.note').click(function (event) {
event.preventDefault();
});
$('#wrp, #wrapper').click(function showNote() {
$('.note').fadeIn();
});
$(function () {
$(document).mousedown(function (event) {
// only proceed if clcik is not anywhere in a note element
if (!$(event.target).closest('.note').length) {
var note2 = $('.note').first();
note2.clone().insertBefore(note2);
console.log(note2);
}
});
});
$('.remove').click(function () {
$(this).closest('.note').remove(".note");
});
window.onload = function () {
var input = $("#item").focus();
};
function date() { //code indentation
var now = new Date();
now2 = now.getMonth() + 1 + '/' + now.getDate() + '/' + now.getFullYear() + ' ' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
$('.time').html(now2);
}
date();
var autosaveOn = false;
function myAutosavedTextbox_onTextChanged() {
if (!autosaveOn) {
autosaveOn = true;
$('.item').everyTime("3000", function () {
$.ajax({
type: "POST",
url: "/echo/html/",
data: "id=1",
success: function (msg) {
$('.msg').text(Saved);
alert("saved");
}
});
}); //closing tag
}
}
$(".note").closest('.note').draggable();
$(function () {
$("#tabs").autoSave(callback, ms);
});
$(".item").autoSave(function () {
var time = new Date().getTime();
$("#msg").text("Draft Autosaved " + time);
}, 500);
It looks like you have one note and then you are cloning it when you click on something other than the note and inserting it next to the previous note. Since you are only binding to the first note you need to use a live function. E.g. something like
$('body').on('click', '.remove', function() {
$(this).closest('.note').remove();
});
since you know that your .remove element is a direct child of the .note, you can just select its parent:
$('.remove').click(function () {
$(this).parent().remove();
});
if the .remove element is NOT a direct child of the .note, you can do this:
$('.remove').click(function () {
$(this).parents(".note").remove();
});
IMPORTANT:
if your notes are generated dynamically, then you will need to utilize event delegation, by attaching the click handler to the wrapper instead of the .remove buttons, and fire when elements with class .remove are clicked inside the wrapper:
$('#wrapper').on("click",".remove",function () {
$(this).parent().remove();
});
Do this:
$('.remove').click(function () {
$(this).closest('.note').remove();
});
That will remove only the closest note, as the closest() function already selects the elements anyway. If you pass a parameter to remove() it will search for all elements that match it, but if you use it on an already selected node, it will remove that node.
DOCS: https://api.jquery.com/remove/
Here is a possible solution. Possibly I am late... got distracted while typing the answer.
$('.remove').on('click', function(){
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="wrapper">
<div id="wrp">
<h1>Click to make a new note!!!</h1>
<hr>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item">Note1</textarea>
<div class="saved">
<span class="msg"></span>
</div>
</div>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item">Note2</textarea>
<div class="saved">
<span class="msg"></span>
</div>
</div>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item">Note3</textarea>
<div class="saved">
<span class="msg"></span>
</div>
</div>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item">Note4</textarea>
<div class="saved">
<span class="msg"></span>
</div>
</div>
<div class="note">
<p class="remove"><b>X</b>
</p>
<div class="time"></div>
<hr>
<textarea class="item">Note5</textarea>
<div class="saved">
<span class="msg"></span>
</div>
</div>
</div>
</div>
</body>
I have a jquery code that is almost complete. I want the new values of the existing parameter to be added on the <a href> using jquery but my code only adds the value at the end of the href.
Sample case:
My parameters in the href are food-option AND talent-option.:
<a href="food-option=0&talent-option=0">
Then I have new values to be added for food option.
values: 123,456
My href should be like this:
<a href="food-option=0,123,456&talent-option=0">
This is my code that adds the value:
$(this).closest(".option-container").find("a.food-form-select-food").each(function () {
var _href = $(this).attr("href");
$(this).attr("href", _href + ',' + addnid);
});
But the result is like this:
<a href="food-option=0&talent-option=0,123,456">
Which is wrong.
Here is a JSfiddle/Demo of my work
Can somebody please help me?
Thank you very much in advance!
You are almost there.
Try this:
$(this).closest(".option-container").
find("a.food-form-select-food").each(function () {
var _href = $(this).attr("href").split("&");
_href[0] += ',' + addnid;
$(this).attr("href", _href.join("&"));
});
i think your looking for something like this:
$(this).closest(".option-container").find("a.food-form-select-food").each(function () {
var _href = $(this).attr("href");
var n = str.indexOf(",");
var output = _href.substr(0, position) + addnid + _href.substr(position);
});
and if you want more answers look at this:
Inserting string at position x of another string
try this, JSFIDDLE
$(document).ready(function () {
$(".select-addon").click(function () {
var addtitle = $(this).closest('.optionlist').find('.option-title').html();
var addnid = $(this).closest('.optionlist').find('.option-nid').html();
var html = '<li class="option-list">' + addtitle + '<div class="addnid2">' + addnid + '</div><span class="remove-addons"> Remove</span></li>';
$(this).closest(".option-container").find('#your-addons').append(html);
$(this).closest(".option-container").find("a.food-form-select-food").each(function () {
var _href = $(this).attr("href");
var splited = _href.split('&');
$(this).attr("href", splited[0] + ',' + addnid+'&'+splited[1]);
});
});
$(document).on('click', '.remove-addons', function () {
var addnid2 = $(this).closest('.option-list').find('.addnid2').html();
$(this).closest(".option-container").find("a.food-form-select-food").each(function () {
var href = $(this).attr('href');
$(this).attr('href', href.replace("," + addnid2, ""));
});
$(this).closest('li').remove()
});
});
.option-nid {
display: none;
}
.addnid2 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="option-container" style="width:200px; float:left">
<div class="optionlist">
<div class="option-title">Food Set A</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">132</div>
</div>
<div class="optionlist">
<div class="option-title">Food Set B</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">133</div>
</div>
<div class="optionlist">
<div class="option-title">Food Set C</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">134</div>
</div>
<br/>
<br/>
<br/>
<ol id="your-addons"></ol>
LINK
</div>
<div class="option-container col-md-6">
<div class="optionlist">
<div class="option-title">Food Set A</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">132</div>
</div>
<div class="optionlist">
<div class="option-title">Food Set B</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">133</div>
</div>
<div class="optionlist">
<div class="option-title">Food Set C</div>
<span class="select-addon">SELECT </span>
<div class="option-nid">134</div>
</div>
<br/>
<br/>
<br/>
<ol id="your-addons"></ol>
LINK
</div>
This is my JS. I dont know why the "X" created by append to last child doesn't work on first click, but it does work on the second click. "x" url is in the cloned div. Is that causing the problem? Or is there something wrong in the HTML?
$(document).ready(function () {
$(".add").click(function () {
var aaa = $(this).parent("div").attr('id')
$(this).parent().children(".add").siblings(".name,.detail,.price").clone().appendTo(".CART").wrapAll('<div class="dump ' + aaa + '"></div>')
$(this).removeClass("add").addClass("added");
$(".dump:last-child").append('<a class="delC" href="javascript:delC()">x</a>');
$(".dump").removeClass("dump")
});
})
////////////////
function delC() {
$(document).on('click', '.delC', function () {
var xx = $(this).parent("div").attr('class')
$("." + xx + "").remove()
})
}
<div id="itemA">
<div class="detail">USB</div>
<div class="name">USB type1</div>
<div class="price">1500</div>
<div class="weight">20 Gr</div>
<a class="add">add</a>
</div>
<div id="itemB">
<div class="detail">RAM</div>
<div class="name">RAM type1</div>
<div class="price">2000</div>
<div class="weight">50 Gr</div>
<a class="add">add</a>
</div>
<div class="CART"></div>
The problem is that you are binding click event inside the delC function. So the first time you click you just bind events (and then you bind more and more event handlers)..
Instead remove delC function and just delegate delete events in the first place:
$(document).ready(function () {
$(".add").click(function () {
var aaa = $(this).parent("div").attr('id')
$(this).parent().children(".add").siblings(".name,.detail,.price").clone().appendTo(".CART").wrapAll('<div class="dump ' + aaa + '"></div>')
$(this).removeClass("add").addClass("added");
$(".dump:last-child").append('x');
$(".dump").removeClass("dump");
});
})
$(document).on('click', '.delC', function () {
var xx = $(this).parent("div").attr('class')
$("." + xx + "").remove()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="itemA">
<div class="detail">USB</div>
<div class="name">USB type1</div>
<div class="price">1500</div>
<div class="weight">20 Gr</div> <a class="add">add</a>
</div>
<div id="itemB">
<div class="detail">RAM</div>
<div class="name">RAM type1</div>
<div class="price">2000</div>
<div class="weight">50 Gr</div> <a class="add">add</a>
</div>
<div class="CART"></div>
You dont need a separate function to be called on href. You can just bind that to a click function.
$(document).on('click', '.delC', function(e){
e.preventDefault();
var xx = $(this).parent("div").attr('class')
$("."+xx+"").remove()
})
Working JsFiddle http://jsfiddle.net/j65uex6t/
This should do the trick
Fiddle
$(function () {
$(".add").click(function () {
var aaa = $(this).parent("div").attr('id')
$(this).parent().children(".add").siblings(".name,.detail,.price").clone().appendTo(".CART").wrapAll('<div class="dump ' + aaa + '"></div>')
$(this).removeClass("add").addClass("added");
$(".dump:last-child").append('<a class="delC">x</a>');
$(".dump").removeClass("dump")
});
$(document).on('click', '.delC', function (e) {
e.preventDefault();
var xx = $(this).parent("div").attr('class')
$("." + xx + "").remove()
})
});
I want to change each div id with change function.
before:
<div id="a_1">a1</div>
<div id="b_1">b1</div>
<div id="c_1">c1</div>
<div id="d_1">d1</div>
<button onclick="change()">Değiştir</button>
after:
<div id="a_2">a2</div>
<div id="b_2">b2</div>
<div id="c_2">c2</div>
<div id="d_2">d2</div>
<button onclick="change()">Değiştir</button>
I've tried this function but it didnt work
function change()
{
var old_id=1;
var new_id=2;
alert( bas( $("#a_1").attr("id")) );
$("div[id$=_"+old_id+"]").attr("id", bas( $("div[id$=_"+old_id+"]").attr("id") ) +new_id);
}
How can I do?
Thanks.
After doing some small changes you can achieve these this easily.
Try this:
HTML Code:
<div id="a_1">a1</div>
<div id="b_1">b1</div>
<div id="c_1">c1</div>
<div id="d_1">d1</div>
<button onclick="change(1, 2)">Değiştir</button>
Javascript/Jquery Code:
function change(oldid, newid)
{
$('div[id $= "_' +oldid+ '"]').each(function(){
var clone =$(this).clone(true).attr('id' , 'id_' + newid);
$('body').append(clone);
});
var nextid = newid + 1;
$('body').append('<button onclick="change(' + newid + ',' + nextid +')">Değiştir</button>');
}
Working Example
I have added class attribute to the div elements. Here is the demo JSFIDDLE
HTML:
<div id="a_1" class="my_div">a1</div>
<div id="b_1" class="my_div">b1</div>
<div id="c_1" class="my_div">c1</div>
<div id="d_1" class="my_div">d1</div>
<button onclick="change_ids()">Değiştir</button>
JS:
change_ids=function()
{
var old_id=1;
var new_id=2;
$('div.my_div').each(function() {
var div_id = $(this).attr('id');
var arr = div_id.split("_");
//alert(arr[0]+" "+arr[1]);
var new_div_id = arr[0]+"_"+new_id;
$(this).attr('id', new_div_id);
$(this).html(new_div_id);
});
alert('Div ids changed')
}