How to grab the previous and next id from an array - javascript

I'm trying to create next and previous buttons for my blog page. My blogs posts are stored within a table in my MySQL database. At the moment I'm getting the following result.
So I can get the current id and current title, but I'm not sure how to go about displaying the previous and next one on a page.
JavaScript code:
router.get('/posts/:permalinkSlug', async(req, res, next) => {
try {
var blogPostArray = []
var results = await _db.rawSql('SELECT id, permalink_slug FROM blog_posts')
blogPostArray.push(results)
const permalinkSlug = req.params.permalinkSlug
const post = await postTools.getPostByPermalinkSlug(permalinkSlug)
res.locals.current_id = post.id
console.log(res.locals.current_id)
console.log(permalinkSlug)
for (i = 0; i < blogPostArray.length; i++) {
console.log(blogPostArray[i])
}
if (post) {
res.render('post/post', {
post: post,
page: await _db.findOne('posts', {})
})
} else next()
} catch (err) {
next(err)
}
})
New code:
var results = await _db.rawSql('SELECT id FROM blog_posts')
console.log(results)
Result:
[
RowDataPacket { id: 12 },
RowDataPacket { id: 13 },
RowDataPacket { id: 14 },
RowDataPacket { id: 15 }
]

If res.locals.current_id is giving a value then following will do the trick.
Replace this code like this:
blogPostArray.push(JSON.parse(JSON.stringify(results)));
This is a bug as methioned here.
var blogPostArray = [{
id: 12,
permalink_slug: 'title1'
},
{
id: 13,
permalink_slug: 'title2'
},
{
id: 14,
permalink_slug: 'title3'
},
{
id: 15,
permalink_slug: 'title4'
}
];
var res = {
locals: {
current_id: 14
}
};
var index = blogPostArray.findIndex(x => Number(x.id) == Number(res.locals.current_id));
var next = getNext(index);
var prev = getPrev(index);
console.log(prev, next);
function getNext(sr) {
sr = Number(sr);
if (sr + 1 == blogPostArray.length) {
return {}
}
return blogPostArray[sr + 1];//if not working try using blogPostArray[0][sr + 1] or blogPostArray[1][sr + 1]
}
function getPrev(sr) {
sr = Number(sr);
if (sr - 1 == -1) {
return {}
}
return blogPostArray[sr - 1];//if not working try using blogPostArray[0][sr - 1] or blogPostArray[1][sr - 1]
}
inside the loop you can use the code as follows:
for (i = 0; i < blogPostArray.length; i++) {
console.log(getNext(i))
console.log(getPrev(i))
}

Related

How does if else works?

I'm trying to figure out where my problem comes from in my algorithm.
I am trying to give the information about the connection status of a data sender with its data table.
I have translated it like this:
if new data is received ( new_id different from id_from_last_request) then I set the connection status to "connected" otherwise I set it to "disconnected"
<script>
export default {
data() {
return {
search: '',
tag_id: ['bts_d02c2b7d9098aaa2', 'bts_c077ffaa9098aaa2'],
headers: [
{
text: 'Tags',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'wifi', value: 'wifi' },
],
val_ia: 0,
desserts: [],
id_memory: [],
}
},
mounted() {
this.CreateTable();
setInterval(this.getDatafor, 1000)
},
methods: {
CreateTable() {
for (let i = 0; i < this.tag_id.length; i++) {
this.desserts.push(
{
name: this.tag_id[i],
},
)
}
},
async getDatafor() {
for (let i = 0; i < this.desserts.length; i++) {
this.val_ia = i;
await Promise.all([this.getAllData()]);
}
},
async getAllData() {
const tag_id_name = encodeURIComponent(this.tag_id[this.val_ia]);
const url = this.$api.getRESTApiUri() + `/all/last_id/${tag_id_name}`;
return fetch(url)
.then(res => res.text())
.then((result) => {
console.log(tag_id_name)
console.log(this.id_memory[this.val_ia]);
console.log(data[0].id)
const b = this.Test(this.id_memory[this.val_ia], data[0].id);
console.log(b)
if(b){
this.desserts[this.val_ia].wifi = 'connecté'
console.log('connecté')
}else{
this.desserts[this.val_ia].wifi = 'déconnecté'
console.log('déconnecté')
}
this.id_memory[this.val_ia] = data[0].id
})
.catch((error) => {
console.log(error)
});
},
Test(x, y) {
const a = x !== y
return a
},
}
}
</script>
Only in case I have no new data
const b = false
here is my console:
I should have the disconnected status only it shows me the connected status
There should be a logical explanation to it but I can't see it..
You are using equality without type coersion (x !== y) in your Test method.
Probably this.id_memory[this.val_ia] and data[0].id have different types - one is number, second one is string or otherwise.
The best solution is to convert those values to the same type before comparing like so:
Test(x,y){
return String(x) !== String(y)
}
Some use cases:
'123' === 123 // false
'123' == 123 // true
When creating my table, I forgot to push variables wifi and bluetooth so they did not update themselves.
CreateTable(){
for(let i = 0; i < this.tag_id.length; i++){
this.desserts.push(
{
name: this.tag_id[i],
wifi: 'déconnecté',
bluetooth: 0,
tension: 0,
courant: 0,
temperature: 0,
acceléromètre: 0,
pression_sys: 0,
pression_dias: 0,
frequence_cardiaque: 0,
taux_oxygène: 0,
},
)
}
},

