I have the following markup in foreach :
#foreach($addedToCart as $item)
<tr class="cart-row">
<td>{{ $item->product->name }}</td>
<td>{{ $item->product->price }}</td>
<td>
<div class="value-button" id="decrease" onclick="decreaseValue()" value="Decrease Value">-</div>
<input type="text" id="number" class="totalQuantity" value="1" />
<div class="value-button" id="increase" class="increase" data-unit-price="{{ $item->product->price }}" onclick="increaseValue()" value="Increase Value" data-value="1">+</div>
</td>
</tr>
#endforeach
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<h3>Total Amount : $ <span id="totalAmount"> 0</span></h3>
</div>
Jquery :
$('#increase').on("click", function () {
var st = 0;
$('.cart-row').each(function () {
var i = $('#increase', this);
var up = $(i).data('unit-price');
var q = $('.totalQuantity').val();
st = st + (up * q);
});
$('#totalAmount').text(st);
});
The issue is that, It only works for only first row.
The <tr></tr> is in foreach and every tr have class cart-row.
What am i missing ?
Its working on 1st element only because there must be only one ID in a DOM. If you put more than one then it will consider the 1st one from top in the DOM.
From the code you have posted, I can see that you have also binded class with the same name. So if you use it as a selector in your jquery code it will work fine.
$('.increase').on("click", function () {
var st = 0;
$('.cart-row').each(function (i, obj) {
var up = $('.cart-row:eq('+i+')').find('.increase').data('unit-price');
var q = $('.cart-row:eq('+i+')').find('.totalQuantity').val();
st = st + (up * q);
});
$('#totalAmount').text(st);
});
Related
I seem to be struggling with getting this "financial tracker" to work. It's supposed to take all of a class's value ($0.00 +) and add it together. The list can grow by creating more '.cost' and add as many items that cost up to $9999. It will then replace the value of "debit".
My problem is that I can't use innerHTML to get/retrieve or replace any values or edit the html directly. I've tried from using .firstChild to .value, converting to global variables. I feel like I'm not understanding "appendChild" enough as I can't figure out how to change innerHTML without using innerHTML in this case.
This is for homework so I'd much rather have a description than just code and nothing to explain so I can progress and learn! I've spent days searching everywhere for this issue and nothing has quite solved it. My code is below:
var purchases = document.querySelector('tbody');
var debit = document.querySelector('.debits');
var credit = document.querySelector('.credits');
var purchCount = 0;
document.querySelector('.frm-transactions').addEventListener('submit', function (evt) {
let div,
checkbox,
label,
labelText,
purchText,
type,
trash;
labelText = evt.target.elements['description'].value;
type = evt.target.elements['type'].value.trim();
amount = evt.target.elements['currency'].value;
purchCount += 1;
if (labelText === '') {
labelText = 'Transaction ' + (purchCount);
}
tr = document.createElement('tr');
td1 = document.createElement('td');
td2 = document.createElement('td');
td3 = document.createElement('td');
td4 = document.createElement('td');
i = document.createElement('i');
label = document.createElement('label');
purchText = document.createTextNode(labelText);
typeText = document.createTextNode(type);
cost = document.createTextNode("$" + amount);
label.setAttribute('for', 'todo-' + purchCount);
tr.appendChild(td1).setAttribute('class', 'weee');
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
td1.appendChild(purchText);
td2.appendChild(typeText);
td2.setAttribute('class', type);
td3.appendChild(cost);
td3.setAttribute('class', 'cost');
td4.appendChild(i).setAttribute('class', 'delete fa fa-trash-o');
tr.appendChild(label);
purchases.appendChild(tr);
if (td2.classList == "debit") {
var totalamount = document.querySelector('input[name="currency"]').value;
var sum = 0;
for (var i = 0; i < totalamount.length; i++) {
sum += totalamount;
}
console.log(totalamount);
debit.firstChild.nodeValue += sum;
console.count(sum);
} else if (td2.classList == "credit") {
console.log(td2);
} else {
console.log('error');
}
evt.target.reset();
evt.preventDefault();
});
Example of the generated HTML:
<section class="wrapper">
<h1>Transaction Tracker</h1>
<form class="frm-transactions">
<fieldset>
<legend>Add Transaction</legend>
<div class="frm-group">
<input class="frm-control" type="text" name="description" size="30" placeholder="description" />
</div>
<div class="frm-group">
<select class="frm-control" name="type">
<option value="">type</option>
<option value="debit">debit</option>
<option value="credit">credit</option>
</select>
</div>
<div class="frm-group">
<i class="edit fa fa-dollar"></i>
<input class="frm-control" type="number" name="currency" min="0" max="9999" step="0.01" size="4" placeholder="0.00" />
</div>
<div class="frm-group">
<input class="frm-control" type="submit" value="add" />
</div>
<div class="error"></div>
</fieldset>
</form>
<h2>Transactions</h2>
<table class="transactions">
<thead>
<tr>
<td colspan="4" class="right">
Total debits: <span class="total debits">$0.00</span>
Total credits: <span class="total credits">$0.00</span>
</td>
</tr>
<tr>
<th>Description</th>
<th>Type</th>
<th class="amount">Amount</th>
<th class="tools">Tools</th>
</tr>
</thead>
</table>
</section>
Update, I'm now trying to figure out why the outcome of sum is showing in decimal places/duplicating itself.
Do you have to construct the DOM with JS?
The only way to get the value of a DOM element without innerHTML() is by using element.value. This means the value="some number" on the element itself must be set.
If you have to use your code to generate the HTML, adding a sample of what that HTML looks like would be nice so it is easier to reference instead of parsing it from your code.
As a side note, variable names like "ttt" are generally frowned upon.
Try to stick to normal human readable names that follow this structure: myVariableDoesThings.
EDIT: For your sum issue:
sum += totalamount; is incorrect. You are adding all of the elements to sum with that code.
If you change up your loop to the following it should work (was not sure how to post this without the example, you were also incorrectly adding a .value to your query selector):
var totalamount = document.querySelector('input[name="currency"]');
var sum = 0;
totalamount.forEach(element => sum += element.value);
forEach is like your for loop, but it passes the current item being iterated over into a lambda expression. To keep the for loop, you use totalAmount[i].value to access the current item in the iteration.
Have php foreach in file
<?php
foreach($_SESSION['cart'] as $item):
$sqlcartprod = mysqli_query(db(),"SELECT * FROM products WHERE id='".$item['product']."' ");
$rowcartprod = mysqli_fetch_array($sqlcartprod);
?>
<tr>
<td class="shoping__cart__item">
<img src="<?=$rowcartprod['ikonka']?>" width="101" alt="">
<h5><?=$rowcartprod['name_'.$lang]?></h5>
</td>
<td class="shoping__cart__price" >
<span id="priceprod"><?=$rowcartprod['price']?></span> azn
</td>
<td class="shoping__cart__quantity">
<div class="quantity">
<div class="pro-qty">
<input type="text" style="cursor: default" readonly value="<?=$item['qty']?>">
</div>
</div>
</td>
<td class="shoping__cart__total" id="totalprice">
<?=$item['price']*$item['qty']?> azn
</td>
</tr>
<?php endforeach; ?>
for this piece of code:
<div class="quantity">
<div class="pro-qty">
<input type="text" style="cursor: default" readonly value="<?=$item['qty']?>">
</div>
</div>
have JS code:
var proQty = $('.pro-qty');
proQty.prepend('<span class="dec qtybtn">-</span>');
proQty.append('<span class="inc qtybtn">+</span>');
proQty.on('click', '.qtybtn', function () {
var $button = $(this);
var oldValue = $button.parent().find('input').val();
if ($button.hasClass('inc')) {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find('input').val(newVal);
var Price = document.getElementById('priceprod').innerText;
var Tprice = document.getElementById('totalprice');
if (Price[i] > 0) {
Tprice.textContent = (Price[i] * newVal) + ' azn';
}
});
The issue is that when I click on qtybtn + or qtybtn -, the js code works only for the first product in the shopping list, even if there are 2,3 or more products in the list. I tried to separate inside the js code with loops, but then the js code somehow stops working at all. How to distribute correctly so that the js code works for each product separately?
I am writing and application using AngularJs, HTML and PHP. In the application I have a dropdown list, which when an option is selected a table is populated with related data drawn from a database. I can add to or delete info from the table. That works perfectly. However, the challenge I have is that each time the table is edited, the web page refreshes/route is reloaded and the drop down list returns to its default value. The effect of this is the user having to manually reselect the dropdown list value to carryout each operation on the table.
How can I alter the code to keep/persist the last selected option value and have the said dropdown list option selected when the webpage/route reloads?
I have seen many help responses to setting initial default value for dropdown lists. However that is not what I am trying to achieve. I am trying to set the post reload value or value after the webpage reloads.
Below is a part of what I have tried. I am at my whits end trying to figure it out. Any help is appreciated.
EDIT
Problem Solved
HTML before changes
<select id="b_year" ng-options="b.year for b in budgets track by b.year" ng-model="b.selectedBudget" ng-change="getBudgetItems(b.selectedBudget.year)" required><option value="">-- Choose budget year --</option></select>
HTML with solution changes
<select id="b_year" ng-options="b.year for b in budgets" ng-model="b.selectedBudget" ng-init="b.selectedBudget" ng-selected="getBudgetItems(b.selectedBudget.year)" required><option value="">-- Choose budget year --</option></select>
Controller snippet before changes
$scope.reloadRoute();
$scope.items.push({'line_item': li.line_item, 'weight': li.weight, 'allocated': li.allocated});
localStorage['b_year'] = year; //Store the selected year in local storage for later use
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if($scope.budgets[i].year === localStorage['b_year']){
$scope.b.selectedBudget[i] = localStorage['b_year'];
}else{
}
}
Controller with solution changes
app.controller(.... {
....
(function(){
$http.get( //Get info on budgets
"http://localhost/TrGway/getbudgetinfo.php"
)
.success(function(data){
$scope.budgets = data.budgets;
for(var i = 0; i < data.budgets.length; i++){
if($scope.budgets[i].year === selectedYear){
$scope.b = {};
$scope.b.selectedBudget = $scope.budgets[i];
}
}
})
.error(function(data){
$scope.message = "Error!! Getting Budget Info Failed: " + data;
});
})();
....
$scope.$watch("b.selectedBudget.year", function(item) {
localStorage.setItem("selectedYear", item);
});
});
App.controller('budgetCtrl', ['$scope', '$http', '$location', '$window', '$route', 'BudgetService', function($scope, $http, $location, $window, $route, BudgetService){
(function(){
$http.get( //Get info on budgets
"http://localhost/TrGway/getbudgetinfo.php"
)
.success(function(data){
server.setBudgets(data.budgets);//Set the budget info in the BudgetService for
//later usage anywhere in the program;
$scope.budgets = data.budgets;
budget_size = server.getBudgetSize();
server.getBudgetInfo();
})
.error(function(data){
$scope.message = "Error!! Getting Budget Info Failed: " + data;
});
})();
(function(){ //Get Line Items Info to populate the table
$http.get(
"http://localhost/TrGway/lineItemInfo.php"
)
.success(function(data){
server.setLineItems(data.items);
$scope.items = data.items;
server.getLineItemsInfo();
})
.error(function(data){
$scope.message = "Error!! Getting Line Items Info Failed: "+data;
});
})();
$scope.addBudget = function(budget){
if( budget.year < new Date().getFullYear() ){
alert("Budgets cannot be created retroactively.\n\
\nPlease enter a budget year greater than "+ new Date().getFullYear() );
$scope.budget.year = "";
}else{
server.addBudget(budget);
server.getBudgetInfo();
$scope.budgets = server.getBudgets();
$scope.budget = {};//Clear the add budget form
}
};
$scope.getBudgetItems = function(year){
/*This is where info on the budget for the selected year is retrieved and passed to the table
This works great every time*/
if( year === undefined ){ //If no year is selected do nothing
$scope.budget_amount = 0;
$scope.budget_amount_used = 0;
$scope.budget_amount_remaining = 0;
}else{
Budgets = server.getBudgets();
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if(Budgets[i].year === year){
$scope.budget_amount = Budgets[i].starting_amount;
$scope.budget_amount_used = Budgets[i].amount_used;
$scope.budget_amount_remaining = Budgets[i].running_balance;
amount_remaining = Budgets[i].starting_amount - Budgets[i].amount_used;
percent_used += (Budgets[i].amount_used / Budgets[i].starting_amount * 100);
server.setSelectedBudget(Budgets[i]);
}else{
//$scope.budget_amount = 0;
}
}
server.setPercentUsed(percent_used);
server.setPercentRemaining( 100 - percent_used);
server.setAmountRemaining(amount_remaining);
}
};
/*======================= THIS IS WHERE THE CHALLENGE IS ====================*/
$scope.addLineItem = function(li, b){
/*This is where the List items are added to the table before page reload*/
if(($scope.budget_amount_used-0 + li.allocated-0) > $scope.budget_amount){
alert("Budgeted amount exceeded!!!\nPlease consider revising");
$location.path('editbudget');
$scope.li.weight = 0;
$scope.li.allocation = 0;
}else{
server.setSelectedBudgetYear(b.selectedBudget.year); //Save selected year to a variable
server.addLineItem(li, b); //Add the new Line items row to database
$scope.reloadRoute();
$scope.items.push({'line_item': li.line_item, 'weight': li.weight, 'allocated': li.allocated});
$scope.b = {};
//$scope.b.selectedBudget = localStorage.getItem("selected");
$scope.$watch("b.selectedBudget.year", function(item) {
localStorage.setItem("selected", item);
});
//$scope.b.selectedBudget.year = server.getSelectedBudgetYear(); //I tried this also
}
$scope.li.line_item = "";
$scope.li.weight = 0;
$scope.li.allocation = 0;
$scope.b.selectedBudget = localStorage.getItem("selected");
/* LEAVING THIS SO YOU CAN SEE WHAT ELSE I HAVE TRIED
$scope.b = {};
$scope.b.selectedBudget = localStorage.getItem("selectedBudget");
$scope.watch("b.selected", function(item) {
localStorage.setItem("selected", item);
});
$scope.b.selectedBudget = localStorage['b_year'];
*/
/* LEAVING THIS SO YOU CAN SEE WHAT ELSE I HAVE TRIED
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if($scope.budgets[i].year === server.getSelectedBudgetYear()){
$scope.b.selectedBudget.year = server.getSelectedBudgetYear();
}else{
}
}*/
};
$scope.deleteLineItem = function(row, b){
$http({
method: "post",
url: "http://localhost/TrGway/deleteLineItem.php",
crossDomain: true,
data:{
'seq': row.seq,
'year': row.year,
'allocated':row.allocated,
'starting_amount': b.selectedBudget.starting_amount,
'amount_used': b.selectedBudget.amount_used,
'running_balance': b.selectedBudget.running_balance
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
var index = -1;
var itemsArr = eval( $scope.items );
for( var i = 0; i < itemsArr.length; i++ ) {
if( itemsArr[i].seq === row.seq ) {
index = i;
break;
}
}
if( index === -1 ) {
alert( "Something has gone wrong!!\nLine item was not deleted.\nPlease try again" );
}
server.reset();
server.reload();
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;
$scope.budget_amount_used = server.getAmountUsed()-0;
$scope.budget_amount_remaining = server.getAmountRemaining()-0;
server.setTotalWeighting($scope.totalweighting + row.weight)-0;
server.setPercentUsed(server.getTotalWeighting())-0;
server.setPercentRemaining(100 - server.getPercentUsed())-0;
$scope.items.splice( index, 1 ); //Remove the row with matching index/seq value
$scope.totalweighting = server.getTotalWeighting();
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;*/
$scope.reloadRoute();
}else{ //If deleting the line item failed
$location.path('editbudget');
$scope.budgetmessage = "Line Item Update Failed: "+response;
}
})
.error(function(response){ //If there was an error connecting to the server
$scope.budgetmessage = "Error!! Updating Line Item Failed: "+response;
});
row.isEditing = false;
};
$scope.updateLineItem = function(row){
$http({
method: "post",
url: "http://localhost/TrGway/updateLineItem.php",
crossDomain: true,
data:{
'seq': row.seq,
'line_item': row.line_item,
'weight': row.weight,
'allocated': row.allocated
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
$location.path('editbudget');
}else{
$location.path('editbudget');
$scope.budgetmessage = "Line Item Update Failed: "+response;
}
})
.error(function(response){
$scope.budgetmessage = "Error!! Updating Line Item Failed: "+response;
});
row.isEditing = false;
};
$scope.cancelLineItemEditing = function(row){
row.isEditing = false;
};
$scope.updateBudget = function(b){
$http({
method: "post",
url: "http://localhost/TrGway/updatebudget.php",
crossDomain: true,
data:{
'year': b.selectedBudget.year,
'starting_amount': b.edit_starting_amount
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
server.setStartingAmount(b.edit_starting_amount);
var line_items = server.getLineItems();
var start_amount = server.getStartingAmount();
var total_weight = 0;
var amount_used = 0;
var amount_remaining = 0;
var percent_used = 0;
var percent_remaining = 0;
for(var i = 0; i < line_items.length; i++){
//Update the line items on the page immediately
line_items[i].weight = ( line_items[i].allocated / start_amount) * 100;
total_weight += line_items[i].weight;
amount_used += line_items[i].allocated-0;
//Update the line items in the database immediately
$scope.updateLineItem(line_items[i]);
}
server.load();
percent_used = ( amount_used / start_amount) * 100;
amount_remaining = start_amount - amount_used;
percent_remaining = 100 - percent_used;
server.setLineItems(line_items);
server.setTotalWeighting(total_weight);
server.setAmountUsed(amount_used);
server.setPercentUsed(percent_used);
server.setAmountRemaining(amount_remaining);
server.setPercentRemaining(percent_remaining);
$scope.items = server.getLineItems();
$scope.total = 0;
$scope.total = server.getStartingAmount();
$scope.totalweighting = server.getTotalWeighting()-0;
$scope.budget_amount_used = server.getAmountUsed()-0;
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;
$scope.budget_amount_remaining = server.getAmountRemaining()-0;
$location.path('editbudget');
}else{
$location.path('editbudget');
$scope.budgetmessage = "Budget Update Failed: "+response;
}
})
.error(function(response){
$scope.budgetmessage = "Error!! Updating Budget Failed: "+response;
});
$scope.b = {};
};
$scope.reloadRoute = function(){
$route.reload();
server.reload();
//alert('Loaded!!');
};
}]);
<div class="breadcrumbs" id="breadcrumbs">
<ul class="breadcrumb">
<li>Home</li>
<li class="active">Add/Edit line Items</li>
<li style="float: right" ng-controller="authCtrl"><a ng-click="logout();">Logout</a></li>
<li style="float: right">Back</li>
</ul>
</div>
<div class="row" ng-cloak="" ng-controller="budgetCtrl">
<div class="col-md-5">
<section>
<form name="LineItemForm" class="form-horizontal" role="form">
<fieldset>
<table class="table table-striped">
<thead>
<tr>
<th style="width: 150px" colspan="1">Select Budget Year To Edit Line Items</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="1">
<div class="col-md-7">
<!-- THIS IS WHERE THE YEAR IS SELECTED -->
<select id="b_year" ng-options="b.year for b in budgets track by b.year" ng-model="b.selectedBudget" ng-change="getBudgetItems(b.selectedBudget.year);" ng-selected="" required>
<option value="">-- Choose budget year --</option>
</select>
</div>
</td>
</tr>
<tr>
<th style="width: 150px" colspan="1">{{b.budgetmessage}}</th>
</tr>
<tr>
<td>
<h3>Add Line Item Here</h3>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="line_item">Line Item</label>
<div class="col-md-7">
<input type="text" class="form-control" name="line_item" id="line_item" ng-model="li.line_item" ng-disabled="!b.selectedBudget" required/>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="weight">weighting %</label>
<div class="col-md-7">
<input type="number:2" class="form-control" name="weight" id="weight" ng-init="li.weight = 0" ng-model="li.weight" ng-disabled="!b.selectedBudget || !li.line_item || li.line_item.length<5" required/>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="allocated">Allocated $</label>
<div class="col-md-7">
<input type="number:2" class="form-control" name="allocated" id="allocated" placeholder="{{li.allocated = (budget_amount * li.weight) / 100 | currency}}" ng-init="li.allocated=0" ng-model="li.allocated" ng-disabled="!b.selectedBudget || !li.weight" required />
</div>
</div>
<div class="form-group" style="padding-right: 100px;">
<span class="lbl col-sm-5"> </span>
<div class="col-md-7 message" >
<span id="message" class="block input-icon input-icon-right">{{message}}</span>
</div>
</div>
<div class="form-group">
<div style="padding-right:100px">
<button type="submit" class="width-35 pull-right btn btn-sm btn-primary" ng-click="addLineItem(li, b)" data-ng-disabled="LineItemForm.$invalid || li.weight===0 || li.line_item.length < 5">
Add Line Item
</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</fieldset>
</form>
</section>
</div>
<div>
<section>
<div class="col-lg-14" style="float: right">
<form>
<fieldset>
<table class="table table-striped" >
<thead>
<tr>
<!--<th>Index</th>-->
<th>Line Items</th><th style="width: 150px">% Weighting</th><th style="width: 150px">Allocation $</th><th style="width: 120px">Tasks</th><!---->
</tr>
</thead>
<tbody>
<tr data-ng-repeat="row in items" ng-model="items" ng-if="row.year === b.selectedBudget.year"><!--<td>{{$index+1}}</td>-->
<td title="'Line Item'" ng-switch="row.isEditing" ng-class="line_item.$dirty ? 'bg-warning' : ''" ng-form="name" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{row.line_item}}</span>
<div class="controls" ng-class="line_item.$invalid && line_item.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="line_item" ng-model="row.line_item" class="editable-input form-control input-sm" required />
</div>
</td>
<td>{{ row.weight = row.allocated / budget_amount * 100 | number: 2 }}</td>
<td title="'Allocation'" ng-switch="row.isEditing" ng-class="allocated.$dirty ? 'bg-warning' : ''" ng-form="allocated" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{ row.allocated | currency }}</span>
<div class="controls" ng-class="allocated.$invalid && allocated.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="allocated" ng-model="row.allocated" class="editable-input form-control input-sm" required/>
</div>
</td>
<td>
<button class="btn btn-primary btn-sm" ng-click="updateLineItem(row)" ng-if="row.isEditing" ng-disabled="rowForm.$pristine || rowForm.$invalid"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-default btn-sm" ng-click="cancelLineItemEditing(row)" ng-if="row.isEditing"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-default btn-sm" ng-click="row.isEditing = true" ng-if="!row.isEditing"><span class="glyphicon glyphicon-pencil"></span></button>
<button class="btn btn-danger btn-sm" ng-click="deleteLineItem(row, b)" ng-if="!row.isEditing"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>TOTAL (Budget Estimate)</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ totalweighting = budget_amount > 0 ? 100 : 0 | number:2 }}%</b><!---->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_amount | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>BUDGET AMOUNT USED</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_percent_used = budget_amount_used > 0 ? budget_amount_used * 100/budget_amount : 0 | number:2 }}%</b>
<!--Adding the -0 forces the compiler to treat the value as a number-->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<!--{{ budget_amount_used + li.allocated | currency }}-->
<b>{{ budget_amount_used | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>BUDGETED AMOUNT REMAINING</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_percent_remaining = 100 - budget_percent_used | number:2 }}%</b>
<!--Adding the -0 forces the compiler to treat the value as a number-->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<!--{{ budget_amount_remaining - li.allocated | currency }}-->
<b>{{ budget_amount_remaining | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
</tbody>
</table>
</fieldset>
</form>
</div>
</section>
</div>
</div>
I'd do something like this:
app.controller(.... {
....
$scope.b = {};
$scope.b.selected = localStorage.getItem("selected");
$scope.watch("b.selected", function(item) {
localStorage.setItem("selected", item);
});
....
});
EDIT
So we suspect that the initial value gets overwritten somewhere. Here is some help how to debug it: You can define a property setter on $scope.b, that could alert or break to debugger. Use something like this:
$scope.b = {
set selectedBudget(v) {
debugger;
// or alert(1);
}
};
Solution
This is the solution I came up with to keep the drop down list selection after webpage refresh. I hope this will help someone. I have added comments to help explain what I did. I hope they are clear. However, I welcome any correction or clarification. I was able to come up with this solution , thanks to help from #Tamas Hegedus, who pointed me in the right direction.
app.controller(.... {
....
(function(){
$http.get( //Get info on budgets
"http://localhost/TrGway/getbudgetinfo.php"
)
.success(function(data){
$scope.budgets = data.budgets; //assign array of elements to the scope variable
for(var i = 0; i < data.budgets.length; i++){ //Loop through each array element
if($scope.budgets[i].year === selectedYear){ //Check if any of the 'year' value in the array match the value stored in localStorage
$scope.b = {}; //reset the selected scope variable
$scope.b.selectedBudget = $scope.budgets[i]; //Assign the array element with the matching year, as the selected scope element
}
}
})
.error(function(data){
$scope.message = "Error!! Getting Budget Info Failed: " + data;
});
})();
....
$scope.$watch("b.selectedBudget.year", function(item) { //Set watch on array element 'year' for changes/selection
localStorage.setItem("selectedYear", item); //When an element is selected from the drop down list, its value is stored in localStorage
});
});
<select id="b_year" ng-options="b.year for b in budgets" ng-model="b.selectedBudget" ng-selected="getBudgetItems(b.selectedBudget.year)" required><option value="">-- Choose budget year --</option></select>
I have a problem, I coded table with some rows, and after that I need to swap some rows after click:
function move_up(x) {
var cur = x.parentNode.parentNode;
var cur_upd = cur.previousSibling.previousSibling;
var temp = cur.innerHTML;
cur.innerHTML = cur_upd.innerHTML;
cur_upd.innerHTML = temp;
}
function move_down(x) {
var cur = x.parentNode.parentNode;
var cur_upd = cur.nextSibling.nextSibling;
var temp = cur.innerHTML;
cur.innerHTML = cur_upd.innerHTML;
cur_upd.innerHTML = temp ;
}
I have table with rows like this:
<tr>
<TD >
Typ projektu 1
</TD>
<TD align="center">
<input type="text" class="order_num" name="x_order_num_PROJECT_TYPE" value="1">
<input type="checkbox" name="x_PROJECT_TYPE_on" checked>
</TD>
<td>
Hore
Dole
</td>
<TD align="LEFT">
<select class="selectbox" name="x_PROJECT_TYPE" style="width: 250px">
<OPTION VALUE="-1" SELECTED>Všetky</option>
<OPTION VALUE="1" SELECTED>Fixed price</option>
<OPTION VALUE="2">Time and materials</option>
</select>
</TD>
<TD>▲
<INPUT TYPE="radio" NAME="x_sort" VALUE="PROJECT_TYPE;asc">
<INPUT TYPE="radio" NAME="x_sort" VALUE="PROJECT_TYPE;desc">
▼
</TD>
</TR>
After I click on href 'Hore' or 'Dole' it look good, but problem is, that after swap column when I call form submit, it submit all imputs from all rows except swapped rows. Input from that rows is not submitted. What can be problem?
Don't use innerHTML to move the elements, just move the DOM elements themselves.
function move_up(x) {
var cur = x.parentNode.parentNode;
var cur_upd = cur.previousSibling.previousSibling;
var parent = cur.parentNode;
parent.insertBefore(cur, cur_upd);
}
function move_down(x) {
var cur = x.parentNode.parentNode;
var cur_upd = cur.nextSibling.nextSibling;
var parent = cur.parentNode;
parent.insertBefore(cur_upd, cur);
}
If there are any event listeners bound to elements, or the application has variables referencing them, converting them back and forth to HTML will lose that.
I have a table with different places, and implemented some simple buttons that allow you to filter the list. First filter is location (north, east, central, south, west) which is based on postcode. Another filter is on "impress". This shows you only the places that have have 4 or higher value in the column. Filters work great separately, but not together. The result that I am after is when I press "West" is shows me the places in "West, when I then click impress, I expect to see the places in west with a 4 or 5 score for impress.
JSFiddle here
$('.table td.postcode').each(function() {
var cellText = $(this).html();
var locationString = cellText.substring(0,2);
if (locationString.indexOf('W') > -1){
$(this).parent().addClass('west');
}
if (locationString.indexOf('C') > -1){
$(this).parent().addClass('central');
}
if (locationString.indexOf('E') > -1){
$(this).parent().addClass('east');
}
if (locationString.indexOf('S') > -1){
$(this).parent().addClass('south');
}
if (locationString.indexOf('N') > -1){
$(this).parent().addClass('north');
}
});
$("input[name='filterStatus'], select.filter").change(function () {
var classes = [];
$("input[name='filterStatus']").each(function() {
if ($(this).is(":checked")) {
classes.push('.'+$(this).val());
}
});
if (classes == "") {
// if no filters selected, show all items
$("#StatusTable tbody tr").show();
} else {
// otherwise, hide everything...
$("#StatusTable tbody tr").hide();
// then show only the matching items
rows = $("#StatusTable tr").filter(classes.length ? classes.join(',') : '*');
if (rows.size() > 0) {
rows.show();
}
}
});
$("input[name='impressStatus']").change(function(){
var classes = [];
$("input[name='impressStatus']").each(function() {
if ($(this).is(":checked")) {
classes.push('.'+$(this).val());
}
});
if(classes == ""){
$("#StatusTable tbody tr").show();
}
else{
$(".table td.impress").each(function(){
if($(this).data("impress") >= 4){
$(this).parent().show();
}
else{
$(this).parent().hide();
}
});
}
});
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--BUTTON FILTERS -->
<div class="btn-toolbar" role="toolbar" aria-label="...">
<div class="btn-group" style="" data-toggle="buttons">
<label class="btn btn-primary outline">
<input type="checkbox" name="filterStatus" value="north" autocomplete="off">North
</label>
<label class="btn btn-primary outline">
<input type="checkbox" name="filterStatus" value="east" autocomplete="off" class="radio">East
</label>
<label class="btn btn-primary outline">
<input type="checkbox" name="filterStatus" value="central" autocomplete="off" class="radio">Central
</label>
<label class="btn btn-primary outline">
<input type="checkbox" name="filterStatus" value="south"autocomplete="off" class="radio">South </label>
<label class="btn btn-primary outline">
<input type="checkbox" name="filterStatus" value="west" autocomplete="off" class="radio">West
</label>
</div><!-- button group -->
<label class="btn btn-primary outline">
<input type="checkbox" name="impressStatus" class="radio" aria-pressed="true" autocomplete="off">Impress her
</label>
</div><!-- btn toolbar-->
<!--TABLE -->
<table class="table" id="StatusTable">
<thead>
<tr>
<th data-sort="string" style="cursor:pointer">name</th>
<!-- <th>Description</th> -->
<th data-sort="string" style="cursor:pointer;">postcode</th>
<th data-sort="int" style="cursor:pointer;">price</th>
<th data-sort="int" style="cursor:pointer;">total</th>
<th data-sort="int" style="cursor:pointer;">impress</th>
<th colspan="4"></th>
</tr>
</thead>
<tbody>
<tr data-link="/places/1">
<td>Name of place 1</td>
<td class="postcode">NW1</td>
<td class="price" data-price='3'>3</td>
<td class="rating" data-rating='69'>69</td>
<td class="impress" data-impress='4'>4</td>
</tr>
<tr data-link="/places/2">
<td>Name of place 2</td>
<td class="postcode">E3</td>
<td class="price" data-price='4'>4</span></td>
<td class="rating" data-rating='89'>89</td>
<td class="impress" data-impress='5'>5</td>
</tr>
<tr data-link="/places/3">
<td>Name of place 3</td>
<td class="postcode">SW3</td>
<td class="price" data-price='2'>2</td>
<td class="rating" data-rating='51'>51</td>
<td class="impress" data-impress='3'>3</td>
</tr>
</tbody>
</table>
Code is probably not the most efficient, but it works :). Once I got this working, I want to add more filters.
(sorry for my bad english)
if these are the only filters you need, you can use two different type of filter:
hide via Javascript
hide via Css
if you use 2 types of filters the filters can work correctly without use a complex javascript code to manage a big number of different cases and combination:
I add a initial (on document load) control that check if a tr has the value impress cell >4, if has it add a new class: is_impress else add an other: no_impress.
$('.table td.impress').each(function(){
var _class = ($(this).data("impress") >= 4) ? "is_impress" : "no_impress";
$(this).parent().addClass(_class);
});
The code of filter by position is the same... but... I edit the filter by impress to add a class to table () when is active and take it off when isn't:
$("input[name='impressStatus']").change(function(){
(!$(this).is(":checked"))
? $("#StatusTable").removeClass("active_impress")
: $("#StatusTable").addClass("active_impress");
});
if the table has the class active_impress a css rules override the inline code of dispaly to hide all the row that haven't an impress >4:
#StatusTable.active_impress tr.no_impress{
display:none !important;
}
This type of filter override any other display modification until the checkbox stay checked.
I edit your fiddle:
https://jsfiddle.net/Frogmouth/gkba343L/1/
USE CSS to more filter
First change on load check, add price:
$('.table tbody tr').each(function(){
var _class = "";
_class += ($(this).find(".price").data("price") >= 2) ? "is_price " : "no_price ";
_class += ($(this).find(".impress").data("impress") >= 4) ? "is_impress " : "no_impress ";
console.log(_class);
$(this).addClass(_class);
});
Add an other handler to new filter:
$("input[name='priceStatus']").change(function(){
(!$(this).is(":checked"))
? $("#StatusTable").removeClass("active_price")
: $("#StatusTable").addClass("active_price");
});
add new selector to the css rule:
#StatusTable.active_impress tr.no_impress,
#StatusTable.active_price tr.no_price{
display:none !important;
}
This is the result:
https://jsfiddle.net/Frogmouth/gkba343L/3/
Optimize code to add more filter:
HTML filter button:
<label class="btn btn-primary outline">
<input type="checkbox" name="impress" class="cssFilter radio" aria-pressed="true" autocomplete="off">Impress her
</label>
use cssFilter to indicate that is a css filter button and use name attribute to define the name of the filter, than use this namespace into the css class:
.active_{name} .no_{name} .is_{name}
And use a generic handler:
$("input.cssFilter").change(function(){
var _name = $(this).attr("name");
console.log(_name);
(!$(this).is(":checked"))
? $("#StatusTable").removeClass("active_"+_name)
: $("#StatusTable").addClass("active_"+_name);
});
With this you can manage all the filter with an unique handler, remember to add the filter to onload check and the new selector for each new filter.
Fiddle:
https://jsfiddle.net/Frogmouth/gkba343L/4/