Phonegap Android: reading a file and saving to localstorage - javascript

Morning.
I am using the following code (Phonegap 2.9) to create/read a file on Android device.
function gotFS(fileSystem) {
//alert('first try');
savedFS = fileSystem;
fileSystem.root.getFile("dp-locations.json", null, gotFileEntry2, fail);
}
function gotFS2(fileSystem) {
//alert('try again');
fileSystem.root.getFile("dp-locations.json", {create: true}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
//alert('call writer');
fileEntry.createWriter(gotFileWriter, fail);
}
function gotFileEntry2(fileEntry) {
alert('fileentry2');
//fileEntry.createWriter(gotFileWriter, fail);
fileEntry.file(gotFile, failRead);
}
function gotFile(file){
alert('gotfile');
readAsText(file);
}
function readAsText(file) {
alert('here I am');
var reader = new FileReader();
reader.onloadend = function(evt) {
alert("Read as text");
alert("rat2: "+evt.target.result);
};
reader.readAsText(file);
reader.onload = function(evt){
alert(reader.result);
};
}
function failRead(evt) {
alert("112: "+evt.target.error.code);
}
function gotFileWriter(writer) {
writer.onwrite = function(evt) {
//console.log("write success");
};
//writer.write('{"routes": {}}');//start writing to JSON file
var routes = new Array();
var test = new Object({"locations":[{"name":"first","values":["cw11 1gb","po45 5wd","ta6 3eq"]},{"name":"second","values":["cw7 2yg","po4 8ej","ta9 3zd"]}]});
routes.push(test);
writer.write(routes);//start writing to JSON file
gotFileEntry2(fileEntry);
}
function fail(error) {
//console.log(error.code);
if(error.code == 1){
alert('not found');
gotFS2(savedFS);
}
alert(error.code);
}
My problem is that the script is creating the file (if it needs to), but, when the file aready exists, it doesn't seem to read it.
Function gotFile is called, but function readAsText does not seem to do as required.
I want the file contents to be added to localStorage.
What am I missing?

Related

How to make an object global in Javascript?

I made a little phonegap/cordova application, and I need to access an object inside my .js file. Turns out I have no idea on how to change the structure of my code to make this happen.
Here is my index.html code :
<!DOCTYPE html>
<html>
<head>
<title>NFC tag ID reader</title>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for device API libraries to load
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getFile("readme.txt", {create: true, exclusive: false}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.createWriter(gotFileWriter, fail);
}
function gotFileWriter(writer) {
writer.onwriteend = function(evt) {
console.log("contents of file now 'some sample text'");
writer.truncate(11);
writer.onwriteend = function(evt) {
console.log("contents of file now 'some sample'");
writer.seek(4);
writer.write(" different text");
writer.onwriteend = function(evt){
console.log("contents of file now 'some different text'");
}
};
};
writer.write("some sample text");
//MAKE THIS OBJECT GLOBAL ?
}
function fail(error) {
console.log(error.code);
}
</script>
</head>
<body>
<div class="app">
<script type="text/javascript">
app.initialize();
</script>
</body>
</html>
And here is my index.js code :
var app = {
/* Application constructor */
initialize: function() {
this.bindEvents();
console.log("Starting NFC Reader app");
},
/* bind any events that are required on startup to listeners: */
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
/* this runs when the device is ready for user interaction: */
onDeviceReady: function() {
nfc.addTagDiscoveredListener(
app.onNfc, // tag successfully scanned
function (status) { // listener successfully initialized
app.displayCpt("<b>"+cpt+"</b>" + ' personnes restantes.');
app.displayBjr("\n");
app.displayBjr("Identifiez-vous:");
},
function (error) { // listener fails to initialize
app.display("NFC reader failed to initialize " +
JSON.stringify(error));
}
);
},
/* displays tag ID from #nfcEvent in message div: */
onNfc: function(nfcEvent) {
var tag = nfcEvent.tag;
var nfcUid = nfc.bytesToHexString(tag.id);
var myDb = {
"04c85ccab52880": {
"name": "name",
"firstname": "fname",
"societe": "work"
}
var mapped = Object.keys(myDb).map(function(uid){
return (myDb[uid].uid = uid) && myDb[uid];
});
for(var i = 0; i < mapped.length ; i++){
if(mapped[i]['uid'] != nfcUid){
mapped[i]['uid'] += 1;
} else {
mapped[i]['uid'] = nfcUid;
app.display(mapped[i]['name'] + ' ' + mapped[i]['firstname'] + ', ' + mapped[i]['societe']);
writer.write(mapped[i]['name'] + ' ' + mapped[i]['firstname'] + ', ' + mapped[i]['societe']);
//I WOULD NEED THIS WRITER USABLE IN ORDER TO WRITE MY ARRAY CONTENT INTO A FILE
}
}
},
}; // end of app
I think my writer object needs to be global in order to make the mapped array write into a file, but I can't find a way to do that.. Any ideas ?
Thanks
Have you tried putting var writer outside of everything and removing it from the arguments list of gotFileWriter(writer)? That should make it a global variable. Note that this isn't exactly the best of programming practices, one should avoid global variables where possible.

Saving in local storage not working

I'm building on top of an existing chrome extension, and I'm trying to maintain a consistent style. I need add a new feature, and I use the following script to save a user's choice from the popup selection, and then set a new popup going forward based on the saved choice.
userchoices.js:
require.scopes["userchoices"] = (function() {
var exports = {};
var userChoices = exports.userChoices = {
userchoices: {},
updateChoice: function(){
self = this;
chrome.storage.local.get('userchoices', function(items){
if(!items.userchoices){
chrome.storage.local.set({userchoices: self.userchoices});
return;
}
self.userchoices = items.userchoices;
});
},
getChoice: function(url){
if(this.userchoices[url]){
return this.userchoices[url][choice];
} else {
return {};
}
},
setChoice: function(url, newChoice){
if(!this.userchoices[url]){
this.userchoices[url] = {};
}
this.userchoices[url][choice] = newChoice;
chrome.storage.local.set({userchoices: this.userchoices});
},
removeChoice: function(url){
if(!this.userchoices[url]){
return;
} else {
delete this.userchoices[url]
}
chrome.storage.local.set({userchoices: this.userchoices});
}
}
return exports;
})();
background.js:
var userChoices= require("userchoices").userChoices;
chrome.windows.onCreated.addListener(function(){
CookieBlockList.updateDomains();
BlockedDomainList.updateDomains();
FakeCookieStore.updateCookies();
userChoices.updateChoice();
});
function refreshIconAndContextMenu(tab)
{
// The tab could have been closed by the time this function is called
if(!tab)
return;
var choice = userChoices.getChoice(tab.url);
if(choice) {
if (choice == "one"){
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupDontCare.html"});
} else if(choice=="two"){
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupSortofCare.html"});
} else if(choice=="three") {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupCare.html"});
} else if(choice=="four") {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupReallyCare.html"});
} else {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popup.html"});
}}
}
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "loading")
refreshIconAndContextMenu(tab);
});
// Update icon if a tab is replaced or loaded from cache
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId){
chrome.tabs.get(addedTabId, function(tab){
refreshIconAndContextMenu(tab);
});
});
popup.js:
var userChoices = require("userchoices").userChoices;
function init()
{
console.log("Initializing popup.js");
// Attach event listeners
$("#Dont_Care_btn").click(doNothing);
$("#Sort_of_Care_btn").click(doBadger);
$("#Care_btn").click(giveSecrecyBadger);
$("#Really_Care_btn").click(giveAdvice);
$("#Nuance_btn").click(addNuance);
}
function doNothing() {
$("#startingQuestion").hide();
$("#DontCareResponse").show();
$("#siteControls").hide();
userChoices.setChoice(tab.url, "one");
refreshIconAndContextMenu(tab);
}
function doBadger() {
$("#startingQuestion").hide();
$("#SortofCareResponse").show();
$("#siteControls").hide();
$("#blockedResourcesContainer").hide();
$("#Nuance_btn").show();
userChoices.setChoice(tab.url, "two");
refreshIconAndContextMenu(tab);
}
function giveSecrecyBadger() {
$("#startingQuestion").hide();
$("#siteControls").hide();
$("#CareResponse").show();
$("#siteControls").hide();
$("#blockedResourcesContainer").hide();
$("#Nuance_btn").show();
userChoices.setChoice(tab.url, "three");
refreshIconAndContextMenu(tab);
}
function giveAdvice() {
$("#startingQuestion").hide();
$("#siteControls").hide();
$("#ReallyCareResponse").show();
userChoices.setChoice(tab.url, "four");
refreshIconAndContextMenu(tab);
}
The popup is currently not being set, and I'm not even sure that the selection is saved successfully. Anyone see a problem?
Ha! In the middle of trying to create a minimal example, I figured out the problem. Turns out the problem was the now-deprecated chrome.tabs.getSelected method when it should have been chrome.tabs.query()
Thanks Xan!

