How to save data in local hd with javascript? - javascript

I'm using CKEditor to create text in a website that create documents. The problem is the internet connection, the PC is far away from town and it's unstable 3G connection. I already have a routine to save a draft every ten seconds (or the time the user wish to be) in the server for safe - simple task. The problem is that if the internet goes down, the user will have to select - copy the text and try to save it locally with some text editor (maybe Word, that will make a mess).
So I'm wondering if already exists a way of to create a file and download to the local HD without remote server, just the JavaScript and navigator. Also, it might be another way to save the job but keeping CPU on and navigator open, but couldn't find in stack overflow.
I found just one non-standard API FireFox compatible:
Device Storage API
Of course, is not JavaScript standard so I don't know if it's a good idea to use right now.
Any ideas?

[Compatibility Note]
This solution uses <a> attribute download, to save the data in a text file.
This html5 attribute is only supported by Chrome 14+, Firefox 20+ and Opera
15+ on
desktop, none on iOS and all current majors except WebView on Android.
-A workaround for IE 10+ is to not hide/destroy the link generated by clickSave()and ask user to right-click > Save target As…
-No known workaround for Safari.
Also note that data will still be accessible via
localStorage.getItem()
for Firefox 3.5+, Chrome&Safari 4+, Opera 10.5+ and IE 9+ (xhr will
crash IE 8-)
I would do it like so, assuming your actual code saves the data via xhr.
function saveData() {
var xhr = new XMLHttpRequest();
//set a timeout, in ms, to see if we're still connected
xhr.timeout = 2000;
xhr.addEventListener('timeout', localStore, false);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// not a good news
if (xhr.status !== 200) {
localStore();
}
else{
document.querySelector('#local_alert').style.display = 'none';
}
}
}
//I assume you already have the part where you set the credentials
xhr.open('POST', 'your/url.php');
xhr.send();
}
//Show the link + Store the text in localStorage
function localStore() {
document.querySelector('#local_alert').style.display = 'block';
var userText = document.querySelector('textArea').value;
localStorage.setItem("myAwesomeTextEditor", userText);
}
//provide a link to download a file with txt content
window.URL = window.URL || window.webkitURL;
function clickSave(e) {
var userText = document.querySelector('textArea').value;
var blob = new Blob([userText], {type: 'plain/text'});
var a = document.createElement('a');
a.download = "myAwesomeTextEditor" + (new Date).getTime() + '.txt';
a.href = URL.createObjectURL(blob);
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
setInterval(saveData, 3000);
#local_alert {
display: none;
position: static;
width: 100%;
height: 3em;
background-color: #AAA;
color: #FFF;
padding: 0.5em;
}
body,
html {
margin: 0
}
<div id="local_alert">You're actually offline, please beware your draft is not saved on our server
<button onclick="clickSave()">Save Now</button>
</div>
<textarea></textarea>
Ps: If your user leaves the page without connection, you'll be able to get the text back via localStorage.getItem("myAwesomeTextEditor")
PPs: A more "live" example can be found here (it won't save to server but you've got the rest of the logic working). Try to disconnect , then reconnect.

Try
var editor = document.getElementById("editor");
var saveNow = document.getElementById("save");
function saveFile() {
if (confirm("save editor text")) {
var file = document.createElement("a");
file.download = "saved-file-" + new Date().getTime();
var reader = new FileReader();
reader.onload = function(e) {
file.href = e.target.result;
document.body.appendChild(file);
file.click();
document.body.removeChild(file);
};
reader.readAsDataURL(new Blob([editor.value], {
"type": "text/plain"
}));
}
};
saveNow.addEventListener("click", saveFile, false);
<button id="save">save editor text</button><br />
<textarea id="editor"></textarea>

Related

How to manage Activex events in JS without Object tag

