Push all objects after a selected object into an array - javascript

I have a web page that returns a list of objects like:
date.pdf
names.csv
address.pdf
age.csv
cost.csv
budget.csv
data.pdf
race.pdf
contractors.csv
When a user checks budget.csv, I want every object with the .csv extension from that point to be pushed into csv_files[]. If they select names.csv, then every .csv including and after names is pushed into the array.
So the only data that gets pushed into the array is from the selected object downwards. How can I implement this?
Current code
const csv_files = []
$scope.listAllobjects = (err, data) => {
$.each(data.Contents, (index, value) => {
if (value.Key.endsWith("csv")) {
csv_files = [];
}
// Handle click on selection checkbox
$("#filesobjects-table tbody").on("click", 'input[type="checkbox"]', (e1) => {
const checkbox = e1.currentTarget;
const $row = $(checkbox).closest("tr");
const data = $tb.DataTable().row($row).data();
let index = -1;
// Prevent click event from propagating to parent
e1.stopPropagation();
// Find matching key in currently checked rows
index = $scope.view.keys_selected.findIndex((e2) => e2.Key === data.Key);
if (checkbox.checked && data.Key.endsWith("csv")) {
console.log(selected csv)
}
});
}

There's a few ways, I suppose, to approach this problem, but the most intuitive to me is this:
const csvList = ["date.pdf","names.csv","address.pdf","age.csv","cost.csv","budget.csv","data.pdf","race.pdf","contractors.csv"];
const selectedCsv = 'budget.csv';
function getCsvsAfter(csvList, selectedCsv) {
const filteredCsvs = [];
let found = false;
for (let csv of csvList) {
if (csv === selectedCsv) found = true;
if (found) filteredCsvs.push(csv);
}
return filteredCsvs;
}
console.log(getCsvsAfter(csvList, selectedCsv));
Iterate over every csv, and when you've hit the one you're trying to match, set a variable called found to true. Once it's true, you can add every following csv onto the list.

const list = ['date.pdf','names.csv','address.pdf','age.csv','cost.csv','budget.csv','data.pdf','race.pdf','contractors.csv'];
const selected = 'budget.csv'
const csv_files = list.slice(list.indexOf(selected))
console.log(csv_files)

Here you go with a pure JavaScript solution (Descriptive comments has been added in the below code snippet).
var contentData = ["date.pdf", "names.csv", "address.pdf", "age.csv", "cost.csv", "budget.csv", "data.pdf", "race.pdf", "contractors.csv"];
var myDiv = document.getElementById("cboxes");
for (var i = 0; i < contentData.length; i++) {
var checkBox = document.createElement("input");
var label = document.createElement("label");
checkBox.type = "checkbox";
checkBox.value = contentData[i];
myDiv.appendChild(checkBox);
myDiv.appendChild(label);
label.appendChild(document.createTextNode(contentData[i]));
}
// Event to handle the checkbox click
document.getElementById('getResult').addEventListener('click', () => {
document.getElementById('showResult').innerHTML = getCheckedValues();
});
function getCheckedValues() {
// filtered out the checked items.
const element = Array.from(document.querySelectorAll('input[type="checkbox"]'))
.filter((checkbox) => checkbox.checked).map((checkbox) => checkbox.value);
// element[0] will always return the first checked element and then we are getting index of that.
const checkedElemIndex = contentData.indexOf(element[0]);
// Slice the content data to get the elements from the checked element index.
return contentData.slice(checkedElemIndex, contentData.length)
}
<div id="cboxes"></div>
<button id="getResult">Get Result</button>
<pre id="showResult"></pre>

Related

How do i store an array in localstorage and then get the contents and then add them to a select object

This is the code i am using to get the array and then add them to the select object.
var select = document.getElementById('select');
var theArray = localStorage.getItem("array")
JSON.parse(theArray)
if (theArray != null){
for (var i=0; i > theArray.length; i++){
select.add(theArray[i])
}
}
Here is the code i am using to set the localStorage values.
var select = document.getElementById('select');
var option = document.createElement("option");
option.text = visText;
option.value = actVal;
select.add(option)
theArray[theArray.length+1] = option;
localStorage.setItem("array",JSON.stringify(theArray))
Can anybody tell me how to fix this?
Looks like you forgot to assign the parsed Json to a variable:
let select = document.getElementById('select')
let data = JSON.parse(localStorage.getItem('array'))
for(let entry of data) {
select.add(new Option(entry))
}
Not 100% sure if it works but should do.
You can just call the session and local storage with dot notation. The snippet below shows this. However, the snippets here are sandboxed, and cannot be written to. So, to demonstrate how to populate a select element from an array, I used a try..catch block so when it errored out, it would at least populate the select options with the original array variable.
const array = new Array(10).fill(0).map((elm, idx) => (elm = idx, elm));
let arrayFromStorage;
try {
window.localStorage.myArray = JSON.stringify(array);
arrayFromStorage = JSON.parse(window.localStorage.myArray);
} catch (error) {
console.warn(error.message)
arrayFromStorage = array;
}
arrayFromStorage.forEach(elm => {
const opt = document.createElement('option');
opt.value = elm;
opt.innerText = `option ${elm}`;
document.querySelector('select').append(opt);
})
<select></select>
If you copy/paste this into a browser console, you can see that it can be set and called using dot notation
const array = new Array(10).fill(0).map((elm, idx) => (elm = idx, elm));
let arrayFromStorage;
window.localStorage.myArray = JSON.stringify(array);
arrayFromStorage = JSON.parse(window.localStorage.myArray);

How to save Items in Local Storage with specific ID

I am practicing blog stuff. posting and deleting posts. mini social media I can say. And I wanted to save posts on localStorge. however I could save only 1 post at a time. and then I wanted to do it with IDs.
I create id with random number generator:
let newId = Math.floor(Math.random() * (1000000 - 100000) + 100000)
let postContents = {
ID : newId,
text: value,
}
an then I upload those values in let storedPosts = [] array.
then I save it to local storage with JSON:
let toJson = () => {
localStorage.setItem('storedPosts', JSON.stringify(storedPosts));
}
and then I get it from Local Storage:
let storedJsonPosts = localStorage.getItem('storedPosts')
let storedPosts_toUpload = JSON.parse(storedJsonPosts)
and then I join these two arrays together:
let storedPostsArray = storedPosts.concat(storedPosts_toUpload)
and after this I don't know what to do. I tried this:
let uploadStoredPosts = () => {
for (let i = 0; i < storedPostsArray.length; i++) {
let post = document.createElement('div')
$post_place.appendChild(post)
let text = document.createElement('p')
post.appendChild(text)
text.textContent = storedPostsArray[i].text
}
}
but it showed this:
It couldn't reach array values. plz help
Is this something that you're after?
The code reads from localStorage, parses that information, returns an empty array if it's the first time the user posted, pushes a new value to the array, stores that array by stringifying it, and the appending the new value to the document.
If you want the page to read from localStorage on page load, you need to add a function that reads from localStorage, and then loops through all posts to add each one of them by using appendToDocument().
StackOverflow doesn't allow the use of localStorage, so I used a variable for demo purposes.
I left out id as a property. You can play around with that by yourself, but I would suggest to use a timestamp as a foreign key ("id").
var justForDemoPurpose = null;
const addPostBtn = document.getElementById("add-button");
const addPostInput = document.getElementById("add-post");
const postContainerEl = document.getElementById("post-container");
addPostBtn.addEventListener('click', addPost);
function readFromLocalStorage(key) {
let localStorageItem = JSON.parse(justForDemoPurpose);
// let localStorageItem = JSON.parse(localStorage.getItem(key));
console.log('returning items:', localStorageItem);
return localStorageItem;
}
function storeInLocalStorage(key, value) {
justForDemoPurpose = JSON.stringify(value);
// JSON.stringify(localStorage.setItem(key, value));
}
function addPost() {
let postValue = addPostInput.value;
if (postValue) {
const LOCAL_STORAGE_KEY = 'posts';
let storedPosts = readFromLocalStorage(LOCAL_STORAGE_KEY) || [];
storedPosts.push(postValue);
storeInLocalStorage(LOCAL_STORAGE_KEY, storedPosts);
appendToDocument(postValue);
}
}
function appendToDocument(postValue) {
let divEl = document.createElement('div')
divEl.textContent = postValue;
postContainerEl.appendChild(divEl);
}
<div class="addPostContainer">
<input id="add-post" placeholder="Type here"> <button id="add-button">Add Post</button>
</div>
<section id="post-container"></section>

JS: Removing from local storage / hiding button text

Evening folks.
Trying to wrap up my to do list and I'm not able to remove items from localStorage without either deleting everything from using the wrong key or the contents just re-appearing on page refresh. A second smaller issue is that button text is merging into the innerText, like it's supposed to, but I can't find a way to exclude it It is currently commented out, if I don't then it breaks the previous entry. I've left my most recent, and rather poor attempt, below but otherwise, the rest appears to be working.
Not sure if it's ok to attach the whole code, but here it is below.
const todoForm = document.querySelector('#todoForm');
const todoList = document.querySelector('#todoList');
let todoItem = document.querySelector('#todoItem');
// const todo = JSON.parse(localStorage.getItem('todo'));
// Pull from storage
const savedList = JSON.parse(localStorage.getItem('todo')) || [];
for (let i = 0; i < savedList.length; i++) {
const newTodo = document.createElement('li');
newTodo.innerText = savedList[i].item;
const newButton = document.createElement('button');
let itemId = { id: new Date().getTime() };
// newButton.innerText = 'Remove';
newButton.setAttribute('id', itemId.id);
newTodo.isCompleted = savedList[i].isCompleted ? true : false;
if(newTodo.isCompleted) {
newTodo.style.textDecoration = 'line-through';
}
todoList.appendChild(newTodo);
newTodo.appendChild(newButton);
}
// Add Item and Remove Button
todoForm.addEventListener('submit', function(e){
e.preventDefault();
const newTodo = document.createElement('li');
const newItem = document.querySelector('#todoItem').value;
const newButton = document.createElement('button');
let itemId = { id: new Date().getTime() };
// newButton.innerText = 'Remove';
newButton.setAttribute('id', itemId.id);
newTodo.innerText = newItem;
newTodo.setAttribute('id', itemId.id);
newTodo.isCompleted = false;
todoList.appendChild(newTodo);
newTodo.appendChild(newButton);
todoForm.reset();
// Save to storage
savedList.push({ item: newTodo.innerText, isCompleted: false, id: new Date().getTime() });
localStorage.setItem('todo', JSON.stringify(savedList));
});
// Strike Through Item
todoList.addEventListener('click', function(e){
let clickListItem = e.target;
if (!clickListItem.isCompleted){
clickListItem.style.textDecoration = 'line-through';
clickListItem.isCompleted = true;
} else {
clickListItem.style.textDecoration = 'none';
clickListItem.isCompleted = false;
}
for (let i = 0; i < savedList.length; i++) {
if (savedList[i].item === clickListItem.innerText) {
savedList[i].isCompleted = !savedList[i].isCompleted;
localStorage.setItem('todo', JSON.stringify(savedList));
}
}
});
// Remove from storage
todoList.addEventListener('click', function(e){
let removeItem = e.target;
const taskId = e.target.id;
if (e.target.tagName === 'BUTTON'){
e.target.parentNode.remove();
removeFunc(taskId);
}
});
function removeFunc(taskId){
for (let i = 0; i < savedList.length; i++){
const key = savedList[i].id;
if(key === taskId.id){
localStorage.removeItem(key);
localStorage.setItem('todo', JSON.stringify(savedList));
}
}
}
Thanks for any insight.
My first guess looking at this would be the that, since the IDs are being defined by Date.getTime() being called at two different times, that those IDs are not the same. I would suggest that, when you push to savedList at the end of the function to add an item, that you set id as newItem.id, like you for the item name, rather than calling getTime() again
I do see few problems in your code. Here we go.
Remove text reappears because on adding an item, you create todo object with item value set to newTodo.innerText, if you check your saved value in the localstorage it holds extra Remove in it, that's because innerText gets the text of elements under newTodo (in our case we have a button in there). As a fix, you just need to set the actual value from the textbox and not the innerText. You already have that stored in a variable called newItem
And yes, as like #cfinn16 pointed it out, the id we save here would be in number format, when you compare the id from remove button attribute with the id from the savedList array you will see a mismatch. As a resolution, you can convert getTime().toString().
savedList.push({ item: newTodo.innerText, isCompleted: false, id: new Date().getTime() });
Deleting an item, not actually removing the item from both in-memory array i.e savedList or from the localStorage. All we want to do it, just get the taskId, filter/remove items from savedList then replace it in the localStorage with same key. But on loading each todoItems on page refresh, you set new date as the value to each todoItems but that should be the value from the localstorage itself.
let itemId = { id: new Date().getTime() };
Strikethrough an item, has a similar problem. Here you are trying to find clicked item from the array using text instead we can use the id itself.
for (let i = 0; i < savedList.length; i++) {
if (savedList[i].item === clickListItem.innerText) {
savedList[i].isCompleted = !savedList[i].isCompleted;
localStorage.setItem('todo', JSON.stringify(savedList));
}
}
Solution:
https://codepen.io/renishb10/project/editor/ANyqqo
Let me know if you've any questions.
With the help from Renish, I've modified to include the follow and posting it here so it may help anyone else.
// Save to storage
savedList.push({ item: newItem, isCompleted: false, id: new Date().getTime().toString() });
localStorage.setItem('todo', JSON.stringify(savedList));
Changed the new Date() to a string. As both Renish and cfinn pointed out I had mismatch .id. Changing newTodo to newItem go around my innerText from the button being carried over.
// Pull from Storage
newButton.innerText = 'Remove';
newButton.setAttribute('id', savedList[i].id);
Modified my pull from storage code to reflect the new button .id.
function removeFunc(taskId){
splicedList = savedList.filter(l => l.id != taskId)
localStorage.setItem('todo', JSON.stringify(splicedList));
}
Used a filter instead to find the items to remove, based on the .id.
Github of the full modified code:
https://github.com/BreadsticksN7/collections/blob/20b679fc704d05af5576faa3963f676c0bd2665e/todolist.js
Thanks to everyone and their assistance.

Pre-fill form with local storage

I'm loading questions from a JSON into my EJS template and want to populate each field from localStorage. The following saves the last value of each dropdown, text, and slider element:
var select = document.getElementsByTagName('select');
for (var i = 0; i < select.length; i++){
select[i].value = localStorage.getItem(i);
}
jQuery("select").change(function () {
for (var i = 0; i < select.length; i++){
localStorage.setItem(i, select[i].value);
}
});
I repeat this for all "input" tags. The issue is that the select values also get passed into text and slider — and vice versa (i.e. if I enter values for text and slider, they overwrite the select values, except they are left blank).
My end goal is to save each form-fields' most recent value so that my entries are not lost when I refresh the page.
It would be a lot more elegant to create a single localStorage entry representing your saved values, rather than pollute LS with many entries for each field. I would recommend something like this:
function save() {
const selects = document.querySelectorAll('select');
// select other element types
// ...
const selectValues = [...selects].map(select => select.value);
const textValues = [...textInputs].map(textInput => textInput.value);
const sliderValues = [...sliderInputs].map(sliderInput => sliderInput.value);
const savedObj = { selectValues, textValues, sliderValues };
localStorage.savedFormValues = JSON.stringify(savedObj);
}
That way, you only create a single entry in localStorage, and each entry type is quite distinct. Then, to get the values, just do the same thing in reverse:
function populate() {
const selects = document.querySelectorAll('select');
// ...
const { selectValues, textValues, sliderValues } = JSON.parse(localStorage.savedFormValues);
selectValues.forEach((selectValue, i) => selects[i].value = selectValue);
// ...

Remove an Item From an Array with JavaScript splice/indexOf

I am trying to add another button that will remove tasks from the list, and allow the user to remove any of them. I am trying to use splice with indexOf but it's not working so far. Here is the code. Thanks for the help.
// tasks.js #2
// This script manages a to-do list.
// Need a global variable:
var tasks = [];
// Function called when the form is submitted.
// Function adds a task to the global array.
function addTask() {
'use strict';
// Get the task:
var task = document.getElementById('task');
// Reference to where the output goes:
var output = document.getElementById('output');
// For the output:
var message = '';
if (task.value) {
// Add the item to the array:
tasks.push(task.value);
// Update the page:
message = '<h2>To-Do</h2><ol>';
for (var i = 0, count = tasks.length; i < count; i++) {
message += '<li>' + tasks[i] + '</li>';
}
message += '</ol>';
output.innerHTML = message;
} // End of task.value IF.
// Return false to prevent submission:
return false;
} // End of addTask() function.
function deleteTask() {
var inputTask = document.getElementById('task');
var taskLength = inputTask.length;
var i = array.indexOf("inputTask");
if (i != -1) {
array.splice(i, taskLength);
}
}
// Initial setup:
function init() {
'use strict';
//document.getElementById('theForm').onsubmit = addTask;
var elem1 = document.getElementById("submit");
elem1.addEventListener("click", addTask, false);
var elem2 = document.getElementById("delete");
elem2.addEventListener("click", deleteTask, false);
} // End of init() function.
window.onload = init;
You store a reference to an element #inputTask in the inputTask variable but then try to get the index of a string "inputTask" in an array array (which does not exsist, as mentionned by #Frits in the comments).
Then you try to splice the array with the index and the length of inputTask which has no length because it's an element, and if it was a string, why use its length to splice ?
Splice removes (and adds) elements : the first argument is the index of the first element you want to remove, the second agrument is the number of elements you want to remove from the array. So if you want to remove one element, it should look like array.splice(index, 1)
If you want to build deleteTask function the same way as addTask built, you need to implement the following algorithm:
1) find the task element in DOM and get its value
2) check whether or not the value is in the `tasks` array
3) if it's there, remove it
Here's one approach to do this:
function deleteTask() {
// 1
var taskEl = document.getElementById('task');
// 2
var taskIndex = tasks.indexOf(taskEl.value);
if (taskIndex !== -1) {
// 3
tasks.splice(taskIndex, 1);
}
return false;
}
In practice, though, I'd probably go a bit different way. Currently addTask and deleteTask have the same code for collecting the value of this task, but it's preventable - just extract the code that retrieves the value into a separate action (named something like getCurrentTask) and make these methods work with task param instead.
const array = ["a", "b", "c", "d"];
const index = array.indexOf("c");
if (index > -1) {
array.splice(index, 1);
}
console.log(array); // ["a","b","d"]

Categories