input value to object and then that object push to array - javascript

Hollow i have some issue and small problem
i have 3 input fields I need to get values on click from them assign them to object and that object push in to array
can somebody can help ore say where to look info I'm searching on MDN but I can't find correct topic whit examples
1)input value to object and then that object push to array
function $(e) {
return document.querySelector(e);
}
function $$(e) {
return document.querySelectorAll(e);
}
var startBtn = $("send");
startBtn.addEventListener('click', creatTask, false);
function creatTask() {
var addTaskName = $(".task-name"),
addCategory = $(".category"),
addTaskSatus = $(".status");
<!-- task.Taskname = addTaskName.value
task.Category = addCategory.value
task.Status = addTaskSatus.value........... ? -- >
var TaskListArray = [];
var task = {
Taskname: undefined,
Category: undefined,
Status: undefined
}
console.log(task)
}
document.write("message")
Link to jsfiddle with html and javascript

Try setting id or className selector at var startBtn = $("send"); defining TaskListArray outside of creatTask function; setting values directly at creation of task object; use Array.prototype.push() to add current task object to TaskListArray array.
Also, use window.onload event, or place <script> after elements in html for elements queried in DOM to be loaded in document before creatTask is called or startBtn defined
<script>
window.onload = function() {
function $(e) {
return document.querySelector(e);
}
function $$(e) {
return document.querySelectorAll(e);
}
var startBtn = $(".send");
var TaskListArray = [];
startBtn.addEventListener('click', creatTask, false);
function creatTask() {
var addTaskName = $(".task-name"),
addCategory = $(".category"),
addTaskSatus = $(".status");
var task = {
Taskname: addTaskName.value,
Category: addCategory.value,
Status: addTaskSatus.value
}
TaskListArray.push(task)
console.log(task)
}
}
// document.write("message")
</script>
<input class="task-name" name="task" />
<br>
<input class="category" name="category" />
<br>
<input class="status" name="status" />
<br>
<input type="button" class="send" value="send" />

Related

How to delete a DOM element from an array after you've clicked on it?