Hi im developing activex control to manage webcam in IE, everything works but i need to refresh the image when a new frame is captures, up to now i display images on click, but i want to listen "Captured frame event" in JS to refresh my html view.
I have seen a lot of samples but all of these are using Object tag in html
<object id="Control" classid="CLSID:id"/>
<script for="Control" event="myEvent()">
alert("hello");
</script>
is there a way to listen activex events using pure JS? using :
Ob = new ActivexObject('PROG.ID');
No, it's not working in purly JavaScript you can only use JScript.
JScript only works in Internet Explorer and there it only works, if the user confirms to execute the scripts, ussualy you use it in an .hta Hyper Text (Markup Language) Application
Example:
<script language="JScript">
"use strict";
function openFile(strFileName) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(strFileName, 1);
if (f.AtEndOfStream) {
return;
}
var file = f.ReadAll();
f.close();
return file;
}
function writeFile(filename, content) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(filename, 2, true);
f.Write(content);
f.Close();
}
</script>
<script language="javascript">
"use strict";
var native_db;
function init() {
var file = openFile("./Natives.json");
native_db = JSON.parse(file);
displayNamespaces();
};
I also would have as alternate an example how it works in modern Browsers, if it helps you out there:
<video id="webcam"></video>
<input type="button" value="activate webcam" onclick="test()">
<script>
function test() {
navigator.mediaDevices.getUserMedia({video: true, audio: true}).then((stream) => { // get access to webcam
const videoElement = document.getElementById('webcam');
videoElement.srcObject = stream; // set our stream, to the video element
videoElement.play();
// This creates a Screenshot on click, as you mentioned
videoElement.addEventListener('click', function(event) {
const canvas = document.createElement('canvas');
canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
const context = canvas.getContext('2d');
context.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight);
// you could just do this, to display the canvas:
// document.body.appendChild(canvas);
canvas.toBlob(function (blob) { // we automatlicly download the screenshot
const a = document.createElement('a');
a.href = URL.createObjectURL(blob); // creates a Datastream Handle Link in your Browser
a.download = 'screenshot.png'; // the name we have to define here now, since it will not use the url name
document.body.appendChild(a); // some Browsers don't like operating with Events of Objects which aren't on DOM
setTimeout(function() { // so we timeout a ms
a.click(); // trigger the download
URL.revokeObjectURL(a.href); // release the Handle
document.body.removeChild(a); // remove the element again
}, 1);
});
});
}).catch(console.error);
}
</script>
I ended up using timer, when i click enable button in the view i call the method startRecord, in this method i read Activex value every 70 ms, I would rather not use timer but it works.
private async startRecord() {
while (this.banCapturing) {
await new Promise(res => setTimeout(res, 70)); //14 ~ 15 fps
this.foto = this.Ob.imageBase64; //Read Activex Value, DLL is updating imageBase64 on camera event.
}
}

Open blob objectURL in Chrome

