Get the value of an input field located inside a table jquery - javascript

This is supposed to be a shopping cart inspired by jeasyui.com. I have three problems with it.
I can't get the value of the quantity when it's changed in the input box.
When I remove an item from the cart, that service must be available in its appropriate tab again.
The services get indented for each new tab. I need them to start at the beginning everytime.
This is the code I have so far:codepen.io. I'm sorry if it's messy, it's my first time working with javascript/jquery. Any help is appreciated. Thank you!
function removeProduct(el) {
var name1 = $(el).closest('tr').find('td').eq(0).text();
var price1;
for (var i = 0; i < data.length; i++) {
if (name1 == data[i][0]) {
price1 = data[i][2];
}
var className = $(el).parent().attr('class');
/**Add a new list item in item class with the class name and the service name and price in paragraphs.*/
$(el).closest('tr').remove();
}
}
function changeQuantity(el) {
var name1 = $(el).closest('tr').find('td').eq(0).text();
var quantity1 = $(el).closest('tr').find('td').eq(1).value;
var price1;
for (var i = 0; i < data.length; i++) {
data[i][1] = quantity1;
data[i][2] = price * quantity1;
if (name1 == data[i][0]) {
price1 = data[i][2];
}
}
$(el).closest('tr').find('td').eq(1).html("<input type='number' value='" + quantity1 + "' style='width:100%;'>");
$(el).closest('tr').find('td').eq(3).html(price1);
}

To get the quantity do:
$(el).closest('tr').find('td').eq(1).find('input').val();
Because you are physically removing the element from the DOM with source.remove(); you can't easily. I would suggest adding a class to the element that will hide it. And then when you remove it from the card, remove that class.
For your third issue, remove the CSS that hides the product classes and instead add this:
Remove:
.Biostatistics {
display: none;
}
.ClinicalLaboratory {
display:none;
}
.Something{
display:none;
}
Add:
.Products li {
display: none;
}
Also change your js to be like this (adding the closest('li'):
x[i].closest('li').style.display = 'none';

Related

How to auto generate number in an input field?

I am creating a table with an auto numbering ID column. I want to be able to have my input text field to auto-generate an ID number(when the user starts typing into the name input field).
How do I auto-generate a number into an input field?
You could use the code below. What it does is every time you click the insert button, it adds a number to the id of the item (the number next to the text field).
This code uses document.getElementById() to modify all of the elements, and uses a variable num to incremement the id value. The part where it adds the item to the list is optional - I just added it to make it look more realistic.
var num = 1;
var input = document.getElementById('item');
var p = document.getElementById('number');
var list = document.getElementById('list');
var button = document.getElementById('insert');
button.addEventListener('click', function() {
num++;
p.innerHTML = num;
list.innerHTML += "<li>" + input.value + "</li>";
});
#item {
display: inline;
}
#number {
display: inline;
margin-right: 10px;
}
<p id='number'>1</p>
<input type='text' id='item' />
<button id='insert'>Insert</button>
<ul id='list'>
</ul>
If you have an HTML table, then you could respond to all edits, listening to the input event, and decide whether to fill a unique number (or wipe it out).
Here is a generic function you could call which takes as argument the table element that should have this feature, and the number of the column that should get these ID values.
Example:
function autoId(table, colNo) {
table.addEventListener("input", function(e) {
const tr = e.target.closest("tr");
const idInput = tr.cells[colNo].querySelector("input");
for (const input of tr.querySelectorAll("input")) {
hasData = input.value.trim() !== "" && input !== idInput;
if (hasData) break;
}
if (hasData && idInput.value.trim() === "") {
idInput.value = (Math.max(...Array.from(
table.querySelectorAll("td:nth-child(" + (colNo+1) + ") input"),
input => +input.value
).filter(v => !isNaN(v))) || 0) + 1;
} else if (!hasData && idInput.value.trim() !== "") {
idInput.value = "";
}
});
}
const table = document.querySelector("table");
// Call the function passing it the table and the column that has the ID -- that's all
autoId(table, 0);
// Let's give user the possibility to add rows, using the first data row as template
document.querySelector("#btnAddRow").addEventListener("click", () => {
table.insertAdjacentHTML("beforeend", table.rows[1].innerHTML);
});
<table>
<tr><th>ID</th><th>Name</th></tr>
<tr><td><input size="2"></td><td><input></td></tr>
</table>
<button id="btnAddRow">Add row</button>

