When I run this code, in Chrome's sources tool in inspect, it says number = undefined for line 7 (groceryList.forEach(function(number) {). The arguments are being passed properly and if I do a console.log for each item it shows properly. Having the same issue with the commented out .map section that does the same thing as foreach.
Can anyone tell me what I'm doing wrong?
//BUSINESS LOGIC
var alphabatize = function(item1,item2,item3,item4){
groceryList = [item1,item2,item3,item4];
groceryList.sort();
upperGroceryList = []
groceryList.forEach(function(number) {
console.log(number);
upperGroceryList.push(number.toUpperCase());
});
/* upperGroceryList = groceryList.map(function(grocery) {
console.log(grocery);
return grocery.toUpperCase();
}); */
return groceryList;
return upperGroceryList;
};
// FRONT END
$(document).ready(function() {
$("form#items-form").submit(function(event) {
event.preventDefault();
var item1 = $("input#item1").val();
var item2 = $("input#item2").val();
var item3 = $("input#item3").val();
var item4 = $("input#item4").val();
alphabatize(item1,item2,item3,item4);
upperGroceryList.forEach(function(currentItem) {
$("#display-list ul").append("<li>" + currentItem + "</li>");
});
});
})
You can't have two return statements from a function. Instead you can return an object contained both arrays like:
var obj = {
groceryList : groceryList,
upperGroceryList : upperGroceryList
};
return obj;
Then you can use this way:
var arr = alphabatize(item1, item2, item3, item4);
arr.upperGroceryList.forEach(function(currentItem) {
$("#display-list ul").append("<li>" + currentItem + "</li>");
});
There are several things here. Yyour function variables are never defined.
var alphabatize = function(item1,item2,item3,item4){
var groceryList = [item1,item2,item3,item4], //use comma to define more than one with one var statement.
upperGroceryList = []; //end var declaration with semicolon.
groceryList.sort();
groceryList.forEach(function(number) {
console.log(number);
upperGroceryList.push(number.toUpperCase());
});
/*
You cannot have return more than once in a function.
return groceryList;
return upperGroceryList;
*/
};
also your upperGroceryList forEach function should be inside of the alphabatize function.
so the full alphabatize function should look like this.
var alphabatize = function(item1,item2,item3,item4){
var upperGroceryList = [],
groceryList = [item1,item2,item3,item4];
groceryList.sort();
groceryList.forEach(function(number) {
console.log(number);
upperGroceryList.push(number.toUpperCase());
});
upperGroceryList.forEach(function(currentItem) {
$("#display-list").append("<li>" + currentItem + "</li>");
});
};
and our submit function looks like this.
$(function(){
$("#items-form").submit(function(event) {
event.preventDefault();
var item1 = $("#item1").val();
var item2 = $("#item2").val();
var item3 = $("#item3").val();
var item4 = $("#item4").val();
alphabatize(item1,item2,item3,item4);
});
});
Related
I have a JSON string:
var jsn = '{"header-v1":{"archives":{"is_author":"all"}},"header-v4":{"archives":{"is_author":"all"}}}';
This object is constantly updated and I want to remove duplicate values. For example, if it is:
var jsn = '{"header-v4":{"archives":{"is_author":"all"}}}';
And if the new rule set which should be added will be equal to
"header-v1":{"archives":{"is_author":"all"}}
then I want to remove "header-v4":{"archives":{"is_author":"all"}} from there, because there is a duplicate of {"archives":{"is_author":"all"}}.
Is that even possible with JavaScript?
var result = [];
$.each(subservices, function (i, e) {
var matchingItems = $.grep(result, function (item) {
return item.name === e.name && item.label === e.label;
});
if (matchingItems.length === 0){
result.push(e);
}
});
//displays result [{"name":"hello","label":"world"},{"name":"abc","label":"xyz"}]
alert(JSON.stringify(result));
JS fiddel
http://jsfiddle.net/defujjhp/
Maybe something like this you can do
var jsn = '{"header-v4":{"archives":{"is_author":"all"}}}';
var jsonObject = JSON.parse(jsn);
var newJsn = '{header-v1":{"archives":{"is_author":"all"}}}';
var newJsonObject = JSON.parse(newJsn);
var matchingKey = [];
Object.keys(newJsonObject).forEach(key => {
Object.keys(jsonObject).forEach(nkey => {
if(newJsonObject[key].toString() === jsonObject[nkey].toString()) {
matchingKey.push(nkey);
}
});
});
matchingKey.forEach(mkey => {
delete jsonObject[mkey];
});
I have a function that keeps repeating itself in my controller.
It looks like this:
//FUNCTION 1
$scope.selectedage = [];
$scope.pushage = function (age) {
age.chosen = true;
$scope.selectedage.push(age);
console.log($scope.selectedage);
};
$scope.unpushage = function (age) {
age.chosen = false;
var index=$scope.selectedage.indexOf(age)
$scope.selectedage.splice(index,1);
console.log($scope.selectedage);
}
//FUNCTION 2
$scope.selectedgender = [];
$scope.pushgender = function (gender) {
gender.chosen = true;
$scope.selectedgender.push(gender);
console.log($scope.selectedgender);
};
$scope.unpushgender = function (gender) {
gender.chosen = false;
var index=$scope.selectedgender.indexOf(gender)
$scope.selectedgender.splice(index,1);
console.log($scope.selectedgender);
}
I have it like 8 times for 8 different arrays.
Is there any way to write it once and reuse it just changing some values?
You can make a generic function that accepts a value (container) where it needs to write the "value". Like:
$scope.push = function(container, value){
value.chosen = true;
container.push(value);
console.log(container);
}
$scope.unpush = function(container, value){
value.chosen = false;
var index = container.indexOf(value)
container.splice(index, 1);
console.log(container);
}
//sample
$scope.push($scope.selectedage, 10);
$scope.push($scope.selectedgender, "Male");
function togglePushStatusOfItem(item, itemKey, chosenStatus){
item.status = chosenStatus;
if(chosenStatus == true){
$scope[itemKey].push(item);
} else {
var index=$scope[itemKey].indexOf(item)
$scope[itemKey].splice(index,1);
}
console.log($scope[itemKey]);
}
togglePushStatusOfItem(user, 'selectedAge',true);
refactoring code to be reused in service
(function() {
'use strict';
angular
.module('myApp')
.factory('ItemFactory', ItemFactory);
ItemFactory.$inject = [];
/* #ngInject */
function ItemFactory() {
var service = {
toggleItemStatus: toggleItemStatus
};
return service;
////////////////
/*
itemContainer - equivalent to scope
item - item to replace or push
itemKey - itemKey
chosenStatus - true to push and false to remove
*/
function toggleItemStatus(itemContainer, item, itemKey, chosenStatus) {
item.status = chosenStatus;
if (chosenStatus == true) {
itemContainer[itemKey].push(item);
} else {
var index = $scope[itemKey].indexOf(item)
itemContainer[itemKey].splice(index, 1);
}
console.log(itemContainer[itemKey]);
}
}
})();
in your controller, you may use it like this
ItemFactory.toggleItemStatus($scope, item, 'selectedAge', true);// to push item
ItemFactory.toggleItemStatus($scope, item, 'selectedAge', false);// to remove item
The only difference I made is that I used the same function to push and unpush item. I hope this doesn't confuse you.
function to_json(workbook) {
var result = {};
workbook.SheetNames.forEach(function(sheetName) {
var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
return result;
}
I have above code. How to alter it, in order to let the anonymous function run only over the first element in SheetNames? (or alternatively alter sth else in order to achieve the same result).
I got this so far, I am not sure it is correct.
...snip
var tmpArray = workbook.SheetNames.slice(0);
tmpArray.forEach(function(sheetName) {
...snip
One way is what you've mentioned, but .slice(0) returns the whole array, so use .slice(0,1) for only the first item:
var tmpArray = workbook.SheetNames.slice(0, 1);
tmpArray.forEach(function(sheetName) { /* ... */ })
But if you only want to process the first item you can cancel the forEach() and the anonymous()
totally:
function to_json(workbook) {
var result = {},
sheetName = workbook.SheetNames[0],
roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0) result[sheetName] = roa;
return result;
}
I am building a Knockout viewmodel. The model has some fields like dateFrom, DateTo, Status and so forth. In addition, there is a list of invoices.
The invoices have some pricing information, which is a price object. My main object also have a price object, which should iterate all the invoice objects and find the total price.
My problem is the following:
The code runs smooth, until I add the following in my view:
<label data-bind="text:totalPrice().price().priceExVat"></label>
Here I get an:
TypeError: $(...).price is not a function
Which refers to my:
exVat += $(ele).price().priceExVat;
I don't understand it, because in my each function, I should have the element. The element have a price() function, so why would it not work? Is it some scope issue?
My viewmodel:
function invoice(invoiceDate, customerName, pdfLink, status) {
var self = this;
self.pdfLink = pdfLink;
self.print = ko.observable(0);
self.customerName = customerName;
self.status = status;
self.pdfPagesCount = function () {
return 1;
};
self.invoiceDate = invoiceDate;
self.price = function () {
return new price(1.8, 2.1);
};
}
function price(exVat, total) {
var self = this;
self.currency = '€';
self.total = total;
self.priceExVat = exVat;
self.vatPercentage = 0.25;
self.vatAmount = self.exVat - self.total;
self.priceExVatText = function() {
return self.priceExVat + ' ' + self.currency;
};
}
var EconomicsViewModel = function (formSelector, data) {
var self = this;
self.dateFrom = data.dateFrom;
self.dateTo = data.dateTo;
self.invoices = ko.observableArray([
new invoice('05-05-2014', 'LetterAmazer IvS', "http://www.google.com","not printed"),
new invoice('05-05-2014', 'LetterAmazer IvS', "http://www.google.com", "not printed")
]);
self.totalPrice = function () {
var exVat = 0.0;
$(self.invoices).each(function (index, ele) {
console.log(ele);
exVat += $(ele).price().priceExVat;
});
return price(exVat, 0);
};
};
From what I read, totalPrice is actually a price object, you don't need to put a .price():
<label data-bind="text:totalPrice().priceExVat"></label>
EDIT:
Sorry, there were also problems on your javascript:
self.totalPrice = function () {
var exVat = 0.0;
$(self.invoices()).each(function (index, ele) { //<-- add () to self.invoices to get the array
console.log(ele);
exVat += ele.price().priceExVat; //<-- remove useless jQuery
});
return new price(exVat, 0); //<-- add 'new'
};
Check this fiddle
EDIT2:
To answer robert.westerlund's comment, you could remove $().each and replace with ko.utils.arrayForEach or even simpler use a for loop:
var arr = self.invoices();
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
exVat += arr[i].price().priceExVat;
}
Updated fiddle
I've been playing around with javascript and casperjs. I have the following lines of code.
casper.thenOpen('somesite', function() {
console.log('clicked ok, new location is ' + this.getCurrentUrl());
// Get info on all elements matching this CSS selector
var town_selector = 'div tr';
var town_names_info = this.getElementsInfo(town_selector); // an array of object literals
// Pull out the town name text and push into the town_names array
var town_names = [];
for (var i = 0; i < town_names_info.length; i++) {
town_names.push(town_names_info[i].text.trim());}
// Dump the town_names array to screen
utils.dump(town_names);
casper.capture('capture5.png');
});
my output is this.
[
"Address:\n \n address",
"City:\n \ncity",
"State:\n \nstate",
"Zip:\n \nzip",
]
how can I make it json? like this.
{
"Address":"address",
"City":"city",
"State":"state",
"Zip":"zip"
}
Thanks in advance.
You can use something like this:
function arrayToObject(arr) {
var out = {};
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '').split(':');
var key = keyvalue[0];
var value = keyvalue[1];
out[key] = value;
});
return out;
}
then you can do:
var json = JSON.stringify(arrayToObject(myArray));
Update:
> How can I change this to split only the first occurrence of colon?
Use this:
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '');
var key = keyvalue.substring(0, element.indexOf(':'));
var value = keyvalue.substring(key.length + 1);
out[key] = value;
});