Am trying to achieve the following:
The user can select a resource name from a datalist.
The selected resource name will be created in another div.
At the same time, the resource name should be removed from the original datalist. Just to prevent from having the user selecting the same resource name again.
I used the following HTML Code:
<div class="container-client">
<form action="#">
<div class="user-details">
<div class="input-box">
<span class="details">Collaborateurs<small>*</small></span>
<input type="text" placeholder="Selectionner un collaborateur" list="resource-list" required autocomplete="off" id="candidate">
<datalist id="customer-list">
<option value="Alex">Menuisier</option>
<option value="Peter">Charpentier</option>
<option value="Alain">Ingénieur béton</option>
<option value="Adam">Placo</option>
</datalist>
</div>
<div class="button-plus">
<input type="button" value="+" onClick="addResource();">
</div>
</div>
</form>
<hr>
<form action="index.html">
<div class="user-details">
<div class="input-box">
<span class="details">Mon équipe:</span>
</div>
<div class="new-box" id="dynamic-list">
</div>
<div class="new-box">
<div class="button">
<input type="submit" value="✔">
</div>
</div>
</div>
</form>
</div>
Here below the JS code I tried to use; adding the resource name to the div works completely fine, however the removal of the resource name doesn't work.
function addResource()
{
var new_team_member = document.getElementById ('dynamic-list');
var generic_list = document.getElementById ('resource-list');
var candidate = document.getElementById("candidate");
if (candidate.value =='')
{
alert('No data selected');
}
else
{
var div = document.createElement("div");
div.setAttribute('class','input-box');
var input = document.createElement("input");
input.setAttribute('type','text');
input.setAttribute('placeholder',candidate.value);
input.setAttribute('disabled','disabled');
div.appendChild(input);
new_team_member.appendChild(div);
generic_list.removeChild(candidate);
document.getElementById('candidate').value = '';
}
}
The error message I got is about "add-resources.js:20 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node." indicating thatt the following JS line is causing the problem: generic_list.removeChild(candidate);
Can you please help recommending a solution. Thanks in advance.
First of all, in the code, you provided the resource-list and customer-list look like they should be the same thing. In the input tag, the customer-list is used, and in the datalist, the resource-list is used. I've guessed that both of these should be resource-list, to link them correctly.
It looks like you are trying to get the datalist item that you clicked. In the code, as it is right now, you are removing the <input> tag as your candidate variable. If you would remove this, the whole input field would be gone, and the error is caused by this input field not being a child of the generic_list variable.
Now to solve this issue, you can use the document.querySelector() function to get the datalist item that was selected. The following change to your code would have the desired effect:
function addResource()
{
var new_team_member = document.getElementById ('dynamic-list');
var generic_list = document.getElementById ('resource-list');
var candidate = document.getElementById("candidate");
if (candidate.value =='')
{
alert('No data selected');
}
else
{
var div = document.createElement("div");
div.setAttribute('class','input-box');
var input = document.createElement("input");
input.setAttribute('type','text');
input.setAttribute('placeholder',candidate.value);
input.setAttribute('disabled','disabled');
div.appendChild(input);
new_team_member.appendChild(div);
// Get datalist item with selected candidate
datalist_item = document.querySelector('#resource-list option[value="'+CSS.escape(candidate.value)+'"]');
// Remove item from list
generic_list.removeChild(datalist_item);
document.getElementById('candidate').value = '';
}
}
This query selector allow you to use CSS like syntax to select elements. In the string '#resource-list option[value="'+CSS.escape(candidate.value)+'"]' it first finds the resource list, and then takes the option tag that has the candidate name as its value.
For security, I also use the CSS.escape() function that makes sure any name with special characters gets correctly escaped in this string.
Related
I checked all the code and there is nothing wrong with it. When I check the "vegetables" radio button, write something in the text field and hit add, it doesn't add the element.
function add() {
var item;
item = document.getElementById("item").value;
if (document.getElementById("1").checked) {
var li = document.createElement(li);
text = document.createTextNode(item);
li.appendChild(text);
document.getElementById("1v").appendChild(li);
}
}
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
<form action="">
<label for="task">I need :</label><br>
<input type="text" placeholder="Example : Apples" id="item" name="item"><br>
<br>
<label for="type">which is :</label><br>
<div class="">
<input type="radio" id="1" name="type" value="Vegetables">
<label for="">Vegetables</label><br>
</div>
<br>
<button id="add" onclick="add()">Add !</button>
</section>
</form>
</div>
<br>
<footer id="white">
<div>
<table border="bold">
<th>Vegetables</th>
<tbody>
<tr>
<td>
<ol id="1v"></ol>
</td>
</tr>
</tbody>
</table>
</div>
</footer>
You have several problems:
You are using a form, so when you click the button, the form
submits and you leave the page. In your case, you aren't really going to submit data anywhere, so you really don't even need the form element or to specify name attributes for your fields.
You don't have li in quotes, so you aren't actually creating an
<li> element. Without quotes, the system thinks li is a variable, but since you don't have a variable called that, a new Global variable is created with a value of undefined, so your code executes as: document.createElement("undefined"), which does actually create: <undefined></undefined>, but since that isn't an actual HTML element, nothing is rendered for it, except the text you placed inside it (but no numbering):
var li;
let el = document.createElement(li);
console.log(el);
You are using label incorrectly. A <label> element correlates to a form-field element (i.e. input, select, textarea) as a way to have a "caption" for that element. To use it, you should set its for attribute to the id of the form-field its associated with or you can not use for and just nest the form-field its associated with inside of the label. label is not just for text you want to display.
Your HTML is not nested properly and you are missing elements.
Tables should really not be used for anything but displaying tabular
data. They should not be used for layout. Since you are creating new
ordered list items for each item added, you should not use a table.
But, even when you do, you can't just have th. th must be inside
of tr, which would then be inside of thead.
A footer element is meant to provide "the fine print" content at the end of a section. Producing your list isn't that kind of content and shouldn't be in a footer.
Here's all of that put toghether:
// Get your DOM references just once
const item = document.getElementById("item");
const list = document.getElementById("1v");
const veg = document.getElementById("type");
// Don't use inline HTML event attributes to set up events.
// Do your event binding in JavaScript, not HTML.
document.getElementById("add").addEventListener("click", add);
function add() {
if (veg.checked) {
var li = document.createElement("li"); // <-- Need quotes around the element name
li.textContent = item.value;
list.appendChild(li);
}
}
table,th,td { border:1px solid black; }
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
I need : <input type="text" placeholder="Example : Apples" id="item"><br>
<br>
which is : <input type="checkbox" id="type" value="Vegetables"> Vegetables
<div><button id="add">Add !</button></div>
</div>
</section>
<br>
<footer id="white">
<div>
Vegetables
<ol id="1v"></ol>
</div>
</footer>
2 quick fixes to your code (personally, I would rewrite the whole thing):
add type="button" to the button. It will prevent the button from defaulting to a submit.
Syntax error in var li = document.createElement(li);. the li should be in quotes:
var li = document.createElement('li');
Hi i need to remove multiple files uploaded from an array based on user selection in javascript or angular.........
I have tried with below code
First we have a files that are uploaded in an array and is displayed in checkboxes as shown below in code
<div *ngFor="let image of uploadedImages" style="margin-left:10%" >
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate: {{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" id="lifecheck"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<div style="padding-left:34px;padding-bottom:3px;">
<button *ngIf="imagefilename.length" class="btn btn-danger" style="width:200px;padding-left:30px" (click)="dropzone.reset();resetimage(image.Checked)">
Reset Selected files
</button>
</div>
The user will click on the checkboxes that are to be removed and the click on the button displayed and
it calls a function as displayed below
resetimage(imageName:any) {
for(var index = 0; index<this.uploadedImages.length;index++){
if(document.getElementByName("lifecheck")[i].checked==true){
this.uploadedImages.splice(index,1);
}
}
}
So in this function ,only first file in an array is getting removed where the user has selected multiple files to remove
So please help me if there is any solution
Expected result :
to remove multiple files uploaded from an array based on user selection in javascript or angular
Actual result :
Getting error
In your typescript document.getElementByName("lifecheck") cannot find the element in the dom hence you getting the error. In your dom you are creating dynamic input elements with id ='lifecheck'. This is already the wrong way of assigning ids, since dom ids must be unique.
So to fix this you can change your view to assign dynamic unique ids to your input elements:
<div *ngFor="let image of uploadedImages;let i=index" style="margin-left:10%" >
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate: {{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" id="lifecheck_{{i}}"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<div style="padding-left:34px;padding-bottom:3px;">
<button *ngIf="imagefilename.length" class="btn btn-danger" style="width:200px;padding-left:30px" (click)="dropzone.reset();resetimage(image.Checked,i)">
Reset Selected files
</button>
So you are creating input elements with id= "lifecheck_1" etc. Then you can pass this id to your typescript function and find the element:
resetimage(imageName:any,id:number) {
for(var index = 0; index<this.uploadedImages.length;index++){
if(document.getElementById("lifecheck_" + id).checked==true){
this.uploadedImages.splice(index,1);
}
}
}
NOTE: this should be the way to fix your error;
I am working on a personal blog website project, and I wanted to implement a simple message board on my index page. Due to the projected site traffic (relatively low) I decided on only using a front-end implementation without linking to a database with the following js and html code:
<section class="message-board">
<div class="title">
<h2>
Leave a message
</h2>
</div>
<textarea class="message" type="text"></textarea><br/>
<input value="submit" type="button" class="submit-btn">
<div class="display-area">
Existing comment:
</div>
</section>
and then the js,
<script>
window.onload=function() {
var displayArea = document.getElementsByClassName("display-area");
var btn = document.getElementsByClassName("submit-btn");
btn.onclick = function() {
var comment = document.getElementsByClassName("message").value;
displayArea.appendChild(comment);
};
}
</script>
My intention was to make my display-area contain whatever was put in textarea via .appendChild when submit is clicked. Sadly, it isn't working as intended-nothing actually happens. I am thinking about potential errors in my js code, but just couldn't figure out anything that would resolve the problem.
Any assistance will be greatly appreciated!!!
getElementsByClassName() returns a collection of elements (note the s in Elements). If you have only one element that matches the class name, you have this element in the first index of the array-like collection.
var displayArea = document.getElementsByClassName("display-area")[0];
var btn = document.getElementsByClassName("submit-btn")[0];
You can also use querySelector(), that uses CSS selectors (like jQuery) and returns a single element:
var displayArea = document.querySelector(".display-area");
In order to append a text node (your variable comment stores a string), use append() instead of appendChild():
displayArea.append(comment);
Two ways this can be done are by calling the JavaScript function on click, or by calling it on form submission.
1) call function onclick:
Wrap your form within a form tag, and call your JavaScript function based on the element Ids.
Note the showInput function is being called onclick when the button is clicked.
function showInput() {
console.log('showInput called...')
var userInput = document.getElementById("userInput").value;
var display = document.getElementById("display");
display.innerHTML = userInput;
}
<section class="message-board">
<div class="title">
<h2>
Leave a message
</h2>
</div>
<form>
<textarea class="message" type="text" id="userInput"></textarea><br/>
</form>
<input type="submit" onclick="showInput();">
<div class="display-area">
Existing comment:
</div>
<p><span id="display"></span></p>
</section>
Here's a jsfiddle, with the same code as above: http://jsfiddle.net/ethanryan/94kvj0sc/
Note the JavaScript in the jsfiddle is being called at the bottom of the Head section of the HTML.
2) call function on form submit:
You can also do this by calling the JavaScript function on the submission of the form, instead of on the click of the button. However, since this form uses a textarea, hitting return will add a line break to the text, and not submit the form, so the button still needs to be clicked for the function to be called.
function showInput() {
console.log('showInput called...')
event.preventDefault()
var userInput = document.getElementById("userInput").value;
var display = document.getElementById("display");
display.innerHTML = userInput;
}
<section class="message-board">
<div class="title">
<h2>
Leave a message
</h2>
</div>
<form onsubmit="showInput()">
<textarea class="message" type="text" id="userInput"></textarea><br/>
<input type="submit" value="Submit">
</form>
<div class="display-area">
Existing comment:
</div>
<p><span id="display"></span></p>
</section>
Note the event.preventDefault() in the form, since the default behavior of forms is to submit data to a backend database.
jsfiddle: http://jsfiddle.net/ethanryan/qpufd469/
3. appending instead of replacing text
Finally, my examples above used innerHTML to replace the userInput text. If you want to append instead of replace the text, you can use insertAdjacentHTML to add the text to the end, and then append a linebreak to it. Finally, you can reset the form.
function showInput() {
console.log('showInput called...')
event.preventDefault()
var userInput = document.getElementById("userInput").value;
var display = document.getElementById("display");
var theForm = document.getElementById("theForm");
var linebreak = document.createElement("br");
display.insertAdjacentHTML('beforeend', userInput);
display.appendChild(linebreak);
theForm.reset();
}
<section class="message-board">
<div class="title">
<h2>
Leave a message
</h2>
</div>
<form onsubmit="showInput()" id="theForm">
<textarea class="message" type="text" id="userInput"></textarea><br/>
<input type="submit" value="Submit">
</form>
<div class="display-area">
Existing comment:
</div>
<p><span id="display"></span></p>
</section>
jsfiddle: http://jsfiddle.net/ethanryan/x4hq0Lzp/
I have a html fragment similar to this
<div class="form-row">
<input type="text" id="foo1">
</div>
<div class="form-row">
<input type="text" id="foo2">
</div>
<div class="form-row">
<input type="text" id="foo3">
</div>
and I wanted to use cheerio to change the id tag to foobar[1,2,3]
my code is
var cheerio = require("cheerio");
var $ = cheerio.load("html as above");
var inputs = $('input[id]');
Object.keys(inputs).forEach(function(key,index) {
if (key == index) {
console.log(key,inputs[key])
//#1
});
at this point (//#1), I wanted to get the value of the id attribute, and according to the docs at https://github.com/cheeriojs/cheerio I can use the .data method to get and change the attribute in the element, but
inputs[key].data("id")
gives me a "TypeError: undefined is not a function" error
I know that I'm missing something simple, but can't see the wood for the trees and would appreciate some pointers.
thanks
update #1
just when I think I've got a grip on this, it slips from my fingers ..
now, I want to move an element :
I have
<label>xyz<i class="fa fa-list"></i></label>
and I want
<label>xyz</label><i class="fa fa-list"></i>
the code - that doesn't work ;) - is this
var icons = $('label i');
icons.each(function(index,icon) {
// #2 now that I've got an element what now ?
}
I know that icons.remove() will delete the element(s) but struggling to get them added to the right place.
The problem is inputs[key]) will be a dom element reference, which will not have methods like data()
Try to set the attribute value like
var cheerio = require("cheerio");
var $ = cheerio.load('<div class="form-row">\
<input type="text" id="foo1">\
</div>\
<div class="form-row">\
<input type="text" id="foo2">\
</div>\
<div class="form-row">\
<input type="text" id="foo3">\
</div>');
var inputs = $('input[id]');
inputs.attr('id', function(i, id){
return id.replace('foo', 'foobar')
});
console.log($.html())
I have the following html page structure:
<div class="result-row clearfix">
<span>Name1</span>
<span>city1</span>
<span>phone1</span>
<span>details1</span>
</div>
<div class="result-row clearfix">
<span>Name2</span>
<span>city2</span>
<span>phone2</span>
<span>details2</span>
</div>
...
... many such similar divs
And I got simple input field from the user
<label for="name">Name</label> <br />
<input type="text" name="name" autocomplete="off" /> <br />
<label for="city">City</label> <br />
<input type="text" name="city" autocomplete="off" /> <br />
On it's blur event, I would like to make invisible all such div's that does not have the text to be searched and just show the div's that has matched (i.e. the div that has the text within the span tag).
I am not able to retrieve and match this using jquery. I have tried the following:
var nodes = $(".result-row");
console.log("Nodes length: "+nodes.length); // Displays the correct number of child nodes
for(var i=0;i < nodes.length; i++) {
var cur = nodes[i];
console.log(cur); // Displays '#text' in browser js console log.
console.log(cur.childNodes[0]); // Gives undefined. Expecting to get the 1st span tag here.
}
EDIT
I need to display the rows that has the span with matching text. Have updated the html little bit, Please refer to the updated question.
I am able to get the complete data as text of all the span's combined. Is there any way to get the array of spans inside the particular div?
You can use :contains selector:
var $row = $('.result-row');
$('input[type=text]').blur(function() {
var val = this.value;
$row.hide();
$row.has('span:contains("'+val+'")').show()
})
http://jsfiddle.net/x3VtX/
nodes[i] is a jquery object, which doesn't have childNodes property i guess.. so you should be using nodes[i].get(0).childNodes instead...