Deleting an object from an array on click of a button - javascript

I am trying to create my own small Twitter.
It is all working fine but I cannot find a way to delete specific tweet on click of a button. I have tried splice() but it deletes the first object of an array always.
Here is my code:
var tweets = []
function postNewTweet() {
var today = new Date();
var date = today.getDate() + '-' + (today.getMonth() + 1) + '-' + today.getFullYear();
var time = today.getHours() + ':' + today.getMinutes();
var id = tweets.length + 1;
var li = document.createElement('li');
var inputValue = document.getElementById('newTweet').value;
var finalValue = id + ' ' + inputValue + ' ' + date + ' ' + time;
var t = document.createTextNode(finalValue);
li.appendChild(t);
tweets.push({
id: id,
content: inputValue,
date: date + ' ' + time
});
document.getElementById('list').appendChild(li);
document.getElementById('newTweet').value = "";
console.log(tweets);
var buttonDelete = document.createElement("button");
buttonDelete.innerHTML = '<i class="far fa-trash-alt"></i>';
buttonDelete.onclick = deleteItem;
function deleteItem(e) {
var ul = document.getElementById('list');
ul.removeChild(li);
var list = document.getElementById('list');
list.addEventListener('click', function(e) {
var index = e.target.getAttribute('value');
tweets.splice(index, 1);
console.log(tweets)
});
}
li.appendChild(buttonDelete);
}
<div id='post'>
<textarea maxlength="160" id='newTweet'></textarea>
<button id='postIt' onclick="postNewTweet()">Post</button>
</div>
<ul id='list'>
</ul>
So it deletes it in HTML, but not in array correctly.

The second part of your deleteItem function's body seems useless. While there are couple of ways to resolve it, I suggest the following:
function deleteItem(e) {
var ul = document.getElementById('list');
ul.removeChild(li);
var foundIndex = tweets.findIndex(function (tweet) {
return tweet.id == id;
});
if (foundIndex > -1) {
tweets.splice(foundIndex, 1);
}
}

There are two issues:
If you just take the length of the array as the id you will get duplicate entries, if you delete an entry. Perhaps go to a timestamp - i just used the one you already had there but added seconds
You retrieve the value-attribute but for splice you need the index of the element. I just added the timestampt as an attribute to the button and used it for removal.
Probably not my best code but I hope it gives you the right hints.
var tweets = []
function postNewTweet() {
var today = new Date();
var date = today.getDate() + '-' + (today.getMonth() + 1) + '-' + today.getFullYear();
var time = today.getHours() + ':' + today.getMinutes() + ':' + today.getSeconds();
var id = tweets.length + 1;
var li = document.createElement('li');
var inputValue = document.getElementById('newTweet').value;
var finalValue = id + ' ' + inputValue + ' ' + date + ' ' + time;
var t = document.createTextNode(finalValue);
li.appendChild(t);
tweets.push({
id: id,
content: inputValue,
date: date + ' ' + time
});
document.getElementById('list').appendChild(li);
document.getElementById('newTweet').value = "";
console.log(tweets);
var buttonDelete = document.createElement("button");
buttonDelete.innerHTML = '<i class="far fa-trash-alt" del-date="'+date + ' ' + time +'">del</i>';
buttonDelete.onclick = deleteItem;
function deleteItem(e) {
var ul = document.getElementById('list');
ul.removeChild(li);
var list = document.getElementById('list');
list.addEventListener('click', function(e) {
var delDate = e.target.getAttribute('del-date');
let index = tweets.map((item) => item.date).indexOf(delDate);
console.log(index);
tweets.splice(index, 1);
console.log(tweets)
});
}
li.appendChild(buttonDelete);
}
<div id='post'>
<textarea maxlength="160" id='newTweet'></textarea>
<button id='postIt' onclick="postNewTweet()">Post</button>
</div>
<ul id='list'>
</ul>