Two jQuery codes but only one executed

I have two functions in jQuery. One of them looks for image extensions from form and another is getting image dimensions and triggers an alert() when an image is not big enough.
Both functions are correctly executed in demos but together only one is executed. Only part where extensions is getting is executed. Sorry for the length of the code but it was the only way to show the problem.
(function ($) {
$.fn.checkFileType = function (options) {
var defaults = {
allowedExtensions: [],
success: function () {},
error: function () {}
};
options = $.extend(defaults, options);
return this.each(function () {
$(this).on('change', function () {
var value = $(this).val(),
file = value.toLowerCase(),
extension = file.substring(file.lastIndexOf('.') + 1);
if ($.inArray(extension, options.allowedExtensions) == -1) {
options.error();
$(this).focus();
} else {
options.success();
}
});
});
};
})(jQuery);
$("#filput").on('change', function () {
var fr = new FileReader;
fr.onload = function () { // file is loaded
var img = new Image;
img.onload = function () {
// image is loaded; sizes are available
var w = img.width
if (w < 500) {
alert("too small");
} else {
alert("big enough");
}
};
img.src = fr.result;
};
fr.readAsDataURL(this.files[0]);
});
$(function () {
$('#filput').checkFileType({
allowedExtensions: ['jpg', 'jpeg', 'png'],
error: function () {
alert('error');
}
});
});
Only part where extentions is getting is executed
That code is wrapped by $(function() { ... }); so, you should probably put both pieces of code there:
$(function() {
$("#filput").on('change', function () {
var fr = new FileReader;
// ...
});
$('#filput').checkFileType({
// ...
});
});
Based on what you have described, the input element wasn't present yet at the time your code is run; by putting both code segments in the DOMReady event handler, you're making sure it exists.