I want to open a PDF in a new tab in chrome browser (Chrome 56.0.2924.87, Ubuntu 14.04) using window.open(fileObjectURL) in javascript. I am creating the blob from base64 encoded data and do create an objectURL like this:
const fileObjectURL = URL.createObjectURL(fileBlob);
It works fine in latest Firefox browser. But in Chrome I can see that the new tab gets opened but then closed immediately. So I don't get any error in the console etc.
The only way it works in Chrome now is to give the base64 data directly to the window.open(fileBase64Data) function. But I don't like the complete data being set in the url.
Maybe this is a safety issue with Chrome blocking opening of blobs?
The cause is probably adblock extension (I had exactly the same problem).
You must open new window before you put blob url in window:
let newWindow = window.open('/')
Also you can use some another page like /loading, with loading indicator.
Then you need to wait newWindow loading, and you can push url of your blob file in this window:
newWindow.onload = () => {
newWindow.location = URL.createObjectURL(blob);
};
Adblock extension don't block it.
I'm using it with AJAX and ES generators like this:
let openPDF = openFile();
openPDF.next();
axios.get('/pdf', params).then(file => {
openPDF.next(file);
});
function* openFile() {
let newWindow = window.open('/pages/loading');
// get file after .next(file)
let file = yield;
// AJAX query can finish before window loaded,
// So we need to check document.readyState, else listen event
if (newWindow.document.readyState === 'complete') {
openFileHelper(newWindow, file);
} else {
newWindow.onload = () => {
openFileHelper(newWindow, file);
};
}
}
function openFileHelper(newWindow, file) {
let blob = new Blob([file._data], {type: `${file._data.type}`});
newWindow.location = URL.createObjectURL(blob);
}
Work around way to by pass adblocker.
coffeescript & jquery
$object = $("<object>")
$object.css
position: 'fixed'
top: 0
left: 0
bottom: 0
right: 0
width: '100%'
height: '100%'
$object.attr 'type', 'application/pdf'
$object.attr 'data', fileObjectURL
new_window = window.open()
new_window.onload = ->
$(new_window.document.body).append $object
In plain vanilly javascript (because I don't have jquery)
let newWindow = window.open('/file.html');
newWindow.onload = () => {
var blobHtmlElement;
blobHtmlElement = document.createElement('object');
blobHtmlElement.style.position = 'fixed';
blobHtmlElement.style.top = '0';
blobHtmlElement.style.left = '0';
blobHtmlElement.style.bottom = '0';
blobHtmlElement.style.right = '0';
blobHtmlElement.style.width = '100%';
blobHtmlElement.style.height = '100%';
blobHtmlElement.setAttribute('type', 'application/pdf');
blobHtmlElement.setAttribute('data', fileObjectURL);
newWindow.document.title = 'my custom document title';
newWindow.document.body.appendChild(blobHtmlElement);
};
/file.html is an almost empty html file, source:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
</body>
</html>
Tested in chrome & firefox (on 20/november/2019)
Unfortunately none of the above solutions worked. The new window still gets blocked in production, in development it works. Only Chrome blocks, in Edge it's all fine.
I do not have Ad blocker. Looks like setting the blob type explicitly to application/pdf will solve this issue.
const newBlob = new Blob([blobData], {type: "application/pdf"});
Salaam
blob:http://***.***.***.**/392d72e4-4481-4843-b0d4-a753421c0433
Blobs are not blocked by chrome but are blocked by AdBlock extension
Either:
Pause on this site
Don't run on pages on this site
Or Disable or Remove AdBlock Extension

Uploaded Image does not show in Safari 5.1 on Windows

I am using this tutorial to upload Image and display it. It works well in Chrome and Firefox but it is not showing uploaded image in safari. Why?
HTML
<div id="page-wrapper">
<h1>Image File Reader</h1>
<div>
Select an image file:
<input type="file" id="fileInput">
</div>
<div id="fileDisplayArea"></div>
Javascript
window.onload = function() {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var imageType = /image.*/;
if (file.type.match(imageType)) {
var reader = new FileReader();
reader.onload = function(e) {
fileDisplayArea.innerHTML = "";
var img = new Image();
img.src = reader.result;
fileDisplayArea.appendChild(img);
}
reader.readAsDataURL(file);
} else {
fileDisplayArea.innerHTML = "File not supported!"
}
});
}
Open web development tools (Firebug for Firefox or CTRL+SHIFT+J in Chrome), select the image element with the element inspector and have a look at the URL that it is loading from and determine how it is different from the URL it should be loading from.
Since you're using Safari 5.1 on Windows, the FileReader API isn't supported and Safari on Windows will no longer be updated your best bet is to use a placeholder image from the server and call this battle a draw. Safari 5.1 market share on Windows is trivial at best and will only decrease as time goes on. Part of programming is knowing when to walk away from a fight.
if (window.FileReader)
{
//Your FileReader code here.
}
else
{
//Insert an image from the server here.
}

Media Source Extensions Not Working