Node.js - How to merge objects inside an array based on condition?

In Node.js, I have 3 sets of data like
[
{
"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
"dailyData":159392.235451,
"dailyDataInUSC":255.284807
}
]
and
[
{
"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
"monthlyData":159392.235451,
"monthlyDataInUSC":255.284807
},
{
"userId":"23fs6fds3-34k4-17de-3123-d2ec81e8aaf3",
"monthlyData":349392.455451,
"monthlyDataInUSC":655.234807
}
]
and
[
{
"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
"threeMonthsData":159392.235451,
"threeMonthsDataInUSC":255.284807
},
{
"userId":"23fs6fds3-34k4-17de-3123-d2ec81e8aaf3",
"threeMonthsData":349392.455451,
"threeMonthsDataInUSC":655.234807
},
{
"userId":"34sdf34-67j4-54nd-6763-d2ec81e8aaf3",
"threeMonthsData":6789392.455451,
"threeMonthsDataInUSC":905.655807
}
]
How can I combine this to one object based on userId(filter) inside an array.
Eg, output should be like
[
{
"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
"dailyData":159392.235451,
"dailyDataInUSC":255.284807,
"monthlyData":159392.235451,
"monthlyDataInUSC":255.284807,
"threeMonthsData":159392.235451,
"threeMonthsDataInUSC":255.284807
}
]
Please help me to achieve this.
A combination of spread, reduce and findIndex can be used to solve the problem.
Combine the original arrays into a single array using the spread operator.
Use reduce to group the elements by key (in this case userId)
Something like this :
const dailyData = [{"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3","dailyData":159392.235451,"dailyDataInUSC":255.284807}];
const monthlyData = [{"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3","monthlyData":159392.235451,"monthlyDataInUSC":255.284807}, {"userId":"23fs6fds3-34k4-17de-3123-d2ec81e8aaf3","monthlyData":349392.455451,"monthlyDataInUSC":655.234807}]
const triMonthlyData = [{"userId":"54c7f3ef-64d4-40de-8100-d2ec81e8aaf3","threeMonthsData":159392.235451,"threeMonthsDataInUSC":255.284807}, {"userId":"23fs6fds3-34k4-17de-3123-d2ec81e8aaf3","threeMonthsData":349392.455451,"threeMonthsDataInUSC":655.234807}, {"userId":"34sdf34-67j4-54nd-6763-d2ec81e8aaf3","threeMonthsData":6789392.455451,"threeMonthsDataInUSC":905.655807}]
const combinedData = [...dailyData, ...monthlyData, ...triMonthlyData].reduce((mergedResult, curElement) => {
let matchingElementIdx = mergedResult.findIndex(ele => ele.userId === curElement.userId);
if (matchingElementIdx !== -1) {
mergedResult[matchingElementIdx] = {...mergedResult[matchingElementIdx], ...curElement};
} else {
mergedResult = [...mergedResult, curElement];
}
return mergedResult;
}, []);
console.log(combinedData);
const aa = () => {
let aa = [
{
userId: "54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
dailyData: 159392.235451,
dailyDataInUSC: 255.284807
}
];
let bb = [
{
userId: "54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
monthlyData: 159392.235451,
monthlyDataInUSC: 255.284807
},
{
userId: "23fs6fds3-34k4-17de-3123-d2ec81e8aaf3",
monthlyData: 349392.455451,
monthlyDataInUSC: 655.234807
}
];
let cc = [
{
userId: "54c7f3ef-64d4-40de-8100-d2ec81e8aaf3",
threeMonthsData: 159392.235451,
threeMonthsDataInUSC: 255.284807
},
{
userId: "23fs6fds3-34k4-17de-3123-d2ec81e8aaf3",
threeMonthsData: 349392.455451,
threeMonthsDataInUSC: 655.234807
},
{
userId: "34sdf34-67j4-54nd-6763-d2ec81e8aaf3",
threeMonthsData: 6789392.455451,
threeMonthsDataInUSC: 905.655807
}
];
let newArrObj = aa;
bb.forEach(item => {
let index = newArrObj.findIndex(item1 => item1.userId === item.userId);
if (index === -1) {
newArrObj = [...newArrObj, item];
} else {
newArrObj[index] = { ...newArrObj[index], ...item };
}
});
cc.forEach(item => {
let index = newArrObj.findIndex(item1 => item1.userId === item.userId);
if (index === -1) {
newArrObj = [...newArrObj, item];
} else {
newArrObj[index] = { ...newArrObj[index], ...item };
}
});
console.log(newArrObj);
};

