Trying to create a text file using TS and HTML5 - html

In my app I'm receiving a string which needs to be saved to the local machine. I', reading this guide (html5 filesystem tutorial). The problem I have to use TS ("typescript": "2.6.1") and looks like part of the API is not supported. The following line gives me two errors:
window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, this.errorHandler);
first:
[ts] Property 'requestFileSystem' does not exist on type 'Window'.
second:
[ts] Property 'TEMPORARY' does not exist on type 'Window'.
Any workaround or an updated documentation? PS I'm aware this is supported only in Chrome.

This API is currently only supported in Chrom and does not work in other browsers. If you are using Chrome however, you have to use the prefixed version of this function which is webkitRequestFileSystem:
var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
The support also goes for window.TEMPORARY.
Now, if you want to create a file and write some content in it, you have to create a so-called writer object:
function onInitFs(fs) {
fs.root.getFile('my-file.txt', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
...
};
fileWriter.onerror = function(e) {
...
};
var blob = new Blob(['Content that goes into the file'], {type: 'text/plain'});
fileWriter.write(blob);
}, errorHandler);
}, errorHandler);
}
requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
For more information on the FileSystemFileEntry API check out this link.

Related

Phonegap / Cordova / HTML5 Create a CSV File to download

I need a little bit of help.
My question is: What is the right way to create a csv(/txt) file in a AndroidApp based on PhoneGap with Cordova and Javascript?
I am playing now a few days with phonegap and im really new in this direction. Now i have seen that since a few weeks the cordova-plugins are not supported anymore. (e.g.) And so im wondering how i can create/generate a csv with my app and provide it do be downloadable to the user?
Thanks in advance for your help.
What do you mean that cordova-plugins are not supported anymore?
Naturally you need to use cordova-plugin-file
Below is simple code snippet of how to do read/write operations on files with this plugin installed.
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dir) {
dir.getFile('test.txt', {create: true}, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function () {
// Create a FileWriter object for our FileEntry (ver.json).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
writeCompleted = true;
//console.log('Write completed.');
};
fileWriter.onerror = function (e) {
writeError = true;
//console.log('Write failed: ' + e.toString());
};
// Create a new Blob and write it to ver.json
var blob = new Blob(['foo;bar;baz'], {type: 'text/csv'});
fileWriter.write(blob);
}, fileErrorHandler);
};
reader.readAsText(file);
}, function () {
console.log('onErrorReadFile');
});
}, fileErrorHandler);
});
After you created file in filesystem you can serve for download with simple <a> tag.

Determine file type using Electron dialog

I used HTML5 File API to drag a file into an Electron application and obtained file details (name, mime-type, size, etc.). How can I achieve the same when selecting a file via Electron's dialog module? Below is the code (renderer process) that leverages HTML5's File API:
const {dialog} = require('electron').remote;
// Using jQuery ($)
var holder = $('#holder');
holder.on('drag dragstart dragend dragover dragenter dragleave drop', function(evt) {
evt.preventDefault();
evt.stopPropagation();
})
.on('drop', function(evt) {
let file = evt.originalEvent.dataTransfer.files[0];
console.log(file.name);
console.log(file.type);
console.log(file.size);
})
.on('click', function(evt) {
dialog.showOpenDialog({
properties: [ 'openFile' ]
}, function(file) {
console.log(file); // just displays local, full path
// code to get name, type, size... how do I?
});
});
Check this library: mmmagic, it will do just what you want.

WebRTC SDP object (local description) by Firefox does not contain DataChannel info unlike Chrome?