How to “autotune” a record sound with Javascript

I managed to record and play my voice like a dictaphone thanks to Cordova. Now i would like to add an "Autotune" or "Vocoder" effect on my voice, how can i do that ?
PS:I work on mobile device.
Here is the the script for record and play my voice :
<script type="text/javascript" charset="utf-8" src="cordova-1.7.0rc1.js"></script>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
var deviceready = false;
var mediaVar = null;
var recordFileName = "recording.wav";
var status = null;
var isIOS = false;
function onBodyLoad()
{
document.addEventListener("deviceready", onDeviceReady, false);
deviceready = true;
}
$(document).ready(function(){
$("#stopBtn").hide();
$("#playBtn").hide();
//validation to check if device is ready is skipped
$("#recordBtn").click(function(){
record();
});
$("#playBtn").click(function(){
play();
});
$("#stopBtn").click(function(){
stop();
});
});
function record()
{
createMedia(function(){
status = "recording";
mediaVar.startRecord();
$("#recordBtn").hide();
$("#stopBtn").show();
$("#playBtn").hide();
},onStatusChange);
}
function createMedia(onMediaCreated, mediaStatusCallback){
if (mediaVar != null) {
onMediaCreated();
return;
}
if (typeof mediaStatusCallback == 'undefined')
mediaStatusCallback = null;
if (isIOS) {
//first create the file
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(recordFileName, {
create: true,
exclusive: false
}, function(fileEntry){
log("File " + recordFileName + " created at " + fileEntry.fullPath);
mediaVar = new Media(fileEntry.fullPath, function(){
log("Media created successfully");
}, onError, mediaStatusCallback); //of new Media
onMediaCreated();
}, onError); //of getFile
}, onError); //of requestFileSystem
} else //it's Android
{
mediaVar = new Media(recordFileName, function(){
log("Media created successfully");
}, onError, mediaStatusCallback);
onMediaCreated();
}
}
function stop()
{
if (mediaVar == null)
return;
if (status == 'recording')
{
mediaVar.stopRecord();
log("Recording stopped");
}
else if (status == 'playing')
{
mediaVar.stop();
log("Play stopped");
}
else
{
log("Nothing stopped");
}
$("#recordBtn").show();
$("#stopBtn").hide();
$("#playBtn").show();
status = 'stopped';
}
function play()
{
createMedia(function(){
status = "playing";
mediaVar.play();
$("#recordBtn").hide();
$("#stopBtn").show();
$("#playBtn").hide();
});
}
function onStatusChange()
{
if (arguments[0] == 4) //play stopped
{
$("#recordBtn").show();
$("#stopBtn").hide();
$("#playBtn").show();
}
}
function onSuccess()
{
//do nothing
}
function onError(err)
{
if (typeof err.message != 'undefined')
err = err.message;
alert("Error : " + err);
}
function log(message)
{
if (isIOS)
console.log(message);
else
console.info(message);
}
function onDeviceReady()
{
}
</script>
Pitch detection and manipulation (Autotune is a brand-name for a product Anteres Audio Technology that achieves it) is a hard digital signal processing problem (DSP) which is computationally intensive.
DPS Dimension provides a good tutorial here are about pitch manipulation, but it's very far from being a complete solution.
You are unlikely to make much headway with it without a strong academic background in DSP. Existing implementations are proprietary and typically implemented in C++. There are many patents in this problem space too.
One option might be to implement the audio processing server-side using a licensed component.
You might have more luck implementing a Vocoder in Javascript - the complexity is lower and there are plenty of algorithms in the public domain to try.

