We are creating an HTML5 website for mobile and need to get camera access through the web browser without being a native app. We are having trouble making this work in iOS. Is anyone aware of a solution for this?
You could try this:
<input type="file" capture="camera" accept="image/*" id="cameraInput" name="cameraInput">
but it has to be iOS 6+ to work. That will give you a nice dialogue for you to choose either to take a picture or to upload one from your album i.e.
An example can be found here:
Capturing camera/picture data without PhoneGap
As of 2015, it now just works.
<input type="file">
This will ask user for the upload of any file. On iOS 8.x this can be a camera video, camera photo, or a photo/video from Photo Library.
<input type="file" accept="image/*">
This is as above, but limits the uploads to photos only from camera or library, no videos.
In iOS6, Apple supports this via the <input type="file"> tag. I couldn't find a useful link in Apple's developer documentation, but there's an example here.
It looks like overlays and more advanced functionality is not yet available, but this should work for a lot of use cases.
EDIT: The w3c has a spec that iOS6 Safari seems to implement a subset of. The capture attribute is notably missing.
I think this one is working.
Recording a video or audio;
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">
or (new method)
<device type="media" onchange="update(this.data)"></device>
<video autoplay></video>
<script>
function update(stream) {
document.querySelector('video').src = stream.url;
}
</script>
If it is not, probably will work on ios6, more detail can be found at get user media
Update 11/2020: The Google Developer link is (currently) dead. The original article with a LOT more explanations can still be found at web.archive.org.
This question is already a few years old but in that time some additional possibilities have evolved, like accessing the camera directly, displaying a preview and capturing snapshots (e.g. for QR code scanning).
This Google Developers article provides an in-depth explaination of all (?) the ways how to get image/camera data into a web application, from "work everywhere" (even in desktop browsers) to "work only on modern, up-to-date mobile devices with camera". Along with many useful tips.
Explained methods:
Ask for a URL: Easiest but least satisfying.
File input (covered by most other posts here): The data can then be attached to a or manipulated with JavaScript by listening for an onchange event on the input element and then reading the files property of the event target.
<input type="file" accept="image/*" id="file-input">
<script>
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', (e) => doSomethingWithFiles(e.target.files));
</script>
The files property is a FileList object.
Drag and drop (useful for desktop browsers):
<div id="target">You can drag an image file here</div>
<script>
const target = document.getElementById('target');
target.addEventListener('drop', (e) => {
e.stopPropagation();
e.preventDefault();
doSomethingWithFiles(e.dataTransfer.files);
});
target.addEventListener('dragover', (e) => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
</script>
You can get a FileList object from the dataTransfer.files property of the drop event.
Paste from clipboard
<textarea id="target">Paste an image here</textarea>
<script>
const target = document.getElementById('target');
target.addEventListener('paste', (e) => {
e.preventDefault();
doSomethingWithFiles(e.clipboardData.files);
});
</script>
e.clipboardData.files is a FileList object again.
Access the camera interactively (necessary if application needs to give instant feedback on what it "sees", like QR codes): Detect camera support with const supported = 'mediaDevices' in navigator; and prompt the user for consent. Then show a realtime preview and copy snapshots to a canvas.
<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="canvas" width=320 height=240></canvas>
<script>
const player = document.getElementById('player');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const captureButton = document.getElementById('capture');
const constraints = {
video: true,
};
captureButton.addEventListener('click', () => {
// Draw the video frame to the canvas.
context.drawImage(player, 0, 0, canvas.width, canvas.height);
});
// Attach the video stream to the video element and autoplay.
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
player.srcObject = stream;
});
</script>
Don't forget to stop the video stream with
player.srcObject.getVideoTracks().forEach(track => track.stop());
Update 11/2020: The Google Developer link is (currently) dead. The original article with a LOT more explanations can still be found at web.archive.org.
The Picup app is a way to take pictures from an HTML5 page and upload them to your server. It requires some extra programming on the server, but apart from PhoneGap, I have not found another way.
Related
I need to preview an image prior to submitting a form.
I work with Rails 3 and needs something that is browser compatible.
Any ideas how I can achieve that?
So! :) The main idea is to use the FileReader Javascript Class, which is really handy for what you need to do.
You just have to listen to the "change" event on your file input and then call a method that will use the "readAsDataURL()" method of the FileReader class. Then you just have to fill the source of a "preview img tag" with the returned result of the method...
I've wrote you a simple jsFiddle that achieves what you want. You can see my code below:
<!-- HTML Code -->
<div class="upload-preview">
<img />
</div>
<input class="file" name="logo" type="file">
//JS File
$(document).ready(function(){
var preview = $(".upload-preview img");
$(".file").change(function(event){
var input = $(event.currentTarget);
var file = input[0].files[0];
var reader = new FileReader();
reader.onload = function(e){
image_base64 = e.target.result;
preview.attr("src", image_base64);
};
reader.readAsDataURL(file);
});
});
And in the Mozilla Documentation, you have another example (surely more robust). This solution should work with Safari (version 6.0+).
This is the only way I know to preview an image prior to submitting a form, but I think it is quite a common way. Of course it has nothing to do with Ruby On Rails as we only use Javascript here... It would be impossible to do it using Rails only as you would have to upload the image before rendering it. (As Rails is server side, I think you perfectly understand why. :) )
HTML:
<input type="file">
<div id="image_preview"></div>
JS (require jquery):
$(document).ready(function(){
$('input[type="file"]').change(function(){
var image = window.URL.createObjectURL(this.files[0]);
$("#image_preview").css("background-image", "url(" + image + ")");
});
});
How can i use google earth API with backbone.js+jquery mobile ?
I have created application using backbone.js, underscore.js and jQuery Mobile.
For google earth API, I am using sample code listed at https://developers.google.com/earth/documentation/#using_the_google_earth_api
My template rendering, and all other pages are working fine But when i load google earth API in one tag, it's not loading and in js console i get message: "ERR_INVALID_DIV ".
Google.earth module never calls back initCallback, It's always calls failureCallback when google.earth.createInstance is invoked.
I explain some sample code of mine application as under, so based on that may be you get my code structure and it helps you to solve my issue.
my js code as under,
myjs1.js
var ge;
function init() {
google.earth.createInstance('map3d', initCB, failureCB);
}
function initCB(instance) {
console.log(' init call back call ');
ge = instance;
ge.getWindow().setVisibility(true);
}
function failureCB(errorCode) {
console.log(errorCode);
}
Now my Backbone code as under,
myjs2.js
WebApp.MyPage= Backbone.View.extend({
initialize:function (result) {
this.template =_.template($('#myPage').html());
},
render:function (eventName) {
var self = this;
mydata = object dict of my data;
$(self.el).html(self.template({mydata:mydata}));
google.load("earth", "1");
init();
google.setOnLoadCallback(init);
}
Now my HTML code like as under,
<script type="text/template" id="myPage">
<div data-role="page">
<div data-role="content">
<div id="map3d" style="height: 400px; width: 600px;"></div>
</div>
</div>
</script>
myhtml.html
Is there any way to fix this?
Any help appreciated.
The Earth API works with the Google Earth Plugin, which is available only on Windows and Mac OSX. It is not available on mobile devices, sorry!
If you're testing on your Mac or Windows system, you should be able to get it working. The error code ERR_INVALID_DIV sounds like it isn't finding the map3d div. I would put a debugger; statement in the code just before the google.earth.createInstance() call, and then look around in the DOM inspector and see if map3d is in the DOM. It should be coming in from your template if that part is working.
But this won't help you when you try to load your site on a mobile device, because you won't have the Earth plugin available there.
I am using popcornjs to load an interact with a video from youtube.
When I use the code from the documentation:
<html>
<head>
<script src="http://popcornjs.org/code/dist/popcorn-complete.min.js"></script>
<script>
// ensure the web page (DOM) has loaded
document.addEventListener("DOMContentLoaded", function () {
// Create a popcorn instance by calling the Youtube player plugin
var example = Popcorn.youtube(
'#video',
'http://www.youtube.com/watch?v=CxvgCLgwdNk' );
// add a footnote at 2 seconds, and remove it at 6 seconds
example.footnote({
start: 2,
end: 6,
text: "Pop!",
target: "footnotediv"
});
// play the video right away
//example.play(); => commented because you can't autoplay on ios
}, false);
</script>
</head>
<body>
<div id="video" style="width: 360px; height: 300px;" ></div>
<div id="footnotediv"></div>
</body>
</html>
It looks perfect on any browser, but nothing shows on the iPad.
When I load a video with popcorn but without using Youtube, it seems to work fine.
What can I do?
Unfortunately, the ipad doesn't support Flash. We do have a ticket in progress with Popcorn to switch to their HTML5 API, which you can view here:
https://webmademovies.lighthouseapp.com/projects/63272/tickets/329-support-youtube-html5-api-playback-engine
Hope that helps,
Brett
Try using the smart media wrapper:
var example = Popcorn.smart(
'#video',
'http://www.youtube.com/watch?v=CxvgCLgwdNk' );
// add a footnote at 2 seconds, and remove it at 6 seconds
example.footnote({
start: 2,
end: 6,
text: "Pop!",
target: "footnotediv"
});
// play the video right away
//example.play(); => commented because you can't autoplay on ios
}, false);
I too am facing the issue, Youtube Popcorn is not working in iPad. But interestingly I found a site using popcorn youtube and it works fine in iPad
Link:
http://www.retn.org/show/south-burlington-school-board-meeting-october-2-2013
So, I guess someone should come up with more specific answer
Edit this file in your code:
https://github.com/mozilla/popcorn-js/blob/master/wrappers/youtube/popcorn.HTMLYouTubeVideoElement.js
Comment body part of onPlayerReady() on line no 117 and add following statements in this function in case of iPad.
addYouTubeEvent("play", onFirstPlay);
playerReady = true;
mediaReady = true;
player.mute();
Reason: Youtube on iPad wants user interaction, you can't start it programmatically and due to player.isMuted() method returns false in case of iPad, addYouTubeEvent("play", onFirstPlay) statement is never called.
For some odd reason the HTML5 Audio API won't give me access to currentTime in iOS 4 and 5 for iPads and iPods. I need to adjust currentTime whenever an audio element is played, but it acts like the current time isn't accessible. Looked everywhere for an answer on this and I can't figure it out. My code below works fine in all modern browsers, so I'm a bit stumped.
My HTML markup
<p>
<a class="audio" href="assets/audio/ambient-sounds-1.mp3" data-flash="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/niftyplayer.swf" data-mp3="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/ambient-sounds-1.mp3" data-ogg="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/ambient-sounds-1.ogg">
Ambient Sounds
<span class="audio-play">Play</span>
<audio preload="">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/ambient-sounds-1.mp3" type="audio/mpeg">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/ambient-sounds-1.ogg" type="audio/ogg">
</audio>
</a>
</p>
<p>
<a class="audio" href="assets/audio/city_street.mp3" data-flash="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/niftyplayer.swf" data-mp3="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/city_street.mp3" data-ogg="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/city_street.ogg">
City Street Sounds
<span class="audio-play">Play</span>
<audio preload="">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/city_street.mp3" type="audio/mpeg">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/city_street.ogg" type="audio/ogg">
</audio>
</a>
</p>
<p>
<a class="audio" href="#" data-flash="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/niftyplayer.swf" data-mp3="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/crash.mp3" data-ogg="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/crash.ogg">
Loud Crash
<span class="audio-play">Play</span>
<audio preload="">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/crash.mp3" type="audio/mpeg">
<source preload="" src="http://athens.sierrabravo.net/~ablue/plato/videoplayer/assets/audio/crash.ogg" type="audio/ogg">
</audio>
</a>
</p>
My JavaScript
AudioPlayer = {
init: function () {
var player = this;
this.audio = $('.audio'); // Save and cache all audio elements so they can be targeted by mass stop()
player.audio.each( function() {
// Bind each audio element
player.bind($(this));
});
},
bind: function (object) {
var player = this;
object.bind('touchstart click', function() {
// get the real DOM element, not the jQuery array
var audio = $(this).find('audio').get(0);
if(audio.paused) { // Check if its playing
player.play(audio);
}
else {
player.stop(audio);
}
return false;
});
},
play: function(audio) {
// Stop all existing audio elements and set them to 0
this.audio.each( function() {
var audioOther = $(this).find('audio').get(0);
audioOther.pause();
});
// Play the audio element
if(audio.currentTime) audio.currentTime = 0;
audio.play();
},
stop: function(audio) {
if(audio.currentTime) audio.currentTime = 0;
audio.play();
}
};
There is an answer as to why my code doesn't work, iOS 4 and 5 need the entire audio element to be completely destroyed (terrible solution, but it works). Here is a quick rundown on how to fix my issue if you've run into it.
Insert only 1 element into the page (I inserted mine right before the closing tag).
On click to play a new audio element, completely destroy the existing and rebuild it from scratch with the new track you want to play.
Call .play on the audio element and you'll be good to go.
I also have the same problem and googled then found this page and the below page
http://remysharp.com/2010/12/23/audio-sprites/
this guy probably found the more detailed answer.
I had these types of problems, and I too started using that desperate way to solve the issue which consists of recreating the audio component, reloading the source, etcetera.
A day or two ago I found that the source of the media content must be "pure" to be able to use it successfully from the ipad.
I want to express with "pure" all content that is not being "transmuted" by previous code that could change or delete it's metadata before it reaches the ipad client.
In the current project I am working on, I found that with Ipad I could not replay nor traverse to mm:ss any content located in the "documents" folder, but if I got that file and moved elsewhere, it worked perfectly, I could replay it on my ipad, go to the minute:second I wished, etcetera.
In my case, an .htaccess was forcing my apache server to send the "get" query through a "download.php" which was checking permissions and doing weird stuff of the like, and then this download.php was dispatching the file to the client, but not in a good way or a way more of the ipad's liking.
I removed the .htaccess bindings and the ipad got a nice audio handling again. (That download.php was of not too much good use anyway...)
I have a subpage in a jquery mobile page where I'd like to insert att Google adwords conversion cookie. But using the traditional snippet from Adwords doesn't work. On Android it even makes the page go blank.
Anyone done this before?
You are probably loading the conversion script later on the page by doing something like this:
(function(){
var s=document.getElementsByTagName('script')[0];
var ga=document.createElement('script');
ga.type='text/javascript';
ga.async=true;
ga.src='http://www.googleadservices.com/pagead/conversion.js';
s.parentNode.insertBefore(ga,s);
})();
Or using a jQuery function to load scripts that is similar to the function above. Turns out that you can't include the conversion.js script in this manner because it uses document.write to write the img tag on the page. Because it uses document.write some browsers will remove everything from the page and replace the content with the output of document.write, which in this case is an empty gif.
You better use the default tag provided by google to mark a conversion. If you need to load it without a page refresh just open an iframe to a page that contains this tracking code.
<script type="text/javascript">
var google_conversion_id = 1234567890;
var google_conversion_language = "en_US";
var google_conversion_format = "1";
var google_conversion_color = "666666";
var google_conversion_label = "Purchase";
if (10.0) {
var google_conversion_value = 10.0
}
</script>
<script type="text/javascript" src="http://www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<img height=1 width=1 border=0
src="http://www.googleadservices.com/pagead/conversion/1234567890/?value=10.0&label=Purchase&script=0">
</noscript>
Of course this is just an example. You should use your own code that have your unique conversiod_id.
I researched this a bit, and came across the following links:
http://www.google.com/ads/mobile/publishers/web-publishers.html
https://support.google.com/adsense/bin/answer.py?hl=en&answer=185668
So it looks like depending on the type of ad you're running, you will have to get a customized unit for mobile.
However, I am still not sure why the page would go blank. I mean, I can totally see how some ad code does that when you try to lazy-load it, but I'm not sure why it happens in your situation.