Show an ID as a :after of a CLASS?

#fp-nav{display:none}
.submenu:after{content:"I WANT #fp-nav HERE"}
<div class="submenu"> </div>
<div id="fp-nav">01 / 52</div>
Let's say I have an ID counter that updates every section change: 01 / XX, 02 / xx and so on...
How can I keep that ID hidden from the page and let it appear as an :after of a CLASS?
Thanks!
Not sure if I got what you are trying to accomplish as epascarello says, it is unclear!
body{
counter-reset: paragraph;
}
p::before {
counter-increment: paragraph;
content: "Paragraph " counter(paragraph) ": ";
}
<p>Name</p>
<p>Last Name</p>
<p>Phone #</p>
<p>Address</p>
You can manipulate the style properties of CSS rules via the styleSheets collection:
// Get the rule's stylesheet and index
let ruleIndex = -1;
let sheet = null;
let sheetRules = null;
Array.from(document.styleSheets).some(s => Array.from(s.rules || s.cssRules).some((rule, index) => {
if (rule.selectorText == ".foo::after") {
sheet = s;
sheetRules = sheet.rules || sheet.cssRules;
ruleIndex = index;
return true;
}
}));
// Update it periodically
let id = 0;
setInterval(() => {
++id;
sheet.deleteRule(ruleIndex);
ruleIndex = sheet.insertRule('.foo::after { content: "' + id + '"; }', ruleIndex);
}, 250);
.foo::after {
content: 'foo';
}
<span class="foo"></span>
You used to be able to change a rule's style properties, but they were made read-only, so now you have to remove the old rule and add a new one.
There is a solution through Jquery , you might not be able to target pseudo class like :after but you would be able to add it in the submenu div tag
//get value from the id
var k = $('#fp-nav').text();
// remove the element
$('#fp-nav').remove();
//add the value inside submenu i just gave it a class value you can change it as per your need
$(".submenu").append( "<div class='idval'>"+k +"</div> ");

Get a div inside a td with Javascript

I want to get the text inside the div in the class "atName".
I am looping though the table td's like this:
var searchString = document.getElementById("search").value;
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable td'),
colslen = cols.length,
i = -1;
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
Here i want to access the text inside the div
}
Every td is set up like this:
<td id="H" class="element nonmetal gasI">
<div class="atN">1</div>
<div class="atS gas"><a class="gas" href="https://en.wikipedia.org/wiki/Hydrogen" target="_blank">H</a></div>
<div class="atName">Hydrogen</div>
<div class="atW">1.00794</div>
</td>
I want the text inside the "atName" div.
Does anyone know how?
Thanks!
The same way you selected the tds:
cols[i].querySelector('.atName').textContent;
btw. you should give different IDs to your tds or use classes because IDs should be unique
UPDATE
To avoid any confusion, I'm already assuming we're looping the tds (from your code), and this line goes here:
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var divText = cols[i].querySelector('.atName').textContent; // <--- here
}
...
}
You can get the object by class name :
document.getElementsByClassName('atName')
But this return you a list of object with this class.
So you can do in your while:
while (++i < colslen)
{
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var text = cols[i].getElementsByClassName('atName')[0].textContent;
}
}
Maybe this will help?
var searchString = "Hy";
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable tr td .atName');
for (var i=0;i<cols.length;i++)
{
if (cols[i].innerHTML.indexOf(searchString)>-1)
{
alert(cols[i].innerHTML);
}
}
}
What you're looking for is element.innerHTML but hopefully this selector trick will help you too.
Edit: element.textContent is different but you might desire to use it instead.

Removing content created by jquery

