I have an input box which you can enter items, submit it, and create a box with it's own delete button to remove it. Problem is, after deleting a number of boxes, and then entering something new in input, all the previous items that were deleted get reloaded, including the new item.
How can I prevent reloading of already removed boxes?
Fiddle (Stacksnippets do not allow submit)
This is my Html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Shopping List Example</title>
<link rel="stylesheet" type="text/css" href="css-list.css">
</head>
<div id="centerPanel">
<form class="my-list-form">
<input type="text" class="input" name="add-input" id="add-input">
<button class="add-button" id="submitBtn">Add</button>
</form>
<ul class="my-list-ul"></ul>
</div>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script src="js-list.js"></script>
</html>
JS:
var state = {items:[]};
var addItem = function(state, item)
{
state.items.push(item);
}
var displayItem = function(state, element){
var htmlItems = state.items.map(function(item){
return '<li class="box">' + item + '</br><button class="divBtns" id="deleteBtn">Delete</button>' + '</li>';
});
element.html(htmlItems);
}
//After deleting items, this button again loads all items that have been created since
//the page loaded up, including the new item.
//Needs to be fixed to not reload the deleted items
$('.my-list-form').submit(function(event){
event.preventDefault();
addItem(state, $('.input').val());
displayItem(state, $('.my-list-ul') );
/* alert(state.items[1]); shows that the items array holds everything that is turned into a div*/
})
$(document).ready(function(e){
$('ul').on('click', '#deleteBtn', function(event){
var rmvButton = $(this).closest('li');
rmvButton.remove();
});
})
css:
* {
font-family: sans-serif;
font-weight: normal;
}
#centerPanel {
margin-left: 50px;
margin-top: 50px;
padding-left: 10px;
}
h1 {
font-size: 34px;
}
.font-size {
font-size: 17px;
}
#add-input {
height:25px;
width: 190px;
font-size: 16px;
}
button {
font-size: 17px;
}
#submitBtn {
height: 30px;
width: 85px;
}
.divBtns {
margin-top: 10px;
}
.box {
border: 1px solid black;
border-color: grey;
width: 153px;
height: 65px;
padding: 20px;
font-style: italic;
font-size: 22px;
margin-bottom:10px;
margin-right: 10px;
}
ul {
list-style-type: none;
margin-left:-40px;
color: grey;
}
li {
float: left;
}
It appears you never remove anything from the state object, which is added to every time you run addItem().
You'd need a way to remove a specific item from this array, probably by getting the index of the li to delete and doing
state.items.splice(index, 1);
Store the index as a data attribute on the button:
var displayItem = function(state, element){
var i = 0;
var htmlItems = state.items.map(function(item){
return '<li class="box">' + item + '</br><button class="divBtns" ' +
'id="deleteBtn" data-index="' + (i++) + '">Delete</button>' + '</li>';
});
element.html(htmlItems);
}
Then you can get it in the click callback
var index = $(this).data('index');
You can update state to solve this problem.
It's my code:
...
var deleteItem = function(state, itemId) {
var index = 0;
var isFind = state.items.some(function(item, i) {
if (item.id == itemId) {
index = i;
return true;
} else {
return false;
}
});
if (isFind) {
state.items.splice(index, 1);
}
}
...
$(document).ready(function(e){
$('ul').on('click', '#deleteBtn', function(event){
...
// update state
deleteItem(state, $(this).parent().data('id'));
});
})
https://jsfiddle.net/q483cLp9/
Related
Here I work on a project where I want to implement open and close buttons but I am not able to do
currently, it's a close button for both, I need to add separate open and close buttons so that when the user clicks on open then it's open and when someones click on close then it should close properly also when I click continuously close then buttons freezes for sometime
Here is the demo of my JSFiddle Demo
please check the js Fiddle demo where buttons doesn't work properly
Here is the code
function createItem(item) {
var elemId = item.data("id");
var clonedItem = item.clone();
var newItem = $(`<div data-id="${elemId}"></div>`);
newItem.append(clonedItem);
newItem.appendTo('.item-append');
}
function countSaveItems() {
$('.count').html($(".item-append div.item-save[data-id]").length);
}
$('.item-all .item-save').click(function() {
$(this).toggleClass('productad')
window.localStorage.setItem('test_' + this.dataset.id, $(this).hasClass('productad'));
});
$('.item-all .item-save').each(function() {
var id = 'test_' + $(this).data("id");
$(this).append(`<button class='close'>Close</button>`);
if (localStorage.getItem(id) && localStorage.getItem(id) == "true") {
$(this).addClass('productad');
createItem($(this));
countSaveItems();
}
});
$(".item-all .item-save").click(function() {
var elemId = $(this).data("id");
var existing = $(`.item-append div[data-id="${elemId}"]`);
if (existing.length > 0) {
existing.remove();
} else {
createItem($(this));
}
countSaveItems();
});
$(".item-append").on("click", ".close", function() {
var id = $(this).parent().data("id");
localStorage.removeItem(`test_${id}`);
$(`.item-save[data-id='${id}']`).removeClass('productad');
$(this).parent().remove();
countSaveItems();
});
.item-save {
position: relative;
display: block;
font-size: 14px;
margin: 5px;
padding: 5px;
background: #a5a5a5;
float: left;
text-align: center;
cursor: pointer;
}
.productad {
background: red;
color: #eee
}
.count {
display: block;
background: #cbcbcb;
float: left;
font-size: 15px;
padding: 5px 18px;
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='item-all'>
<div class='item-save' data-id='123'>
Save1
</div>
<div class='item-save' data-id='124'>
Save2
</div>
<div class='item-save' data-id='125'>
Save3
</div>
<div class='item-save' data-id='126'>
save4
</div>
</div>
<div class='item-append'>
</div>
<div class='count'>0</div>
Any Kind of help or suggestion is highly appreciated
To do the effect you need to add the open button into the HTML because that will be static, then switch between "Open" and "Close" when the user clicks into the "Open" or close the item, also needs to fix the local storage instead of removing in the close button just switch the value to false and validate based on that value. check the following code to see if that is what you are looking for:
function createItem(item){
var elemId = item.data("id");
var clonedItem = item.clone();
var newItem = $(`<div data-id="${elemId}"></div>`);
newItem.append(clonedItem);
clonedItem.children('.open').remove();
clonedItem.append(`<button class='close'>Close</button>`);
newItem.appendTo('.item-append');
}
function countSaveItems(){
$('.count').html($(".item-append div.item-save[data-id]").length);
}
$('.item-all .item-save').click(function() {
var id = $(this).data("id");
var lsId = `test_${id}`;
$(this).toggleClass('productad');
if (!$(this).hasClass('productad')){
window.localStorage.setItem(lsId, false);
$(this).children(".open").html("Open");
createItem($(this));
}else{
window.localStorage.setItem(lsId, true);
$(this).children(".open").html("Close");
$(`.item-append div[data-id='${id}']`).remove();
}
countSaveItems();
});
$('.item-all .item-save').each(function() {
var id = 'test_' + $(this).data("id");
if (localStorage.getItem(id) && localStorage.getItem(id) == "true") {
$(this).addClass('productad');
createItem($(this));
}
countSaveItems();
});
$(".item-all .item-save").click(function() {
var elemId = $(this).data("id");
var existing = $(`.item-append div[data-id="${elemId}"]`);
if (existing.length > 0){
existing.remove();
}else{
createItem($(this));
}
countSaveItems();
});
$(".item-append").on("click", ".close", function() {
var id = $(this).parent().data("id");
window.localStorage.setItem(`test_${id}`, false);
$(`.item-save[data-id='${id}']`).removeClass('productad');
$(`.item-save[data-id='${id}']`).children(".open").html("Open");
$(this).parent().parent().remove();
countSaveItems();
});
.item-save {
position: relative;
display: block;
font-size: 14px;
margin: 5px;
padding: 5px;
background: #a5a5a5;
float: left;
text-align: center;
cursor: pointer;
}
.productad {
background: red;
color: #eee
}
.count {
display: block;
background: #cbcbcb;
float: left;
font-size: 15px;
padding: 5px 18px;
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='item-all'>
<div class='item-save' data-id='123'>
Save1 <button class='open'>Open</button>
</div>
<div class='item-save' data-id='124'>
Save2 <button class='open'>Open</button>
</div>
<div class='item-save' data-id='125'>
Save3 <button class='open'>Open</button>
</div>
<div class='item-save' data-id='126'>
Save4 <button class='open'>Open</button>
</div>
</div>
<div class='item-append'></div>
<div class='count'>0</div>
Good evening everyone. I'm implementing the autocomplete function as source code below. But when I apply it to IE11, it doesn't work, it doesn't do autocomplete when the user enters, but only works when we click on the input. I went to find the cause but still can't find it, hope everyone will help me. Thanks very much.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body {
font-family: 'Source Sans Pro', sans-serif;
font-size: large;
max-width: 500px;
margin: 0 auto;
}
input[type=email] {
font-size: large;
width: 400px;
-webkit-appearance: none;
appearance: none;
}
input::-webkit-calendar-picker-indicator {
display: none;
}
label {
display: block;
font-size: small;
text-transform: uppercase;
letter-spacing: 2px;
color: #999;
}
</style>
</head>
<body>
<label for="email">Email</label>
<input id="email" name="email" type="email" placeholder="your#email.com">
<script>
const EmailDomainSuggester = {
domains: ["yahoo.com", "gmail.com", "google.com"],
bindTo: $('#email'),
init: function () {
this.addElements();
this.bindEvents();
},
addElements: function () {
// Create empty datalist
this.datalist = $("<datalist />", {
id: 'email-options'
}).insertAfter(this.bindTo);
// Corelate to input
this.bindTo.attr("list", "email-options");
this.bindTo.attr("autocomplete", "off");
},
bindEvents: function () {
this.bindTo.on("keyup", this.testValue);
},
testValue: function (event) {
let el = $(this),
value = el.val();
// email has #
// remove != -1 to open earlier
if (value.indexOf("#") != -1) {
value = value.split("#")[0];
EmailDomainSuggester.addDatalist(value);
} else {
// empty list
EmailDomainSuggester.datalist.empty();
}
},
addDatalist: function (value) {
let i, newOptionsString = "";
for (i = 0; i < this.domains.length; i++) {
newOptionsString += "<option value='" + value + "#" + this.domains[i] + "'>";
}
// add new ones
this.datalist.html(newOptionsString);
}
}
EmailDomainSuggester.init();
</script>
</body>
</html>
I am trying to remove item from the array by selecting a cell to the left of the button, I have tried using .previous selector but it doesn't work.
var films = [];
function test2(e) {
$("button").one("click", function(r) {
r.preventDefault();
var movie = $(e).attr("name");
if (films.includes(movie)) {
alert("This movie is in your basket")
} else {
films.push(movie);
var r = films.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + films[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
})
};
function newtest2(e) {
$(e).parents('tr').remove();
}
.cart {
float: right;
position: relative;
margin-right: 15%;
margin-top: 5%;
}
.cart2 {
background-color: white;
border-radius: 19px;
-moz-border-radius: 19px;
-webkit-border-radius: 19px;
padding: 2% 3%;
border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cart">
<div class="cart2">
<h1>Cart: </h1>
<table id="table1">
</table>
</div>
</div>
<button name="Black Mirror" id="BM" id="carttest" onclick="test2(this)" value="Black Mirror" class="button1">Book now (Black Mirror)</button>
<br>
<button name="Star Wars" id="SW" id="carttest" onclick="test2(this)" value="Star Wars" class="button1">Book now(Star Wars)</button>
I also have this bug that I have to click the button twice to fire the function.
Edit:
Whenever the user clicks Order button, it runs the loop that creates the table with a button "remove" and adds the item to 'Films[]' Array. I want the remove button to remove the selected row but I also want it to remove the item from the array.
Well it needs a lot of fixes in your code.
First. Identifiers must be unique for each element.
2nd. When you push in array, you'll have to remove it too.
Here is what was missing in your code
var films = [];
$(".button1").click(function(e){
var movie = $(this).attr("name");
if (films.includes(movie)) {
alert("This movie is in your basket")
} else {
films.push(movie);
var r = films.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + films[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
})
function newtest2(e) {
$(e).parents('tr').remove();
films.splice(films.indexOf($(e).parent().prev().text()), 1)
}
.cart {
float: right;
position: relative;
margin-right: 15%;
margin-top: 5%;
}
.cart2 {
background-color: white;
border-radius: 19px;
-moz-border-radius: 19px;
-webkit-border-radius: 19px;
padding: 2% 3%;
border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cart">
<div class="cart2">
<h1>Cart: </h1>
<table id="table1">
</table>
</div>
</div>
<button name="Black Mirror" id="BM" value="Black Mirror" class="button1">Book now (Black Mirror)</button>
<br>
<button name="Star Wars" id="SW" value="Star Wars" class="button1">Book now(Star Wars)</button>
Don't need prevent preventDefault() for a click
var films = [];
function test2(e) {
//Don't need preventDefault()
var movie = $(e).attr("name");
if (films.includes(movie)) {
alert("This movie is in your basket")
} else {
films.push(movie);
var r = films.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + films[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
};
function newtest2(e) {
const
//parents of the clicked button
parents = $(e).parents('tr'),
//children of the parents
children = parents.children(),
//text content from first child
text = children[0].textContent,
//position of the text in array
pos = $.inArray(text, films)
//if position is not -1 (not found)
if (pos !== -1 ) {
//use position to remove item from the array
films.splice(pos, 1)
}
console.log(`films:`,films)
//remove the tr element from the view
$(e).parents('tr').remove();
}
The muasif80's code works just fine too.
I am currently playing with some jquery and as i tried to create a simple todo-list I came across a problem.
So far the goal is to be able to add paragraphs by clicking the green square and remove them by clicking it once and then dragging it to the red square.
Everything works out fine except the deleting of the dragged paragraph.
Right now it only works by removing the whole class but I want to only delete the dragged one.
Here the code: https://codepen.io/anon/pen/OXXXpY
jQuery:
$(document).ready(function() {
var send = $("#send");
var dlt = $("#delete");
send.click(function() {
var input = $("input").val();
$("#container").prepend("<p class='entry'>" + input + "</p>");
});
$(document).on("click", ".entry", function() {
$(this).draggable();
$("#delete").droppable({
drop: function() {$(".entry").remove();}
});
});
});
Please don't mind my English and the real use of this project. This is just an jQuery experiment.
Use $(this) to target the dragged element
$(document).on("click", ".entry", function() {
var $this = $(this);
$(this).draggable();
$("#delete").droppable({
drop: function() {
$($this).remove();
}
});
});
$(document).ready(function() {
var send = $("#send");
var dlt = $("#delete");
send.click(function() {
var input = $("input").val();
$("#container").prepend("<p class='entry'>" + input + "</p>");
});
$(document).on("click", ".entry", function() {
var $this = $(this);
$(this).draggable();
$("#delete").droppable({
drop: function() { $($this).remove(); }
});
});
});
body {
text-align: center;
}
h1 {
font-family: Helvetica;
}
form input {
width: 500px;
font-size: 30px;
}
form input:focus {
outline: none;
}
.inline {
display: inline-block;
}
#send {
width: 40px;
height: 40px;
background-color: green;
}
#delete {
width: 40px;
height: 40px;
background-color: red;
}
.entry {
font-family: helvetica;
border: solid 1px grey;
-webkit-user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<h1>ToDo</h1>
<form class="">
<div class="inline" id="delete"></div>
<input type="text" name="input" value="">
<div class="inline" id="send"></div>
</form>
<div id="container"></div>
I've made a simple jQuery script which stores values "voted1", "voted2", "voted3" in localStorage. The problem is that on click it stores all values at the same time, and I need it per click as it should be later called (e.g. if "value3" exists begin jQuery logic...)
I can't figure this out, after weeks of testing..
HTML:
[gallery link="none" size="medium" ids="102,13,27,25,23,15" orderby="rand"]
<div class="exists" style="display: none;">Thank you for voting!</div>
CSS:
.gallery-item a {
background-color: black;
border: 1px solid orange;
border-radius: 6px;
color: orange;
display: inline-table;
font-size: 14px;
font-weight: bold;
max-width: 100%;
width: 32%;
}
.exists {
background-color: black;
border-radius: 18px;
box-shadow: 1px 3px 20px -3px grey inset;
display: block;
height: 32%;
left: 24%;
margin-left: 10%;
margin-right: 10%;
margin-top: 10%;
max-width: 100%;
padding-left: 12%;
padding-top: 6%;
position: fixed;
top: 23%;
width: 36%;
z-index: 999999;
color: olivedrab;
font-weight: bold;
cursor: context-menu;
}
.voted {
background-color: green !important;
}
jQuery:
$(document).ready(function() {
var voteLink = $('.gallery-item a');
var votedYes = $('.exists');
voteLink.one('click', function() {
// localStorage.setItem('voted1', 'yes1');
$(this).text('Thank you!');
$(this).addClass('voted');
})
voteLink.one('click', function() {
// localStorage.setItem('voted2', 'yes2');
$(this).text('Thank you!');
$(this).addClass('voted');
})
voteLink.one('click', function() {
localStorage.setItem('voted3', 'yes3');
$(this).text('Thank you!');
$(this).addClass('voted');
if($('.voted').length === 3){
voteLink.fadeOut('slow');
$('.exists').fadeIn(1800);
}
if (localStorage.getItem("voted3")) {
voteLink.remove();
votedYes.fadeIn(1800);
}
});
As I said, on first click it places all values in localStorage and I need this separated.
Thanks guys.
$(document).ready(function() {
var voteLink = $(".gallery-item a");
var votedYes = $(".exists");
if (localStorage.getItem("count") === null) {
localStorage.setItem("count", 1)
}
if (!(localStorage.getItem("voted3") === "yes3")) {
var i = Number(localStorage.getItem("count")),
fn = function(e) {
if (i < 3) {
localStorage.setItem("voted" + i, "yes" + i);
$(this).text("Thank you! for vote " + i)
.addClass("voted" + i);
localStorage.setItem("count", 1 + i);
i = Number(localStorage.getItem("count"));
} else {
localStorage.setItem("voted" + i, "yes" + i);
$(this).text("Thank you! for vote " + i)
.addClass("voted" + i)
.fadeOut("slow");
if (localStorage.getItem("voted3") === "yes3") {
voteLink.remove();
votedYes.fadeIn(1800);
}
}
};
voteLink.on("click", fn);
} else {
// if `localStorage` has property `"voted3"` and value equals `"yes3"`,
// do stuff
}
})
Caveat: This answer may be completely off, since your question comes without all the details of your use case. However ...
The following code assumes that ...
up to 3 votes shall be recorded in localStorage
in order to cast the vote n+1, vote n must have been recorded before.
Either register the handlers contingent on the content in localStorage:
if (
localStorage.getItem("voted1")
&& !localStorage.getItem("voted2")
) {
voteLink.one('click', function() {
localStorage.setItem('voted2', 'yes2');
//...
});
}
... or test the localStorage contents inside your event handler:
fn_vote2 = function() {
if (
localStorage.getItem("voted1")
&& !localStorage.getItem("voted2")
) {
localStorage.setItem('voted2', 'yes2');
//...
voteLink.off('click', fn_vote2);
}
};
voteLink.on('click', fn_vote2);
The generalization for vote1, vote3 should come easy. Note that the latter solution implies that you register the handler not just for a single event. Instead you deregister it upon success.
The advantage of the method is the option for cascaded voting without reloading the page.
Btw, since localStorage persists over sessions, it is advisable not to use generic keys like vote<n>.