I have been working on an arcgis project for the last two weeks and I have ran into an issue with my upload shapefile function in my code. I keep getting an dom is undefined error and I don't know what to do.
Here is the code:
<div class="modal fade" id="UpdateShapefileForm" tabindex="-1" role="dialog" aria- labelledby="Set View" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<form enctype="multipart/form-data" method="post" id="uploadForm">
<div class="field">
<label class="file-upload">
<span><strong>Add File</strong></span>
<input type="file" name="file" id="inFile"/>
</label>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="http://js.arcgis.com/3.9/"></script>
<script src="/static/js/mapping/mapobject.js" type="text/javascript"></script>
<script src="/static/js/mapping/mapmanager.js" type="text/javascript"></script>
<script type="text/javascript">
var map, toolbar;
var PROJECT_OUTLINE, PROJECT_FILL, PARCEL_OUTLINE, PARCEL_FILL, PLOT_OUTLINE, PLOT_FILL;
var toolbarEvent;
var mapManager = new MapManager();
var markerPictures = {
'project': '/static/assets/grnball.png',
'parcel': '/static/assets/bluball.png',
'plot': '/static/assets/redball.png'
}
require([
"esri/config",
"esri/InfoTemplate",
"esri/map",
"esri/request",
"esri/geometry/scaleUtils",
"esri/layers/FeatureLayer",
"esri/renderers/SimpleRenderer",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleMarkerSymbol",
"dojo/dom",
"dojo/json",
"dojo/on",
"dojo/parser",
"dojo/sniff",
"dojo/_base/array",
"esri/Color",
"dojo/_base/lang",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
esriConfig, InfoTemplate, Map, request, scaleUtils, FeatureLayer,
SimpleRenderer, PictureMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol,
dom, JSON, on, parser, sniff, arrayUtils, Color, lang
) {
map = new Map("mapcanvas", {
center: [-56.049, 38.485],
zoom: 3,
basemap: "hybrid"
});
map.on("load", function() {
$("#waiting_img").hide();
createToolbar();
setConstants();
parser.parse();
var portalUrl = "http://www.arcgis.com";
esriConfig.defaults.io.proxyUrl = "/proxy";
on(dom.byId("uploadForm"), "change", function (event) {
var fileName = event.target.value.toLowerCase();
if (sniff("ie")) { //filename is full path in IE so extract the file name
var arr = fileName.split("\\");
fileName = arr[arr.length - 1];
}
if (fileName.indexOf(".zip") !== -1) {//is file a zip - if not notify user
generateFeatureCollection(fileName);
}
else {
dom.byId('upload-status').innerHTML = '<p style="color:red">Add shapefile as .zip file</p>';
}
map.graphics.on("click", function(evt) {
console.log("geometry type: " + evt.graphic.geometry.type);
if(evt.graphic.geometry.type == "polygon")
{
selectPolygon();
}
else if(evt.graphic.geometry.type == "multipoint" || evt.graphic.geometry.type == "point")
{
selectMarker();
}
});
});
});
});
function generateFeatureCollection (fileName) {
var name = fileName.split(".");
//Chrome and IE add c:\fakepath to the value - we need to remove it
//See this link for more info: http://davidwalsh.name/fakepath
name = name[0].replace("c:\\fakepath\\", "");
dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;
//Define the input params for generate see the rest doc for details
//http://www.arcgis.com/apidocs/rest/index.html?generate.html
var params = {
'name': name,
'targetSR': map.spatialReference,
'maxRecordCount': 1000,
'enforceInputFileSizeLimit': true,
'enforceOutputJsonSizeLimit': true
};
//generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
//This should work well when using web mercator.
var extent = scaleUtils.getExtentForScale(map, 40000);
var resolution = extent.getWidth() / map.width;
params.generalize = true;
params.maxAllowableOffset = resolution;
params.reducePrecision = true;
params.numberOfDigitsAfterDecimal = 0;
var myContent = {
'filetype': 'shapefile',
'publishParameters': JSON.stringify(params),
'f': 'json',
'callback.html': 'textarea'
};
//use the rest generate operation to generate a feature collection from the zipped shapefile
request({
url: portalUrl + '/sharing/rest/content/features/generate',
content: myContent,
form: dom.byId('uploadForm'),
handleAs: 'json',
load: lang.hitch(this, function (response) {
if (response.error) {
errorHandler(response.error);
return;
}
var layerName = response.featureCollection.layers[0].layerDefinition.name;
dom.byId('upload-status').innerHTML = '<b>Loaded: </b>' + layerName;
addShapefileToMap(response.featureCollection);
}),
error: lang.hitch(this, errorHandler)
});
}
function errorHandler (error) {
dom.byId('upload-status').innerHTML =
"<p style='color:red'>" + error.message + "</p>";
}
function addShapefileToMap (featureCollection) {
//add the shapefile to the map and zoom to the feature collection extent
//If you want to persist the feature collection when you reload browser you could store the collection in
//local storage by serializing the layer using featureLayer.toJson() see the 'Feature Collection in Local Storage' sample
//for an example of how to work with local storage.
var fullExtent;
var layers = [];
arrayUtils.forEach(featureCollection.layers, function (layer) {
var infoTemplate = new InfoTemplate("Details", "${*}");
var featureLayer = new FeatureLayer(layer, {
infoTemplate: infoTemplate
});
//associate the feature with the popup on click to enable highlight and zoom to
featureLayer.on('click', function (event) {
map.infoWindow.setFeatures([event.graphic]);
});
//change default symbol if desired. Comment this out and the layer will draw with the default symbology
fullExtent = fullExtent ?
fullExtent.union(featureLayer.fullExtent) : featureLayer.fullExtent;
layers.push(featureLayer);
});
map.addLayers(layers);
map.setExtent(fullExtent.expand(1.25), true);
dom.byId('upload-status').innerHTML = "";
}
function setConstants() {
PROJECT_OUTLINE = new esri.Color(([0,255,0]));
PROJECT_FILL = new esri.Color([0,255,0,0.5]);
PARCEL_OUTLINE = new esri.Color(([0,0,255]));
PARCEL_FILL = new esri.Color([0,0,255,0.5]);
PLOT_OUTLINE = new esri.Color(([255,0,0]));
PLOT_FILL = new esri.Color([255,0,0,0.5]);
}
function createToolbar() {
toolbar = new esri.toolbars.Draw(map);
}
function drawEnd(geometry, pType, outline, fill) {
toolbar.deactivate();
map.showZoomSlider();
console.log("geometry: " + geometry.type);
var text_symbol = null;
switch (geometry.type) {
case "point":
case "multipoint":
symbol = new esri.symbol.PictureMarkerSymbol(markerPictures[pType], 13, 13);
break;
default:
symbol = new esri.symbol.SimpleFillSymbol();
symbol.setColor(fill);
symbol.setOutline(new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, outline, 2));
break;
}
var graphic = new esri.Graphic(geometry, symbol);
map.graphics.add(graphic);
var map_obj = new MapObject(pType, pType, graphic, geometry.type);
mapManager.Add(map_obj);
if(toolbarEvent != null)
{
toolbarEvent.remove();
toolbarEvent = null;
}
}
error happens specifically on this line:
dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;
You've got a simple scoping error - the variable dom is declared as an argument to this function:
require([...,"dojo/dom",...], function(...,dom,...) {...});
Your next function declaration is this:
function generateFeatureCollection (fileName) {
...
dom.byId(...);
...
}
but the variable dom is not defined in this function, so you can't use it here. You need to either pass it to the function:
function generateFeatureCollection (fileName, dom) {...}
which gets very clumsy if you're going to pass it around to every function, assign the dom variable in your require function to a global variable, or redeclare it where you need it. From the docs:
require(["dojo/dom"], function(dom){
// fetch a node by id="someNode"
var node = dom.byId("someNode");
});
Related
I have some data in a Google Spreadsheet, which I'm pulling with Tabletop.js. I'm able to display my data as well in my showInfo() function. All good.
Now I try to achieve to display this data in a default Google Chart. In this case I use their map package to display my data on a map. They provided me some sample code, see here.
At the moment I'm struggling with the following function, whole code in my Fiddle:
mapdata.addRows([
// PREFERRED DATA TO COLLECT:
// [data.geoloc, data.GM_NAAM, 'blue' ],
// THE HARDCODED WAY:
['Kerkbrink 2 ANLOO', 'ANLOO', 'green'],
['Grote Kerkstraat 32 WIJK EN AALBURG', 'WIJK EN AALBURG', 'blue']
]);
How do I approach? I managed to display all data with a forEach in the showInfo function, but this does not work in this array.
I'm pretty new in JS-land, so I appreciate every help on achieving this.
Thanks in advance!
please find the updated fiddle here
is this what you are looking for ?
updated js code:
/* 1: tabletop shizzle */
var publicSpreadsheetUrl = 'https://docs.google.com/spreadsheets/d/1cpSdKrQK0DfRoC9_xgmAqwVaDqw8BKMOL7drA_QFIn0/edit?usp=sharing';
function init() {
Tabletop.init( { key: publicSpreadsheetUrl,
callback: showInfo,
simpleSheet: true } )
}
function showInfo(data, tabletop) {
alert('Successfully processed!')
var chartdiv = document.querySelector(".chart_div");
console.log("data: ", data);
data.forEach( function(data) {
// card
var card = document.createElement('div');
card.classList.add("card");
//content
var content = document.createElement('div');
content.classList.add('content');
content.innerHTML = data.GM_NAAM + ' ' + data.geoloc;
// append
chartdiv.appendChild(card);
card.appendChild(content);
});
// trigger the google charts drapMap function and send the data to it
drawMap(data);
}
window.addEventListener('DOMContentLoaded', init);
/* 2: google chart shizzle */
google.charts.load('current', {
'packages': ['map'],
// DEFAULT GOOGLE API KEY
'mapsApiKey': 'AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY'
});
google.charts.setOnLoadCallback(drawMap);
function drawMap(data) {
var mapdata = new google.visualization.DataTable();
mapdata.addColumn('string', 'Address');
mapdata.addColumn('string', 'Location');
mapdata.addColumn('string', 'Marker')
console.log(data);
data = data ? data : [];
var rows = [];
data.forEach(function(item){
rows.push([item.GM_NAAM, item.geoloc, 'green'])
})
// THIS IS THE PART I NEED THE DATA.
mapdata.addRows(rows);
// SOME OPTIONS
var url = 'https://icons.iconarchive.com/icons/icons-land/vista-map-markers/48/';
var options = {
zoomLevel: 7,
showTooltip: true,
showInfoWindow: true,
useMapTypeControl: true,
icons: {
blue: {
normal: url + 'Map-Marker-Ball-Azure-icon.png',
selected: url + 'Map-Marker-Ball-Right-Azure-icon.png'
},
green: {
normal: url + 'Map-Marker-Push-Pin-1-Chartreuse-icon.png',
selected: url + 'Map-Marker-Push-Pin-1-Right-Chartreuse-icon.png'
}
}
};
var map = new google.visualization.Map(document.getElementById('map_div'));
map.draw(mapdata, options);
}
Trying to rename all files in folder, nothing much, just want to add an prefix in all files, using Javascript. Getting error as: "Uncaught TypeError: gapi.client.drive.files.patch is not a function"
listFiles Function is able to fetch the file id and current name, but gapi.client.drive.files.patch throws above error.
Tried with gapi.client.drive.properties.patch but it also gave an error.!
Code:
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>
<p id="list" style="display: none;">Enter Folder ID:
<input type="text" id="listInput" size="40" />
<button id="list-button" onClick="listFiles();">Get List</button></p>
<pre id="content"></pre>
<script type="text/javascript">
var CLIENT_ID = '';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"];
var SCOPES = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.scripts';
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
var pre = document.getElementById('content');
var list = document.getElementById('list');
var listInput = document.getElementById('listInput');
var listButton = document.getElementById('list-button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
list.style.display = 'block';
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
list.style.display = 'none';
clearPre();
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
function appendPre(message) {
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
function clearPre() {
pre.innerHTML = "";
}
function listFiles() {
clearPre();
appendPre('Getting Files List......');
gapi.client.drive.files.list({
'q' : "'" + listInput.value + "' in parents",
'orderBy' : 'name',
'pageSize': 1000,
'fields': "nextPageToken, files(id, name, parents, mimeType)"
}).then(function(response) {
clearPre();
var files = response.result.files;
console.log(files);
if (files && files.length > 0) {
var currentFile;
var currentFileId;
appendPre('Count: ' + files.length + ' Files:');
for (var i = 0; i < files.length; i++) {
currentFile = files[i].name;
currentFileId = files[i].id;
appendPre(currentFile);
alert(currentFileId + ' Rename ' + currentFile);
*********Getting Error here*********
var request = gapi.client.drive.files.patch({
'fileId': currentFileId,
'resource': {'title': 'Rename ' + currentFile}
});
request.execute(function(resp) {
console.log('New Title: ' + resp.title);
});
}
} else {
appendPre('No files found.');
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js" nload="this.onload=function(){};handleClientLoad()" onreadystatechange="if this.readyState === 'complete') this.onload()">
</script>
I can see in your code that you are using V3.
gapi.client.drive.files.patch is deprecated in the said version, you can use Files: update instead, to update the desired filenames.
Or other way around, you can switch to V2 and use the code provided in the documentation.
/**
* Rename a file.
*
* #param {String} fileId <span style="font-size: 13px; ">ID of the file to rename.</span><br> * #param {String} newTitle New title for the file.
*/
function renameFile(fileId, newTitle) {
var body = {'title': newTitle};
var request = gapi.client.drive.files.patch({
'fileId': fileId,
'resource': body
});
request.execute(function(resp) {
console.log('New Title: ' + resp.title);
});
}
Appreciate the original question was Javascript and V2 of the Google Drive API...
Trying to use Python and V3, it took me a while to work out how to do this. The bit I was missing was the body={} keyword argument that you need to submit the name property.
Assuming you've already gotten the file_id you want to rename in a separate call, like this:
drive.files().update(
fileId=file_id,
supportsAllDrives='true',
body={'name': 'new name for this file'}
).execute()
After 3 attempts to use other folks NPM modules for Google Drive, I decided it was time to do my own and I was JUST adding mv() functionality so I had this fight and here's what I came up with and use in my library. It isn't public today and will change names, but if anyone wants to try a beta version, hit me up on twitter by this same name.
note:
You only need addParents and removeParents if you're "moving" a file and you only need name if you're actually going to rename it.
drive.files.update({
fileId: driveFileId,
addParents: commaStringOfParents,
removeParents: commaStringOfParents,
resource: { name: newFileName }
}, (err, res) => {
if (err) handleError(err);
let files = res.data
// Do stuff here
}
I'm trying to record audio from a website user and save the audio to my server. Many of the posts I have studied so far have referenced Matt Diamond's recorderjs. I attempted to recreate the demo at http://webaudiodemos.appspot.com/AudioRecorder/index.html by opening the source code through my browser. I copied the html, "audiodisplay.js", "recorder.js", and "main.js" and put them on my server. I also added the "recorderWorker.js" file from his GitHub site. In the recorder.js file, I changed var WORKER_PATH = 'js/recorderjs/recorderWorker.js' to var WORKER_PATH = 'recorderWorker.js';
When I run the demo I set up, I'm getting the "would you like to share your microphone.." warning and I can start the recording by pressing the mic icon on the right side. However, when I stop recording, the audio waveform doesn't show up below like in Matt's demo and the save icon doesn't become activated.
If I can get the demo up and running, the next problem I have is saving the wav file to the server instead of locally like in the demo. I've found several posts saying to use XMLHttpRequest(), however I can't really figure out how to connect those examples to recorderjs. Saving WAV File Recorded in Chrome to Server HTML5 & getUserMedia - Record Audio & Save to Web Server after Certain Time RecorderJS uploading recorded blob via AJAX
Using XMLHttpRequest to post wav or mp3 blobs to server is simple.
Just run this code wherever you have access to the blob element:
var xhr=new XMLHttpRequest();
xhr.onload=function(e) {
if(this.readyState === 4) {
console.log("Server returned: ",e.target.responseText);
}
};
var fd=new FormData();
fd.append("audio_data",blob, "filename");
xhr.open("POST","upload.php",true);
xhr.send(fd);
I prefer XMLHttpRequest to $.ajax() because it does not require jQuery.
Server-side, upload.php is as simple as:
$input = $_FILES['audio_data']['tmp_name']; //temporary name that PHP gave to the uploaded file
$output = $_FILES['audio_data']['name'].".wav"; //letting the client control the filename is a rather bad idea
//move the file from temp name to local folder using $output name
move_uploaded_file($input, $output)
Source: https://blog.addpipe.com/using-recorder-js-to-capture-wav-audio-in-your-html5-web-site/
Live demo: https://addpipe.com/simple-recorderjs-demo/
I figured out one solution, but would still welcome others related to recorderjs. I used MP3RecorderJS at https://github.com/icatcher-at/MP3RecorderJS. The demo html works if you change the top of the html from src="js/jquery.min.js" and src="js/mp3recorder.js" to wherever they're located in your server. For me, it is src="jquery.min.js" and src="mp3recorder.js" I also had to do the same thing to the "mp3recorder.js" file: var RECORDER_WORKER_PATH = 'js/recorderWorker.js'; var ENCODER_WORKER_PATH = 'js/mp3Worker.js'; changed to var RECORDER_WORKER_PATH = 'recorderWorker.js'; var ENCODER_WORKER_PATH = 'mp3Worker.js';
The program is set up to record both mp3 and wav. I wanted wav, so I made a few more adjustments to the html file. At line 55 you'll find:
recorderObject.exportMP3(function(base64_mp3_data) {
var url = 'data:audio/mp3;base64,' + base64_mp3_data;
var au = document.createElement('audio');
I changed that to:
recorderObject.exportWAV(function(base64_wav_data) {
var url = 'data:audio/wav;base64,' + base64_wav_data;
var au = document.createElement('audio');
The demo appends a new player each time you record. To prevent this, I deleted (commented out) the $recorder.append(au); part, made a new div to store the audio player, and then I clear that div each time, before the audio player is created. To upload to my server, I used a technique I learned from uploading images to a server save canvas image to server Basically, the "url" variable in line 56 was what I needed, but couldn't figure out how to put it in a universal variable to use by another function. So, I made a hidden div and made the contents of it equal to "url". I then referenced that div in a new function called "upload". I then used a php file called "uploadWav.php". I still have to figure out a way to activate and deactivate the upload button to prevent the user from uploading a blank file before recording, but that's another issue. Here's the final html and php that worked for me:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>MP3 Recorder test</title>
</head>
<body id="index" onload="">
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="mp3recorder.js"></script>
<script type="text/javascript">
var audio_context;
function __log(e, data) {
log.innerHTML += "\n" + e + " " + (data || '');
}
$(function() {
try {
// webkit shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
window.URL = window.URL || window.webkitURL;
var audio_context = new AudioContext;
__log('Audio context set up.');
__log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
} catch (e) {
alert('No web audio support in this browser!');
}
$('.recorder .start').on('click', function() {
$this = $(this);
$recorder = $this.parent();
navigator.getUserMedia({audio: true}, function(stream) {
var recorderObject = new MP3Recorder(audio_context, stream, { statusContainer: $recorder.find('.status'), statusMethod: 'replace' });
$recorder.data('recorderObject', recorderObject);
recorderObject.start();
}, function(e) { });
});
$('.recorder .stop').on('click', function() {
$this = $(this);
$recorder = $this.parent();
recorderObject = $recorder.data('recorderObject');
recorderObject.stop();
recorderObject.exportWAV(function(base64_wav_data) {
var url = 'data:audio/wav;base64,' + base64_wav_data;
var au = document.createElement('audio');
document.getElementById("playerContainer").innerHTML = "";
//console.log(url)
var duc = document.getElementById("dataUrlcontainer");
duc.innerHTML = url;
au.controls = true;
au.src = url;
//$recorder.append(au);
$('#playerContainer').append(au);
recorderObject.logStatus('');
});
});
});
</script>
<script>
function upload(){
var dataURL = document.getElementById("dataUrlcontainer").innerHTML;
$.ajax({
type: "POST",
url: "uploadWav.php",
data: {
wavBase64: dataURL
}
}).done(function(o) {
console.log('saved');
});
}
</script>
<div class="recorder">
Recorder 1
<input type="button" class="start" value="Record" />
<input type="button" class="stop" value="Stop" />
<pre class="status"></pre>
</div>
<div><button onclick="upload()">Upload</button></div>
<div id="playerContainer"></div>
<div id="dataUrlcontainer" hidden></div>
<pre id="log"></pre>
</body>
</html>
and the "uploadWav.php" file:
<?php
// requires php5
define('UPLOAD_DIR', 'uploads/');
$img = $_POST['wavBase64'];
$img = str_replace('data:audio/wav;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.wav';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>
//**Server Side Code**
package myPack;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
#WebServlet("/MyServlet")
#MultipartConfig
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public MyServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String name = request.getParameter("fname");
String url = request.getParameter("myUrl");
url = url.replace("data:audio/wav;base64,", "");
url = url.replace(" ", "+");
byte[] bytes = url.getBytes();
byte[] valueDecoded = Base64.decodeBase64(bytes);
FileOutputStream os = new FileOutputStream(new File("D://" + name
+ ".wav"));
os.write(valueDecoded);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
**Client Side Code**
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>MP3 Recorder test</title>
</head>
<body id="index" onload="">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/recorder.js"></script>
<script type="text/javascript">
var audio_context;
function __log(e, data) {
log.innerHTML += "\n" + e + " " + (data || '');
}
$(function() {
try {
// webkit shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
window.URL = window.URL || window.webkitURL;
var audio_context = new AudioContext;
__log('Audio context set up.');
__log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
} catch (e) {
alert('No web audio support in this browser!');
}
$('.recorder .start').on('click', function() {
$this = $(this);
$recorder = $this.parent();
navigator.getUserMedia({audio: true}, function(stream) {
var recorderObject = new MP3Recorder(audio_context, stream, { statusContainer: $recorder.find('.status'), statusMethod: 'replace' });
$recorder.data('recorderObject', recorderObject);
recorderObject.start();
}, function(e) { });
});
$('.recorder .stop').on('click', function() {
$this = $(this);
$recorder = $this.parent();
recorderObject = $recorder.data('recorderObject');
recorderObject.stop();
recorderObject.exportWAV(function(base64_wav_data) {
var url = 'data:audio/wav;base64,' + base64_wav_data;
var au = document.createElement('audio');
document.getElementById("playerContainer").innerHTML = "";
//console.log(url)
var duc = document.getElementById("dataUrlcontainer");
duc.innerHTML = url;
au.controls = true;
au.src = url;
//$recorder.append(au);
$('#playerContainer').append(au);
var fd = new FormData();
fd.append('fname', 'test.wav');
fd.append('myUrl', duc.innerHTML);
$.ajax({
type: "POST",
url: "/audioPart2/MyServlet",
data: fd,
processData: false,
contentType: false
});
recorderObject.logStatus('');
});
});
});
</script>
<div class="recorder">
Recorder 1 <input type="button" class="start" value="Record" /> <input
type="button" class="stop" value="Stop" />
<div id="playerContainer"></div>
<div id="dataUrlcontainer" hidden></div>
<pre class="status"></pre>
</div>
<!-- <div class="recorder"> -->
<!-- Recorder 2 <input type="button" class="start" value="Record" /> <input -->
<!-- type="button" class="stop" value="Stop" /> -->
<!-- <pre class="status"></pre> -->
<!-- </div> -->
<pre id="log"></pre>
</body>
</html>
**// Required JS
1)jquery.min.js
2) recorder.js**
**recorder.js is below**
(function(window){
var RECORDER_WORKER_PATH = 'js/recorderWorker.js';
var ENCODER_WORKER_PATH = 'js/mp3Worker.js';
var MP3Recorder = function(context, stream, cfg) {
var config = cfg || { statusContainer: null, statusMethod: 'append' }
var bufferLen = 4096;
var recording = false;
this.source = context.createMediaStreamSource(stream);
this.node = (context.createScriptProcessor || context.createJavaScriptNode).call(context, bufferLen, 1, 1);
var recorderWorker = new Worker(RECORDER_WORKER_PATH);
var encoderWorker = new Worker(ENCODER_WORKER_PATH);
var exportCallback;
// initialize the Recorder Worker
recorderWorker.postMessage({ cmd: 'init', sampleRate: context.sampleRate });
// the recording loop
this.node.onaudioprocess = function(e) {
if(!recording) return;
recorderWorker.postMessage({ cmd: 'record', buffer: e.inputBuffer.getChannelData(0) });
}
this.start = function() {
recording = true;
this.logStatus('recording...');
}
this.stop = function() {
recording = false;
this.logStatus('stopping...');
}
this.destroy = function() { recorderWorker.postMessage({ cmd: 'destroy' }); }
this.logStatus = function(status) {
if(config.statusContainer) {
if(config.statusMethod == 'append') {
config.statusContainer.text(config.statusContainer.text + "\n" + status);
} else {
config.statusContainer.text(status);
}
}
}
this.exportBlob = function(cb) {
exportCallback = cb;
if (!exportCallback) throw new Error('Callback not set');
recorderWorker.postMessage({ cmd: 'exportBlob' });
}
this.exportWAV = function(cb) {
// export the blob from the worker
this.exportBlob(function(blob) {
var fileReader = new FileReader();
// read the blob as array buffer and convert it
// to a base64 encoded WAV buffer
fileReader.addEventListener("loadend", function() {
var resultBuffer = new Uint8Array(this.result);
cb(encode64(resultBuffer));
});
fileReader.readAsArrayBuffer(blob);
});
}
this.exportMP3 = function(cb) {
this.logStatus('converting...');
// export the blob from the worker
this.exportBlob(function(blob) {
var fileReader = new FileReader();
fileReader.addEventListener("loadend", function() {
var wavBuffer = new Uint8Array(this.result);
var wavData = parseWav(wavBuffer);
encoderWorker.addEventListener('message', function(e) {
if (e.data.cmd == 'data') {
cb(encode64(e.data.buffer));
}
});
encoderWorker.postMessage({ cmd: 'init', config: { mode: 3, channels: 1, samplerate: wavData.sampleRate, bitrate: wavData.bitsPerSample } });
encoderWorker.postMessage({ cmd: 'encode', buf: Uint8ArrayToFloat32Array(wavData.samples) });
encoderWorker.postMessage({ cmd: 'finish' });
});
fileReader.readAsArrayBuffer(blob);
});
}
// event listener for return values of the recorderWorker
recorderWorker.addEventListener('message', function(e) {
switch(e.data.from) {
case 'exportBlob':
exportCallback(e.data.blob);
break;
};
});
// HELPER FUNCTIONS
function encode64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for(var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
function parseWav(wav) {
function readInt(i, bytes) {
var ret = 0, shft = 0;
while(bytes) {
ret += wav[i] << shft; shft += 8;
i++; bytes--;
}
return ret;
}
if(readInt(20, 2) != 1) throw 'Invalid compression code, not PCM';
if(readInt(22, 2) != 1) throw 'Invalid number of channels, not 1';
return { sampleRate: readInt(24, 4), bitsPerSample: readInt(34, 2), samples: wav.subarray(44) };
}
function Uint8ArrayToFloat32Array(u8a){
var f32Buffer = new Float32Array(u8a.length);
for (var i = 0; i < u8a.length; i++) {
var value = u8a[i<<1] + (u8a[(i<<1)+1]<<8);
if (value >= 0x8000) value |= ~0x7FFF;
f32Buffer[i] = value / 0x8000;
}
return f32Buffer;
}
this.source.connect(this.node);
this.node.connect(context.destination); // this should not be necessary
}
window.MP3Recorder = MP3Recorder;
})(window);
I have a case where i need to load a char based on the input from another javascript. But it doesn't work in my case. I have added the code below:
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['corechart', 'table']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var json = $.ajax({
url: fileURL, // make this url point to the data file
dataType: 'json',
cahce:false,
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(json);
var options = {
title: graphTitle,
is3D: 'true',
width: 800,
height: 600
};
var tableOptions = {
title: 'App Listing'
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
and I pass the value for graphtitle and fileURL as below:
<script type="text/javascript">
$(document).ready(function () {
var fileURL = "";
var graphTitle = "";
function showDiv() {
if($firstCheck) {
var selText;
$("#dd4 li a").show(function () {
selText = $(this).text();
});
if(selText !== "Factor"){
if(selText == "IA Architecture Usage"){
fileURL = "get_json.php";
graphTitle = "IA Architecture Variation";
}else if(selText == "Tablet to Phone"){
fileURL = "get_tablet_support.php";
graphTitle = "Tablet Usage Variation";
}
document.getElementById('chart_div').style.display = "block";
}
}else{
document.getElementById('chart_div').style.display = "none";
}
}
</script>
Both these javascript are within the same file. I can't pass the fileURL and graphTitle when I used the above code. Any idea how to solve this issue?
Use global variables with window. E.g.
$(document).ready(function () {
window.fileURL = "";
window.graphTitle = "";
});
Don't specify "var" or it will only be within the scope of the function.
EDIT: Also make sure that the script in which your variables are assigned initially is before the other one.
How about something a bit more OO oriented (not really OO, but less inline code) ? It's cleaner and easier to read/maintain ..example could still use some work, but i"m sure you get the idea.
function loadChart(title, url) {
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['corechart', 'table']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var json = $.ajax({
url : url, // make this url point to the data file
dataType: 'json',
cahce : false,
async : false
});
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(json);
var options = {
title : title,
is3D : 'true',
width : 800,
height: 600
};
var tableOptions = {
title: 'App Listing'
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
}
$(document).ready(function () {
var fileURL = "";
var graphTitle = "";
function showDiv() {
if($firstCheck) {
var selText;
$("#dd4 li a").show(function () {
selText = $(this).text();
});
if(selText !== "Factor") {
if(selText == "IA Architecture Usage"){
fileURL = "get_json.php";
graphTitle = "IA Architecture Variation";
} else if(selText == "Tablet to Phone"){
fileURL = "get_tablet_support.php";
graphTitle = "Tablet Usage Variation";
}
document.getElementById('chart_div').style.display = "block";
}
} else {
document.getElementById('chart_div').style.display = "none";
}
loadChart(graphTitle, fileURL);
}
}
btw i think you have an error in your code: .responseText seems pretty useless to me, and most likely throws an error in itself. Also i have no idea who is calling showDiv() in the code. From the example, i'd say it never fires.
I'm using Kendo UI Mobile via Icenium Extension for Visual Studio. I'm very new at this, but I'm stumbling along. I've written a method (called popDataSource) in a view that gets some data (reads the names of files in a folder) and returns those file names. The method works perfectly if I wire it up to a button click event, but what I really want is for the method to be called when the page first loads. I've tried setting data-show=popDataSource and even data-after-show=popDataSource, but when I do that I get the error Object [object Object] has no method 'set' when I try to return the data. I'm also not that well versed in javascript, which I'm sure isn't helping me any.
Here's my code:
Snippet from index.html:
<div id="tabstrip-listSonicImages" data-role="view" data-title="Sonic Images List" data-model="app.listSonicImagesService.viewModel"
data-after-show="app.listSonicImagesService.viewModel.popDataSource">
<div data-role="content" class="view-content">
<div data-role="scroller">
<div class="buttonArea">
<a id="btnShowList" data-role="button" data-bind="click: popDataSource"
class="login-button">Display List</a>
</div>
<ul class="forecast-list" data-role="listview" data-bind="source: sonicImagesDataSource" data-template="sonic-image-list-template">
</ul>
</div>
</div>
</div>
<script type="text/x-kendo-tmpl" id="sonic-image-list-template">
<a data-role="listview-link" href="\#tabstrip-playSonicImage?fileName=${fileName}">${fileName}</a>
</script>
listiconimages.js
(function(global) {
var SonicImageListViewModel,
app = global.app = global.app || {};
SonicImageListViewModel = kendo.data.ObservableObject.extend({
popDataSource: function () {
var that = this;
var listSI = new Array();
try{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function (fileSys) {
fileSys.root.getDirectory("SIData", { create: true, exclusive: false},
function (dataDirEntry) {
var directoryReader = dataDirEntry.createReader ();
directoryReader.readEntries(
function (entries) {
var rows = entries.length;
for (i = 0; i < rows; i++) {
var fName = entries[i].name;
listSI[i] = { "fileName": fName, "image": "xxx" };
}
},
function (error) {
alert("error: " + error.code);
}
);
},
null);
},
null
);
var dataSource = new kendo.data.DataSource(
{
data: listSI,
filter: { field: "fileName", operator: "endswith", value: ".simg" }
}
);
that.set("sonicImagesDataSource", dataSource);
} catch (ex) {
alert(ex.message);
}
}
});
app.listSonicImagesService = {
viewModel: new SonicImageListViewModel()
};
}
)(window);
app.js
(function (global) {
var mobileSkin = "",
app = global.app = global.app || {};
document.addEventListener("deviceready", function () {
app.application = new kendo.mobile.Application(document.body, { layout: "tabstrip-layout" });
}, false);
app.changeSkin = function (e) {
if (e.sender.element.text() === "Flat") {
e.sender.element.text("Native");
mobileSkin = "flat";
}
else {
e.sender.element.text("Flat");
mobileSkin = "";
}
app.application.skin(mobileSkin);
};
})(window)
As I said, I'm new to Icenium and Kendo, and my javascript knowledge is limited, so I'm not quite sure where the answer lies. Any help would be greatly appreciated.
Thanks