(according webshop)
I want to add an function remove, where I remove the whole entry inserted using ajax & jquery, but it is not working as I want to.
Using the following code:
$('#div').on('click', '.orderd', function() {
$(this).remove();
});
function UpdateTotal() {
ToAddHTML = '<h1>Shopping cart</h1>';
Totalprice = 0;
for (var i = 0; i < orders.length ; i++) {
var zoekresultaat = SubMenuItems.filter(function(v) {
return v.submenu_id === orders[i];
})[0];
Totalprice += parseFloat(searched.price);
ToAddHTML += '';
}
ToAddHTML += ''
$("#totalen").html(ToAddHTML);
}
This works, but when I console.log the array "orderd items", it still repeats the orderd items.
So when I click on a different item, the "just-deleted" order is popping up again.
It's kind of hard to explain my current problem, but I hope i've informed enough! For any questions, please ask! ill update my question!
You should remove the ordered id from your array, and recalculate your "basket" when an item is removed.
// =======================================================================
// ! Functie maken die de totalen-lijst bijwerkt
// =======================================================================
function WerkTotalenBij() {
ToeTeVoegenHTML = '<h1>Winkelmandje</h1>';
Totaalprijs = 0;
for (var i = 0; i < Bestellingen.length ; i++) {
var zoekresultaat = SubMenuItems.filter(function(v) {
return v.submenu_id === Bestellingen[i];
})[0];
Totaalprijs += parseFloat(zoekresultaat.price);
// here I put a "data-itemid" attribute to keep a raw reference to the item id
// this ID can be retrieved in the remove handler
ToeTeVoegenHTML += '<div class=besteld id=nummer'+Bestellingen[i]+' data-itemid="'+Bestellingen[i]+'">'+'€'+zoekresultaat.price+' '+zoekresultaat.title+'</br>(verwijder)</div><hr>';
}
ToeTeVoegenHTML += '<br/>Totale prijs per persoon :<br/> € '+Totaalprijs+'<br/>Minimaal 10 personen<br/> Aantal personen:<input type=text width="10px" /><input type="button" value="Ik ben klaar!">';
$("#totalen").html(ToeTeVoegenHTML);
}
$('#totalen').on('click', '.besteld', function() {
var itemID = $(this).data("itemid");
// remove the item ID from the array
var index = Bestellingen.indexOf(itemID);
if (index > -1) {
Bestellingen.splice(index, 1);
}
$(this).remove();
// recalculate orders
WerkTotalenBij();
});
But anyway, this is the typical work where you should rather use for example knockout.js libaray, where you can bind your DOM elements directly to your data, and it's enought to manipulate with your data, the GUI will automatically reflect to the changes. Believe me, it's worth to learn it, you won't regret.

A good JavaScript to add/remove items from/to array?

