Hey so I'm reasonably new to Node.js and Mongodb, I am making a roster creation system and I want to make it so that only two users/employees can work on a given shift. For simplicity the shifts are split into 'day' and 'night' which are in a table of radio buttons that the user can chosen. Onload of the shifts page however I want to disable those buttons which have already been chosen by two other users.
I think that the outer loop should iterate through the shifts array of the users (Monday --> Sunday), the inner loop should then iterate through each user in the mongodb database. Eventually I want to have the code working for each day of the week but for now just need Monday to function properly.
Thanks for any help and advise
function disableOnLoad() {
console.log("disableOnLoad reached");
var dayCount=0;
var nightCount=0;
$.getJSON( '/shiftsTable', function( data ) {
$.each(data, function(){
userListData = data;
for(i = 0; i < 7; i++) {
**//$.each(data, function(){**
if(this.shifts[i]=='day'){
if(i==0){
dayCount++;
console.log("dayCount: "+dayCount);
if(dayCount>2){document.getElementById("monDay").disabled=true;}
}
}
else if(this.shifts[0]=='night'){
nightCount++;
if (nightCount>2){document.getElementById("monNight").disabled=true;}
}
}
});
});
};
Assuming this is the data
data = [{
"_id": "589f60999c471a32c6a3a380",
"name": "Ciara",
"position": "Sales assistant",
"location": "Dublin",
"admin": 0,
"shifts": ["day", "day", "night", null, null, null, null, "23"]
},
{
"_id": "589f60999c471a32c6a3a380",
"name": "Ciara2",
"position": "Sales assistant",
"location": "Dublin",
"admin": 0,
"shifts": ["day", "day", "night", null, null, null, null, "23"]
},{
"_id": "589f60999c471a32c6a3a380",
"name": "Ciara3",
"position": "Sales assistant",
"location": "Dublin",
"admin": 0,
"shifts": ["day", "day", "night", null, null, null, null, "23"]
}];
So this code works for me
$.each(data, function(val) {
userListData = data;
for (i = 0; i < 7; i++) { //* * //$.each(data, function(){**
if (i==0 && this.shifts[i] == 'day') {
dayCount++;
if (dayCount == 2) {
document.getElementById("monDay").disabled = true;
}
} else if (i==0 && this.shifts[i] == 'night') {
nightCount++;
if (nightCount == 2) {
document.getElementById("monNight").disabled = true;
}
}
}
});
}
Let me know if it works.
Related
i'm using google apps script, and I have a JSON array consisting of nested parent and child objects.
"logisticalHierarchies": [
{
"product_key_id": 48232671,
"gtin": "05449000696878",
"lastRequest": null,
"productIdentifier": null,
"children": [
{
"product_key_id": 48232673,
"gtin": "05449000283863",
"quantity": 130,
"productIdentifier": null,
"children": [
{
"product_key_id": 48232457,
"gtin": "05449000283856",
"quantity": 4,
"productIdentifier": null,
"children": [
{
"product_key_id": 48232675,
"gtin": "05449000214843",
"quantity": 6,
"productIdentifier": null,
"children": [],
"contentOwner_id": 10525,
"isMainHierarchyUnit": false,
I would like by entering the GTIN object as parameters, to succeed in recovering the GTIN object of the father of the product that I have just entered.
For example if I enter the GTIN: 05449000283856
I get the GTIN FATHER: 05449000283863
For the moment I am able to retrieve only the first GTIN of the list (the first father) using this script:
var url='https://apis.alkemics.com/public/v1/products?'+params;
//Logger.log(url);
var content =UrlFetchApp.fetch(url, options);
//Logger.log(content);
//Logger.log(content.getResponseCode())
if (content. getResponseCode() ==200) {
var return =JSON.parse(content.getContentText());
next_page=back.next_page;
var data=return.data;
for(i=0; i<data.length;i++) {
var product=data[i]; // A product in JSON format
var childrens = data.map(({logisticalHierarchies}) => logisticalHierarchies.map(o => [o.children?.gtin || ""]));
Logger.log(childrens)
var line=[
product.gtin,
product.logisticalHierarchies[0] != null? product.logisticalHierarchies[0].children[0].gtin: ' ',
];
So a recursion would help, passing the father as you go into deeper level. This one written for readability not for efficiency as you should break from the loop early if you find the searched item.
var logisticalHierarchies = [{
"product_key_id": 48232671,
"gtin": "05449000696878",
"lastRequest": null,
"productIdentifier": null,
"children": [{
"product_key_id": 48232673,
"gtin": "05449000283863",
"quantity": 130,
"productIdentifier": null,
"children": [{
"product_key_id": 48232457,
"gtin": "05449000283856",
"quantity": 4,
"productIdentifier": null,
"children": [{
"product_key_id": 48232675,
"gtin": "05449000214843",
"quantity": 6,
"productIdentifier": null,
"children": [],
"contentOwner_id": 10525,
"isMainHierarchyUnit": false,
}, {
"product_key_id": 12323,
"gtin": "05449000214847",
"quantity": 6,
"productIdentifier": null,
"children": [],
"contentOwner_id": 10525,
"isMainHierarchyUnit": false,
}]
}]
}]
}]
function find_gtin_father(arr, gtin, parent) {
parent = parent || null;
var found = null;
arr.forEach(function(item) {
if (item.gtin === gtin) {
found = parent;
} else {
if (item.children) {
found = found || find_gtin_father(item.children, gtin, item);
}
}
})
return found;
}
var item = find_gtin_father(logisticalHierarchies, "05449000214847")
console.log(item)
.as-console-wrapper {max-height: 100% !important}
I have been playing around with the Angular UI Tree drag and drop and have come by an issue that has stumped me. The json is being received from my services. When it is received by my controller, I must format it properly with an empty array so it will be able to hold childen:
Formatting:
function categorySuccessPost(data) {
var emptyCategoryArray = {
Categories: []
}
for (var i = 0; i < data.length; i++) {
$.extend(data[i], emptyCategoryArray);
}
$scope.categoryData = data;
}
It is now formatted and looks like:
[ { "CategoryId": 27054, "MerchantId": 5594, "ProductCategoryId": 1310,
"Name": "BulkUpload", "Description": "BulkUpload", "DateCreated":
"/Date(1446793200000-0000)/", "IsActive": true, "IsDefault": false, "ItemCount":
5, "ResponseStatus": { "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15,
"Categories": [] }, { "CategoryId": 23267, "MerchantId": 5594,
"ProductCategoryId": 818, "Name": "Coupon", "Description": "Coupon",
"DateCreated": "/Date(-62135596800000-0000)/", "IsActive": true, "IsDefault":
true, "ItemCount": 1, "ResponseStatus": { "ErrorCode": "SUCCESS" },
"TotalRecordCount": 15, "Categories": [] } }
I have tried two different functions when attempting to add a child:
Function 1 (Uses model value):
$scope.newSubItem = function (scope) {
var currentCategoryData = scope.$modelValue;
currentCategoryData.Categories.push({
CategoryId: currentCategoryData.CategoryId * 10 + currentCategoryData.Categories.length,
Name: currentCategoryData.Name + '.' + (currentCategoryData.Categories.length + 1),
Categories: []
});
};
Function 2 (Uses index of object in the array, and yes, I have made sure the correct index is being passed):
$scope.newSubItem = function (index) {
var array = $scope.categoryData;
array[index].Categories.push({
CategoryId: 12312,
Name: 'test',
Categories: []
});
};
The issue is that instead of pushing the new data to the selected index, it adds the json to every Categories :
[ { "CategoryId": 27054, "MerchantId": 5594, "ProductCategoryId": 1310,
"Name": "BulkUpload", "Description": "BulkUpload", "DateCreated":
"/Date(1446793200000-0000)/", "IsActive": true, "IsDefault": false, "ItemCount":
5, "ResponseStatus": { "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15,
"Categories": [ { "CategoryId": 12312, "Name": "test", "Categories": [] } ] }, {
"CategoryId": 23267, "MerchantId": 5594, "ProductCategoryId": 818, "Name": "Coupon", "Description": "Coupon", "DateCreated": "/Date(-62135596800000-
0000)/", "IsActive": true, "IsDefault": true, "ItemCount": 1, "ResponseStatus":
{ "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15, "Categories": [ {
"CategoryId": 12312, "Name": "test", "Categories": [] } ] }
I am not showing the HTML because it does not appear to be an issue. Here's where I have narrowed it down to, but still have no explanation:
If I use the data that goes through the $.extend method then it adds a child to every parent. But if I copy the json that is generated after the formatting, put it into and object and then read from that, then it only adds a child to the selected parent like I want. But it is necessary to add the empty array. Any idea why this is happening and any solution?
EDIT
One more piece of information that may be important: When I add a full Category (different function), rather than adding a subcategory and then try to add a child to the newly generated category then it works correctly (adding only a child to that category):
$scope.addCategory = function () {
var name = $scope.categoryName;
// Temporary
var categoryId = Math.floor((Math.random() * 50000) + 1)
console.log(name, categoryId)
$scope.categoryData.unshift({ CategoryId: categoryId, Name: name, Categories: [] })
$scope.categoryName = "";
$("#addCategoryModal").modal('hide');
Notification.success({ message: 'Category Added Successfully!', delay: 3000 });
}
I'm still not sure exactly why this is happening, but this was my solution to fixing the issue:
Remove the $.extend for loop and $.extend function:
function categorySuccessPost(data) {
$scope.categoryData = data;
}
When adding an item, check if the array has been initialized, if not, create it in the current scope:
$scope.newSubItem = function (scope) {
var currentCategoryData = scope.$modelValue;
if(currentCategoryData.Categories === 'undefined'){
currentCategoryData.Categories = [];
}
currentCategoryData.Categories.push({
CategoryId: currentCategoryData.CategoryId * 10 + currentCategoryData.Categories.length,
Name: currentCategoryData.Name + '.' + (currentCategoryData.Categories.length + 1),
Categories: []
});
};
The issue with this method is that you can no longer drag a node into an empty parent.
This is my saved localstorage,
[{"industry_Id":1,"merchant_id":2}]
I want to filter below result, to get HP.
{
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
}
I thought of using multiple $.each but it have to iterate few times and it's quite redundant.
I would prefer using Javascript for loop, that way you can skip iterating over every object once required element is found.
Without jQuery (using for)
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
With jQuery (using $.each)
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
var arg = [{"industry_Id":1,"merchant_id":2}];
var data = {
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
};
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
console.log(merchant);
document.writeln("<b>Without jQuery:</b><br>");
document.writeln((merchant !== null) ? "Found " + merchant['name'] : "Not found");
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
console.log(merchant_found);
document.writeln("<br><br><b>With jQuery:</b><br>");
document.writeln((merchant_found) ? "Found " + merchant_found['name'] : "Not found");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
selectors.map(function(selector) {
return data.industries.filter(function(industry) {
return industry.id == selector.industry_Id;
})[0].merchant.filter(function(merchant) {
return merchant.id == selector.merchant_id;
})[0].name;
});
// => DEF
If you want "HP", you want industry 2, not industry 1.
.filter(...)[0] is not really optimal. You could use .find(...), but that is not yet universally supported. Or you could use plain old JavaScript and write for loops instead to make it fast. Or you could use objects with ID keys instead of arrays to make lookups faster.
When it comes into a position where collection of data is what you're processing, I suggest you to take a look at underscore.js. It's not optimal choice for the best performance but it does make you code more readable and makes more sense especially when compared with loop.
Say data is a variable which stores your JSON data.
Try this:
// Given this selector criteria
var select = [{"industry_Id":1,"merchant_id":2}];
function filterByCriteria(criteria, data){
var match = [];
_.each(criteria, function(crit){
function matchIndustry(rec){ return rec.id===crit.industry_Id }
function matchMerchant(rec){ return rec.id===crit.merchant_id }
// Filter by industry id
var industry = _.first(_.where(data.industry, matchIndustry));
// Filter by merchant id
var merchant = _.where(industry.merchant, matchMerchant);
_.each(merchant, function addToMatchResult(m){
match.push(m.name);
});
});
return match;
}
var filteredData = filterByCriteria(select, data);
From snippet above, any merchants which match the search criteria will be taken to the match list. Is it more readable to you?
Do you even need numerical id's? Gets super easy when you don't.
/*
{
"industry": {
"oil and gas":{
"merchant": {
"ABC": {
"name": "ABC oil"
},
"DEF": {
"name": "DEF gas"
},
"GHJ" :{
"name": "GHJ oil and gas"
}
}
},
"IT": {
"merchant": {
"Apple" : {
"name": "Apple computers"
},
"HP": {
"name": "Hewlett Packard"
},
"Google": {
"name": "Google. Maw haw haw"
}
}
}
}
}
*/
var data = '{"industry": {"oil and gas":{"merchant": {"ABC": {"name": "ABC oil"},"DEF": {"name": "DEF gas"},"GHJ" :{"name": "GHJ oil and gas"}}},"IT": {"merchant": {"Apple" : {"name": "Apple computers"},"HP": {"name": "Hewlett Packard"},"Google": {"name": "Google. Maw haw haw"}}}}}';
data = JSON.parse(data);
var merchant = data.industry['IT'].merchant['HP'];
alert(merchant.name);
//console.log(merchant.name);
I am working on a solution where I need to search for an element in a deeply nested JSON by its id. I have been advised to use underscore.js which I am pretty new to.
After reading the documentation http://underscorejs.org/#find , I tried to implement the solution using find, filter and findWhere.
Here is what I tried using find :
var test = {
"menuInputRequestId": 1,
"catalog":[
{
"uid": 1,
"name": "Pizza",
"desc": "Italian cuisine",
"products": [
{
"uid": 3,
"name": "Devilled chicken",
"desc": "chicken pizza",
"prices":[
{
"uid": 7,
"name": "regular",
"price": "$10"
},
{
"uid": 8,
"name": "large",
"price": "$12"
}
]
}
]
},
{
"uid": 2,
"name": "Pasta",
"desc": "Italian cuisine pasta",
"products": [
{
"uid": 4,
"name": "Lasagne",
"desc": "chicken lasage",
"prices":[
{
"uid": 9,
"name": "small",
"price": "$10"
},
{
"uid": 10,
"name": "large",
"price": "$15"
}
]
},
{
"uid": 5,
"name": "Pasta",
"desc": "chicken pasta",
"prices":[
{
"uid": 11,
"name": "small",
"price": "$8"
},
{
"uid": 12,
"name": "large",
"price": "$12"
}
]
}
]
}
]
};
var x = _.find(test, function (item) {
return item.catalog && item.catalog.uid == 1;
});
And a Fiddle http://jsfiddle.net/8hmz0760/
The issue I faced is that these functions check the top level of the structure and not the nested properties thus returning undefined. I tried to use item.catalog && item.catalog.uid == 1; logic as suggested in a similar question Underscore.js - filtering in a nested Json but failed.
How can I find an item by value by searching the whole deeply nested structure?
EDIT:
The following code is the latest i tried. The issue in that is that it directly traverses to prices nested object and tries to find the value. But my requirement is to search for the value in all the layers of the JSON.
var x = _.filter(test, function(evt) {
return _.any(evt.items, function(itm){
return _.any(itm.outcomes, function(prc) {
return prc.uid === 1 ;
});
});
});
Here's a solution which creates an object where the keys are the uids:
var catalogues = test.catalog;
var products = _.flatten(_.pluck(catalogues, 'products'));
var prices = _.flatten(_.pluck(products, 'prices'));
var ids = _.reduce(catalogues.concat(products,prices), function(memo, value){
memo[value.uid] = value;
return memo;
}, {});
var itemWithUid2 = ids[2]
var itemWithUid12 = ids[12]
I dont use underscore.js but you can use this instead
function isArray(what) {
return Object.prototype.toString.call(what) === '[object Array]';
}
function find(json,key,value){
var result = [];
for (var property in json)
{
//console.log(property);
if (json.hasOwnProperty(property)) {
if( property == key && json[property] == value)
{
result.push(json);
}
if( isArray(json[property]))
{
for(var child in json[property])
{
//console.log(json[property][child]);
var res = find(json[property][child],key,value);
if(res.length >= 1 ){
result.push(res);}
}
}
}
}
return result;
}
console.log(find(test,"uid",4));
Below is the json data that I have which contains array of states. The size of array is always 2, but the order of elements of the array is not fixed. The array elements values can be null. The sample data is as shown below:
{
"status": "SUCCESS",
"status_message": "Susscessfully queried details.",
"total_records": 2,
"m_details":
[
{
"p_id": 1023,
"pname": "india",
"states":
[
{
"state": "karnataka",
"capital": "bangalore"
},
{
"state": null,
"capital": null,
}
]
},
{
"p_id": 1023,
"pname": "india",
"states":
[
{
"state": null,
"capital": null
},
{
"state": "Tamilnadu",
"capital": "chennai"
}
]
}
]
}
My questions:
How to convert the null values to some default text say "-".
How can I sort all the states in asc or desc order.
You can iterate through all elements in your data to switch any null values to "-" with an iterator with a callback like this.
function iterateObject(item, callback) {
if (typeof item === "object" && item !== null) {
if (item instanceof Array) {
for (var i = 0; i < item.length; i++) {
item[i] = iterateObject(item[i], callback);
}
} else {
for (var prop in item) {
if (item.hasOwnProperty(prop)) {
item[prop] = iterateObject(item[prop], callback);
}
}
}
} else {
// call the callback on any item that is not an array or object
return callback(item);
}
return item;
}
var data = {
"status": "SUCCESS",
"status_message": "Susscessfully queried details.",
"total_records": 2,
"m_details":
[
{
"p_id": 1023,
"pname": "india",
"states":
[
{
"state": "karnataka",
"capital": "bangalore"
},
{
"state": null,
"capital": null,
}
]
},
{
"p_id": 1023,
"pname": "india",
"states":
[
{
"state": null,
"capital": null
},
{
"state": "Tamilnadu",
"capital": "chennai"
}
]
}
]
};
// iterate through the object and convert all `null` values to `"-"`
iterateObject(data, function(item) {
return (item === null) ? "-" : item;
});
You can then sort each of the states arrays like this:
function sortStates(item) {
var array = item.m_details;
for (var i = 0; i < array.length; i++) {
array[i].states.sort(function(a, b) {
return a.state.localeCompare(b.state);
});
}
}
sortStates(data);
If you want the opposite sort order, then just swap the arguments a and b in the .sort() callback.
Working demo: http://jsfiddle.net/jfriend00/MTQ86/
Just for your information javascript array objects have a sort function that implements some basic built in sorting functionalities. If you need to perform a more specific sorting (you do) you can always passing in a function to the sort function and implement your own custom logic. This article from W3Schools has some examples which quoting one of them here...
var points = [40,100,1,5,25,10];
points.sort(function(a,b){return b-a}); //sorts numbers in descending order
Now, to "convert" null values to a '-' literal I guess you will need to add more details to your question so I can provide a good solution. Why do you need to convert them? Where's this json coming from?