How to only trigger event on element being clicked - javascript

I am trying to create custom increment / subtract number input arrows
The issue I'm having is how to find a way to only trigger the event on the element being clicked - Currently it's triggering the function on all input fields
EDIT**
Code has been updated as I should mention I am looping through items and each input has a wrapper div with the class ".cart__qty-input"
var quantityInput = document.querySelectorAll('.cart__qty-input');
var plusBtn = document.querySelectorAll('.inc_plus');
var minusBtn = document.querySelectorAll('.inc_minus');
for (i = 0; i < plusBtn.length; i++) {
plusBtn[i].addEventListener('click', addQuantity)
}
function addQuantity(event) {
const currentTarget = event.currentTarget;
let activeIndex = null;
// Find Index
for (index = 0; index < plusBtn.length; index++) {
if(plusBtn[index] === currentTarget) {
activeIndex = index;
}
}
var quantityValue = Number(quantityInput[activeIndex].value)
var newQuantity = quantityValue + 1;
quantityInput[activeIndex].value = newQuantity;
}
for (i = 0; i < minusBtn.length; i++) {
minusBtn[i].addEventListener('click', minusQuantity)
}
function minusQuantity(event) {
const currentTarget = event.currentTarget;
let activeIndex = null;
// Find Index
for (index = 0; index < minusBtn.length; index++) {
if(minusBtn[index] === currentTarget) {
activeIndex = index;
}
}
var quantityValue = Number(quantityInput[activeIndex].value)
var newQuantity = quantityValue - 1
quantityInput[activeIndex].value = newQuantity
}
<div class="cart__qty-input">
<span class="inc_minus">-</span>
<input id="test" class="cart__qty-input" type="number" name="updates[]" value="1" min="0" pattern="[0-9]*">
<span class="inc_plus">+</span>
</div>
<br>
<div class="cart__qty-input">
<span class="inc_minus">-</span>
<input id="test" class="cart__qty-input" type="number" name="updates[]" value="1" min="0" pattern="[0-9]*">
<span class="inc_plus">+</span>
</div>

Your current issue is that you have not implemented a logc to pick which is the row against which the +/- button has been clicked.
I have done that in the following way.
Select the target node against which the +/- button has been clicked.
Parse through the array of the +/- buttons to find the index.
Once the index has been found, update the input corresponding to that index only.
Hope this is helpful
<div class="cart__qty-input">
<span class="inc_minus">-</span>
<input id="test" class="cart__qty-input" type="number" name="updates[]" value="1" min="0" pattern="[0-9]*">
<span class="inc_plus">+</span>
</div>
<br>
<div class="cart__qty-input">
<span class="inc_minus">-</span>
<input id="test" class="cart__qty-input" type="number" name="updates[]" value="1" min="0" pattern="[0-9]*">
<span class="inc_plus">+</span>
</div>
<script>
var quantityInput = document.querySelectorAll('.cart__qty-input input.cart__qty-input');
var plusBtn = document.querySelectorAll('.inc_plus');
var minusBtn = document.querySelectorAll('.inc_minus');
for (i = 0; i < plusBtn.length; i++) {
plusBtn[i].addEventListener('click', addQuantity)
}
function addQuantity(event) {
const currentTarget = event.currentTarget;
let activeIndex = null;
// Find Index
for (index = 0; index < plusBtn.length; index++) {
if (plusBtn[index] === currentTarget) {
activeIndex = index;
}
}
var quantityValue = Number(quantityInput[activeIndex].value)
var newQuantity = quantityValue + 1;
quantityInput[activeIndex].value = newQuantity;
}
for (i = 0; i < minusBtn.length; i++) {
minusBtn[i].addEventListener('click', minusQuantity)
}
function minusQuantity(event) {
const currentTarget = event.currentTarget;
let activeIndex = null;
// Find Index
for (index = 0; index < minusBtn.length; index++) {
if (minusBtn[index] === currentTarget) {
activeIndex = index;
}
}
var quantityValue = Number(quantityInput[activeIndex].value)
var newQuantity = quantityValue - 1
quantityInput[activeIndex].value = newQuantity
}
</script>

Related

Shopping Cart Update Total Function doesnt work