I was making a simple to-do list. You submit itens from an input and they go to the To-DO section. When you click over them they go to the 'Done' section. And when you click on them again, they vanish forever. It was all working fine.
But I realized the doneItens array kept growing in length, which I wanted to optimize. So I came up with this line of code
doneItens.splice(i, 1);
which goes inside an onclick event, which you can see in the code inside the deleteDone function.
That gives the error, though,
Error:{
"message": "Uncaught TypeError: doneItens.splice is not a function"
If I put it outside and below the onclick event it also doesn't work. How can I do it?
var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
const newItem = document.createElement('li');
newItem.setAttribute('class', 'item');
newItem.append(input.value);
toDo.append(newItem);
input.value='';
deleteItem();
}
function deleteItem() {
const toBeDone = document.getElementsByClassName('item');
for(let i = 0; i < toBeDone.length; i++) {
toBeDone[i].onclick = () => {
appendItemDone(toBeDone[i]);
toBeDone[i].style.display = 'none';
deleteDone();
}
}
}
function appendItemDone(item) {
const newDone = document.createElement('li');
newDone.setAttribute('class', 'feito')
newDone.append(item.innerText);
done.append(newDone);
}
function deleteDone() {
const doneItens = document.getElementsByClassName('feito');
console.log('done length', doneItens.length)
for (let i = 0; i < doneItens.length; i++) {
doneItens[i].onclick = () => {
doneItens[i].style.display = 'none';
doneItens.splice(i, 1);
}
}
}
<div id='flex'>
<form class='form' onsubmit='handleSubmit(event)'>
<input placeholder='New item' type='text' id='play'>
<button>Send</button>
</form>
<div id='left'>
<h1 id='todo' >To-do:</h1>
<p class='instruction'><i>(Click over to mark as done)</i></p>
<ol id='here'></ol>
</div>
<div id='right'>
<h1>Done:</h1>
<p class='instruction'><i>(Click over to delete it)</i></p>
<p id='placeholder'></p>
<ol id='done'></ol>
</div>
</div>
With the use of JavaScript DOM API such as Node.removeChild(), Element.remove() and Node.parentNode, your task can be solved with this code:
const input = document.getElementById('play');
const todo = document.getElementById('todo');
const done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
// create new "todo" item
const newTodo = document.createElement('li');
newTodo.textContent = input.value;
todo.append(newTodo);
// clean the input field
input.value = '';
// listen to "click" event on the created item to move it to "done" section
newTodo.addEventListener('click', moveToDone);
}
function moveToDone(event) {
// remove "click"-listener to prevent event listener leaks
event.target.removeEventListener('click', moveToDone);
// move clicked todo-element to "done" section
const newDone = event.target.parentNode.removeChild(event.target);
done.append(newDone);
// listen to "click" event on the moved item to then completely delete it
newDone.addEventListener('click', removeFromDone);
debugElementsLeak();
}
function removeFromDone(event) {
// remove "click"-listener to prevent event listener leaks
event.target.removeEventListener('click', removeFromDone);
// complete remove clicked element from the DOM
event.target.remove();
debugElementsLeak();
}
function debugElementsLeak() {
const todoCount = todo.childElementCount;
const doneCount = done.childElementCount;
console.log({ todoCount, doneCount });
}
<div id="flex">
<form class="form" onsubmit="handleSubmit(event)">
<input placeholder="New item" type="text" id="play">
<button>Add item</button>
</form>
<div id="left">
<h1>To-do:</h1>
<p class="instruction"><em>(Click over to mark as done)</em></p>
<ol id="todo"></ol>
</div>
<div id="right">
<h1>Done:</h1>
<p class="instruction"><em>(Click over to delete it)</em></p>
<p id="placeholder"></p>
<ol id="done"></ol>
</div>
</div>
You'll want to use splice,
and then rather than use hidden, 'refresh' the done element by adding all elements in the spliced array.
I've commented my code where I've made changes and why
var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
const newItem = document.createElement('li');
newItem.setAttribute('class', 'item');
newItem.append(input.value);
toDo.append(newItem);
input.value='';
deleteItem();
}
function deleteItem() {
const toBeDone = document.getElementsByClassName('item');
for(let i = 0; i < toBeDone.length; i++) {
toBeDone[i].onclick = () => {
appendItemDone(toBeDone[i].cloneNode(true));
toBeDone[i].style.display = 'none';
deleteDone();
}
}
}
function appendItemDone(item) {
const newDone = document.createElement('li');
newDone.setAttribute('class', 'feito')
newDone.append(item.innerText);
done.append(newDone);
}
function deleteDone() {
var doneItens = document.getElementsByClassName('feito');
for (let i = 0; i < doneItens.length; i++) {
doneItens[i].onclick = () => {
var splicedArray = spliceFromArray(doneItens,doneItens[i]);// NEW BIT -CALL NEW SPLICE FUNCTION
done.innerHTML=""; // NEW BIT - SET OVERALL DONE TO BLANK ON DELETE
for(var index in splicedArray){// NEW BIT - fOR EACH RETURNED ELEMENT IN THE SPLICE, ADD IT TO THE OVERALL DONE ELEMENT
done.appendChild(splicedArray[index]);
}
}
}
}
function spliceFromArray(arrayInput,element){// NEW BIT - SPLICE FUNCTION THAT RETURNS SPLICED ARRAY
var array = Array.from(arrayInput);
var index = array.indexOf(element);
if(index!=-1){
if(array.length==1 && index == 0){
array = [];
}
else{
array.splice(index,1);
}
}
return array;
}
<div id='flex'>
<form class='form' onsubmit='handleSubmit(event)'>
<input placeholder='New item' type='text' id='play'>
<button>Send</button>
</form>
<div id='left'>
<h1 id='todo' >To-do:</h1>
<p class='instruction'><i>(Click over to mark as done)</i></p>
<ol id='here'></ol>
</div>
<div id='right'>
<h1>Done:</h1>
<p class='instruction'><i>(Click over to delete it)</i></p>
<p id='placeholder'></p>
<ol id='done'></ol>
</div>
</div>

How to add task to current method?