As you have access to li in your delete function, you have access to all the other data too. You can use them to find out the element to remove from the tweets array.
For example, in your current code, you can use the id:
tweets.splice(id - 1, 1)
Or you can use filter with any of the data that you store in tweets.And I don't see any use for this part:
var list = document.getElementById('list');
list.addEventListener('click', function(e) {
var index = e.target.getAttribute('value');
tweets.splice(index, 1);
console.log(tweets)
});
You can just remove the tweet under the ul.removeChild

Related

Amchart4 not shown till end of Datatime From json file in parseend event

I looking for solution to shown all my data in amcharts4 , My data not shown exact and just sme out before them is shown , what is soltion for them ?
chart.dataSource.url ="/static/json/{{ Post.Datasource|safe }}.json";
chart.dataSource.parser = new am4core.JSONParser();
chart.dataSource.reloadFrequency = 5000;
chart.dateFormatter.inputDateFormat = "i";
var title = chart.titles.create();
//Funtion Date From and to
chart.dataSource.events.on("parseended", function(ev) {
var data = ev.target.data;
for (var i = 0; i < data.length; i++) {
var startdate = new Date(data[0]["DATETIME"]).toISOString().replace("T"," ").replace("Z","").replace(".000","");
var enddate = new Date(data[data.length -1]["DATETIME"]).toISOString().replace("T"," ").replace("Z","").replace(".000","");
}
title.html = (
"Data from :" + '<span class="colors"> ' +
startdate+ '</span> ' +
" to " + '<span class="colors">' +
enddate + '</span>'
);
});
Text shown less than exact lenght of data, also my title not refreshed
Moment library can convert data easy
starttime = moment(starttime).format("YYYY-MM-DD HH:mm:ss");

How to update div content by changing panel name

When I edit panels name I want to update div content, that will have tab-pane name.
I tried to get the value and change it "onchange", but
I think I did something incorrectly.
http://jsfiddle.net/agata666/5zLmtqby/139/
var $foo = $(".tab-pane");
var $newPanelDefault = $foo.clone();
var hash = 1;
$(".add").on("click", function() {
var $newPanel = $newPanelDefault.clone();
var hashClass = 'zone-panel-' + generateHash();
$newPanel.find(".panel").data('hash', hashClass).attr("href", "#" + (++hash)).text("Zone " + hash);
$newPanel.attr("id", "tab" + hashClass);
var nextTab = $('.tabs li').size()+1;
$('<li class="' + hashClass + '">Zone ' + hash + ' <i class="fas fa-pencil-alt pencil"></i></li>').appendTo('.tabs');
$($newPanel).appendTo('.tab-content');
$(".pencil").click(function() {
$(".nav-tabs li.active").attr('contenteditable',$(".nav-tabs li.active").attr('contenteditable')==='true'?'false':'true' );
});
});
var panelDefault = document.querySelectorAll('.panel-default');
var exTabFirst = document.querySelectorAll('.exTabFirst');
var exTabSecond = document.querySelectorAll('.exTabSecond');
var addZoneButton = document.getElementById('add');
function generateHash() {
return Math.random().toString(16).substr(-5);
}
addZoneButton.addEventListener('click', function () {
var randomNumber = generateHash();
panelDefault.innerHTML = 'panel panel-default foo template ' + randomNumber;
exTabFirst.innerHTML = 'exTabFirst ' + randomNumber;
exTabSecond.innerHTML = 'exTabSecond ' + randomNumber;
});
$(".pencil").click(function() {
$(".nav-tabs li.active").attr('contenteditable',$(".nav-tabs li.active").attr('contenteditable')==='true'?'false':'true' );
});
Could you help me?

Jquery Clone method increment name tag