I am building an eCommerce store website, and I am facing an issue. The function updateCartTotal doesn't work at all. The script is also added to the bottom of the HTML body.
Thanks in advance.
HTML:
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>
Javascript:
let cartIcon = document.getElementById("cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
var removeCartButtons = document.getElementsByClassName("material-symbols-outlined");
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem)
}
// Quantity Change //
var quantitInputs = document.getElementsByClassName("cart qty");
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
quantityChanged = (event) => {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
}
function updateCartTotal() {
var cartContainer = document.getElementsByClassName("cart-content")[0];
var cartBox = cartContainer.getElementsByClassName("cart-box");
var total = 0
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
var priceElement = cartBox.getElementsByClassName("cart-price")[0]
var quantityElement = cartBox.getElementsByClassName("cart-qty")[0]
price = parseFloat(priceElement.innerText.replace("£", ""))
quantity = quantityElement.value
total = total + (price * quantity)
}
document.getElementsByClassName("total-price")[0].innerText = total
}
i am expecting the total to update as the quantity changes, and the function to work
You have the following mistakes-
There is no element with the class name cart qty.
var quantitInputs = document.getElementsByClassName("cart qty");
quantityChanged function should have a function keyword.
You are using the same name variable cartBox in updateCartTotal function which is creating confusion-
var cartBox = cartContainer.getElementsByClassName("cart-box");
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
}
Now, after fixing these mistakes, your code will look like the below which is working.
Note- I moved all the declarations to the top and I replaced those two methods-
getElementsByClassName() = querySelectorAll()
getElementsByClassName()[0] = querySelector()
let cartIcon = document.querySelector("#cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
var quantitInputs = document.querySelectorAll(".cart-qty");
var removeCartButtons = document.querySelectorAll(".material-symbols-outlined");
var cartContainer = document.querySelector(".cart-content");
var cartBox = cartContainer.querySelectorAll(".cart-box");
var totalEl = document.querySelector(".total-price")
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem);
}
// Quantity Change //
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
function quantityChanged(event) {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
};
function updateCartTotal() {
var total = 0;
for (var i = 0; i < cartBox.length; i++) {
var cartBoxEl = cartBox[i];
var priceElement = cartBoxEl.querySelector(".cart-price");
var quantityElement = cartBoxEl.querySelector(".cart-qty");
price = parseFloat(priceElement.innerText.replace("£", ""));
quantity = quantityElement.value;
total = total + price * quantity;
}
if (totalEl) {
totalEl.innerText = total;
}
}
<div>
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>

Generated row of table event listener not working instantly