I am trying to do a web app similar to google calendar. I have done the object and methods within it but now it's time to be able to add what I want as a task. My idea is for the user to add something to the input and that input being console.logged for now.
Any idea?
HTML
<div class="new-task" id="task-input">
<div id="add-new-task">Task: <input type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" onclick="">Save task</button>
</div>
Javascript
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var newTask = document.getElementById("add-new-task")
newTask.addEventListener('click',tasksManager.add())
console.log(tasksManager.array)
As you can see with console.log above the array index [0] is logged as undefined but I wanted the user to write in the input " Go to the gym" and this to be logged within the array.
Thanks
Some issues:
You are not assigning the click handler. Instead you execute it immediately (not on click).
When you call .add() you don't provide an argument: the name of the task
The click handler should be on the button element, not on the div that has the input element. And so it will be useful to give that button an id attribute.
You should retrieve the value from the input element, and so it would be more appropriate to give that element an id and not so much the div that wraps it.
The console.log at the end of your script is executed immediately. It should be done only when the user has clicked the button.
Snippet with some corrections (also in the HTML!):
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
let taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var button = document.getElementById("save-task"); // <-- the button
var input = document.getElementById("add-new-task"); // <-- the input (move the ID attribute to the input!)
button.addEventListener('click', () => {
tasksManager.add(input.value);
console.log(tasksManager.array)
})
<div class="new-task" id="task-input">
<div >Task: <input id="add-new-task" type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" id ="save-task" onclick="">Save task</button>
</div>

Bind HTML element to Javascript object and store object in array - Update object with input value from child element

In vanilla JavaScript how can I bind an element to an object so that if a child element of the object has a value I can update the object with it? Need to be compatible with IE10+ and all other browsers.
With a button I am dynamically adding an element (createElement()) containing a form input. When the element is created it also creates an object that should also be the element so I can update the object with the input value on change.
I then store each new object in an array.
The issue I am having is connecting the input value with the correct object. I tried looping through the array hoping to update each object in turn with the current input value of the event target but couldn't succeed. I tried registering the element (deprecated) and various other things but I cannot quite workout how to link the input to the container object (lineObject).
I could really use some help solving this problem and understanding how to bind an element to an object in the way I need.
//lineNumber *** //
let lineNumber = document.querySelectorAll('.lineNumber');
let numberOfLines = lineNumber.length;
//first instance of input element
let lineText = document.querySelector('.lineText');
//first input value of element
let lineTextValue = document.querySelector('input[name="lineText"]').value;
//create initial lineObject for first line
let lastLine = lineNumber[numberOfLines - 1];
let lineContainer;
//lineNumber object constructor
function LineObject(lineText, writable) {
//set properties
this.lineText = lineText;
this.writable = writable;
}
//new object at new lineNumber element, set values
let lineObject = new LineObject(lineTextValue, true);
//create array containing initial line object
let lineArray = [lineObject];
//line functions
(function lineGeneration(){
//add or remove lines
document.addEventListener('click', function(e) {
//this
let self = e.target;
// has class .addLine
if (hasClass(self, 'addLine')) {
//call function to get variables
insertLineHTML();
//clone new line after the last line\
self.parentElement.parentElement.parentElement.parentElement.parentElement.appendChild(lineObject.cloneNode(true));
//lineNumber input location
let newlineTextInput = self.parentElement.parentElement.parentElement.parentElement.nextElementSibling.querySelector('input[name="lineText"]');
//input value of new element
let lineTextValue = newlineTextInput.value;//normally "" when created unless placeholder text
//new object at new lineNumber element
lineObject = new LineObject(lineTextValue, true);
//add new object to lineArray
lineArray.push(lineObject);
refreshLineNodeList();
}
});
//combine accordion / refresh
function refreshLineNodeList(){
//refresh number of elements in nodelist
lineNumber = document.querySelectorAll('.lineNumber');
//get new length
numberOfLines = lineNumber.length;
}
//line html and vars
function insertLineHTML(){
lineObject = document.createElement('div');
lineObject.setAttribute('class', 'lineNumber');
lineObject.innerHTML = `
<div class="accordion-title">
<h3>Line 2</h3>
</div>
<div class="input-section">
<div class="input-row">
<div class="input-container">
<label>Line 2 :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>`;
console.log(lineNumber);
}
})();
//lineText addEventListener update object value
document.addEventListener('keyup', function(e) {
let self = e.target;//input field
let lineTextValue = self.value;
// has class .lineText
if (hasClass(self, 'lineText')) {
//for each lineObject in LineArray
//lineArray.forEach(function(arrayObject) {
//update lineObject HTMLelement.prototype
Object.defineProperty(lineObject, 'lineText', {
//update object value to event target value
get: function() {
return this.lineTextValue;//how can I get the right lineObject object from the array when I update the input
},
set: function(lineTextValue) {
this.lineText = lineTextValue;//how can I aet the right lineObject object in the array when I update the input
}
});
//debugging
//console.log('objectProperty = ' + arrayObject.lineText);
console.log('this.lineText = ' + this.lineText);
console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('lineObject.lineText = '+ lineObject.lineText);
//console.log('lineTextValue = '+ lineTextValue);
//});
};
});
let button = document.getElementById('test');
button.addEventListener( "click", testFunction );
function testFunction(){
button.addEventListener( "click", testFunction );
//console.log('Object.keys(lineObject) - '+ Object.keys(lineObject));
//console.log('Reflect.ownKeys(lineObject) - ' + Reflect.ownKeys(lineObject));
//console.log('Object.values - ' + Object.values(lineObject));
//console.log('lineObject = '+ lineObject.lineText);
//console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('Object.entries(lineObjectClone) - ' + Object.entries(lineObjectClone));
//console.log('lineObjectClone.lineText = ' + lineObject.lineText);
//console.log('lineObjectClone[1].lineText = ' + lineObjectClone.lineText);
//console.log('lineArray[0] = ' + lineArray[0].lineText);
console.log('lineArray = ' + lineArray);
console.log('numberOfLines = ' + numberOfLines);
for(let i = 0; i < numberOfLines; ++i ){
console.log('lineArray[i].lineText = ' + lineArray[i].lineText)
}
};
//does the element have the class specified?
function hasClass(elem, className) {
return elem.classList.contains(className);
};
<section>
<button id="test">Test</button>
<div class="lineNumber">
<div class="accordion-title">
<h3>Line</h3>
</div>
<div class="input-section" style="display: block;">
<div class="input-row">
<div class="input-container">
<label>Line Text :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>
</div>
</section>
One way to do this is to use a closure.
The purpose of a closure is to capture variables from the containing function so those variables can be used later, after the containing function exits.
A simple example could look like this:
let data = {
nameGenerator: 0
};
function addInput() {
// generate a new name and property in data object
let propertyName = String.fromCharCode("a".charCodeAt() + data.nameGenerator++);
// initialize property value to its name
data[propertyName] = propertyName;
// add <div><input value="(property)"></div> to container
let containerElement = document.getElementById("container");
let lineElement = document.createElement("div");
let inputElement = document.createElement("input");
lineElement.appendChild(inputElement);
containerElement.appendChild(lineElement);
// initialize input value (note: this does not bind the two, just initializes)
inputElement.value = data[propertyName];
// create a closure that binds the property to the element
inputElement.addEventListener("keyup", function () {
// inside this function, propertyName and inputElement
// are "captured" in the closure
data[propertyName] = inputElement.value;
})
}
Note that the propertyName and inputElement variables are defined in the outer addInput function, but they are captured in the closure that is created when you assign the anonymous function as an event listener.
Here is a fiddle with a complete working example: https://jsfiddle.net/b3ta60cn/