Hello I am trying to add increment in my all form fields from zero to the number whenever I add new clone it assigns the next number to the name tag, I tried all the ways but no any methods works for me.
Here is my fiddle
https://jsfiddle.net/o5wam5r2/
and here is my JS code
var formItem;
$(document).ready(function() {
//Clone and remove your div instead of hiding it
formItem = $('.ScheduleextraPartTemplate').clone();
$('.ScheduleextraPartTemplate').remove();
formItem.addClass('clone clone-1');
$('#Schedulecontainer').append(formItem);
});
$(document).on('click', '#ScheduleaddRow', function() {
var cloneForm = $('.clone').last().clone();
var cloneNum = $('.clone').length;
cloneForm.removeClass('clone-'+cloneNum).addClass('clone-' + (cloneNum+1));
var date = cloneForm.find('[name="txtSchedule"]').val();
cloneForm.find('[name="txtSchedule"]').val(addOneMonth(date));
$('#Schedulecontainer').append(cloneForm);
})
function addOneMonth(date) {
var year = parseInt(date.split("-")[0]);
var month = parseInt(date.split("-")[1]) + 1;
var day = parseInt(date.split("-")[2]);
if(month > 12) {
month = month - 12;
year++
}
return year + "-" + month + "-" + day;
}
I fixed it by changing a little piece of code
var formItem;
var counter = 0;
$(document).ready(function() {
//Clone and remove your div instead of hiding it
formItem = $('.ScheduleextraPartTemplate').clone();
formItem.find('[name^=txtSchedule]')[0].name = "txtSchedule" + counter;
formItem.find('[name^=txtScheduleAmountPay]')[0].name = "txtScheduleAmountPay" + counter;
$('.ScheduleextraPartTemplate').remove();
formItem.addClass('clone clone-1');
$('#Schedulecontainer').append(formItem);
});
$(document).on('click', '#ScheduleaddRow', function() {
var lens = counter++;
var cloneForm = $('.clone').last().clone();
var cloneNum = $('.clone').length;
cloneForm.removeClass('clone-'+cloneNum).addClass('clone-' + (cloneNum+1));
var date = cloneForm.find('[name^="txtSchedule"]').val();
cloneForm.find('[name^="txtSchedule"]').val(addOneMonth(date));
cloneForm.find('[name^=txtSchedule]')[0].name = "txtSchedule" + (lens+1);
cloneForm.find('[name^=txtScheduleAmountPay]')[0].name = "txtScheduleAmountPay" + (lens+1);
$('#Schedulecontainer').append(cloneForm);
})
function addOneMonth(date) {
var d = new Date( date );
d.setMonth( d.getMonth( ) + 1 );
return d.getFullYear() + '-' + ("0" + ((d.getMonth() + 1))).slice(-2) + '-' + ("0" + (d.getDate())).slice(-2);
}

JS/HTML function

Can someone please help me understand why the function writeOptions logs optionCounter twice?
console.log("<option values=" + optionCounter + ">"+optionCounter);
Why is there a second optionCounter placed after the option element?
<script type = "text/javascript">
function writeOptions(startNumber,endNumber)
{
var optionCounter;
for(optionCounter = startNumber;
optionCounter <= endNumber; optionCounter++)
{
document.write("<option value=" + optionCounter + ">" + optionCounter);
}
}
function writeMonthOptions()
{
var theMonth;
var monthCounter;
var theDate = new Date(1);
for(monthCounter = 0; monthCounter < 12; monthCounter++)
{
theDate.setMonth(monthCounter);
theMonth = theDate.toString();
theMonth = theMonth.substr(4,3);
document.write("<option value=" + theMonth + ">" + theMonth);
}
}
function recalcDateDiff()
{
var myForm = document.form1;
var firstDay =
myForm.firstDay.options[myForm.firstDay.selectedIndex].value;
var secondDay =
myForm.secondDay.options[myForm.secondDay.selectedIndex].value;
var firstMonth =
myForm.firstMonth.options[myForm.firstMonth.selectedIndex].value;
var secondMonth =
myForm.secondMonth.options[myForm.secondMonth.selectedIndex].value;
var firstYear =
myForm.firstYear.options[myForm.firstYear.selectedIndex].value;
var secondYear =
myForm.secondYear.options[myForm.secondYear.selectedIndex].value;
var firstDate =
new Date(firstDay + " " + firstMonth + " " + firstYear);
var secondDate = new Date(secondDay + " " + secondMonth + " " + secondYear);
var daysDiff = (secondDate.valueOf() - firstDate.valueOf());
daysDiff = Math.floor(Math.abs((((daysDiff/1000)/60)/60)/24));
myForm.txtDays.value = daysDiff;
}
function window_onload()
{
var theForm = document.form1;
var nowDate = new Date();
theForm.firstDay.options[nowDate.getDate() - 1].selected =true;
theForm.secondDay.options[nowDate.getDate() - 1].selected = true;
theForm.firstMonth.options[nowDate.getMonth() - 1].selected = true;
theForm.secondMonth.options[nowDate.getMonth() - 1].selected = true;
theForm.firstYear.options[nowDate.getFullYear() - 1970].selected = true;
theForm.secondYear.options[nowDate.getFullYear() - 1970].selected = true;
}
</script>
as you can see this is the entire Javascript codeblock for this particular example.
I believe you know HTML. Each <option> tag has a display text (or label) and a value. And your code is creating the html option tag with both. So, when you write:
document.write("<option value=" + optionCounter + ">" + optionCounter);
the first optionCounter is for value and second one is for label/display text.
Note: I don't see the option tag being closed which could result in issues if not handled properly by the browser, so modify the statement as follows to render correct HTML:
document.write("<option value=" + optionCounter + ">" + optionCounter + "</option>");
Refer more about select tag & option tag on w3schools.com.

