Hoping someone can help me.
Checked other, similar questions on this forum but still can't solve this problem.
Trying to create a simple shopping cart using HTML5 (Drag and Drop) and JavaScript. I've copied most of the code below from an online tutorial (code was open source and free to use). I want to extend the code so that, as items are dragged into cart area, the total cost of all items in the cart is displayed. This total would be updated as more items are added.
Also, I'm trying to update the code so that a user can purchase more than one of any item and am trying to get the display to also show quantity of each item in cart.
I've added an updateCart() function but I'm confused as to how to get it working properly (obviously it's not functioning as intended). Since the drag and drop from original code is working the problem must be in my updateCart function.
I've added ' data-price' and 'data-quantity' attributes to the li tags of shop items. I've tried to get total price to display but haven't looked at item quantity yet.
Any advice would be appreciated.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Drag and drop in HTML 5, demonstration with a shop</title>
<style>
body {
padding:32px;
}
.shop {
border-radius:6px;
list-style-type:none;
padding:0;
margin:0;
}
.shop li{
display:inline;
}
.cart {
border: 4px solid #0066FF;
border-radius:6px;
min-height:128px;
display:block;
}
.product {
border:3px solid white;
}
.product:hover {
border:3px solid red;
cursor:move;
}
.itemchoosen {
this.style.opacity = 0.5;
this.style.border = "2px solid red";
}
.itemblurred {
this.style.border = none;
}
#cartArea {
position: relative;
height: 200px;
width: 100%;
float: left;
border: 1px dotted #999;
}
</style>
</head>
<body >
<fieldset><legend>The shop</legend>
<ul id="shop" class="shop">
<li data-price="30.00" data-quantity="1"><img class="product" id="chair" src="images/chair.jpg" width="96" height="96"></li>
<li data-price="250.00" data-quantity="1"><img class="product" id="monitor" src="images/screen.jpg" width="96" height="96"></li>
<li data-price="80.00" data-quantity="1"><img class="product" id="bag" src="images/bag.jpg" width="96" height="96"></li>
<li data-price="350.00" data-quantity="1"><img class="product" id="transat" src="images/transat.jpg" width="96" height="96"></li>
</ul>
</fieldset>
<fieldset id="mycart" class="cart"><legend>My cart</legend>
<div id="cartArea"></div>
</fieldset>
<fieldset id="mycart" class="cart"><legend>Total</legend>
<p id="the_sub_total"></p>
<p id="the_total"></p>
</fieldset>
<script>
var cartArea = document.querySelector('#cartArea');
var prods = document.querySelectorAll('.product');
for(var i = 0; i < prods.length; i++)
{
prods[i].setAttribute('draggable', 'true'); // optional with images
prods[i].addEventListener('dragstart', function(evnt) {
this.className = 'itemchoosen';
evnt.dataTransfer.effectAllowed = 'copy';
evnt.dataTransfer.setData('text', this.id);
return false;
}, false);
}
cartArea.addEventListener('dragover', function(evnt) {
if (evnt.preventDefault) evnt.preventDefault();
evnt.dataTransfer.dropEffect = 'copy';
return false;
}, false);
cartArea.addEventListener('dragenter', function(evnt) {
return false;
}, false);
cartArea.addEventListener('dragleave', function(evnt) {
return false;
}, false);
cartArea.addEventListener('drop', function(evnt) {
if (evnt.stopPropagation) evnt.stopPropagation();
var id = evnt.dataTransfer.getData('text');
var theitem = document.getElementById(id);
//theitem.parentNode.removeChild(el);
theitem.className='itemblurred';
var y = document.createElement('img');
y.src = theitem.src;
cartArea.appendChild(y);
evnt.preventDefault(); // for Firefox
updateCart();
return false;
}, false);
function updateCart(){
var total = 0.0;
var cart_items = document.querySelectorAll("#shop li")
for (var i = 0; i < cart_items.length; i++) {
var cart_item = cart_items[i];
var quantity = cart_item.getAttribute('data-quantity');
var price = cart_item.getAttribute('data-price');
var sub_total = parseFloat(quantity * parseFloat(price));
//document.querySelectorAll("#the_sub_total")[0].innerHTML = " = " + sub_total.toFixed(2);
total += sub_total;
}
document.querySelectorAll("#the_total")[0].innerHTML = total.toFixed(2);
}
</script>
</body>
</html>
try using this code :
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Drag and drop in HTML 5, demonstration with a shop</title>
<style>
body {
padding:32px;
}
.shop {
border-radius:6px;
list-style-type:none;
padding:0;
margin:0;
}
.shop li{
display:inline;
}
.cart {
border: 4px solid #0066FF;
border-radius:6px;
min-height:128px;
display:block;
}
.product {
border:3px solid white;
}
.product:hover {
border:3px solid red;
cursor:move;
}
.itemchoosen {
this.style.opacity = 0.5;
this.style.border = "2px solid red";
}
.itemblurred {
this.style.border = none;
}
#cartArea {
position: relative;
height: 200px;
width: 100%;
float: left;
border: 1px dotted #999;
}
</style>
</head>
<body >
<fieldset><legend>The shop</legend>
<ul id="shop" class="shop">
<li data-price="30.00" data-quantity="1"><img class="product" id="chair" src="images/chair.jpg" width="96" height="96"></li>
<li data-price="250.00" data-quantity="1"><img class="product" id="monitor" src="images/screen.jpg" width="96" height="96"></li>
<li data-price="80.00" data-quantity="1"><img class="product" id="bag" src="images/bag.jpg" width="96" height="96"></li>
<li data-price="350.00" data-quantity="1"><img class="product" id="transat" src="images/transat.jpg" width="96" height="96"></li>
</ul>
</fieldset>
<fieldset id="mycart" class="cart"><legend>My cart</legend>
<div id="cartArea"></div>
</fieldset>
<fieldset id="mycart" class="cart"><legend>Total</legend>
<p id="the_sub_total"></p>
<p id="the_total"></p>
</fieldset>
<script>
var total = 0.0;
var cartArea = document.querySelector('#cartArea');
var prods = document.querySelectorAll('.product');
for(var i = 0; i < prods.length; i++)
{
prods[i].setAttribute('draggable', 'true'); // optional with images
prods[i].addEventListener('dragstart', function(evnt) {
this.className = 'itemchoosen';
evnt.dataTransfer.effectAllowed = 'copy';
evnt.dataTransfer.setData('text', this.id);
return false;
}, false);
}
cartArea.addEventListener('dragover', function(evnt) {
if (evnt.preventDefault) evnt.preventDefault();
evnt.dataTransfer.dropEffect = 'copy';
return false;
}, false);
cartArea.addEventListener('dragenter', function(evnt) {
return false;
}, false);
cartArea.addEventListener('dragleave', function(evnt) {
return false;
}, false);
cartArea.addEventListener('drop', function(evnt) {
if (evnt.stopPropagation) evnt.stopPropagation();
var id = evnt.dataTransfer.getData('text');
var theitem = document.getElementById(id);
console.log(theitem.parentNode.attributes);
var quantity=theitem.parentNode.attributes['data-quantity'].value;
var price = theitem.parentNode.attributes['data-price'].value;
console.log(price);
theitem.className='itemblurred';
var y = document.createElement('img');
y.src = theitem.src;
cartArea.appendChild(y);
evnt.preventDefault(); // for Firefox
updateCart(quantity,price);
return false;
}, false);
function updateCart(quantity,price){
var sub_total = parseFloat(quantity * parseFloat(price));
total = total+sub_total;
document.getElementById('total').value= total;
document.querySelectorAll("#the_total")[0].innerHTML = total.toFixed(2);
}
</script>
</body>
</html>
Updated Code:
You are running a loop in updateCart() to first get the price of all the items and then check what all items are there in the cart, instead you can send the price as the parameter in the updateCart() function, as you are already getting the element which is recently dropped in the cartArea.addEventListener('drop', function(evnt).
You can add a scroll to the cartArea if you want.
But I am not getting why you have used sub_total in this, if you want to show the item price below the item image, then there is no need.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Drag and drop in HTML 5, demonstration with a shop</title>
<style>
body {
padding:32px;
}
.shop {
border-radius:6px;
list-style-type:none;
padding:0;
margin:0;
}
.shop li{
display: inline-table;
}
.cart {
border: 4px solid #0066FF;
border-radius:6px;
min-height:128px;
display:block;
padding: 20px 10px;
}
.product {
border:3px solid white;
}
.product:hover {
border:3px solid red;
cursor:move;
}
.itemchoosen {
this.style.opacity = 0.5;
this.style.border = "2px solid red";
}
.itemblurred {
this.style.border = none;
}
#cartArea {
position: relative;
min-height: 200px;
width: 100%;
float: left;
}
#cartArea img {
float: left;
width: 20%;
margin: 2%;
}
.itemPrice {
width: 100%;
float: left;
}
</style>
</head>
<body >
<fieldset><legend>The shop</legend>
<ul id="shop" class="shop">
<li><img class="product" id="chair" src="images/chair.jpg" width="96" height="96" data-price="30.00" data-quantity="1"></li>
<li><img class="product" id="monitor" src="images/screen.jpg" width="96" height="96" data-price="250.00" data-quantity="1"></li>
<li><img class="product" id="bag" src="images/bag.jpg" width="96" height="96" data-price="80.00" data-quantity="1"></li>
<li><img class="product" id="transat" src="images/transat.jpg" width="96" height="96" data-price="350.00" data-quantity="1"></li>
</ul>
</fieldset>
<fieldset id="mycart" class="cart">
<legend>My cart</legend>
<div id="cartArea"></div>
</fieldset>
<fieldset id="mycart" class="cart">
<legend>Total</legend>
<p id="the_sub_total"></p>
<p id="the_total">0</p>
</fieldset>
<script>
var cartArea = document.querySelector('#cartArea');
var prods = document.querySelectorAll('.product');
var itemPriceElement;
for(var i = 0; i < prods.length; i++) {
itemPriceElement = document.createElement("span");
itemPriceElement.className = "itemPrice";
itemPriceElement.innerHTML = prods[i].getAttribute("data-price");
prods[i].parentNode.insertBefore(itemPriceElement, prods[i].nextSibling);
prods[i].setAttribute('draggable', 'true'); // optional with images
prods[i].addEventListener('dragstart', function(evnt) {
//this.className = 'itemchoosen';
this.classList.add('itemchoosen');
evnt.dataTransfer.effectAllowed = 'copy';
evnt.dataTransfer.setData('text', this.id);
return false;
}, false);
}
cartArea.addEventListener('dragover', function(evnt) {
if (evnt.preventDefault) evnt.preventDefault();
evnt.dataTransfer.dropEffect = 'copy';
return false;
}, false);
cartArea.addEventListener('dragenter', function(evnt) {
return false;
}, false);
cartArea.addEventListener('dragleave', function(evnt) {
return false;
}, false);
cartArea.addEventListener('drop', function(evnt) {
if (evnt.stopPropagation) evnt.stopPropagation();
var id = evnt.dataTransfer.getData('text');
var theitem = document.getElementById(id);
//theitem.parentNode.removeChild(el);
//theitem.className='itemblurred';
theitem.classList.add('itemblurred');
var y = document.createElement('img');
y.src = theitem.src;
cartArea.appendChild(y);
evnt.preventDefault(); // for Firefox
updateCart(theitem.getAttribute("data-price"));
return false;
}, false);
function updateCart(price){
var the_total = document.getElementById("the_total").innerHTML;
the_total = parseInt(the_total);
the_total = the_total + parseInt(price);
document.getElementById("the_total").innerHTML = the_total;
}
</script>
</body>
</html>
Related
--- UPDATED QUESTION ---
Thanks for all the answers. I wrote the JS code to delete the parent div when clicking its corresponding button in my JS PRACTICE!!!
However, the same JS code does not work in my real JS project where all the parent div are created dynamically. The complete code can be found below.
There is no error but the JS code just does not work. Any ideas?
BELOW IS THE SIMPLIFIED **REAL JS PROJECT ** COMPLETE CODE
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload Imgs</title>
<style type="text/css">
.container {
width: 100%;
}
.display-area {
width: 100%;
height: auto;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
img {
max-width: 100%;
}
.image-preview {
width: 80%;
min-height: 300px;
border: 2px dashed #dddddd;
display: block;
/*default text*/
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #cccccc;
}
.newbtns {
border: 0;
background: lightgrey;
text-shadow: 1px 1px 1px white;
border: 1px solid #999;
position: absolute;
display: block;
}
</style>
</head>
<body>
<div class="container">
<div id='inputFiles'><input type="file" class="file" name="image_uploads" accept="image/png, image/jpeg, image/jpg"
multiple></div>
<div class="display-area" id='imgDisplay'>
</div>
<div id="defaultContent">
<p>No images</p>
</div>
<button type="button" value="Reload page" onclick="window.location.reload()">Reload Page</button>
</div>
</div>
</body>
<script>
var input = document.querySelector('input');
var uploadBox = document.getElementById('uploadBox');
var defaultContent = document.getElementById('defaultContent');
var imgDisplay = document.getElementById('imgDisplay')
//upload & preview
input.addEventListener('change', function () {
var imgFiles = input.files;
defaultContent.style.display = 'none';
for (var i = 0; i < imgFiles.length; i++) {
var imgDiv = document.createElement('div');
imgDiv.className = 'imgBox';
imgDiv.id = 'box' + i;
imgDiv.style.width = "20%";
var images = document.createElement('img');
images.src = URL.createObjectURL(imgFiles[i]);
var newbtn = document.createElement("button");
newbtn.type = "button";
newbtn.className = "newbtns";
newbtn.innerHTML = "X";
newbtn.style.color = "orange";
newbtn.style.background = 'red';
newbtn.id = 'newbtn' + i;
imgDiv.appendChild(newbtn);
imgDiv.appendChild(images);
imgDisplay.appendChild(imgDiv);
}
});
allButtons = document.getElementsByTagName('button');
for (var n = 0; n < allButtons.length; n++) {
if (allButtons[n].getAttribute('id') === 'newbtn' + n) {
allButtons[n].onclick = function () {
this.parentNode.parentNode.removeChild(this.parentNode);
}
} else { };
}
</script>
</html>
you can do something like this:
const buttonOne = document.getElementById('btn1');
const buttonTwo = document.getElementById('btn2');
buttonOne.addEventListener("click", () => deleteElementAndThisChildNodes('box1'))
buttonTwo.addEventListener("click", () => deleteElementAndThisChildNodes('box2'))
function deleteElementAndThisChildNodes(parentId) {
document.getElementById(parentId).remove()
}
To each of your button elements add onclick="DeleteParent(this)" then outside of your dynamic divs include the following:
<script type="text/javascript">
function DeleteParent(button){
button.parentElement.remove();
}
</script>
You can do this:
const display = document.getElementById("imgdisplayarea");
display.addEventListener("click", e => {
if(e.target.tagName === 'BUTTON'){
//if an element within a display div for a button, remove your father
e.target.parentNode.remove();
}
});
Here is a very simple example that works exactly how you want it (based on your question):
function disable() {
document.getElementById("demo").style.display = "none";
}
<div id="demo">
<button onclick="disable()">
Click Me
</button>
<h3>
This is part of the div
</h3>
</div>
I'm trying to make a Single Page Application with pure JavaScript (no additional frameworks or libraries). The problem is that the values I add to the TODO list are not storing in the localStorage (and are not showing).
I would appreciate any help with that task.
How can I simplify the code? (without using any additional libraries and frameworks (ex.jquery etc.))
Here is my code:
let inputTask = document.getElementById('toDoEl');
let editTask = document.getElementById('editTask');
let checkTask = document.getElementById('list');
let emptyList = document.getElementById('emptyList');
let items = [];
let id = [];
let labelToEdit = null;
const empty = 0;
let pages = ['index', 'add', 'modify'];
load();
function load() {
items = loadFromLocalStorage();
id = getNextId();
items.forEach(item => renderItem(item));
}
function show(shown) {
location.href = '#' + shown;
pages.forEach(function(page) {
document.getElementById(page).style.display = 'none';
});
document.getElementById(shown).style.display = 'block';
return false;
}
function getNextId() {
for (let i = 0; i<items.length; i++) {
let item = items[i];
if (item.id > id) {
id = item.id;
}
}
id++;
return id;
}
function loadFromLocalStorage() {
let localStorageItems = localStorage.getItem('items');
if (localStorageItems === null) {
return [];
}
return JSON.parse(localStorageItems);
}
function saveToLocalStorage() {
localStorage.setItem('items', JSON.stringify(items));
}
function setChecked(checkbox, isDone) {
if (isDone) {
checkbox.classList.add('checked');
checkbox.src = 'https://image.ibb.co/b1WeN9/done_s.png';
let newPosition = checkTask.childElementCount - 1;
let listItem = checkbox.parentNode;
listItem.classList.add('checked');
checkTask.removeChild(listItem);
checkTask.appendChild(listItem);
} else {
checkbox.classList.remove('checked');
checkbox.src = 'https://image.ibb.co/nqRqUp/todo_s.png';
let listItem = checkbox.parentNode;
listItem.classList.remove('checked');
}
}
function renderItem(item) {
let listItem = document.getElementById('item_template').cloneNode(true);
listItem.style.display = 'block';
listItem.setAttribute('data-id', item.id);
let label = listItem.querySelector('label');
label.innerText = item.description;
let checkbox = listItem.querySelector('input');
checkTask.appendChild(listItem);
setChecked(checkbox, item.isDone);
emptyList.style.display = 'none';
return listItem;
}
function createNewElement(task, isDone) {
let item = { isDone, id: id++, description: task };
items.push(item);
saveToLocalStorage();
renderItem(item);
}
function addTask() {
if (inputTask.value) {
createNewElement(inputTask.value, false);
inputTask.value = '';
show('index');
}
}
function modifyTask() {
if (editTask.value) {
let item = findItem(labelToEdit);
item.description = editTask.value;
labelToEdit.innerText = editTask.value;
saveToLocalStorage();
show('index');
}
}
function findItem(child) {
let listItem = child.parentNode;
let id = listItem.getAttribute('data-id');
id = parseInt(id);
let item = items.find(item => item.id === id);
return item;
}
// Chanhe img to checked
function modifyItem(label) {
labelToEdit = label;
editTask.value = label.innerText;
show('modify');
editTask.focus();
editTask.select();
}
function checkItem(checkbox) {
let item = findItem(checkbox);
if (item === null) {
return;
}
item.isDone = !item.isDone;
saveToLocalStorage();
setChecked(checkbox, item.isDone);
}
function deleteItem(input) {
let listItem = input.parentNode;
let id = listItem.getAttribute('data-id');
id= parseInt(id);
for (let i in items) {
if (items[i].id === id) {
items.splice(i, 1);
break;
}
}
if (items.length === empty) {
emptyList.style.display = 'block';
}
saveToLocalStorage();
listItem.parentNode.removeChild(listItem);
}
* {
box-sizing: border-box;
}
body {
font-family: sans-serif;
}
h2, li, #notification {
text-align: center;
}
h2 {
font-weight: normal;
margin: 0 auto;
padding-top: 20px;
padding-bottom: 20px;
}
#root {
width: 400px;
height: 550px;
margin: 0 auto;
position: relative;
}
#root>ul {
display: block;
}
#addButton {
display: block;
margin: 0 auto;
}
.checkbox, .delete {
height: 24px;
bottom: 0;
}
.checkbox {
float: left;
}
.delete {
float: right;
}
ul {
margin: 20px 30px 0 30px;
padding-top: 20px;
padding-left: 20px;
text-align: center;
}
#toDoEl {
width: 50%;
}
li {
width: 100%;
list-style: none;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
margin: 15px auto;
}
label {
margin: 0 auto;
text-align: justify;
text-justify: inter-word;
}
label:hover {
cursor: auto;
}
li.checked {
background-color: gray;
}
span.button {
cursor: pointer;
}
#add, #modify {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Homework 12 - Simple TODO List</title>
<link rel="stylesheet" href="./assets/styles.css">
</head>
<body>
<div id="root">
<!--Main page-->
<div id="index">
<h2>Simple TODO Application</h2>
<button class="button" id="addButton" onclick="show('add')">Add New Task</button>
<p id="emptyList">TODO is empty</p>
<ul id="list">
<li id="item_template" style="display: none">
<input class="checkbox" type="image" alt="checkbox" src="https://image.ibb.co/nqRqUp/todo_s.png" onclick="checkItem(this)">
<label onclick="modifyItem(this)"></label>
<input id="delete" class="delete" type="image" alt="remove" src="https://image.ibb.co/dpmqUp/remove_s.jpg" onclick="deleteItem(this)">
</li>
</ul>
</div>
<!--Add page-->
<div id="add">
<h2>Add Task</h2>
<input type="text" id="toDoEl">
<button class="button cancel" onclick="show('index')">Cancel</button>
<button class="button save" onclick="addTask()">Save changes</button>
</div>
<!--Modify page-->
<div id="modify">
<h2>Modify item</h2>
<input type="text" id="editTask">
<button class="button cancel" onclick="show('index')">Cancel</button>
<button class="button save" onclick="modifyTask()">Save changes</button>
</div>
</div>
<script src="./src/app.js"></script>
</body>
</html>
Your code does appear to work. If you console.log(JSON.parse(localStorageItems)) right above line 49 in the loadFromLocalStorage function, it shows as expected in the console. Also, upon refreshing the items persist.
If what you mean is that you're checking localStorage and you don't see the items, it might be that you're looking at the preview version of localStorage. (I'm assuming you're using Chrome.) Hover over the top of the empty section and pull down, this should reveal the values stored. If you click on one, it should show in the preview section. I think this was a Chrome dev tools UI change recently implemented.
I checked your code in Codepen and it works.
I have a grid and when selecting an item in it, i want to add different classes to every column that is before or after the current item. I came up with the following function to do this, but wondering if theres an easier and simpler way to do this:
var items = document.querySelectorAll('.item');
var bodyWidth = 200;
var itemWidth = 50;
var itemsInRow = Math.floor(bodyWidth/itemWidth);
var activeItemIndexInRow;
var directionClass;
var otherItemIndexInRow;
var removeClasses = function(){
items.forEach(function (item, i) {
item.className = 'item';
});
}
items.forEach(function (selectedItem, selectedItemIndex) {
selectedItem.addEventListener('click', function(event) {
removeClasses();
activeItemIndexInRow = selectedItemIndex-Math.floor(selectedItemIndex/itemsInRow)*itemsInRow;
selectedItem.classList.add('active');
items.forEach(function (otherItem, otherItemIndex) {
otherItemIndexInRow = otherItemIndex-Math.floor(otherItemIndex/itemsInRow)*itemsInRow;
if(otherItemIndexInRow < activeItemIndexInRow) directionClass = 'green';
if(otherItemIndexInRow === activeItemIndexInRow) directionClass = 'red';
if(otherItemIndexInRow > activeItemIndexInRow) directionClass = 'blue';
otherItem.classList.add(directionClass);
});
});
});
* {
margin:0;
padding:0;
}
#wrapper {
width: 400px;
}
.item {
width:25%;
background:gray;
text-align:center;
height:100px;
line-height:100px;
color:#fff;
font-size:30px;
float:left;
}
.item.green {background:green}
.item.red {background:red}
.item.blue {background:blue}
.item.active {background:black}
<div id="wrapper">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div><div class="item">9</div><div class="item">10</div>
</div>
This should work.
var items = document.querySelectorAll('.item');
var itemsInRow = 4;
items.forEach(function(selectedItem, selectedItemIndex) {
selectedItem.addEventListener('click', function(event) {
var directionClass;
selectedItem.classList.add('active');
var selectedCol = selectedItemIndex % itemsInRow;
items.forEach(function(otherItem, otherItemIndex) {
otherItem.className = 'item';
var otherCol = otherItemIndex % itemsInRow;
if (otherItemIndex === selectedItemIndex) directionClass = 'active';
else if (otherCol === selectedCol) {
directionClass = 'red';
} else {
directionClass = selectedCol < otherCol ? 'blue' : 'green'
}
otherItem.classList.add(directionClass);
});
});
});
* {
margin: 0;
padding: 0;
}
#wrapper {
width: 400px;
}
.item {
width: 25%;
background: gray;
text-align: center;
height: 100px;
line-height: 100px;
color: #fff;
font-size: 30px;
float: left;
}
.item.green {
background: green
}
.item.red {
background: red
}
.item.blue {
background: blue
}
.item.active {
background: black
}
<div id="wrapper">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
I got a variable that represents required number of items and counting of dropped items inside droppable area. You can view example here. So what I want is to pass a variable to javascript and then calculate the difference.
I put my variable into div:
<div id="numbr" >10</div>
And here is the js code which counts dropped items and displays the total:
var n = $(this).closest("div.proc").find(".dropClass").length -1;
$(this).closest("div.proc").find("div.dropped").text("Items Dropped: " + n + ".");
My goal is to find differences between <div class="numbr"> and n, and then display it. How can I achieve this in js?
It is just an example.In my system, the number is a php variable received from user's input. There could be more than 2 boxes: it depends on user's input.
Try the following in both the drop event and the click event:
var proc = $(this).closest("div.proc");
proc.find('.dif').text('Difference ' +(proc.find('.numbr').text() - n));
demo: https://jsfiddle.net/d1ddsj8m/2/
var itm = [];
$("#savebutton").click(function() {
LISTOBJ.saveList();
});
$("#myAccordion").accordion({
heightStyle: "content",
active: false,
collapsible: true
});
$("#myAccordion li").draggable({
appendTo: "body",
helper: "clone",
start: function(ev, ui) {
ui.helper.width($(this).width());
}
});
$(".projLeader ol").droppable({
tolerance: 'pointer',
hoverClass: 'highlight',
drop: function(ev, ui) {
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false) {
var item = ui.draggable;
if (!ui.draggable.closest('.placeholder').length) item = item.clone().draggable(); // if item was dragged from the source list - clone it
//this.innerHTML = ''; // clean the placeholder
item.addClass('dropClass').appendTo(this);
// append item to placeholder
//add to array
itm.push(zz);
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find(".dropped").text("Items Dropped: " + n + ".");
$(this).closest("div.proc").find('.dif').text('Difference ' + ($(this).closest("div.proc").find('.numbr').text() - n));
} else {
alert('Name is Already Exist');
}
}
});
$(".projLeader").on('click', '.closer', function() {
var item = $(this).closest('.item');
var element = $("#myAccordion ul li").filter(function() {
return $(this).text() == item.text();
});
itm.splice(item);
var n = $(this).closest("div.proc").find(".dropClass").length - 1;
$(this).closest("div.proc").find("div.dropped").text("Items Dropped: " + n + ".");
$(this).closest("div.proc").find('.dif').text('Difference ' + ($(this).closest("div.proc").find('.numbr').text() - n));
item.fadeTo(200, 0, function() {
item.remove();
})
});
var LISTOBJ = {
saveList: function() {
var listCSV = "";
$(".projLeader li").each(function() {
if (listCSV === "") {
listCSV = $(this).text();
} else {
listCSV += ", " + $(this).text();
}
$("#output").text(listCSV);
$(".hiddenListInput").val(listCSV);
});
}
}
body {
font-family: verdana;
font-size: 12px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
margin-bottom: 10px;
}
ol {
list-style-type: none;
}
.item {
height: 20px;
width: 180px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.item .closer {
position: absolute;
right: 5px;
top: 2px;
font: bold 14px arial;
color: #666;
padding: 1px 3px;
line-height: 1;
cursor: pointer;
display: none;
}
.item .closer:hover {
color: #000;
}
.placeholder {
height: 30px;
width: 195px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.placeholder .item {
margin: 0;
}
ol .item .closer {
display: block;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
}
.dropClass {
background-color: lightblue;
padding-left: 10px;
width: 180px;
border: 1px solid black;
border-radius: 8px;
margin-bottom: 5px;
}
.dropped {
display: inline;
}
.dif {
display: inline;
}
.numbr {
display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.0/jquery-ui.min.js" integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E=" crossorigin="anonymous"></script>
<h1 class="ui-widget-header">Products</h1>
<div id="myAccordion">
<h3>T-Shirts</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Lolcat Shirt</li>
<li class="item"><span class="closer">x</span>Cheezeburger Shirt</li>
<li class="item"><span class="closer">x</span>Buckit Shirt</li>
</ul>
</div>
<h3>Bags</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Zebra Striped</li>
<li class="item"><span class="closer">x</span>Black Leather</li>
<li class="item"><span class="closer">x</span>Alligator Leather</li>
</ul>
</div>
<h3>Gadgets</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>iPhone</li>
<li class="item"><span class="closer">x</span>iPod</li>
<li class="item"><span class="closer">x</span>iPad</li>
</ul>
</div>
</div>
<div class='proc'><pre>
<br /></pre>
<div class="projLeader">
<label>Box1. Required number:
<div class="numbr">10</div>.
<div class="dropped"></div>
<div class="dif">Difference:</div>
</label>
<div class="ui-widget-content">
<ol>
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput1" />
</ol>
</div>
</div>
</div>
<div class='proc'><pre>
<br /></pre>
<div class="projLeader">
<label>Box2. Required number:
<div class="numbr">5</div>.
<div class="dropped"></div>
<div class="dif">Difference:</div>
</label>
<div class="ui-widget-content">
<ol>
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput1" />
</ol>
</div>
</div>
</div>
<br/>
<input type="submit" id="savebutton" class="button" value="Save" onclick="userSubmitted = true;" />
<div id="output"></div>
It looks like you are using jQuery, which makes it really easy to manipulate the DOM dynamically.
Here is what I would do. First, add a difference div which will hold the difference of n and numbr:
<div id="numbr">10</div>
<div id="difference"></div>
And in your JS, calculate the difference and add it to the div:
var n = $(this).closest("div.proc").find(".dropClass").length - 1;
var difference = parseInt($('#numbr').text(), 10) - n;
if (difference >= 0) {
$('#difference').text('Difference ' + difference);
}
Do you mean that you can use a PHP variable in javascript. If that's the case, this is probably what you are looking for:
<?php
$myVariable = 200;
?>
<script type="text/javascript">
$(document).ready(function () {
var myvar = <?= $myVariable; ?>;
$(document).on('change', '.numbr', function () {
var number = parseInt($(this).text(), 10);
var difference = myvar - number;
$('.somediv').text($difference);
});
});
</script>
<div class="numbr">20</div>
To get the dropClass content, use the text() method. length will give you the number of nodes for the given selector, it's not what you want here.
You can get the numbr and dropClass content with the text() method.
Try this(added some html for the snippet to work):
inner = $('#innerproc').closest("div.proc");
numbr = $('#numbr').text();
n = inner.find(".dropClass").text();
inner.find("div.dropped").text("Items Dropped: " + (n - numbr) + ".");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="numbr">10</div>
<div class="proc">
<div id="innerproc"></div>
<div class="dropClass">21</div>
<div class="dropped"></div>
</div>
Javascript report designer should allow to create copies of selected divs into same panel.
I tried to use
function DesignerClone() {
$(".ui-selected").each(function () {
var newDiv = $(this).prop('outerHTML'),
parentpanel = $(this).parent(".designer-panel-body");
parentpanel.prepend(newDiv);
});
}
but all divs are lost. and empty panel appears.
To reproduce, run code snippet and select some divs by mouse click.
After that press clone button.
How to clone boxes ?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<style>
.designer-panel-body {
min-height: 1px;
overflow: hidden;
margin: 0;
padding: 0;
}
.panel-footer {
background-color: inherit;
}
.designer-panel,
.designer-resetmargins {
margin: 0;
padding: 0;
}
.designer-verticalline,
.designer-horizontalline,
.designer-rectangle {
font-size: 1pt;
border: 1px solid #000000;
}
.designer-field {
border: 1px solid lightgray;
white-space: pre;
overflow: hidden;
}
.ui-selecting {
background-color: lightskyblue;
color: white;
}
.ui-selected {
background-color: lightskyblue;
border-color: darkblue;
color: white;
}
.designer-label {
white-space: pre;
}
.designer-field,
.designer-label {
font-family: "Times New Roman";
font-size: 10pt;
z-index: 2;
}
.designer-verticalline,
.designer-horizontalline,
.designer-rectangle,
.designer-field,
.designer-image,
.designer-label {
position: absolute;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
function DesignerClone() {
$(".ui-selected").each(function () {
var newDiv = $(this).prop('outerHTML'),
parentpanel = $(this).parent(".designer-panel-body");
parentpanel.prepend(newDiv);
});
}
function getpos(e) {
return {
X: e.pageX,
Y: e.pageY
};
}
function Rect(start, stop) {
this.left = Math.min(start.X, stop.X);
this.top = Math.min(start.Y, stop.Y);
this.width = Math.abs(stop.X - start.X);
this.height = Math.abs(stop.Y - start.Y);
}
$(function () {
var startpos;
var selected = $([]),
offset = {
top: 0,
left: 0
};
$(".designer-verticalline, .designer-rectangle, .designer-field, .designer-image").resizable();
var $liigutatavad = $(".designer-verticalline, .designer-horizontalline, .designer-rectangle, .designer-field, .designer-image, .designer-label");
$liigutatavad.draggable({
start: function (event, ui) {
var $this = $(this);
if ($this.hasClass("ui-selected")) {
// if this is selected, attach current offset
// of each selected element to that element
selected = $(".ui-selected").each(function () {
var el = $(this);
el.data("offset", el.offset());
});
} else {
// if this is not selected, clear current selection
selected = $([]);
$liigutatavad.removeClass("ui-selected");
}
offset = $this.offset();
},
drag: function (event, ui) {
// drag all selected elements simultaneously
var dt = ui.position.top - offset.top,
dl = ui.position.left - offset.left;
selected.not(this).each(function () {
var $this = $(this);
var elOffset = $this.data("offset");
$this.css({
top: elOffset.top + dt,
left: elOffset.left + dl
});
});
}
});
// ...but manually implement selection to prevent interference from draggable()
$(".designer-panel-body").on("click", "div", function (e) {
if ( /*!e.metaKey &&*/ !e.shiftKey && !e.ctrlKey) {
// deselect other elements if meta/shift not held down
$(".designer-panel-body").removeClass("ui-selected");
$(this).addClass("ui-selected");
} else {
if ($(this).hasClass("ui-selected")) {
$(this).removeClass("ui-selected");
} else {
$(this).addClass("ui-selected");
}
}
});
$(".designer-panel-body").selectable({});
});
</script>
</head>
<body>
<button type="button" class="btn btn-default" onclick="javascript:false;DesignerClone()">
<span class="glyphicon glyphicon-paste"></span>
</button>
<div class='panel designer-panel'>
<div class='panel-body designer-panel-body panel-warning' style='height:4cm'>
<div class='designer-field' contenteditable='true' style='top:2.30cm;left:5.84cm;width:10.24cm;height:0.63cm;font-family:Arial;font-size:14pt;font-weight:bold;'>vnimi+' '+dok.tasudok</div>
<div class='designer-field' contenteditable='true' style='top:2.30cm;left:16.37cm;width:2.68cm;height:0.61cm;font-size:14pt;'>DOK.kuupaev</div>
<div class='rectangle' style='border-width: 1px;background-color:#FFFFFF;top:2.99cm;left:1.34cm;width:18.05cm;height:5.29cm'></div>
<div class='designer-field' contenteditable='true' style='top:3.01cm;left:1.53cm;width:9.71cm;height:0.55cm;font-size:12pt;'>m.FIRMA</div>
<div class='designer-field' contenteditable='true' style='top:3.01cm;left:12.13cm;width:3.13cm;height:0.53cm;font-size:12pt;'>ise.telefon</div>
</div>
<div class='bg-warning'>
<div class='panel-footer'><i class='glyphicon glyphicon-chevron-up'></i> GroupHeader 1: str(dokumnr)+str(koopia,2)</div>
</div>
</div>
</body>
</html>
.appendTo takes selected element and removes it from previous position in the DOM.
jQuery.clone() is what you might be looking for.