Storage and show multiple outputs

I have a simple text input where users type anything and after sumbitting text appear on a page and stays there, which I done with localStorage, but after refreshing the page only last typed input is showing, Ill post my code to be more specific:
HTML:
<body>
<input id="NewPostField" type="text" value="">
<button onclick="myFunction()">Post</button>
<div id="Posts"></div>
</body>
JavaScript:
function myFunction() {
var NewPostField =
document.getElementById("NewPostField");
var newPost = document.createElement("p");
localStorage.setItem('text',
NewPostField.value);
newPost.innerHTML = NewPostField.value;
var Posts = document.getElementById("Posts");
Posts.appendChild(newPost);
}
(function() {
const previousText = localStorage.getItem('text');
if (previousText) {
var NewPostField = document.getElementById("NewPostField");
NewPostField.value = previousText;
myFunction();
}
})();
Any help will be great!
It seems that your code is only storing the last value posted.
To store more than one post, one idea is to stringify an array of values to store in localStorage.
Then, parse that stringified value back into an array as needed.
Here's an example:
function getExistingPosts() {
// fetch existing data from localStorage
var existingPosts = localStorage.getItem('text');
try {
// try to parse it
existingPosts = JSON.parse(existingPosts);
} catch (e) {}
// return parsed data or an empty array
return existingPosts || [];
}
function displayPost(post) {
// display a post
var new_post = document.createElement("p");
new_post.innerHTML = post;
posts.appendChild(new_post);
}
function displayExistingPosts() {
// display all existing posts
var existingPosts = getExistingPosts();
posts.innerHTML = '';
inputPost.value = '';
if (existingPosts.length > 0) {
existingPosts.forEach(function(v) {
displayPost(v);
});
inputPost.value = existingPosts.slice(-1)[0];
}
}
function addPost(post) {
// add a post
var existing = getExistingPosts();
existing.push(post);
localStorage.setItem('text', JSON.stringify(existing));
displayPost(post);
}
function clearPosts() {
// clear all posts
localStorage.removeItem('text');
displayExistingPosts();
}
var posts = document.getElementById("posts");
var inputPost = document.getElementById("input_post");
var btnPost = document.getElementById('btn_post');
var btnClear = document.getElementById('btn_clear');
btnPost.addEventListener('click', function() {
addPost(inputPost.value)
});
btnClear.addEventListener('click', clearPosts);
displayExistingPosts();
<input id="input_post" type="text" value="">
<button type="button" id="btn_post">Post</button>
<button type="button" id="btn_clear">Clear</button>
<div id="posts"></div>
Since localStorage isn't supported in StackSnippets, here's a JSFiddle to help demonstrate.

