Svelte: how to create a Blob from `writable store`? - blob

How can I use a "writable store" to create a "blob"?
I am new to Svelte.
I am trying to code a simple markdown editor for visually impaired users. The content of the "textarea" is stored in a "writable store" for further use:
speech-synthesis
markdown-preview
the content of an existing text file is stored in it
save text to file
But saving the text content via download to a file does not work.
<script>
let blob = new Bob([$textStore], type:"text/plain");
let url = URL.createObjectURL(blob);
</script>
<button>
<a href={url} download="untitled.md" id="link">Download
</a>
</button>
An empty file is saved or it has the content "[object Object]", when I use curley brackets:
let blob = new Blob ([{$textStore}], {type: 'text/plain'});
File for testing:
// TextStore.js
import { writable } from "svelte/store";
export const textStore = writable('');
<!-- EditorTest.svelte -->
<script>
import { textStore } from "./TextStore.js";
let blob = new Blob ([{$textStore}], {type: 'text/plain'});
let url = URL.createObjectURL(blob);
</script>
<h1>Blob-Test</h1>
<textarea bind:value={$textStore} cols="20" rows="5"></textarea>
<hr>
<pre>{$textStore}</pre>
<br>
<button>
Save
</button>
Can someone help, thanks a lot already.

The main issue is, that the code is not reacting to the changes. The Blob is created once at the beginning, when the store is still empty. You could make it reactive using $:, but that is not a great idea, as it unnecessarily re-creates the Blob over and over.
I would recommend using a click handler on the button (the link inside it is invalid HTML anyway), and then creating the Blob there:
<button on:click={onDownload}>
Save
</button>
function onDownload() {
const blob = new Blob([$textStore], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = 'file.md';
link.href = url;
link.click();
URL.revokeObjectURL(url); // Object URLs should be revoked after use
}

Related

How to read data received by firestore get()

I use vue and firestore.
I receive data through get().
onMounted(async () => {
const forminfo = db.collection('forms').doc(route.params.id)
const doc = await forminfo.get()
content.value = doc.data().content
url.value = doc.data().url
}
And use <p>{{content}} {{ url }} </p> in the template.
However, this method does not reflect the line break when writing and does not make url into an image.
For the image to display from the given url use
<img :src='url'/>
for the line break add <br> where you want to create a new line

Vuejs binding to img src only works on component rerender

I got a component that let's the user upload a profile picture with a preview before sending it off to cloudinary.
<template>
<div>
<div
class="image-input"
:style="{ 'background-image': `url(${person.personData.imagePreview})` } "
#click="chooseImage"
>
<span
v-if="!person.personData.imagePreview"
class="placeholder"
>
<i class="el-icon-plus avatar-uploader-icon"></i>
</span>
<input
type="file"
ref="fileInput"
#change="previewImage"
>
</div>
</div>
</template>
The methods to handle the preview:
chooseImage() {
this.$refs.fileInput.click()
},
previewImage(event) {
// Reference to the DOM input element
const input = event.target;
const files = input.files
console.log("File: ", input.files)
if (input.files && input.files[0]) {
this.person.personData.image = files[0];
const reader = new FileReader();
reader.onload = (e) => {
this.person.personData.imagePreview = e.target.result;
}
// Start the reader job - read file as a data url (base64 format)
reader.readAsDataURL(input.files[0]);
}
},
This works fine, except for when the user fetches a previous project from the DB. this.person.personData.imagePreview get's set to something like https://res.cloudinary.com/resumecloud/image/upload/.....id.jpg Then when the user wants to change his profile picture, he is able to select a new one from his local file system, and this.person.personData.imagePreview is read again as a data url with base64 format. But the preview doesn't work. Only when I change routes back and forth, the correct image selected by the user is displayed.
Like I said in the comment on my post. Turns out I'm an idiot. When displaying the preview, I used this.person.personData.imagePreview . When a user fetches a project from the DB, I just did this.person.personData = response.data. That works fine, apart from the fact that I had a different name for imagePreview on my backend. So I manually set it on the same load method when fetching from the DB like: this.person.personData.imagePreview = this.loadedPersonData.file. For some reason, that screwed with the reactivity of Vue.

Export a web page as a pdf

I want to print a web page in a pdf or extract it as a html single file.
I use data analytics tool (Apache Zeppelin) where I create a report. I want to create a static report from this tool for demo purposes. I cannot export this report from the tool (it is not embedded as an option yet) so I want to try to print in pdf. If I try to simply print it in pdf the result is a mess (images overleaping with text).
Has anyone has an idea on how to do it?
Someone suggested a solution here that you could try. Let me know if it works. Here is the code too:
%angular
<div id="divtest">Wooooo!</div>
<button id="cmd" type="submit" onclick="useJSPDF()">Generate PDF</button>
<script type="text/javascript">
function useJSPDF() {
var element = $('#divtest');
var doc = new jsPDF();
doc.fromHTML(element.html(), 15, 15,
{ 'width': 170, }
);
doc.save('sample-file.pdf');
}
if (window.jsPDF) {
} else
{ var sc = document.createElement('script'); sc.type = 'text/javascript'; sc.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/0.9.0rc1/jspdf.min.js'; sc.onerror = function(err) \{ alert(err); }
document.getElementsByTagName('head')[0].appendChild(sc);
}
</script>
Once the code is being executed, a button should be displayed like this

Storing Image to remote server using Http Adapter

I want to display Image and store Image on remote server.I am using Ibm Worklight Version 6.2.I Have gone through many links but didn't find the solution
My HTML Page code is
<fieldset style="height:auto;width:100% ">
<div id="Image" style="float:left;">
</div>
<div id ="delImage">
</div>
</fieldset>
and my Js Code is
uploadImage = function (){
navigator.camera.getPicture(onSuccessCallBack, onFailCallBack, {
quality: 50,
sourceType: Camera.PictureSourceType.CAMERA,
destinationType: Camera.DestinationType.FILE_URI
});
};
function onSuccessCallBack (imageData){
var img = document.createElement("img");
img.style.width = "60px";
img.style.height="60px";
img.src = imageData;
var Image = document.getElementById("Image");
Image.appendChild(img);
var delImg = document.createElement("img");
delImg.style.width = "60px";
delImg.style.height="60px";
delImg.src = "images/brws_gal.png";
var deleteImg = document.getElementById("delImage");
deleteImg.appendChild(delImg);
var invocationData = {
adapter : 'DisbursalRequestImageAdapter',
procedure : "uploadImageForDisbursal",
parameters : [ requestObject, sessionId, operationFlag,'','' ]
};
var options = {
timeout : timeout,
onSuccess : successCreateImg,
onFailure : failureCreateImg
};
WL.Client.invokeProcedure(invocationData, options);
};
Here, I am appending Dynamic Image in a div.
My Question is
I want to store the image to remote server using Http Adapter
I want to open the picture on the click of Picture.
I am not arrange the div vertically i.e. every time the photo is taken a new div should be created.
If you want to send an image to a remote server, you need to base64 encode the image and then send this string to be stored in the remote server's database.
If you want to then retrieve it you need to get the string and then decode the base64 string back to an image filetype and display the image in your HTML (the image should be stored in the device storage using Cordova APIs as you have demonstrated use of).
In fact, had you searched, the above is what you would've found in searches.

Google Script for Uploading File Not Working

I wrote a script for uploading files to my Google Drive using the Google Script. I deployed it as a WebApp but it's not working and I don't know why. The button just gets stuck on "Subiendo..." and never changes anything inside my Drive. I'm sure I gave the script all the permissions and I already tried to see what's happening on my own without any sucess. Can you maybe help me find what should I do? I post the code here:
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('main').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function serverFunc(theForm) {
try{
var folder_name = "publicaciones";
var folder,folders = DriveApp.getFoldersByName(folder_name);
if(folders.hasNext()){
folder = folders.next();
}else{
folder = DriveApp.createFolder(folder_name);
}
Logger.log("TheForm", theForm == null);
var blob = theForm.theFile;
Logger.log("Blob!", blob == null);
var file = folder.createFile(blob);
Logger.log("File:", file.getName());
return "Archivo subido exitosamente: " + file.getUrl();
} catch(error){
Logger.log("error: ", error.toString());
return error.toString();
}
}
** main.html **
<div>
<form id="myForm">
<input type="file" name="theFile">
<input type="hidden" name="anExample">
<br>
<input type="button" value="Subir Archivo" onclick="this.value='Subiendo...';
google.script.run.withSuccessHandler(fileUploaded).serverFunc(this.parentNode);
return false;">
</form>
</div>
<div id="output">
</div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
I'd appreaciate any help or pointers you can give me. Thanks a lot!
Looks like there is a bug currently that Google is working on. I found a possible fix:
Change your input tag to this:
<input type="button" value="Subir Archivo" onclick="callServerCode()"/>
Add a function to the <script> tag:
<script>
function callServerCode() {
var formToSend = document.getElementById('myForm');
google.script.run
.withSuccessHandler(fileUploaded)
.serverFunc(formToSend);
};
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
Note that inside the new function, it gets the form using var formToSend = document.getElementById('myForm');
And change IFRAME to NATIVE.
It's a doc issue needs to fix with Google when using SandBoxMode=IFRAME currently. See here. I've tested it works by swapping IFRAME to NATIVE. You can simply do it:
function doGet() {
return HtmlService.createHtmlOutputFromFile('main');
}
Google has turned of NATIVE for SandBoxMode. It is now set to IFRAME only.
See here