I have a table like this :
I have added an event listener assetTableEvent() to each text box in the table. My issue is when I add new row to the table, i also add the corresponding event listener to it assetTableEvent(), but the total value does not pop while entering value, it shows only when next row has values entered.
function assetTableEvent() {
let total = 0;
for (var k = 0; k < document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
I even tried calling assetTableEvent() every time there is a change, but it just does not work. Can somebody help me in Javascript how to make dynamically added rows correspond to event listener like above rows.
HTML for Asset table:
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>
And add row event listener :
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
Trying to use incremental IDs is more work than it is worth, especially when you start removing rows.
I suggest you use classes instead and delegate the event listener to the table itself. When an input event occurs you get the closest row and query for the elements within that row for the row total, then query all of the rows totals for the master total
Basic example with functional add row
const table = document.querySelector('#myTable'),
cloneRow = table.rows[0].cloneNode(true);
table.addEventListener('input',(e) => {
if (e.target.matches('.qty, .price')) {
const row = e.target.closest('tr'),
price = row.querySelector('.price').valueAsNumber || 0,
qty = row.querySelector('.qty').valueAsNumber || 0;
row.querySelector('.amt').value = qty * price;
setTotalAmt()
}
});
document.querySelector('#add-row').addEventListener('click', (e) => {
table.appendChild(cloneRow.cloneNode(true))
});
function setTotalAmt() {
const sum = [...table.querySelectorAll('.amt')].reduce((a, el) => a + (+el.value || 0), 0)
document.querySelector('#total').value = sum;
}
<button id="add-row">
Add Row
</button>
Total:<input id="total" />
<table id="myTable">
<tr>
<td>Qty:
<input type="number" class="qty" value="0" />
</td>
<td>Price:
<input type="number" class="price" value="0" />
</td>
<td>Amt:
<input class="amt" readonly value="0" />
</td>
</tr>
</table>
#charlietfl 's solition is more elegant but if you wonder what is the problem in your code, you should change the < to <= in k < document.getElementById("assetTable").rows.length; part
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
Here is the working example:
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>

JavaScript not further executed once a button is disabled

I am using next and prev buttons so one question will be shown at a time, however, once next or prev buttons are disabled, the other button doesn't work anymore either. Here's my code:
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
function next() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 1) {
document.getElementById("next").disabled = true;
} else {
console.log(i);
qElems[i + 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i + 1] = 1;
}
break;
}
}
}
function prev() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 4) {
document.getElementById("prev").disabled = true;
} else {
qElems[i - 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i - 1] = 1;
}
break;
}
}
}
I think you want this simplified script
I had to guess the HTML, but there is only one function.
window.addEventListener("load", function() {
let showing = 0;
const questions = document.querySelectorAll(".q");
questions[showing].style.display = "block";
const next = document.getElementById("next");
const prev = document.getElementById("prev");
document.getElementById("nav").addEventListener("click", function(e) {
var but = e.target, dir;
if (but.id === "prev") dir = -1;
else if (but.id === "next") dir = 1;
else return; // not a button
questions[showing].style.display = "none"; // hide current
showing += dir; // up or down
next.disabled = showing === questions.length-1;
if (showing <= 0) showing = 0;
prev.disabled = showing === 0
questions[showing].style.display = "block";
})
})
.q { display:none }
<div class="q" id="q0">Question 0</div>
<hr/>
<div class="q" id="q1">Question 1</div>
<hr/>
<div class="q" id="q2">Question 2</div>
<hr/>
<div class="q" id="q3">Question 3</div>
<hr/>
<div id="nav">
<button type="button" id="prev" disabled>Prev</button>
<button type="button" id="next">Next</button>
</div>
Since this is a quiet interesting java script task, Im doing my own solution.
Hope this matches the requirement.
I have created 4 divs of which first one is only displayed at first. Remaining divs are placed hidden. On clicking next, the divs are displayed according to index. Once the last and first indexes are interpreted, the respective next and previous buttons are enabled and disabled.
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
var qElems = [];
function initialize() {
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
}
function updatevisibilitystatus(showindex, hideindex) {
qElems[showindex].style.display = 'block';
qElems[hideindex].style.display = 'none';
showing[showindex] = 1;
}
function next() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 2) {
document.getElementById("next").disabled = true;
}
updatevisibilitystatus(i + 1, i);
document.getElementById("prev").disabled = false;
break;
}
}
}
function prev() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == 1) {
document.getElementById("prev").disabled = true;
}
updatevisibilitystatus(i - 1, i);
document.getElementById("next").disabled = false;
break;
}
}
}
<body onload="initialize()">
<div id="q0" style="display: block;">Q0</div>
<div id="q1" style="display: none;">Q1</div>
<div id="q2" style="display: none;">Q2</div>
<div id="q3" style="display: none;">Q3</div>
<button id="prev" disabled onclick="prev()">Prev</button>
<button id="next" onclick="next()">Next</button>
</body>

How to show nearest div id for a given input number?