I'm testing WebRTC procedure step by step for my sake.
I wrote some testing site for server-less WebRTC.
http://webrtcdevelop.appspot.com/
In fact, STUN server by google is used, but no signalling server deployed.
Session Description Protocol (SDP) is exchanged manually by hand that is CopyPaste between browser windows.
So far, here is the result I've got with the code:
'use strict';
var peerCon;
var ch;
$(document)
.ready(function()
{
init();
$('#remotebtn2')
.attr("disabled", "");
$('#localbtn')
.click(function()
{
offerCreate();
$('#localbtn')
.attr("disabled", "");
$('#remotebtn')
.attr("disabled", "");
$('#remotebtn2')
.removeAttr("disabled");
});
$('#remotebtn')
.click(function()
{
answerCreate(
new RTCSessionDescription(JSON.parse($('#remote')
.val())));
$('#localbtn')
.attr("disabled", "");
$('#remotebtn')
.attr("disabled", "");
$('#remotebtn')
.attr("disabled", "");
});
$('#remotebtn2')
.click(function()
{
answerGet(
new RTCSessionDescription(JSON.parse($('#remote')
.val())));
$('#remotebtn2')
.attr("disabled", "");
});
$('#msgbtn')
.click(function()
{
msgSend($('#msg')
.val());
});
});
var init = function()
{
//offer------
peerCon =
new RTCPeerConnection(
{
"iceServers": [
{
"url": "stun:stun.l.google.com:19302"
}]
},
{
"optional": []
});
var localDescriptionOut = function()
{
console.log(JSON.stringify(peerCon.localDescription));
$('#local')
.text(JSON.stringify(peerCon.localDescription));
};
peerCon.onicecandidate = function(e)
{
console.log(e);
if (e.candidate === null)
{
console.log('candidate empty!');
localDescriptionOut();
}
};
ch = peerCon.createDataChannel(
'ch1',
{
reliable: true
});
ch.onopen = function()
{
dlog('ch.onopen');
};
ch.onmessage = function(e)
{
dlog(e.data);
};
ch.onclose = function(e)
{
dlog('closed');
};
ch.onerror = function(e)
{
dlog('error');
};
};
var msgSend = function(msg)
{
ch.send(msg);
}
var offerCreate = function()
{
peerCon
.createOffer(function(description)
{
peerCon
.setLocalDescription(description, function()
{
//wait for complete of peerCon.onicecandidate
}, error);
}, error);
};
var answerCreate = function(descreption)
{
peerCon
.setRemoteDescription(descreption, function()
{
peerCon
.createAnswer(
function(description)
{
peerCon
.setLocalDescription(description, function()
{
//wait for complete of peerCon.onicecandidate
}, error);
}, error);
}, error);
};
var answerGet = function(description)
{
peerCon.setRemoteDescription(description, function()
{ //
console.log(JSON.stringify(description));
dlog('local-remote-setDescriptions complete!');
}, error);
};
var error = function(e)
{
console.log(e);
};
var dlog = function(msg)
{
var content = $('#onmsg')
.html();
$('#onmsg')
.html(content + msg + '<br>');
}
Firefox(26.0):
RtpDataChannels
onopen event is fired successfully, but send fails.
Chrome(31.0):
RtpDataChannels
onopen event is fired successfully, and send also succeeded.
A SDP object by Chrome is as follows:
{"sdp":".................. cname:L5dftYw3P3clhLve
\r\
na=ssrc:2410443476 msid:ch1 ch1
\r\
na=ssrc:2410443476 mslabel:ch1
\r\
na=ssrc:2410443476 label:ch1
\r\n","type":"offer"}
where the ch1 information defined in the code;
ch = peerCon.createDataChannel(
'ch1',
{
reliable: false
});
is bundled properly.
However, a SDP object (local description) by Firefox does not contain DataChannel at all, and moreover, the SDP is much shorter than Chrome, and less information bundled.
What do I miss?
Probably, I guess the reason that send fails on DataChannel is due to this lack of information in the SDP object by firefox.
How could I fix this?
I investigated sources of various working libraries, such as peerJS, easyRTC, simpleWebRTC, but cannot figure out the reason.
Any suggestion and recommendation to read is appreciated.
[not an answer, yet]
I leave this here just trying to help you. I am not much of a WebRTC developer. But, curious i am, this quite new and verry interresting for me.
Have you seen this ?
DataChannels
Supported in Firefox today, you can use DataChannels to send peer-to-peer
information during an audio/video call. There is
currently a bug that requires developers to set up some sort of
audio/video stream (even a “fake” one) in order to initiate a
DataChannel, but we will soon be fixing that.
Also, i found this bug hook, witch seems to be related.
One last point, your version of adapter.js is different from the one served on code.google. And .. alot. the webrtcDetectedVersion part is missing in yours.
https://code.google.com/p/webrtc/source/browse/stable/samples/js/base/adapter.js
Try that, come back to me with good newz. ?
After last updating, i have this line in console after clicking 'get answer'
Object { name="INVALID_STATE", message="Cannot set remote offer in
state HAVE_LOCAL_OFFER", exposedProps={...}, more...}
but this might be useless info ence i copy pasted the same browser offre to answer.
.. witch made me notice you are using jQuery v1.7.1 jquery.com.
Try updating jQuery (before i kill a kitten), and in the meantime, try make sure you use all updated versions of scripts.
Woups, after fast reading this : https://developer.mozilla.org/en-US/docs/Web/Guide/API/WebRTC/WebRTC_basics then comparing your javascripts, i see no SHIM.
Shims
As you can imagine, with such an early API, you must use the browser
prefixes and shim it to a common variable.
> var PeerConnection = window.mozRTCPeerConnection ||
> window.webkitRTCPeerConnection; var IceCandidate =
> window.mozRTCIceCandidate || window.RTCIceCandidate; var
> SessionDescription = window.mozRTCSessionDescription ||
> window.RTCSessionDescription; navigator.getUserMedia =
> navigator.getUserMedia || navigator.mozGetUserMedia ||
> navigator.webkitGetUserMedia;

backbone.js fetch json success will not hit

i use fetch from backbone.js to load a json model but success will not hit.
var DialogModel = Backbone.Model.extend({
url : function() {
return '/messages/getDialog';
},
parse : function(res) {
return res.dialog;
}
});
var DialogView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
var onDataHandler = function() {
this.render();
};
this.model = new DialogModel();
this.model.fetch({ success : onDataHandler});
},
render: function(){
var data = {
dialogModel : this.model
};
var form = new Backbone.Form({
model: data
});
$(this.el).html(form.render().el);
}
});
What happens now:
DialogView initialize is called.
this.model.fetch is called but the onDataHandler function will not be hit if success.
/messages/getDialog throws a json file back.
The json file is loading well as i can see in the network browser.
Thanks for your help!
Oleg
The problem you're having is due to a typical JS gotcha and not related to Backbone itself. Try
var that = this;
this.model.fetch({
success : function () {
that.render();
}
});
The way you're currently passing onDataHandler is problematic as it will cause this to refer to the global object instead of the DialogView, when the function is called.
This fiddle demonstrates the problematic version vs one that works.
(You may also want to take a look at JS strict mode which can shield you from this type of errors.)
Even better is to listen for an event:
this.model.on("sync", this.render).fetch();
I ran across this question while looking for something else, but the currently accepted answer drives me nuts. There's no good reason to be sprinkling this and that all over your code. Backbone (underscore) includes a context parameter that you can bind to.
that = this makes no sense. If you must implement obsolete 2007-era Crockford patterns, then say var self = this. Saying that = this is like saying left = right. Everyone Stop.

