Localstorage display only latest string of array - node.js

I followed a tutorial on how to make a live chat room. But now the problem is that the messages will dissapear after a refresh. So instead I tried to store those messages that get submitted by the user in localStorage. But I can't get it to work. Because when I try it it would just keep showing me the whole array instead of the lastest new string that was added to the array. The chatroom is made with socket.io and I am using nodejs.
This is what I tried first:
function appendMessage(message) {
const messageElement = document.createElement('div')
messageContainer.append(messageElement)
var a = []
if (localStorage.getItem('session') == null) {
} else {
a = JSON.parse(localStorage.getItem('session'))
}
a.push(message)
localStorage.setItem('session', JSON.stringify(a))
messageElement.innerText = a
}
But it would just show me the whole array. So then I tried this:
function appendMessage(message) {
const messageElement = document.createElement('div')
messageContainer.append(messageElement)
var a = []
if (localStorage.getItem('session') == null) {
} else {
a = JSON.parse(localStorage.getItem('session'))
}
a.push(message)
localStorage.setItem('session', JSON.stringify(a))
messageElement.innerText = a[a.length -1]
}
But this won't show it correctly because after a refresh the text is gone. How could I make it so that it would only show the latest new string that is stored in the localStorage inside the array that stays there after a page refresh?

Related

Meteor Tabular not reacting to ReactiveDict's values changing

I'm using the great Tabular package. https://github.com/Meteor-Community-Packages/meteor-tabular.
I'm making use of the client-side selector helper to Reactively change my table by having Server modify the query for my dataset.
I have multiple HTML inputs that act as filters and am populating a ReactiveDict with the values. A search-button click event triggers the ReactiveDict to get populated with an Object using .set
Initialization of ReactiveDict
Template.tbl.onCreated(function () {
const self = this;
self.filters = new ReactiveDict({});
});
Population of ReactiveDict
'click #search-button'(e, template) {
//clear to 'reset' fields in ReactiveDict that could've been cleared by User
template.filters.clear();
const searchableFields = getSearchableFields();
//Initialize standard JS Obj that ReactiveDict will then be set to
const filterObj = {};
//Loop through search fields on DOM and populate into Obj if they have a val
for (let field of searchableFields) {
const value = $(`#${field}-filter`).val();
if (value) {
filterObj[field] = new RegExp(escapeStringRegex(value.trim()), 'i');
}
}
if (Object.keys(filterObj).length) {
template.filters.set(filterObj);
}
},
Selector Helper
selector: () => {
const filters = Template.instance().filters.all();
const selector = { SOME_DEFAULT_OBJ, ...filters };
return selector;
},
I'm noticing the server doesn't notice any changes from a ReactiveDict if all keys remain the same.
I'm testing this by logging in the serve-side's changeSelector md and verifying that my logging does not occur if just a value in selector has changed.
Is there a solution to this?
I.e. {foo:'foo'} to {foo:'bar'} should reactively trigger the server to re-query but it does not. But {foo:'foo'} to {bar:'bar'} would get triggered.
Is this an issue with how I'm using the ReactiveDict or is this on the Tabular side?
Thanks

Why does my for loop only goes through once when i call function inside it?