Let's say I have the following input field:
<input id="inputField" type="number" value="">
and some divs such as:
<div id="1000"></div>
<div id="1200"></div>
<div id="1500"></div>
<div id="1900"></div>
...
When the user enters a number in the input field, I want my code to go to the nearest div id to that number.
e.g: If user enters 1300 then show div with id = "1200".
What's the most efficient way to implement that in javascript considering there will be a large number of divs?
Right now I'm doing:
<script>
function myFunction()
{
var x = document.getElementById("inputField").value;
if(x >= 1750 && x <= 1900)
{
window.location.hash = '#1800';
}
}
</script>
One way is to wrap all your divs with number ids in another div if you can (and give it some id, say 'numbers'); this allows you to find all the divs in your javascript file.
Javascript:
// Get all the divs with numbers, if they are children of div, id="numbers"
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
// Append the integer of the id of every child to an array
array.push(parseInt(children[i].id));
}
// However you are getting your input number goes here
let number = 1300 // Replace
currentNumber = array[0]
for (const value of array){
if (Math.abs(number - value) < Math.abs(number - currentNumber)){
currentNumber = value;
}
}
// You say you want your code to go to the nearest div,
// I don't know what you mean by go to, but here is the div of the closest number
let target = document.getElementById(currentNumber.toString());
Let me know if there's more I can add to help.
Demo
function closestNum() {
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
array.push(parseInt(children[i].id));
}
let number = document.getElementById('inputnum').value;
currentNumber = array[0]
for (const value of array) {
if (Math.abs(number - value) < Math.abs(number - currentNumber)) {
currentNumber = value;
}
}
let target = document.getElementById(currentNumber.toString());
document.getElementById('target').innerHTML = target.innerHTML;
}
<div id="numbers">
<div id="1000">1000</div>
<div id="2000">2000</div>
<div id="3000">3000</div>
<div id="4000">4000</div>
<div id="5000">5000</div>
</div>
<br />
<input type="text" id="inputnum" placeholder="Input Number" onchange="closestNum()" />
<br />
<br /> Target:
<div id="target"></div>
With some optimization this shall be ok-
var element;
document.addEventListener("change",
function(evt){
if(element && element.classList){
element.classList.remove("selected", false);
element.classList.add("unselected", true);
}
var listOfDivs =
document.querySelectorAll(".unselected");
var val = evt.target.value;
var leastAbs=listOfDivs[0].id;
for(let anIndex=0, len=listOfDivs.length;anIndex<len;anIndex++){
if(Math.abs(listOfDivs[anIndex].id-val)<leastAbs){
leastAbs = Math.abs(listOfDivs[anIndex].id-val);
element = listOfDivs[anIndex];
}
}
element.classList.remove("unselected");
element.classList.add("selected");
});
.selected{
background-color:red;
}
.unselected{
background-color:yellow;
}
.unselected, .selected{
width:100%;
height:50px;
}
<input id="inputField" type="number" value="">
<div id="1000" class='unselected'>1</div>
<div id="1200" class='unselected'>2</div>
<div id="1500" class='unselected'>3</div>
<div id="1900" class='unselected'>4</div>
This may work for you. Loops through each div and compared it to your inputted ID. Tracks closest one, hides all divs, then displays the closest.
document.getElementById("inputField").addEventListener("change", function(){
var divs = document.getElementsByTagName("div");
var closestDiv = -1;
var inputId = document.getElementById("inputField").value;
for(var i=0; i<divs.length; i++)
{
if(Math.abs(inputId - closestDiv) > Math.abs(inputId - divs[i].id) || closestDiv == -1)
{
closestDiv = divs[i].id;
for (var x = 0; x < divs.length; x++) {
divs[x].style.display = 'none';
}
divs[i].style.display = "block";
}
}
});
See it Live: jsfiddle.net

Sorting table using javascript sort()

