I am making a database website using AngularJs, mongodb, and restheart.
I design a table that if I input text in any of the five input area, the data with the keywords will show up.
<input types="text" ng-model="query.uniport_AC" ng-change="change()">
......
<input types="text" ng-model="query.site" ng-change="change()">
and in the javascript, my code is
$scope.change = function(){
var url = "";
angular.forEach($scope.query, function(value, key) {
if(!angular.isUndefined(value)){
url = url + "'"+key+"':{'$regex':'(?i)"+value+".*'},";
};
test = "http...&filter={" +url+ "}";
$http.get(test+"}").then(
function(res){
$scope.db = res.data._embedded["rh:doc"];
$scope.pages = res.data._total_pages;
$scope.sizes = res.data._size;
console.log(res);
},
function(err){
console.log(err);
}
);
My problem is, let say I input a and g in the first 2 input area, respectively, I wish to create a string like this
http...filter={'uniprot_AC':{'$regex':'(?i)a.*'},'gene_name':{'$regex':'(?i)g.*'},
However, I get a string like this
http...filter={'uniprot_AC':{'$regex':'(?i)a.*'},'uniprot_AC':{'$regex':'(?i)a.*'},'gene_name':{'$regex':'(?i)g.*'},'gene_name':{'$regex':'(?i)g.*'},
The url (let say 'uniprot_AC':{'$regex':'(?i)a.*'},) is repeated one more times. Can anyone point what is wrong with my code?
Related
I have some JS that stores the name and value of selected checkboxes on one page and then, on a button click, adds this data to a table on page 2.
This works, but now I am looking to do the same for a textbox containing a number. Specifically, I'm looking to take the value entered by the user and add this to a cell in the table. What would be the best way to approach this? Add to the existing function or create a separate on button click function specifically for the textbox value?
I have added a screenshot of the HTML table on page 2 along with where I would like the textbox value to go (highlighted with a red rectangle).
Here's what I have so far:
HTML for textbox (page 1):
<div class="selecttier">
<h1>5. Number of Clicks</h1>
<input id="numberofclickstextbox" name="numberofclicks" type="text" value="0" data-total="0" oninput="calculatetier()" />
</div>
JS on page 1:
$('#sales_order_form_button').click(function() {
let table_info = [];
$('input[type=checkbox]').each(
function(index, value) {
if($(this).is(':checked')) {
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
}
);
}
});
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
});
JS on page 2:
// Helper function
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.href);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
// actual code
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
for(let i = 0; i < data_from_page_1.length; i++){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text(data_from_page_1[i].name);
let recordValue = $("<td></td>").text(data_from_page_1[i].value);
row.append(recordName, recordValue);
$('#output_table').append(row);
}
// code to sum CPC column
var sum1 = 0;
$("#output_table tr > td:nth-child(2)").each(
(_,el) => sum1 += Number($(el).text()) || 0
);
$("#sum1").text(sum1);
//datetime stamp
var dt = new Date();
document.getElementById("datetime").innerHTML = dt.toLocaleString();
Output HTML table (page 2):
<table id="output_table">
<tr>
<th>Name</th>
<th>Value</th>
<th>Number of Clicks</th>
</tr>
<tfoot>
<tr>
<th id="total" colspan="1">Total CPC:</th>
<td id="sum1"></td>
</tr>
</tfoot>
</table>
As stated in the #Manu Varghese comment, the way to go would be using sessionStorage or localStorage.
First, let's differentiate both. According to the Stack Overflow question "HTML5 Local storage vs Session Storage", we have the following answer:
localStorage and sessionStorage both extend Storage. There is no difference between them except for the intended "non-persistence" of sessionStorage.
That is, the data stored in localStorage persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.
For sessionStorage, changes are only available per tab. Changes made are saved and available for the current page in that tab until it is closed. Once it is closed, the stored data is deleted.
Considering they are used the same way and you must to choose between what better fits your case, I will proceed using sessionStorage.
For that, in the first page you must use:
sessionStorage.setItem("key", "value")
You may set the item right when you perceives a change, like in the input 'blur' event.
and when you land in the second page (right when jQuery calls its start event), you will retrieve your data using:
sessionStorage.getItem("key")
Take in mind that localStorage/sessionStorage can support a limited amount of data. Even if that limit is way bigger than URL, most browsers will store only 2.5MB to 10MB per origin, according to the browser implementation (you may test by yourself in the link recommended in MDN (Mozilla Development Network), http://dev-test.nemikor.com/web-storage/support-test/).
Also, you may want to avoid storing sensitive data in the storages, due to some some discussions about security, which seems not to be a complaint here.
Implementation in the given case
Your code can be modified in three steps:
Change the way you save the data to use the storage
Creates a JSON of an object containing the array, instead the make the JSON using the array itself. Then you can add more fields.
Load the JSON object and its fields (the array and the number).
Step 1 - Changing to sessionStorage
Just now you have your Javascript on page 1 creating an array of data and stringifying that data to a JSON string.
If you want to use the storage rather than the URL for all the data, just change these lines of code from:
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
to the code that will save the data into a (local/session)Storage:
let jsonStr=JSON.stringify(table_info); // converts to JSON string
sessionStorage.setItem("oldData", jsonStr); // save to storage
window.location = "page2.html"; // navigate to other page
Notice that the storage can receive any string, but only strings, then we can remove the btoa function, but we must keep the stringify.
Step 2 -- Adding more data to save
Now you have one JSON that is an array of items. But what do you want is to include one more field, parallel to this array. Of course, you can't include it in the array, as it is a different thing. So, what we must to do is to create a JSON object which has a number field AND the array field itself.
Your function to create the array is all ok, then we will use the same "table_data" as the array and include it to a new JSON object:
let table_data = []; // the array you have
$('input[type=checkbox]').each(
... rest of code ...
); // the function that creates the array (I abbreviated it here)
// Creates an object with an array and a number
let jsonObj = {
table_data: table_data,
number_of_clicks: theNumberYouHave/* your variable with the number here */
};
// This is the bit above with CHANGES into variable names
// Instead of "table_data", now we save "jsonObj"
let jsonStr=JSON.stringify(jsonObj); // converts the "jsonObj" to a JSON string
sessionStorage.setItem("oldData", jsonStr);
window.location = "page2.html";
Remember to change "theNumberYouHave" to whatever your variable with the number is called. The you will append the number as a field of the JSON object.
In other words, this simply will create an structure like that:
{
number_of_clicks: 5216,
table_data: [
{ name: "...", value: "..."},
{ name: "...", value: "..."},
{ name: "...", value: "..."},
...
]
}
See? Your table_data is still there, but with a new sibling (number_of_clicks) inside an object.
Step 3 -- Loading data from page 1
For now, you have these two lines of code in page 2 to read data from page 1:
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
What do you need there, is to simply replace the getUrlParameter function to read from the storage, and remove the atob function to reflect the changes we made in page 1, this way:
let jsonObj = sessionStorage.getItem("oldData"); // reads the string
let data_from_page_1 = JSON.parse(jsonObj); // parse the JSON string
let table_data = data_from_page_1.table_data; // grab the table data
let number_of_clicks = data_from_page_1.number_of_clicks; // grab the number
Now you are free to use the variable "table_data" like you did, and to use the "number_of_clicks" in the way you want to use it. It is the number passed from page 1, then you may set it to your table cell.
You have it with the unique ID "sum1", the you may just:
$("#sum1").text(number_of_clicks);
And you are done!
I highly recommend localStorage and sessionStorage to be used, as per this and this
Page 1 code full source
$('#next_page_button').click(function(){
let table_info = [];
// Do for checkboxes
$('.campaignstrategy input[type=checkbox]').each(
function(index, value){
if($(this).is(':checked')){
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
type: 'checkbox'
}
);
}
});
$('.campaignstrategy input[type=text]').each(
function(index, value){
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
type: 'text'
}
);
});
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
});
Page 2 Code full source
// Helper function
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.href);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
// actual code
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
// clear table
$('#output_table').html("");
// generator checboxes
for(let i=0;i<data_from_page_1.length;i++){
if(data_from_page_1[i].type == "checkbox"){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text(data_from_page_1[i].name);
let recordValue = $("<td></td>").text(data_from_page_1[i].value);
let recordCount = $("<td></td>").text("");
row.append(recordName, recordValue, recordCount); // not used but needed
$('#output_table').append(row);
}
}
// generate textboxes
for(let i=0;i<data_from_page_1.length;i++){
if(data_from_page_1[i].type == "text"){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text("");
let recordValue = $("<td></td>").text("");
let recordCount = $("<td></td>").text(data_from_page_1[i].value);
row.append(recordName, recordValue, recordCount);
$('#output_table').append(row);
}
}
ANSWER:
What would be the best way to approach this?
window.localStorage - stores data with no expiration date
window.sessionStorage - stores data for one session
I try to accomplish that I will be able to change the color of marker icons to be visible in the map. They are in the map in different colors. Those colors are correspondenting to the json cat_id key's.
1: "http://dev.openlayers.org/img/marker.png",
2: "http://dev.openlayers.org/img/marker-blue.png",
3: "http://dev.openlayers.org/img/marker-gold.png",
4: "http://dev.openlayers.org/img/marker-green.png",
Each marker icon that is in the map is getting it's position, color and other valuable data from the json objects in the data id in the script tag. I didn't code the part of that work's close with the openlayer libary's. I wrote the following part of the total of the script:
var json = document.getElementById('data').innerHTML;
json = JSON.parse(json); // converts text into JSON
// search criteria (could be changed)
var $search_postal = "8912JB";
var $search_number = "10";
var $change_cat = 1;
function changeColor() {
for (var key in json) {
if (json.hasOwnProperty(key)) {
if (json[key].postal == $search_postal) {
if (json[key].number == $search_number) {
alert("Gonna change cat_id " + json[key].cat_id + " of the number search string " + $search_number + " of the postal search string " + $search_postal + " to cat_id " + $change_cat);
json[key].cat_id = "1";
alert('Changed!');
const posts = json; // the constant that is used to display the icons
var myJSON = json;
document.getElementById('demo').innerHTML = JSON.stringify(myJSON, undefined, 2); // changes of the json data to see on screen
}
}
}
}
}
const posts = json; //the constant that is used to display the icons
var myJSON = JSON.stringify(json);
document.getElementById('demo').innerHTML = myJSON;
This script will change the cat_id of the given search input. In the example it does a search for postal 8912JB with number 1. Once it has made the loop to find it's position it will change the cat_id value of 3 to 1. In other words the json data has been changed. Since it is stored in the const posts I replace this cons with the changed data. My problem is that I'm unable to refresh the marker icon(s) in the map with the new json data that is changed (cat_id: 1 of postal 8912JB number 10). This has to do with less knowledge about openlayers and Javascript. I'm struggling already 2 weeks with this. Can anybody help me to accomplish this? If it changes from color is the only thing that is required. I would only need to give the changes to the variables $search_postal, $search_number and $change_cat.
Here is the page for debug: https://jsfiddle.net/j4z1vpht/4/
Thanks for any help,
grid
You need to update the new category to the map feature, like this:
const updateFeatureCategory = (featureId, categoryId) => {
const feature = marker_layer.getSource().getFeatureById(featureId);
const post = feature.get("post");
const updatedPost = {
...post,
cat_id: categoryId
}
feature.set("post", updatedPost);
}
function changeColor() {
...
json[key].cat_id = "1";
updateFeatureCategory(key, "1");
...
}
Here's a working fiddle: https://jsfiddle.net/wsm2h3qz/1/
I'm a beginner to Node.js and MySQL so bear with me. The code below is in my routes for my localhost server and the database when saved at first is fine, but when I try to retrieve it and push it back into my database by storing the old one in a new array, it changes the "" to \"\". What I want is for it to be still "".
I've tried looking around the web for ways to change the formatted string quotes from \"\" back to "" but to no avail and I also tried formatting the score from string back to a number but I realized that even if I did that, it would still end up being a string when stored in the database and when I retrieve it, it would be the same.
let { score } = req.body;
let { date } = req.body;
score = Number(score);
var score_date = [score, date];
wMissing.findOne({
raw : true
}).then((missing) => {
var sessionID = missing.testSessionID;
registerPatient.findOne({
where: {
nric : sessionID
},
raw : true
}).then((patient) => {
var height = patient.height;
height = height / 100
var weight = patient.weight;
var bmiVar = (weight / (height * height)).toFixed(2);
// *This is where my problem starts*
if (missing.wMissingScore == null){
var newArray = score_date;
} else {
var newArray = [missing.wMissingScore];
newArray.push(score_date);
}
newArray = JSON.stringify(newArray);
wMissing.update({
bmi: bmiVar,
wMissingScore: newArray,
name: patient.fullname,
nric: sessionID,
datePlayed: date
}, {
where: {
nric: sessionID
}
}).then(() => {
res.redirect('workoutDiets');
}).catch(err => console.log(err));
The expected output is supposed to be [["2","24/7/2019"],["3","24/7/2019"]]
But instead I'm getting ["[\"2\",\"24/7/2019\"]",["3","24/7/2019"]]
I'm still unaware of any method to change back the \"\" to "" instead. can anyone please help me to improve on my code?
Actually, what's happening is that the first element of the array is being stored as a string, if you watch carefully, the second element is written correctly as an array of strings.
The problem is the first element, you're having a special case.
If i understand correctly ´´´missing.wMissingScore´´´ is a pure string
What you can do is:
´´´
if (missing.wMissingScore == null){
var newArray = score_date;
} else {
var formatedMissingScore= missing.wMissingScore.replace("\"", "").replace("[", "").replace("]", "").split(",");
var newArray = [formatedMissingScore];
newArray.push(score_date);
}
´´´
That way you're formatting your first element string so its not text anymore and should match what you are trying to get.
#charlietfl mentioned about JSON.parse() and it worked! I just changed my else statement to
var newArray = [JSON.parse(missing.wMissingScore)];
and it managed to save the score back to what it originally was.
I'm quite new at using node.js. Right now I'm trying to pull data from MongoDB and display it in a table using Javascript + HTML. However, my table is populating with undefined in all the fields. I think something is definitely wrong with how I'm reading data through to the Javascript function b/c I am able to render the full results from the people.js file straight to the webpage. Thank you in advance!! Below is my code:
Code for my people.js file:
exports.getPeople = (req, res) => {
People.find((err, docs) => {
if (err) { return next(err); }
if (docs != null){
console.log(docs.length)
docs.forEach(function(docs, index) {
console.log(index + " key: " + docs.name)
});
res.render('people', { people: docs });
}
else{
res.render('people', { people: docs() });
}
});
};
My Javascript + HTML that's populating my webpage.
script(type='text/javascript', src='http://code.jquery.com/jquery-1.9.1.js', charset='UTF-8')
script.
$(document).ready(function(){
var obj= '$(people)'
var tbl = "<table>"
var content="";
for(i=0; i<obj.length;i++){
content +=
'<tr>+<td>' +obj[i]["name"]+
'</td><td>'+obj[i]["type"]+
'</td><td>'+obj[i]["min_hours"]+
'</td><td>'+obj[i]["max_hours"]+
'</td><td>'+obj[i]["email"]+
'</td><td>'+obj[i]["phone_number"]+
'</td><td>'+ '<input type="button" value = "Update" onClick="Javacsript:deleteRow(this)">' +
'</td><td>'+'<input type="button" value = "Delete" onClick="Javacsript:deleteRow(this)">';
'</td></tr>';
}
content += "</table>"
$('#myTableData').append(content);
});
As you mentioned, you can render the array results from the people.js file directly into the webpage. So, you don't have to read the data through a JavaScript function using jQuery. The template engine language is built on top of JavaScript and it supports plenty of methods and features to do what you're trying to achieve here. So, for example, you may use an iteration method like each..in to build your table (see docs - Iteration):
// ...
body
table(id="myTableData")
// for each person in the people array (from people.js) ...
each person in people
// build a new table row
tr
// insert table data
td #{person.name}
td #{person.type}
td #{person.min_hours}
td #{person.max_hours}
td #{person.email}
td #{person.phone_number}
// add the update and delete buttons
td
input(type="button" value = "Update" onclick=" ... ")
input(type="button" value = "Delete" onclick=" ... ")
// move to next person in the people array ...
The Problem
var obj = '$(people)' does not work as you may expect. You want obj to hold the people array from the people.js file so that you can loop over each object in the array, but this is not what's happening. obj is actually a string value of length 9, so the for loop evaluates 9 string values (not objects). This is why all of your fields are undefined.
To see what I mean, run this code snippet:
var obj = '$(people)';
for (var i = 0; i < obj.length; i++){
console.log(obj[i]);
console.log(obj[i]["name"]);
}
The reason $(people) does not evaluate to an object is mainly because the parent element, script. causes everything below it to evaluate to plain text. The . after the tag causes the template engine to render plain text (see docs: Block in a Tag).
If you wanted to assign people to obj in your inline script you may try it this way:
script
| var obj = #{people};
But this will cause an Unexpected identifier JavaScript error because of the _id field on each item in people. By default _id is an ObjectID hex value from MongoDb so you would have to either remove the _id field from the docs or add quotes to each doc._id so it evaluates to a string. This would all have to be done in person.js before you return the data.
To see what I mean about the Unexpected identifier error, run this code snippet:
// works
var obj = { _id: '583ab33cdaf857b543c76afe',
name: 'john'};
// Error: Unexpected identifier
var obj = { _id: 583ab33cdaf857b543c76afe,
name: 'john'};
When I query a database table, I get back values "yes" or "no" for records that represent whether an item is present or not (the item is the column name). I want to create a string that represents the products that are available by name (rather than what I am doing now "kitchen table =" + kitchenTable;
I am thinking this can be solved (poorly) by a series of if statements setting variables to either the product name or to "" and then include all variables in the string
var kt;
if (kitchenTable == yes) kt = "kitchen table";
else kt = "";
if (kitchenCabinet == yes) kc = "kitchen cabinet";
else ka = "";
output = kt + ', ' + kc;
There are about 50 items that can be presented to the user, is there a more efficient way of accomplishing this task?? One option is to change how values are entered into the datbase table such that instead of yes, its the item name but this seems like a poorer way to resolve the issue
Of course you don't give all the details about how do you make query so that is an imaginary mockup of a function simulating query
var available = [];
var result = query("kitchen table");
result === "yes" && ( available.push("kitchen table") );
......
var output = available.join();
What you want is actually built into javascript itself.
I would say using an object literal will really simply your life in this situation by organizing your code and turning it into a more readable format.
I would also recommend turning your server data into true and false as this is a standardized way to communicated a Boolean and allows for the method below to work as it does:
// From server response
var results = {
kitchenCabinet: true,
kitchenTable: true
}
// Use this for your storage of all related items
var kitchenProps = {
kitchenCabinet: 'kitchen cabinet',
kitchenTable: 'kitchen table'
}
// Reuse this function for each time your need a new category (masterBathroomProps...)
function getItemDataIfExists(results, hashTable){
'use strict';
var output = 'Your total is: ';
for (var item in results) {
if (!results.hasOwnProperty(item)) return;
if (results[item]) output += 'A '+hashTable[item]+' ';
}
return output;
}
getItemDataIfExists(results, kitchenProps);
Explanation:
You loop through a result set of an object containing keys names and true false values. In the loop, if the keyname's value is true, then use that keyname to access the properties (in this case a string of your choice. The "key" here is that the key names in each object must line up.
Here is a live demo:
http://codepen.io/nicholasabrams/pen/JXXbYz?editors=0010