folks! Today I created this script that has the following functionality:
add new items to array
list all items from the array
remove an item from the array
There are two functions:
addToFood() - adds the value of input to the array and updates
innerHTML of div
removeRecord(i) - remove a record from the array and updates
innerHTML of div
The code includes 3 for loops and you can see it at - http://jsfiddle.net/menian/3b4qp/1/
My Master told me that those 3 for loops make the solution way to heavy. Is there a better way to do the same thing? Is it better to decrease the loops and try to use splice? Thanks in advance.
HTML
<!-- we add to our foodList from the value of the following input -->
<input type="text" value="food" id="addFood" />
<!-- we call addToFood(); through the following button -->
<input type="submit" value="Add more to food" onClick="addToFood();">
<!-- The list of food is displayed in the following div -->
<div id="foods"></div>
JavaScript
var foodList = [];
function addToFood () {
var addFood = document.getElementById('addFood').value;
foodList.push(addFood);
for (i = 0; i < foodList.length; i++) {
var newFood = "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML += newFood;
}
function removeRecord (i) {
// define variable j with equal to the number we got from removeRecord
var j = i;
// define and create a new temporary array
var tempList = [];
// empty newFood
// at the end of the function we "refill" it with the new content
var newFood = "";
for (var i = 0; i < foodList.length; i++) {
if(i != j) {
// we add all records except the one == to j to the new array
// the record eual to j is the one we've clicked on X to remove
tempList.push(foodList[i]);
}
};
// make redefine foodList by making it equal to the tempList array
// it should be smaller with one record
foodList = tempList;
// re-display the records from foodList the same way we did it in addToFood()
for (var i = 0; i < foodList.length; i++) {
newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML = newFood;
}
You should use array.splice(position,nbItems)
function removeRecord (i) {
foodList.splice(i, 1); // remove element at position i
var newFood = "";
for (var i = 0; i < foodList.length; i++) {
newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> "
+ foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML = newFood;
}
http://jsfiddle.net/3b4qp/5/
Now using JQuery:
$(function(){
$(document).on('click','input[type=submit]',function(){
$('#foods')
.append('<div>X '
+ $('#addFood').val() + '</div>');
});
$(document).on('click','.item',function(){
$(this).parent().remove();
});
});
http://jsfiddle.net/jfWa3/
Your problem isn't the arrays, your problem is this code:
node.innerHTML += newFood;
This code is very, very, very slow. It will traverse all exising DOM nodes, create strings from them, join those strings into one long string, append a new string, parse the result to a new tree of DOM nodes.
I suggest to use a framework like jQuery which has methods to append HTML fragments to existing DOM nodes:
var parent = $('#foods');
...
for (var i = 0; i < foodList.length; i++) {
parent.append( "<a href='#' onClick='removeReco..." );
That will parse the HTML fragments only once.
If you really must do it manually, then collect all the HTML in a local string variable (as suggested by JohnJohnGa in his answer) and then assign innerHTML once.
Here's some tips to, at least, make your code more portable (dunno if it will be better performance wise, but should be, since DOM Manipulation is less expensive)
Tips
First separate your event handle from the HTML
Pass the "new food" as a function paramater
Tie the array elements to the DOM using the ID
Instead of rerendering everything when something changes (using innerHTML in the list), just change the relevant bit
Benefits:
You actually only loop once (when removing elements from the array).
You don't re-render the list everytime something changes, just the element clicked
Added bonus: It's more portable.
Should be faster
Example code:
FIDDLE
HTML
<div id="eventBinder">
<!-- we add to our foodList from the value of the following input -->
<input id="addFood" type="text" value="food" />
<!-- we call addToFood(); through the following button -->
<button id="addFoodBtn" value="Add more to food">Add Food</button>
<!-- The list of food is displayed in the following div
-->
<div id="foods"></div>
</div>
JS
// FoodList Class
var FoodList = function (selectorID) {
return {
foodArray: [],
listEl: document.getElementById(selectorID),
idCnt: 0,
add: function (newFood) {
var id = 'myfood-' + this.idCnt;
this.foodArray.push({
id: id,
food: newFood
});
var foodDom = document.createElement('div'),
foodText = document.createTextNode(newFood);
foodDom.setAttribute('id', id);
foodDom.setAttribute('class', 'aFood');
foodDom.appendChild(foodText);
this.listEl.appendChild(foodDom);
++this.idCnt;
},
remove: function (foodID) {
for (var f in this.foodArray) {
if (this.foodArray[f].id === foodID) {
delete this.foodArray[f];
var delFood = document.getElementById(foodID);
this.listEl.removeChild(delFood);
}
}
}
};
};
//Actual app
window.myFoodList = new FoodList('foods');
document.getElementById('eventBinder').addEventListener('click', function (e) {
if (e.target.id === 'addFoodBtn') {
var food = document.getElementById('addFood').value;
window.myFoodList.add(food);
} else if (e.target.className === 'aFood') {
window.myFoodList.remove(e.target.id);
}
}, false);
Here is another sugestion:
function remove(arr, index) {
if (index >= arr.lenght) { return undefined; }
if (index == 0) {
arr.shift();
return arr;
}
if (index == arr.length - 1) {
arr.pop();
return arr;
}
var newarray = arr.splice(0, index);
return newarray.concat(arr.splice(1,arr.length))
}

Categories

Resources