Set a property of scope object dynamically in Angular Js

I am writing a generic method to get some data from a service and populate in the dynamic property name passed in the function. the value does gets assigned to the text box using angular.element assignment but does not gets populated in the model. following is the code.
<div class="input-group">
<input class="form-control" id="ImgRollover" name="ImgRollover" ng-model="contentEntity.imgRollover" placeholder="" readonly="readonly" type="text">
<div class="input-group-btn">
<button class="btn" type="button" ng-click="pickImage('contentEntity.imgRollover')">
</button>
</div>
here is my controller method which internally uses a service which sends back a promise
$scope.pickImage = function (attrModel) {
ImageSelector.selectImage().then(
function (value) {
//angular.element("#" + attrModel).val(value);
$scope[attrModel] = value;
});
};
attrModel is a property name in the scope object contentEntity but the name of the property is known ONLY dynamically via the method parameter.
<button class="btn" type="button" ng-click="pickImage('contentEntity', 'imgRollover')"></button>
$scope.pickImage = function (attrModel1, attrModel2) {
ImageSelector.selectImage().then(function (value) {
$scope.[attrModel1][attrModel2] = value;
});
};
should work
I know this has already been well answered but I wanted to make a dynamic property creator.
It splits attrModel by '.' and then edits $scope and adds and/or returns each property if it either exists already or not, we preserve the last key outside of the while loop so that the value just has to be appended to it.
$scope.pickImage = function (attrModel) {
ImageSelector.selectImage().then(
function (value) {
var parent = $scope,
current,
attribute,
attributes = attrModel.split('.');
while(attributes.length > 1 &&
(attribute = attributes.shift()) &&
(current = parent[attribute] || (parent[attribute] = {}))) {
parent = current;
}
current[attributes[0]] = value;
});
};
Of course, if you want to do it the angular way you'd have to use a service in order to do that, it could look like this
jsfiddle here
angular.module('myApp').service('ObjectWalker', function () {
var getNodeData = function (object, path) {
var parent = object,
current,
attribute,
attributes = path.split('.');
while(attributes.length > 1 &&
(attribute = attributes.shift()) &&
(current = parent[attribute] || (parent[attribute] = {}))) {
parent = current;
}
return [current, attributes[0]];
};
return {
set: function(object, path, value) {
var nodeData = getNodeData(object, path);
nodeData[0][nodeData[1]] = value;
},
get: function(object, path) {
var nodeData = getNodeData(object, path);
return nodeData[0][nodeData[1]];
}
};
})
There is already an answer but, just like to post something for dynamic properties...
<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.2.23/angular.js"></script>
<script type="text/javascript">
var value = 0;
function mainCtrl($scope) {
value++;
$scope.pickImage = function (attrModel) {
value++;
alert(attrModel)
$scope[attrModel] = value;
};
$scope.getValue = function(attrModel) {
return $scope[attrModel];
}
}
</script>
</head>
<body ng-app ng-controller="mainCtrl">
<input type="text" ng-model="test.obj" />
<br/>
<button ng-click="pickImage(test.obj)">test</button>
<br/>
display the value afoter button click,
note there is no single quote
<br/>
value: {{ getValue(test.obj) }}
</body>
</html>

Categories

Resources