I am trying to use the MediaSource API to append separate WebM videos to a single source.
I found a Github project that was attempting the same thing, where a playlist of WebMs is loaded, and each one is appended as a SourceBuffer. But it was last committed a year ago, and thus out-of-sync with the current spec. So I forked it and updated to the latest API properties/methods, plus some restructuring. Much of the existing code was taken directly from the spec’s examples and Eric Bidelman’s test page.
However, I can not get it to work as expected. I am testing in two browsers, both on Mac OS X 10.9.2: Chrome 35 stable (latest at the time of this writing), and Firefox 30 beta with the flag media.mediasource.enabled set to true in about:config (this feature will not be introduced until FF 25, and current stable is 24).
Here are the problems I’m running into.
Both browsers
I want the video to be, in the end, one long video composed of the 11 WebMs (00.webm, 01.webm, …, 10.webm). Right now, each browser only plays 1 segment of the video.
Chrome
Wildly inconsistent behavior. Seems impossible to reproduce any of these bugs reliably.
Sometimes the video is blank, or has a tall black bar in the middle of it, and is unplayable.
Sometimes the video will load and pause on the first frame of 01.webm.
Sometimes, the video will play a couple of frames of the 02.webm and pause, having only loaded the first three segments.
The Play button is initially grayed out.
Pressing the grayed out Play button produces wildly inconsistent behaviors. Sometimes, it loads a black, unplayable video. Other times, it will play the first segment, then, when you get to the end, it stops, and when you press Play/Pause again, it will load the next segment. Even then, it will sometimes skip over segments and gets stuck on 04.webm. Regardless, it never plays the final segment, even though the console will report going through all of the buffers.
It is honestly different every time. I can’t list them all here.
Known caveats: Chrome does not currently implement sourceBuffer.mode, though I do not know what effect this might have.
Firefox
Only plays 00.webm. Total running time is 0:08, the length of that video.
Video seeking does not work. (This may be expected behavior, as there is nothing actually happening in the onSeeking event handler.)
Video can not be restarted once finished.
My initial theory was that this had to do with mediaSource.sourceBuffers[0].timestampOffset = duration and duration = mediaSource.duration. But I can’t seem to get anything back from mediaSource.duration except for NaN, even though I’m appending new segments.
Completely lost here. Guidance very much appreciated.
EDIT: I uncommented the duration parts of the code, and ran mse_webm_remuxer from Aaron Colwell's Media Source Extension Tools (thanks Adam Hart for the tips) on all of the videos. Voila, no more unpredictable glitches in Chrome! But alas, it still pauses once a media segment ends, and even when you press play, it sometimes gets stuck on one frame.
In Firefox Beta, it doesn’t play past the first segment, responding with:
TypeError: Value being assigned to SourceBuffer.timestampOffset is not a finite floating-point value.
Logging the value of duration returns NaN (but only in FF).
The main problem is with the video files. If you open chrome://media-internals/ you can see error Media segment did not begin with keyframe. Using properly formatted videos, like the one from Eric Bidelman's example (I hope he doesn't get mad that I keep linking directly to that video, but it's the only example video I've found that works), your code does work with the following change in appendNextMediaSegment():
duration = mediaSource.duration;
mediaSource.sourceBuffers[0].timestampOffset = duration;
mediaSource.sourceBuffers[0].appendBuffer(mediaSegment);
You can try Aaron Colwell's Media Source Extension Tools to try to get your videos working, but I've had limited success.
It also seems a little weird that you're looking at the onProgress event before appending segments, but I guess that could work if you only want to append if the video is actually playing. It could make the seekbar act odd since the video length is unknown, but that can be a problem in any case.
I agree with the opinion Adam Hart said. With a webm file, I tried to implement an example like http://html5-demos.appspot.com/static/media-source.html and then made a conclusion that its problem caused the source file I used.
If you have an arrow left, how about trying to use "samplemuxer" introduced at https://developer.mozilla.org/en-US/docs/Web/HTML/DASH_Adaptive_Streaming_for_HTML_5_Video.
In my opinion, samplemuxer is one of encoders like FFMPEG.
I found that the converted file works with mediaSource API. If you will also see it works, please let me know.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>MediaSource API Demo</title>
</head>
<body>
<h3>Appending .webm video chunks using the Media Source API</h3>
<section>
<video controls autoplay width="320" height="240"></video>
<pre id="log"></pre>
</section>
<script>
//ORIGINAL CODE http://html5-demos.appspot.com/static/media-source.html
var FILE = 'IU_output2.webm';
var NUM_CHUNKS = 5;
var video = document.querySelector('video');
var mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
function callback(e) {
var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
logger.log('mediaSource readyState: ' + this.readyState);
GET(FILE, function(uInt8Array) {
var file = new Blob([uInt8Array], {type: 'video/webm'});
var chunkSize = Math.ceil(file.size / NUM_CHUNKS);
logger.log('num chunks:' + NUM_CHUNKS);
logger.log('chunkSize:' + chunkSize + ', totalSize:' + file.size);
// Slice the video into NUM_CHUNKS and append each to the media element.
var i = 0;
(function readChunk_(i) {
var reader = new FileReader();
// Reads aren't guaranteed to finish in the same order they're started in,
// so we need to read + append the next chunk after the previous reader
// is done (onload is fired).
reader.onload = function(e) {
try {
sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
logger.log('appending chunk:' + i);
}catch(e){
console.log(e);
}
if (i == NUM_CHUNKS - 1) {
if(!sourceBuffer.updating)
mediaSource.endOfStream();
} else {
if (video.paused) {
video.play(); // Start playing after 1st chunk is appended.
}
sourceBuffer.addEventListener('updateend', function(e){
if( i < NUM_CHUNKS - 1 )
readChunk_(++i);
});
} //end if
};
var startByte = chunkSize * i;
var chunk = file.slice(startByte, startByte + chunkSize);
reader.readAsArrayBuffer(chunk);
})(i); // Start the recursive call by self calling.
});
}
mediaSource.addEventListener('sourceopen', callback, false);
// mediaSource.addEventListener('webkitsourceopen', callback, false);
//
// mediaSource.addEventListener('webkitsourceended', function(e) {
// logger.log('mediaSource readyState: ' + this.readyState);
// }, false);
function GET(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
xhr.onload = function(e) {
if (xhr.status != 200) {
alert("Unexpected status code " + xhr.status + " for " + url);
return false;
}
callback(new Uint8Array(xhr.response));
};
}
</script>
<script>
function Logger(id) {
this.el = document.getElementById('log');
}
Logger.prototype.log = function(msg) {
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createTextNode(msg));
fragment.appendChild(document.createElement('br'));
this.el.appendChild(fragment);
};
Logger.prototype.clear = function() {
this.el.textContent = '';
};
var logger = new Logger('log');
</script>
</body>
</html>
another test code
<!DOCTYPE html>
<html>
<head>
<title>MediaSource API Demo</title>
</head>
<body>
<h3>Appending .webm video chunks using the Media Source API</h3>
<section>
<video controls autoplay width="320" height="240"></video>
<pre id="log"></pre>
</section>
<script>
//ORIGINAL CODE http://html5-demos.appspot.com/static/media-source.html
var FILE = 'IU_output2.webm';
// var FILE = 'test_movie_output.webm';
var NUM_CHUNKS = 10;
var video = document.querySelector('video');
var mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
function callback(e) {
var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
logger.log('mediaSource readyState: ' + this.readyState);
GET(FILE, function(uInt8Array) {
logger.log('byteLength:' + uInt8Array.byteLength );
sourceBuffer.appendBuffer(uInt8Array);
});
}
mediaSource.addEventListener('sourceopen', callback, false);
// mediaSource.addEventListener('webkitsourceopen', callback, false);
//
// mediaSource.addEventListener('webkitsourceended', function(e) {
// logger.log('mediaSource readyState: ' + this.readyState);
// }, false);
function GET(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
xhr.onload = function(e) {
if (xhr.status != 200) {
alert("Unexpected status code " + xhr.status + " for " + url);
return false;
}
callback(new Uint8Array(xhr.response));
};
}
</script>
<script>
function Logger(id) {
this.el = document.getElementById('log');
}
Logger.prototype.log = function(msg) {
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createTextNode(msg));
fragment.appendChild(document.createElement('br'));
this.el.appendChild(fragment);
};
Logger.prototype.clear = function() {
this.el.textContent = '';
};
var logger = new Logger('log');
</script>
</body>
</html>
Thanks.