Blackberry Webworks/Phonegap file browser

I'm moving from Air/Actionscript to WebWorks and having some difficulty. I've tried several Phonegap file browser tutorials and samples I've found around the web but they're not working on the Playbook. I've added the access_shared permission to the config. I have an and when my app is launched it's supposed to load the directories and files into the .
My js is below:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
window.requestFileSystem(
LocalFileSystem.PERSISTENT,
0, onFileSystemSuccess, fail
);
}
function onFileSystemSuccess(fileSystem) {
// Create some test files
fileSystem.root.getDirectory("myDirectory",
{ create: true, exclusive: false },
null,fail);
fileSystem.root.getFile("readthis.txt",
{ create: true, exclusive: false },
null,fail);
var directoryReader = fileSystem.root.createReader();
// Get a list of all the entries in the directory
directoryReader.readEntries(success,fail);
}
function success(entries) {
var i;
var objectType;
for (i=0; i<entries.length; i++) {
if(entries[i].isDirectory == true) {
objectType = 'Directory';
} else {
objectType = 'File';
}
$('#directoryList').append('<li><h3>' + entries[i].name + '</
h3><p>' + entries[i].toURI() + '</p><p class="ui-li-aside">Type:
<strong>' + objectType + '</strong></p></li>');
}
$('#directoryList').listview("refresh");
}
function fail(error) {
alert("Failed to list directory contents: " + error.code);
}
I found the DIR example in KitchenSink showed me what I needed to know.

Categories