What is wrong with this javascript closure?

I have a recursive function (exploreNode)that updates the value of a variable (branch_queue) that is declared right above it.
When I run normally (without a closure function), it works as expected.
When I place inside of a closure function, the recursive function doesn't iterated through children nodes the way its supposed to. it remains on the same initial node, until a "Max Call Stack" error fires.
The purpose of the recursive function is to explore a JSON tree, until a desired ID is found. As it traverses through the tree, the branch_queue var is updated with the roadmap to the node of interest.
The closure was to not have the branch_queue as a global function.
I tried both in es6 and es5, thinking it could be a problem with scope and using "const" and "let".
The examples are below.
I also have the code block below that worked without the closure.
Tree that I feed in as a parameter
let u = [
{
id: 0,
label: 'l0',
children: [
{
id: 1,
label: 'l1'
},
{
id: 2,
label: 'l2',
children: [
{
id: 3,
label: 'l3'
},
{
id: 4,
label: 'l4'
},
{
id: 5,
label: 'l5'
},
{
id: 6,
label: 'l6',
children: [
{
id: 7,
label: 'l7'
},
{
id: 8,
label: 'l8'
},
{
id: 9,
label: 'l9'
},
{
id: 10,
label: 'l10'
}
]
}
]
}
]
}
]
WHAT DID WORK
let branch_queue = [];
// Assumes that the ID exists!
const exploreNode = (nodeIdOfInterest, nodeTree) => {
// var branch_queue = [];
for (let i = 0; i < nodeTree.length; i++) {
const nodeToCheck = nodeTree[i];
if (nodeToCheck.id == nodeIdOfInterest) {
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
}
exploreNode(3, contentTree);
console.log(branch_queue); // prints the correct roadmap
WHAT DOESN'T WORK
ES5
function fn (nodeIdOfInterest, nodeTree) {
let branch_queue = [];
console.log('here');
// Assumes that the ID exists!
function exploreNode () {
var branch_queue = [];
console.log('in here');
for (var i = 0; i < nodeTree.length; i++) {
var nodeToCheck = nodeTree[i];
console.log(`${nodeToCheck.label} : ${nodeToCheck.id}`);
if (nodeToCheck.id == nodeIdOfInterest) {
console.log('found it');
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
console.log('checking children');
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
};
exploreNode();
return branch_queue;
}
console.log(fn(3, contentTree)); // throws call stack error
ES6
const fn = (nodeIdOfInterest, nodeTree) => {
let branch_queue = [];
console.log('here');
// Assumes that the ID exists!
const exploreNode = () => {
// var branch_queue = [];
console.log('in here');
for (let i = 0; i < nodeTree.length; i++) {
let nodeToCheck = nodeTree[i];
console.log(`${nodeToCheck.label} : ${nodeToCheck.id}`);
if (nodeToCheck.id == nodeIdOfInterest) {
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
};
exploreNode();
return branch_queue;
};
console.log(fn(3, contentTree)); // throws call stack error
Expected output => [0 2 3]
Actual => . Max call stack error
The recursive function never moves beyond the very first level, and repeats indefinitely.
nodeTree in your recursive version of exploreNode is always the same starting point, the one passed into fn. Every call to exploreNode in that version starts fresh: Your calls to exploreNode are passing arguments, but it's ignoring them. The "what did work" version isn't ignoring the arguments passed to it, so it works.

Matching a string to one of many patterns and extracting data

I have a problem I want to solve with RegEx, or any other method if there is a better one. I've tried several ways to achieve the goal, but nothing really worked.
I have an array with endpoints:
const endpoints = [
{
id: 1,
url: "/api/items/:itemId"
},
{
id: 2,
url: "/api/users/:userName/delete"
},
{
id: 3,
url: "/api/users/:userName/edit"
}
];
And a request URL:
const url = "/api/users/max/edit";
Now what I want is to have a function which acts like this:
const rewrite = (url, endpoints) => {
// What is the best way to achieve the following return value:
return {
endpointId: 3,
values: {
userName: "max"
}
};
};
Explanation: The function should find the appropriate endpoint for the url. All parts of the endpoint url which start with a colon are not static, but should rather be replaced with values from the request url. In this case :userName should be replaced with max.
I've been in web development for some time now, but to be honest I've almost no clue how to solve such a problem.
const rewrite = (url, endpoints) => {
var doubledArray = Array.prototype.map.call(endpoints, function(el) {
return {
id: el.id,
url: el.url.split('/')
};
});
var parts = url.split('/');
var i = 0;
parts.forEach(function(element) {
doubledArray = doubledArray.filter(el => (element == el.url[i] || el.url[i].startsWith(':')));
i++;
});
return {
endpointId: doubledArray[0].id,
values: {
[`${doubledArray[0].url.filter(el => el.startsWith(':'))[0].substring(1)}`]: parts[doubledArray[0].url.findIndex(function (el) { return el.startsWith(':'); } )],
}
};
};
You can go through the endpoints making each .url into a RegExp to test the url against.
When a matching one is found, it is just a matter of extracting the needed part and making up an Object with the property name:
<script>
const myEndpoints = [
{
id: 1,
url: "/api/items/:itemId"
},
{
id: 2,
url: "/api/users/:userName/delete"
},
{
id: 3,
url: "/api/users/:userName/edit"
}
];
const myUrl = "/api/users/nermal/edit";
const rewrite = (url, endpoints) => {
for (let i = 0; i < endpoints.length; i++) {
var rep = new RegExp(":(\\w+)", "m");
var propName = rep.exec(endpoints[i].url);
var reu = new RegExp(endpoints[i].url.replace(propName[0], "(.*)"));
var a = reu.exec(url);
if (a !== null) {
var x = new Object;
x["endpointId"] = endpoints[i].id;
var y = new Object;
y[propName[1]] = a[1];
x["values"] = y;
return x;
}
}
return null;
};
var q = rewrite(myUrl, myEndpoints);
console.log(q);
console.log(q.values);
</script>
Outputs:
Object { endpointId: 3, values: {…} }
Object { userName: "nermal" }

Semantic UI - Search API: how I can highlight certain characters that match the query?

I have a problem when I want to highlight certain characters that match the query in search module.
an example is like this forum: https://forums.meteor.com
Previously, I already asked this issue at https://github.com/Semantic-Org/Semantic-UI/issues/4930#issuecomment-275011130, but until now not been resolved.
here is my current demo: https://jsfiddle.net/agaust/5854gae9/4/
$(document).ready(function() {
$.fn.api.settings.api = {
'search': 'https://gist.githubusercontent.com/agusmakmun/e258a3243367105c32919c083eb577fe/raw/8b0038b0141f5813c03baece0b2730e17216f8c9/result-data.json?q={query}'
};
$('.ui.search.quick-search').search({
type : 'category',
minCharacters : 1, // just under devel to make it easy
apiSettings : {
action: 'search',
onResponse: function(searchApiResponse) {
var response = {
results : {},
//action : searchApiResponse.action // dict action
};
// translate `searchApiResponse` response to work with search
var numbThreads = 0, numbUsers = 0;
$.each(searchApiResponse.items, function(index, item) {
var
model = item.model || 'Unknown',
maxResults = 6,
maxItems = maxResults/2 // max results per-Category
;
if(index >= maxResults) {
return false;
}
// create new model category
if(response.results[model] === undefined) {
response.results[model] = {
name : model,
results : []
};
}
if(item.model === 'Threads') {
if ((numbThreads < maxItems) || (numbUsers < numbThreads)) {
response.results[model].results.push({
title: item.title,
description: item.description,
url: item.url
});
}
numbThreads++;
}else if (item.model === 'Users') {
if ((numbUsers < maxItems) || (numbThreads < numbUsers)) {
response.results[model].results.push({
title: item.username,
description: item.username,
url: item.profile_url,
image: item.gravatar_url,
price: item.total_threads
});
}
numbUsers++;
}
});
// only showing the bottom action button if under limited
if (searchApiResponse.limited_items) {
response["action"] = searchApiResponse.action;
}
console.log(response);
return response;
}
}
});
});
any help would be apreciated.. :)

Categories

Resources