how to validate image size and dimensions before saving image in database

I am using ASP.NET C# 4.0, my web form consist of input type file to upload images.
i need to validate the image on client side, before saving it to my SQL database
since i am using input type= file to upload images, i do not want to post back the page for validating the image size, dimensions.
Needs your assistance
Thanks
you can do something like this...
You can do this on browsers that support the new File API from the W3C, using the readAsDataURL function on the FileReader interface and assigning the data URL to the src of an img (after which you can read the height and width of the image). Currently Firefox 3.6 supports the File API, and I think Chrome and Safari either already do or are about to.
So your logic during the transitional phase would be something like this:
Detect whether the browser supports the File API (which is easy: if (typeof window.FileReader === 'function')).
If it does, great, read the data locally and insert it in an image to find the dimensions.
If not, upload the file to the server (probably submitting the form from an iframe to avoid leaving the page), and then poll the server asking how big the image is (or just asking for the uploaded image, if you prefer).
Edit I've been meaning to work up an example of the File API for some time; here's one:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Show Image Dimensions Locally</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
function loadImage() {
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('imgfile');
if (!input) {
write("Um, couldn't find the imgfile element.");
}
else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
}
else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = document.createElement('img');
img.onload = imageLoaded;
img.style.display = 'none'; // If you don't want it showing
img.src = fr.result;
document.body.appendChild(img);
}
function imageLoaded() {
write(img.width + "x" + img.height);
// This next bit removes the image, which is obviously optional -- perhaps you want
// to do something with it!
img.parentNode.removeChild(img);
img = undefined;
}
function write(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
}
</script>
</head>
<body>
<form action='#' onsubmit="return false;">
<input type='file' id='imgfile'>
<input type='button' id='btnLoad' value='Load' onclick='loadImage();'>
</form>
</body>
</html>
Works great on Firefox 3.6. I avoided using any library there, so apologies for the attribute (DOM0) style event handlers and such.
function getImgSize(imgSrc) {
var newImg = new Image();
newImg.onload = function() {
var height = newImg.height;
var width = newImg.width;
alert ('The image size is '+width+'*'+height);
}
newImg.src = imgSrc; // this must be done AFTER setting onload
}

Categories

Resources