I got list of videos from API, it has list of urls fo thumbnail and i would like to combine thumbnails of each video to gif. When i loop through videos and don't generate gifs it goes through 5 times as expected, but if i include function that should generate gifs it only goes through once, without any errors. I have no idea what is happening
I'm using node.js, discord.js, get pixels and gif-encoder modules to generate thumbnails.
for(i=0;i<5;i++){
generateThumbnail(data[i].video.video_id,data[i].video.thumbs,function(){
var tags = '';
for(t=0;t<data[i].video.tags.length;t++){
tags = tags + data[i].video.tags[t].tag_name+', ';
}
fields = [
{name:data[i].video.title,
value:value},
{name:'Tags',
value:tags}
]
msg.channel.send({embed: {
color: 3447003,
thumbnail: {
"url": ""
},
fields: fields,
}});
});
}
function generateThumbnail(id,images,fn){
var pics = [];
console.log(id)
var file = require('fs').createWriteStream(id+'.gif');
var gif = new GifEncoder(images[0].width, images[0].height);
gif.pipe(file);
gif.setQuality(20);
gif.setDelay(1000);
gif.setRepeat(0)
gif.writeHeader();
for(i=0;i<images.length;i++){
pics.push(images[i].src)
}
console.log(pics)
addToGif(pics,gif);
fn()
}
var addToGif = function(images,gif, counter = 0) {
getPixels(images[counter], function(err, pixels) {
gif.addFrame(pixels.data);
gif.read();
if (counter === images.length - 1) {
gif.finish();
} else {
addToGif(images,gif, ++counter);
}
})
}
if i dont use GenerateThumbnail function it goes through 5 times as expected and everything works fine, but if i use it it goes through only once, and generated only 1 gif
Use var to declare for vars. Ie for(var i=0....
If you declare vars without var keyword, they are in the global scope. ..... and you are using another i var inside the function but now it is the same var from the outer for loop.

Why is array.push() not working correctly?

I have a function which returns an array of dishes from a firestore database.
With console.log I check that the dish I want to push is correctly formatted, then push it.
Finally I console.log the array to check if everything is alright.
Here is what I got:
https://image.noelshack.com/fichiers/2019/05/5/1549048418-arraypush.png
switch (type) {
case "Plats": {
this.nourritureCollection.ref.get().then(data => {
let platArray : Plat[] = [];
data.docs.forEach(doc => {
this.plat.name = doc.data().nourritureJson.name;
this.plat.price = doc.data().nourritureJson.price;
this.plat.ingredients = doc.data().nourritureJson.ingredients;
this.plat.type = doc.data().nourritureJson.type;
this.plat.availableQuantity = doc.data().nourritureJson.availableQuantity;
this.plat.isAvailableOffMenu = doc.data().nourritureJson.isAvailableOffMenu;
this.plat.imgUrl = doc.data().nourritureJson.imgUrl;
this.plat.temp = doc.data().nourritureJson.temp;
console.log(this.plat)
platArray.push(this.plat);
});
console.log(platArray)
return platArray;
});
break;
}...
plat is instantiated within my service component, I couldn't declare a new Plat() inside my function.
The expected result is that dishes should be different in my array of dishes.
You are updating this.plat in every iteration. So it will have n number of references in the array pointing to the same object, therefore, the values for all the array elements will be last updated value of this.plat
What you need is to create new Plat object for every iteration.
data.docs.forEach(doc => {
let plat: Plat = new Plat();
plat.name = doc.data().nourritureJson.name;
plat.price = doc.data().nourritureJson.price;
plat.ingredients = doc.data().nourritureJson.ingredients;
plat.type = doc.data().nourritureJson.type;
plat.availableQuantity = doc.data().nourritureJson.availableQuantity;
plat.isAvailableOffMenu = doc.data().nourritureJson.isAvailableOffMenu;
plat.imgUrl = doc.data().nourritureJson.imgUrl;
plat.temp = doc.data().nourritureJson.temp;
console.log(plat)
platArray.push(plat);
});
As pointed out in the comment, you can only use new Plat() if Plat is a class, if it is an interface, just let plat:Plat; would do.

Titanium mobile - Common JS. Objects values are lost when lauching a fireEvent

I'm dev an app into titanium mobile in javascript.
The dynamic menu insert each new object(id,text,...., page) into a loop for (var x in tab).
with thoses items, specifics views are made.
var items = [];
var menuIconsItem = require('view/module/menuIconsItem');
for(var i in itemTab) {
var page = itemTab[i].page;
items[i] = new menuIconsItem(itemTab[i]);
menuFirstLine.add(items[i]);
(function(itemsEvent) {
itemsEvent.addEventListener('click', function() {
Ti.App.fireEvent('test' +i, {
id : i
});
})
})(items[i]);
}
on the other controller side, i only get the last id reference.
If i = 0 to 5, i only get the last reference. The rest is undefined.
How could i do please?
First you have to set id for your menuIconsItem, I am taking button an an example here.
items[i] = Titanium.UI.createButton({
id:"button_"+i,
_index: i
})
Then do this:
(function(itemsEvent) {
itemsEvent.addEventListener('click', function(e) {
alert(e.source.id);
})
})(items[i]);

How to snap a polyline to a road with walking travelmode in Google Maps?

II want an user to draw a route with polylines on GoogleMaps. I've found a way to snap a polyline ( example in the link, code in below ). The code works with the directions service to draw a polyline on a road, the only problem is this only works with G_TRAVELMODE_DRIVING but I want to use G_TRAVELMODE_WALKING and when you use WALKING you have to supply the map and a div in the constructor of the directions object. When I do that it automatically removes the last line and only displays the current line. I've tried several things like supplying the map as null, or leaving out the map in the constructor.. I've also tried to give a second map in the constructor, get the polylines from the directions service and display them on the right map. But nothing works! I'd appreciate it if someone could help me!
http://econym.org.uk/gmap/example_snappath.htm
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(53.7877, -2.9832),13)
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
var dirn = new GDirections();
var firstpoint = true;
var gmarkers = [];
var gpolys = [];
var dist = 0;
GEvent.addListener(map, "click", function(overlay,point) {
// == When the user clicks on a the map, get directiobns from that point to itself ==
if (!overlay) {
if (firstpoint) {
dirn.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true});
} else {
dirn.loadFromWaypoints([gmarkers[gmarkers.length-1].getPoint(),point.toUrlValue(6)],{getPolyline:true});
}
}
});
// == when the load event completes, plot the point on the street ==
GEvent.addListener(dirn,"load", function() {
// snap to last vertex in the polyline
var n = dirn.getPolyline().getVertexCount();
var p=dirn.getPolyline().getVertex(n-1);
var marker=new GMarker(p);
map.addOverlay(marker);
// store the details
gmarkers.push(marker);
if (!firstpoint) {
map.addOverlay(dirn.getPolyline());
gpolys.push(dirn.getPolyline());
dist += dirn.getPolyline().Distance();
document.getElementById("distance").innerHTML="Path length: "+(dist/1000).toFixed(2)+" km. "+(dist/1609.344).toFixed(2)+" miles.";
}
firstpoint = false;
});
GEvent.addListener(dirn,"error", function() {
GLog.write("Failed: "+dirn.getStatus().code);
});
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
I know it's an old post, but since no answer came forward and I've recently been working on this sort of code (and got it working), try swapping the addListener with this.
GEvent.addListener(map, "click", function(overlay,point) {
// == When the user clicks on a the map, get directiobns from that point to itself ==
if (!overlay) {
if (firstpoint) {
dirn1.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{ getPolyline:true,travelMode:G_TRAVEL_MODE_WALKING});
} else {
dirn1.loadFromWaypoints([gmarkers[gmarkers.length-1].getPoint(),point.toUrlValue(6)],{ getPolyline:true,travelMode:G_TRAVEL_MODE_WALKING});
}
}
});

Resources