From f7b2477bab6f73ea4549d36ae38906283934a6fa Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Sun, 3 Mar 2013 23:26:51 -0500 Subject: [PATCH] Rewrite of camera mobile spec page. -Now allows setting of all the options. -Follow-up actions do not make you reselect image. --- camera/index.html | 491 ++++++++++++++++++---------------------------- master.css | 1 + 2 files changed, 187 insertions(+), 305 deletions(-) diff --git a/camera/index.html b/camera/index.html index 82e0a3c8..1aa03402 100644 --- a/camera/index.html +++ b/camera/index.html @@ -35,46 +35,62 @@ var deviceReady = false; var platformId = cordova.require('cordova/platform').id; var CameraPopoverOptions = cordova.require('cordova/plugin/CameraPopoverOptions'); + var pictureUrl = null; + var fileObj = null; + var pageStartTime = +new Date(); //------------------------------------------------------------------------- // Camera //------------------------------------------------------------------------- - var onGetPictureError = function(e) { - console.log("Error getting picture: " + e.code); - document.getElementById('camera_status').innerHTML += "Error getting picture: " + e.code + "
"; - }; + function log(value) { + console.log(value); + document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n'; + } + + function clearStatus() { + document.getElementById('camera_status').innerHTML = ''; + document.getElementById('camera_image').src = 'about:blank'; + var canvas = document.getElementById('canvas'); + canvas.width = canvas.height = 1; + pictureUrl = null; + fileObj = null; + } - function showPicture(url, callback) { + function setPicture(url, callback) { + pictureUrl = url; + log('URL: ' + url.slice(0, 100)); var img = document.getElementById('camera_image'); - img.style.visibility = "visible"; - img.style.display = "block"; + var startTime = new Date(); img.src = url; - img.onloadend = callback; - }; + img.onloadend = function() { + log('Image tag load time: ' + (new Date() - startTime)); + callback && callback(); + }; + } - function getPictureFail(e) { - console.log("Error getting picture: " + e); - document.getElementById('camera_status').innerHTML = "Error getting picture."; + function onGetPictureError(e) { + log('Error getting picture: ' + e.code); } function getPictureWin(data) { - showPicture(data); - document.getElementById('camera_status').innerHTML = "Success"; + setPicture(data); } - /** - * Capture picture - */ function getPicture() { clearStatus(); - navigator.camera.getPicture(getPictureWin, getPictureFail, - { quality: 50, - destinationType: Camera.DestinationType.FILE_URI, - sourceType : Camera.PictureSourceType.CAMERA }); + var options = extractOptions(); + log('Getting picture with options: ' + JSON.stringify(options)); + var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options); + + // Reposition the popover if the orientation changes. + window.onorientationchange = function() { + var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0); + popoverHandle.setPosition(newPopoverOptions); + } } - function uploadImage(srcUrl) { + function uploadImage() { var ft = new FileTransfer(), uploadcomplete=0, progress = 0, @@ -83,161 +99,84 @@ options.fileName='test.jpg'; options.mimeType="image/jpeg"; ft.onprogress = function(progressEvent) { - console.log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total); + log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total); }; var server = "http://cordova-filetransfer.jitsu.com"; - ft.upload(srcUrl, server + '/upload', uploadedProfilePicture, function(message) { console.log("error: " + JSON.stringify(message)); }, options); - function uploadedProfilePicture(information_back){ - console.log('win!'); + ft.upload(pictureUrl, server + '/upload', win, fail, options); + function win(information_back){ + log('upload complete'); + } + function fail(message) { + log('upload failed: ' + JSON.stringify(message)); } } - /** - * Select image from library using a FILE_URI destination type - */ - function getImageUsingFileUri(upload) { - clearStatus(); - var popoverHandle = navigator.camera.getPicture( - function(data) { - getPictureWin(data); - if (upload) { - uploadImage(data); - } - }, getPictureFail, - { destinationType: Camera.DestinationType.FILE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY}); + function makeFileEntry() { + var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' '); + return new FileEntry('image_name.png', path); + } - // Reposition the popover if the orientation changes. - window.onorientationchange = function() { - var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0); - popoverHandle.setPosition(newPopoverOptions); - } - }; + function logCallback(apiName, success) { + return function() { + log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments))); + }; + } /** * Select image from library using a NATIVE_URI destination type * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL. */ - function getImageUsingNativeUri() { - var onMetadataReceived = function(metadata) { - document.getElementById('camera_status').innerHTML += "FileEntry.getMetadata success: modificationTime = " + metadata.modificationTime + "
"; - }; - - var onGetMetadataError = function(e) { - handleUnexpectedError("FileEntry.getMetadata", e.code); - }; - - var onMetadataSet = function() { - handleUnexpectedSuccess("FileEntry.setMetadata"); - }; - - var onSetMetadataError = function(e) { - checkForExpectedError("FileEntry.setMetadata", undefined, e.code); - }; - - var onParentReceived = function() { - if (platformId == 'ios') { - handleUnexpectedSuccess("FileEntry.getParent"); - } else if (platformId == 'android') { - document.getElementById('camera_status').innerHTML += "FileEntry.getParent success
" - } - }; - - var onGetParentError = function(e) { - if (platformId == 'ios') { - checkForExpectedError("FileEntry.getParent", FileError.NOT_READABLE_ERR, e.code); - } else if (platformId == 'android') { - handleUnexpectedError("FileEntry.getParent", e.code); - } - }; - + function getFileInfo() { var onFileReadAsDataURL = function(evt) { var img = document.getElementById('camera_image'); img.style.visibility = "visible"; img.style.display = "block"; img.src = evt.target.result; - document.getElementById('camera_status').innerHTML += "FileReader.readAsDataURL success
" + log("FileReader.readAsDataURL success"); }; var onFileReceived = function(file) { - document.getElementById('camera_status').innerHTML += "FileEntry.file success: fullPath = " + file.fullPath + "; name = " + file.name; - document.getElementById('camera_status').innerHTML += "; type = " + file.type + "; size = " + file.size + "; date = " + file.lastModifiedDate + "
"; - - // Test File API here. - var dataUrlReader = new FileReader(); - dataUrlReader.onload = onFileReadAsDataURL; - dataUrlReader.onerror = function(evt) { - onError(evt.target.error); + log('Got file: ' + JSON.stringify(file)); + fileObj = file; + + var reader = new FileReader(); + reader.onload = logCallback('FileReader.readAsDataURL', true); + reader.onerror = logCallback('FileReader.readAsDataURL', false); + reader.onloadend = function() { + log('DataURL size: ' + reader.result.length); }; - dataUrlReader.readAsDataURL(file); - }; - - var onGetFileError = function(e) { - handleUnexpectedError("FileEntry.file", e.code); + reader.readAsDataURL(file); }; - clearStatus(); - navigator.camera.getPicture( - function(data) { - var fileEntry = new FileEntry('image_name.png', data); - - // Test FileEntry API here. - fileEntry.getMetadata(onMetadataReceived, onGetMetadataError); - fileEntry.setMetadata(onMetadataSet, onSetMetadataError, { "com.apple.MobileBackup": 1 }); - fileEntry.getParent(onParentReceived, onGetParentError); - fileEntry.file(onFileReceived, onGetFileError); - }, - onGetPictureError, - { destinationType: Camera.DestinationType.NATIVE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); + var fileEntry = makeFileEntry(); + + // Test FileEntry API here. + fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false)); + fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 }); + fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false)); + fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false)); + fileEntry.file(onFileReceived, logCallback('FileEntry.file', false)); + // Test out onFileReceived when the file object was set via a native elements. + if (fileObj) { + onFileReceived(fileObj); + } }; /** * Copy image from library using a NATIVE_URI destination type * This calls FileEntry.copyTo and FileEntry.moveTo. */ - function copyImageUsingNativeUri() { - var onFileCopied = function(fileEntry) { - document.getElementById('camera_status').innerHTML += "FileEntry.copyTo success
"; - }; - - var onFileCopyError = function(e) { - handleUnexpectedError("FileEntry.copyTo", e.code); - }; - - var onFileMoved = function(fileEntry) { - if (platformId == 'ios') { - handleUnexpectedSuccess("FileEntry.moveTo"); - } else if (platformId == 'android') { - document.getElementById('camera_status').innerHTML += "FileEntry.moveTo success
"; - } - }; - - var onFileMoveError = function(e) { - if (platformId == 'ios') { - checkForExpectedError("FileEntry.moveTo", FileError.INVALID_MODIFICATION_ERR, e.code); - } else if (platformId == 'android') { - handleUnexpectedError("FileEntry.moveTo", e.code); - } - }; - + function copyImage() { var onFileSystemReceived = function(fileSystem) { - navigator.camera.getPicture( - function(data) { - var fileEntry = new FileEntry('image_name.png', data); - var destDirEntry = fileSystem.root; - - // Test FileEntry API here. - fileEntry.copyTo(destDirEntry, 'copied_file.png', onFileCopied, onFileCopyError); - fileEntry.moveTo(destDirEntry, 'moved_file.png', onFileMoved, onFileMoveError); - }, - onGetPictureError, - { destinationType: Camera.DestinationType.NATIVE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); + var fileEntry = makeFileEntry(); + var destDirEntry = fileSystem.root; + + // Test FileEntry API here. + fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false)); + fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false)); }; - clearStatus(); window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null); }; @@ -245,51 +184,22 @@ * Write image to library using a NATIVE_URI destination type * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate. */ - function writeImageUsingNativeUri() { - var onFileWrite = function(evt) { - handleUnexpectedSuccess("FileWriter.write"); - }; - - var onFileWriteError = function(evt) { - checkForExpectedError("FileWriter.write", FileError.NO_MODIFICATION_ALLOWED_ERR, evt.target.error.code); - }; - - var onFileTruncate = function(evt) { - handleUnexpectedSuccess("FileWriter.truncate"); - }; - - var onFileTruncateError = function(evt) { - checkForExpectedError("FileWriter.truncate", FileError.NO_MODIFICATION_ALLOWED_ERR, evt.target.error.code); - }; - + function writeImage() { var onFileWriterReceived = function(fileWriter) { - fileWriter.onwrite = onFileWrite; - fileWriter.onerror = onFileWriteError; + fileWriter.onwrite = logCallback('FileWriter.write', true); + fileWriter.onerror = logCallback('FileWriter.write', false); fileWriter.write("some text!"); }; var onFileTruncateWriterReceived = function(fileWriter) { - fileWriter.onwrite = onFileTruncate; - fileWriter.onerror = onFileTruncateError; + fileWriter.onwrite = logCallback('FileWriter.truncate', true); + fileWriter.onerror = logCallback('FileWriter.truncate', false); fileWriter.truncate(10); }; - var onCreateWriterError = function(e) { - handleUnexpectedError("FileEntry.createWriter", e.code); - }; - - clearStatus(); - navigator.camera.getPicture( - function(data) { - var fileEntry = new FileEntry('image_name.png', data); - - // Test FileEntry API here. - fileEntry.createWriter(onFileWriterReceived, onCreateWriterError); - fileEntry.createWriter(onFileTruncateWriterReceived, onCreateWriterError); - }, - onGetPictureError, - { destinationType: Camera.DestinationType.NATIVE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); + var fileEntry = makeFileEntry(); + fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false)); + fileEntry.createWriter(onFileTruncateWriterReceived, null); }; /** @@ -297,15 +207,6 @@ * This calls FileTransfer.upload. */ function uploadImageUsingNativeUri() { - var onFileUploaded = function(response) { - document.getElementById('camera_status').innerHTML += "FileTransfer.upload success: response = " + response.responseCode + ".
"; - }; - - var onFileUploadError = function(error) { - document.getElementById('camera_status').innerHTML += "FileTransfer.upload error (code: " + error.code + ").
"; - }; - - clearStatus(); navigator.camera.getPicture( function(data) { var options = new FileUploadOptions(); @@ -313,74 +214,39 @@ options.mimeType = "image/png"; var fileTransfer = new FileTransfer(); - fileTransfer.upload(data, "http://cordova-filetransfer.jitsu.com/upload", onFileUploaded, onFileUploadError, options); + fileTransfer.upload(data, "http://cordova-filetransfer.jitsu.com/upload", + logCallback('FileTransfer.upload', true), + logCallback('FileTransfer.upload', false), options); }, onGetPictureError, { destinationType: Camera.DestinationType.NATIVE_URI, sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); }; - /** - * Display image from library using a NATIVE_URI destination type - * This uses img and canvas tags. - */ - function displayImageUsingNativeUri() { - clearStatus(); - navigator.camera.getPicture( - function(data) { - // First, we display the image using the img tag. - document.getElementById('camera_status').innerHTML += "img tag:
"; - - // Next, the canvas tag. - document.getElementById('camera_status').innerHTML += "canvas tag: "; - var canvas = document.getElementById('nativeUriCanvas'); - var context = canvas.getContext('2d'); - var image = new Image(); - image.onload = function() { - context.drawImage(image, 0, 0); - }; - image.src = data; - }, - onGetPictureError, - { destinationType: Camera.DestinationType.NATIVE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); + function displayImageUsingCanvas() { + var canvas = document.getElementById('canvas'); + var img = document.getElementById('camera_image'); + var w = img.width; + var h = img.height; + h = 100 / w * h; + w = 100; + canvas.width = w; + canvas.height= h; + var context = canvas.getContext('2d'); + context.drawImage(img, 0, 0, w, h); }; /** * Remove image from library using a NATIVE_URI destination type * This calls FileEntry.remove. */ - function removeImageUsingNativeUri() { - var onFileEntryRemoved = function() { - if (platformId == 'ios') { - handleUnexpectedSuccess("FileEntry.remove"); - } else if (platformId == 'android') { - document.getElementById('camera_status').innerHTML += "FileEntry.remove success
" - } - }; - - var onFileEntryRemoveError = function(e) { - if (platformId == 'ios') { - checkForExpectedError("FileEntry.remove", FileError.INVALID_MODIFICATION_ERR, e.code); - } else if (platformId == 'android') { - handleUnexpectedError("FileEntry.remove", e.code); - } - }; - - clearStatus(); - navigator.camera.getPicture( - function(data) { - var fileEntry = new FileEntry('image_name.png', data); - - // Test FileEntry API here. - fileEntry.remove(onFileEntryRemoved, onFileEntryRemoveError); - }, - onGetPictureError, - { destinationType: Camera.DestinationType.NATIVE_URI, - sourceType: Camera.PictureSourceType.PHOTOLIBRARY }); + function removeImage() { + var fileEntry = makeFileEntry(); + fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false)); }; - function testNativeFile(inputEl) { + function testInputTag(inputEl) { + clearStatus(); // iOS 6 likes to dead-lock in the onchange context if you // do any alerts or try to remote-debug. window.setTimeout(function() { @@ -399,65 +265,82 @@ return; } var URLApi = window.URL || window.webkitURL; - var statusText = ''; if (URLApi) { var blobURL = URLApi.createObjectURL(file); if (blobURL) { - showPicture(blobURL, function() { + setPicture(blobURL, function() { URLApi.revokeObjectURL(blobURL); }); } else { - statusText = 'URL.createObjectURL returned null'; + log('URL.createObjectURL returned null'); } } else { - statusText = 'URL.createObjectURL() not supported.'; + log('URL.createObjectURL() not supported.'); } - document.getElementById('camera_status').innerHTML = statusText; - var reader = new FileReader(); - reader.onloadend = function() { - if (!reader.result) { - statusText += ' FileReader.readAsDataURL() failed'; + } + + function extractOptions() { + var els = document.querySelectorAll('#image-options select'); + var ret = {}; + for (var i = 0, el; el = els[i]; ++i) { + var value = el.value; + if (value === '') continue; + if (el.isBool) { + ret[el.keyName] = !!value; } else { - statusText += ' DataURL size: ' + reader.result.length; + ret[el.keyName] = +value; } - document.getElementById('camera_status').innerHTML = statusText; - }; - reader.readAsDataURL(file); - }; - - function handleUnexpectedError(methodName, errorCode) { - document.getElementById('camera_status').innerHTML += "" + methodName + " error (code: " + errorCode + ").
"; - }; - - function handleUnexpectedSuccess(methodName) { - document.getElementById('camera_status').innerHTML += "" + methodName + " failure (succeeded when it should fail).
"; - }; - - function checkForExpectedError(methodName, expectedErrorCode, actualErrorCode) { - if (actualErrorCode == expectedErrorCode) { - document.getElementById('camera_status').innerHTML += "" + methodName + " success (failed as expected, with error code " + actualErrorCode + ").
"; - } else { - document.getElementById('camera_status').innerHTML += "" + methodName + " failure (failed as expected, but with error code " + actualErrorCode + " instead of " + expectedErrorCode + ").
"; } - }; + return ret; + } - function clearStatus() { - document.getElementById('camera_status').innerHTML = ""; - document.getElementById('camera_image').style.visibility = "hidden"; - }; + function createOptionsEl(name, values) { + var container = document.createElement('div'); + container.style.display = 'inline-block'; + container.appendChild(document.createTextNode(name + ': ')); + var select = document.createElement('select'); + select.keyName = name; + container.appendChild(select); + var opt = document.createElement('option'); + opt.value = ''; + opt.textContent = ''; + select.appendChild(opt); + select.isBool = typeof values == 'boolean'; + if (select.isBool) { + values = {'true': 1, 'false': 0}; + } + for (var k in values) { + var opt = document.createElement('option'); + opt.value = values[k]; + opt.textContent = k; + select.appendChild(opt); + } + var optionsDiv = document.getElementById('image-options'); + optionsDiv.appendChild(container); + } /** * Function called when page has finished loading. */ function init() { document.addEventListener("deviceready", function() { - deviceReady = true; - console.log("Device="+device.platform+" "+device.version); - }, false); + deviceReady = true; + console.log("Device="+device.platform+" "+device.version); + createOptionsEl('sourceType', Camera.PictureSourceType); + createOptionsEl('destinationType', Camera.DestinationType); + createOptionsEl('encodingType', Camera.EncodingType); + createOptionsEl('mediaType', Camera.MediaType); + createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}); + createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048}); + createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048}); + createOptionsEl('allowEdit', true); + createOptionsEl('correctOrientation', true); + createOptionsEl('saveToPhotoAlbum', true); + }, false); window.setTimeout(function() { - if (!deviceReady) { - alert("Error: Apache Cordova did not initialize. Demo will not run correctly."); - } + if (!deviceReady) { + alert("Error: Apache Cordova did not initialize. Demo will not run correctly."); + } },1000); }; @@ -467,28 +350,26 @@

Camera

-
- Status:
- +
+ Status:
+ img: + canvas:
-

Action

-
Take Picture
-
Select Image Using File URI
-

Native URI

-
Select Image
-
Copy Image
-
Write Image
-
Upload Image
-
Display Image
-
Remove Image
-

input type=file

- -

capture=camera

- -

capture=camcorder

- -

capture=microphone

- +

Cordova Camera API

+
+
camera.getPicture()
+

Native File Inputs

+
input type=file
+
capture=camera
+
capture=camcorder
+
capture=microphone
+

Actions

+
Get File Object
+
Copy Image
+
Write Image
+
Upload Image
+
Draw Using Canvas
+
Remove Image

Back
diff --git a/master.css b/master.css index 2549d177..e93c9376 100644 --- a/master.css +++ b/master.css @@ -37,6 +37,7 @@ clear:both; margin:15px 6px 0; min-width:295px; + max-width:97%; padding:4px 0px 2px 10px; word-wrap:break-word; margin-bottom:10px;