I am trying to sort a table. I've seen several jQuery and JavaScript solutions which do this through various means, however, haven't seen any that use JavaScript's native sort() method. Maybe I am wrong, but it seems to me that using sort() would be faster.
Below is my attempt, however, I am definitely missing something. Is what I am trying to do feasible, or should I abandon it? Ideally, I would like to stay away from innerHTML and jQuery. Thanks
var index = 0; //Index to sort on.
var a = document.getElementById('myTable').rows;
//sort() doesn't work on collection
var b = [];
for (var i = a.length >>> 0; i--;) {
b[i] = a[i];
}
var x_td, y_td;
b.sort(function(x, y) {
//Having to use getElementsByTagName is probably wrong
x_td = x.getElementsByTagName('td')[index].data;
y_td = y.getElementsByTagName('td')[index].data;
return x_td == y_td ? 0 : (x_td < y_td ? -1 : 1);
});
A td element doesn't have a .data property.
If you wanted the text content of the element, and if there's only a single text node, then use .firstChild before .data.
Then when that is done, you need to append the elements to the DOM. Sorting a JavaScript Array of elements doesn't have any impact on the DOM.
Also, instead of getElementsByTagName("td"), you can just use .cells.
b.sort(function(rowx, rowy) {
x_td = rowx.cells[index].firstChild.data;
y_td = rowy.cells[index].firstChild.data;
return x_td == y_td ? 0 : (x_td < y_td ? -1 : 1);
});
var parent = b[0].parentNode;
b.forEach(function(row) {
parent.appendChild(row);
});
If the content that you're comparing is numeric, you should convert the strings to numbers.
If they are text strings, then you should use .localeCompare().
return x_td.localeCompare(y_td);
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>All Sorting Techniques</title>
<script type="text/javascript">
var a = [21,5,7,318,3,4,9,1,34,67,33,109,23,156,283];
function bubbleSort(a)
{
var change;
do {
change = false;
for (var i=0; i < a.length-1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
change = true;
}
}
} while (change);
document.getElementById("bublsrt").innerHTML = "Bubble Sort Result is: "+a;
}
var b = [1,3,4,5,7,9,21,23,33,34,67,109,156,283,318];
function binarySearch(b, elem){
var left = 0;
var right = b.length - 1;
while (left <= right){
var mid = parseInt((left + right)/2);
if (b[mid] == elem)
return mid;
else if (b[mid] < elem)
left = mid + 1;
else
right = mid - 1;
}
return b.length;
}
function searchbinary(){
var x = document.getElementById("binarysearchtb").value;
var element= binarySearch(b,x);
if(element==b.length)
{
alert("no. not found");
}
else
{
alert("Element is at the index number: "+ element);
}
}
function quicksort(a)
{
if (a.length == 0)
return [];
var left = new Array();
var right = new Array();
var pivot = a[0];
for (var i = 1; i < a.length; i++) {
if (a[i] < pivot) {
left.push(a[i]);
} else {
right.push(a[i]);
}
}
return quicksort(left).concat(pivot, quicksort(right));
}
function quicksortresult()
{
quicksort(a);
document.getElementById("qcksrt").innerHTML = "Quick Sort Result is: "+quicksort(a);
}
function numeric(evt){
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault)
theEvent.preventDefault();
}
}
function insertionsorting(a)
{
var len = a.length;
var temp;
var i;
var j;
for (i=0; i < len; i++) {
temp = a[i];
for (j=i-1; j > -1 && a[j] > temp; j--) {
a[j+1] = a[j];
}
a[j+1] = temp;
}
document.getElementById("insrtsrt").innerHTML = "Insertion Sort Result is: "+a;
}
function hiddendiv()
{
document.getElementById("binarytbdiv").style.display = "none";
document.getElementById("Insertnotbdiv").style.display = "none";
}
function binarydivshow()
{
document.getElementById("binarytbdiv").style.display = "block";
}
function insertnodivshow()
{
document.getElementById("Insertnotbdiv").style.display = "block";
}
function insertno(a)
{
var extrano = document.getElementById("Insertnotb").value;
var b= a.push(extrano);
var change;
do {
change = false;
for (var i=0; i < a.length-1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
change = true;
}
}
} while (change);
document.getElementById("insrtnosearch").innerHTML = "Sorted List is: "+a;
alert("Index of "+extrano +" is " +a.indexOf(extrano));
}
</script>
</head>
<body onload="hiddendiv()">
<h1 align="center">All Type Of Sorting</h1>
<p align="center">Your Array is : 21,5,7,318,3,4,9,1,34,67,33,109,23,156,283</p>
<div id="main_div" align="center">
<div id="bubblesort">
<input type="button" id="bubblesortbutton" onclick="bubbleSort(a)" value="Bubble Sort">
<p id="bublsrt"></p>
</div><br>
<div id="quicksort">
<input type="button" id="quicksortbutton" onclick="quicksortresult()" value="Quick Sort">
<p id="qcksrt"></p>
</div><br>
<div id="insertionsort">
<input type="button" id="insertionsortbutton" onclick="insertionsorting(a)" value="Insertion Sort">
<p id="insrtsrt"></p>
</div><br>
<div id="binarysearch">
<input type="button" id="binarysearchbutton" onclick="binarydivshow();" value="Binary Search">
<div id="binarytbdiv">
<input type="text" id="binarysearchtb" placeholder="Enter a Number" onkeypress="numeric(event)"><br>
<input type="button" id="binarysearchtbbutton" value="Submit" onclick="searchbinary()">
<p id="binarysrch">Sorted List is : 1,3,4,5,7,9,21,23,33,34,67,109,156,283,318</p>
</div>
</div><br>
<div id="Insertno">
<input type="button" id="insertno" onclick="insertnodivshow()" value="Insert A Number">
<div id="Insertnotbdiv">
<input type="text" id="Insertnotb" placeholder="Enter a Number" onkeypress="numeric(event);"><br>
<input type="button" id="Insertnotbbutton" value="Submit" onclick="insertno(a)">
<p id="insrtnosearch"></p>
</div>
</div>
</div>
</body>
</html>

Categories

Resources