javascript change class doesn't perform the event

I am trying to make a ajax load of a table. I have 2 buttons "Free Cars", "Reservations". When click "Free Cars" load all info from database and on click of tr it redirects to an url.
$('.cars_table').on('click', 'tr', function() {
var values = $(this).find('td').map(function() {
return $(this).text();
});
var startdate = $('input[name$="startdate"]').val();
var starttime = $('input[name$="starttime"]').val();
var enddate = $('input[name$="enddate"]').val();
var endtime = $('input[name$="endtime"]').val();
window.location.href = 'rental/create/' + values[0] + '~' + startdate + ' ' + starttime + '~' + enddate + ' ' + endtime + '';
});
Then on click of "Reservations" I change the class of tbody :
$('#cars_table').removeClass('cars_table').addClass('res_made');
But it doesn't perform the script which
$('.res_made').on('click', 'tr', function() {
var values = $(this).find('td').map(function() {
return $(this).text();
});
var startdate = $('input[name$="startdate"]').val();
var starttime = $('input[name$="starttime"]').val();
var enddate = $('input[name$="enddate"]').val();
var endtime = $('input[name$="endtime"]').val();
window.location.href = 'reservations/create/' + values[0] + '~' + startdate + ' ' + starttime + '~' + enddate + ' ' + endtime + '';
});
Instead it performs the first script and on click of reservations rows it goes to the .cars_table redirect url. With inspect element it shows that the class has changed but then it doesnt performs the script for that class. What is happening?
Event bindings happen on the DOM elements themselves. If you try to bind an event on all .res_made elements before there are any elements with this class, no events will be bound.
To solve your problem, you could bind your event once and check inside the handler which class is currently set.
You should dynamically bind the click events, because the class of the table can dynamically change. So to make it work in your case, you should change your javascript to the following:
$(document).on('click', '.cars_table tr', function() {
var values = $(this).find('td').map(function() {
return $(this).text();
});
var startdate = $('input[name$="startdate"]').val();
var starttime = $('input[name$="starttime"]').val();
var enddate = $('input[name$="enddate"]').val();
var endtime = $('input[name$="endtime"]').val();
window.location.href = 'rental/create/' + values[0] + '~' + startdate + ' ' + starttime + '~' + enddate + ' ' + endtime + '';
});
$(document).on('click', '.res_made tr', function() {
var values = $(this).find('td').map(function() {
return $(this).text();
});
var startdate = $('input[name$="startdate"]').val();
var starttime = $('input[name$="starttime"]').val();
var enddate = $('input[name$="enddate"]').val();
var endtime = $('input[name$="endtime"]').val();
window.location.href = 'reservations/create/' + values[0] + '~' + startdate + ' ' + starttime + '~' + enddate + ' ' + endtime + '';
});
See this FIDDLE for an example. Of course, as an alternative, you could also bind the event once and check for the class of the table in the event handler, like Martin Denk suggested.

Categories

Resources