I have a simple project with some comboboxes that set values to localStorage (39 comboboxes)
i figured out a way to copy whole localStorage to clipboard
// копирование всего localStorage в буфер обмена
async function copyJson() {
try {
await navigator.clipboard.writeText(
JSON.stringify(localStorage)
);
console.log('Content copied to clipboard');
/* Resolved - text copied to clipboard successfully */
} catch (err) {
console.error('Failed to copy: ', err);
/* Rejected - text failed to copy to the clipboard */
}
}
Then i'm able to clear local storage:
// полная очистка localStorage
function clearJson() {
localStorage.clear();
}
Now that's clear, i need to paste data from clipboard, which could look like this:
{"postval":"Пусто","kuzval1":"Пусто","kuzparkval11":"Пусто"}
I tried to use this code:
// вставка localStorage (В разработке!)
var raw = navigator.clipboard.readText(JSON.stringify())
// This will check if raw is valid JSON
async function loadJson(){
try {
localStorage.setItem(raw,raw);
}
catch (e) {
// show error to user
}
}
But instead of pasting values and keys, all it stores is this:
{"[object Promise]":"[object Promise]"}
How can i overcome this problem?
readText already returns you a string so you don't need to stringify.
And setItem can only set 1 string key at once so you need to iterate through your data and set 1 by 1.
// вставка localStorage (В разработке!)
var raw = navigator.clipboard.readText()
// This will check if raw is valid JSON
async function loadJson(){
const storageData = JSON.parse(raw)
try {
for (const key in storageData) {
localStorage.setItem(key, storageData[key]);
}
}
catch (e) {
// show error to user
console.error(e)
}
}
Related
I tried the following, where the country is the new item I want to push/add to the pre-existing countries using text input and concat to previous array data like this.
e.g.
saveData = async () => {
try {
let countries = AsyncStorage.getItem('countries');
AsyncStorage.setItem('countries', countries.concat(this.state.country));
alert('Data successfully saved')
console.log('countries',countries)
} catch (e) {
alert(e)
}
}
//I tried Many Solutions..
var countries = await AsyncStorage.getItem('countries');
AsyncStorage.setItem('countries', countries += JSON.stringify(country));
//my output is like this
e.g : "name""email""address"
means no comma no bracket like arrays
i want output like this e.g ['name','email','address']
I tried many solutions but I did not get results. Can anybody help me?
Hope it works for you
const saveData = async () => {
try {
let countries = AsyncStorage.getItem("countries")
if (countries) {
countries = JSON.parse(countries)
AsyncStorage.setItem(
"countries",
JSON.stringify(countries.push(this.state.country))
)
} else
AsyncStorage.setItem("countries", JSON.stringify([this.state.country]))
alert("Data successfully saved")
console.log("countries", countries)
} catch (e) {
alert(e)
}
}
AsyncStorage can only store string data. It is pointed out in the documentation. Usage | AsyncStorage
Async Storage can only store string data, so in order to store object data you need to serialize it first. For data that can be serialized to JSON you can use JSON.stringify() when saving the data and JSON.parse() when loading the data.
If you want to store array or objects you need to convert and store it as json. And when you want to retrieve that data you just need to parse it and convert it to array again like the docs says.
saveData = async () => {
try {
let countries = AsyncStorage.getItem('countries');
if (countries) countries = JSON.parse(countries);
AsyncStorage.setItem('countries', JSON.stringify(countries.concat(this.state.country)));
alert('Data successfully saved')
console.log('countries', countries)
} catch (e) {
alert(e)
}
}
I've written a webapp that allows you to store the images in the localStorage until you hit save (so it works offline, if signal is poor).
When the localStorage reaches 5MB Google Chrome produces an error in the javascript console log:
Uncaught Error: QUOTA_EXCEEDED_ERR: DOM Exception 22
How do I increase the size of the localStorage quota on Google Chrome?
5MB is a hard limit and that is stupid. IndexedDB gives you ~50MB which is more reasonable. To make it easier to use try Dexie.js https://github.com/dfahlander/Dexie.js
Update:
Dexie.js was actually still an overkill for my simple key-value purposes so I wrote this much simpler script https://github.com/DVLP/localStorageDB
with this you have 50MB and can get and set values like that
// Setting values
ldb.set('nameGoesHere', 'value goes here');
// Getting values - callback is required because the data is being retrieved asynchronously:
ldb.get('nameGoesHere', function (value) {
console.log('And the value is', value);
});
Copy/paste the line below so ldb.set() and ldb.get() from the example above will become available.
!function(){function e(t,o){return n?void(n.transaction("s").objectStore("s").get(t).onsuccess=function(e){var t=e.target.result&&e.target.result.v||null;o(t)}):void setTimeout(function(){e(t,o)},100)}var t=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;if(!t)return void console.error("indexDB not supported");var n,o={k:"",v:""},r=t.open("d2",1);r.onsuccess=function(e){n=this.result},r.onerror=function(e){console.error("indexedDB request error"),console.log(e)},r.onupgradeneeded=function(e){n=null;var t=e.target.result.createObjectStore("s",{keyPath:"k"});t.transaction.oncomplete=function(e){n=e.target.db}},window.ldb={get:e,set:function(e,t){o.k=e,o.v=t,n.transaction("s","readwrite").objectStore("s").put(o)}}}();
You can't, it's hard-wired at 5MB. This is a design decision by the Chrome developers.
In Chrome, the Web SQL db and cache manifest also have low limits by default, but if you package the app for the Chrome App Store you can increase them.
See also Managing HTML5 Offline Storage - Google Chrome.
The quota is for the user to set, how much space he wishes to allow to each website.
Therefore since the purpose is to restrict the web pages, the web pages cannot change the restriction.
If storage is low, you can prompt the user to increase local storage.
To find out if storage is low, you could probe the local storage size by saving an object then deleting it.
You can't but if you save JSON in your localStorage you can use a library to compress data like : https://github.com/k-yak/JJLC
demo : http://k-yak.github.io/JJLC/
Here you can test your program , you should handle also the cases when the cuota is exceed
https://stackoverflow.com/a/5664344/2630686 The above answer is much amazing. I applied it in my project and implement a full solution to request all kinds of resource.
// Firstly reference the above ldb code in the answer I mentioned.
export function get_file({ url, d3, name, enable_request = false }) {
if (name === undefined) { // set saved data name by url parsing alternatively
name = url.split('?')[0].split('/').at(-1).split('.')[0];
}
const html_name = location.href.split('/').at(-1).split('.')[0]
name = `${html_name}_${name}`
let ret = null;
const is_outer = is_outer_net(url); // check outer net url by its start with http or //
// try to access data from local. Return null if not found
if (is_outer && !enable_request) {
if (localStorage[name]) {
ret = new Promise(resolve => resolve(JSON.parse(localStorage[name])));
} else {
ret = new Promise(r => {
ldb.get(name, function (value) {
r(value)
})
});
}
} else {
ret = new Promise(r => r(null))
}
ret.then(data => {
if (data) {
return data
} else {
const method = url.split('.').at(-1)
// d3 method supported
if (d3 && d3[method]) {
ret = d3[method](url)
} else {
if (url.startsWith('~/')) { // local files accessed supported. You need a local service that can return local file data by requested url's address value
url = `http://localhost:8010/get_file?address=${url}`
}
ret = fetch(url).then(data => {
// parse data by requested data type
if (url.endsWith('txt')) {
return data.text()
} else {
return data.json()
}
})
}
ret = ret.then(da => {
data = da
if (is_outer) { // save data to localStorage firstly
localStorage[name] = JSON.stringify(data);
}
}).catch(e => { // save to ldb if 5MB exceed
ldb.set(name, data);
}).finally(_ => {
return data;
});
}
})
return ret;
}
I use the following to send some data to another window;
try{
win.webContents.once('dom-ready', () => win.webContents.send('send-data', data));
}
catch(err){
console.log("Caught ",err);
}
And for receivig;
ipcRenderer.on('send-data', function (event,data) {
console.log("Loaded ", data);
});
The thing is, the "data" here is sometimes assembled very quickly and it works fine. However, sometimes it takes a while and the other window is already loaded at this point. No data is received in that case, and no error message either. But then I can simply use the following to send it without problems;
win.webContents.send('send-data', data)
I couldn't find a way to apply for both cases. Any suggestions?
The short answer is no.
Electron doesn't have a function to wait for the window to load, then send a message, or send a message right away if the window's already loaded.
However this can be done with some simple code:
var hasWindowLoaded = false;
var hasDataBeenSent = false;
var data = {};
win.webContents.once('dom-ready', () => {
hasWindowLoaded = true;
if (!hasDataBeenSent && data) {
win.webContents.send('send-data', data);
hasDataBeenSent = true;
}
});
// Now add this where you build the `data` variable.
function loadData () {
data = {'sampleData': 'xyz'};
if (!hasDataBeenSent && hasWindowLoaded) {
win.webContents.send('send-data', data);
hasDataBeenSent = true;
}
}
Once the data's loaded in loadData it'll check if the window's finished loading and if it has then it sends the data right away.
Otherwise it stores the data in a varible (data) and once the window loads it sends it to the window.
Another approach that you may want to consider is sending data to the browserWindow using query strings.
const data = { hello: "world" }; // sample data
// send it using query strings
browserWindow.loadFile(YOUR_HTML_FILE_PATH, {
query: { data: JSON.stringify(data) },
});
// parse this data in the browserWindow
const querystring = require("querystring");
const query = querystring.parse(global.location.search);
const data = JSON.parse(query["?data"]);
console.log(data); // { hello: "world" }
I am trying to use the WebMidi.js library to read inputs from my midi controller.
When I try to log the inputs or outputs, it comes up as an empty array. Here is my code:
WebMidi.enable(function (err) {
if (err) {
console.log("WebMidi could not be enabled.", err);
} else {
console.log("WebMidi enabled!");
console.log(WebMidi.inputs);
console.log(WebMidi.outputs);
}
});
The log I get is 2 empty arrays for input and output.
And here are pictures of my Midi Studio setup in Mac. I'm not sure if I'm supposed to do some extra configuration here to make my Roland A-PRO show up as an input/output. I see that it is grayed out which makes me think it must need some extra configuration.
The controller works when I run it through Ableton, however.
example for vanilla JS
function midiOnStateChange(event) {
console.log('midiOnStateChange', event);
}
function midiOnMIDImessage(event) {
console.log('midiOnMIDImessage', event);
}
function requestMIDIAccessSuccess(midi) {
var inputs = midi.inputs.values();
for (var input = inputs.next(); input && !input.done; input = inputs.next()) {
console.log('midi input', input);
input.value.onmidimessage = midiOnMIDImessage;
}
midi.onstatechange = midiOnStateChange;
}
navigator.requestMIDIAccess().then(requestMIDIAccessSuccess);
run example in browser
https://surikov.github.io/webaudiofont/examples/midikey.html
I want to add multiple lines of data into an IndexedDB. The data will be parsed from CSV file, each line has an id. Only new id's should be added to the DB, so I use add. This works well so far.
But how can i find out, which lines/objects where NOT added? (because of duplicate id's) If I use onerror and inspect the object e on console of chrome, I can not find the object, which I send to the DB. So i only know, something was not added, but not what it was. So how to track this?
// ....
for (var key in csvObject.data ) {
var request = store.add(csvObject.data[key]);
}
request.onerror = function(e) {
console.log(e); // e contains not the value of CSVobject.data[key]
};
You should do this. Write the function within the loop and pass your object as an argument to it.
for (var key in csvObject.data) {
(function(obj) {
var request = store.add(obj);
request.onerror = function(e) {
console.log(obj, e.target.error, e.target.source); // some error messages
};
})(csvObject.data[key]);
}