HTML5 Filesystem API: downloading a sandboxed file?

I have some data in indexeddb files, and I'd like to allow my users to download that data to import into other applications. I can use Blobs to do this easily:
var blob = new Blob(['herp!'], {type: 'application/octet-stream'});
var iframe = document.createElement("iframe");
iframe.id = "myiframe";
iframe.style.display = "none";
iframe.src = window.webkitURL.createObjectURL(blob); // needs a revokeObjectURL
$('#dlplaceholder').append(iframe);
The correct type parameter to Blob is key: if I set it to text/plain, it won't download the file. If I have the iframe a height and width and a display type of block, I can see the data in the iframe.
However, I'll want to build one file out of multiple values from my database, and each of those values can be large, and I can have a lot of entries. I can concatenate those values in the Blob constructor, but I'm worried about having so much data in memory that I blow up.
So I decided to create a file in the sandboxed system and append each value to it, and use the file instead of the blob as the argument to createObjectURL. But when I do that, it
doesn't download; it behaves exactly as if I had used my Blob code with a type of text/plain. Here's the code:
var fname = 'mybadtest'; //UPDATE here's the problem: needs .bin file extension
var init_fs = function ( fs ) {
// first, write to the sandboxed file
fs.root.getFile(fname, {create: true, exclusive: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
// write to file completed. now use the file for download
fs.root.getFile(fname, {}, function(fileEntry) {
fileEntry.file(function(file) {
var iframe = document.createElement("iframe");
iframe.id = "myiframe";
iframe.style.display = "none";
iframe.src = window.webkitURL.createObjectURL(file) // needs revokeObjURL
$('#dlplaceholder').append(iframe);
}, errorHandler);
}, errorHandler);
};
var blob = new Blob(['derp!'], {type: 'application/octet-stream'});
fileWriter.write(blob);
}, errorHandler);
}, errorHandler);
};
window.webkitStorageInfo.requestQuota(PERSISTENT, mysz, function(grantedBytes) {
window.webkitRequestFileSystem(PERSISTENT, grantedBytes, init_fs, errorHandler);
}, err_function );
If I give the iframe a size and set the display to block, I can see the data I wrote to the file. So I know I got the file writing part right.
Any ideas on how I can give the file the right type so I can download it? I've been through the MDN docs, the HTML5 Rocks tuts, and Eric Bidelman's "Using the Filesystem API" book, but I don't see anything that addresses this situation. I'm using Chrome version 27.0.1453.110.
UPDATE: problem solved; see comment below.
UPDATED UPDATE: see Rob W's useful comment about an alternate approach below.