diff --git a/lms/static/js/vendor/jpegcam/webcam.min.js b/lms/static/js/vendor/jpegcam/webcam.min.js deleted file mode 100644 index f1118ef9be..0000000000 --- a/lms/static/js/vendor/jpegcam/webcam.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/* JPEGCam v1.0.11 *//* Webcam library for capturing JPEG images and submitting to a server *//* Copyright (c) 2008 - 2009 Joseph Huckaby *//* Licensed under the GNU Lesser Public License *//* http://www.gnu.org/licenses/lgpl.html *//* Usage: - - Take Snapshot -*/// Everything is under a 'webcam' Namespace -window.webcam={version:"1.0.11",ie:!!navigator.userAgent.match(/MSIE/),protocol:location.protocol.match(/https/i)?"https":"http",callback:null,swf_url:"webcam.swf",shutter_url:"shutter.mp3",api_url:"",loaded:false,quality:90,shutter_sound:true,stealth:true,hooks:{onLoad:null,onAllow:null,onComplete:null,onError:null},set_hook:function(a,b){this.hooks[a]=b},fire_hook:function(a,b){if(this.hooks[a]){if(typeof this.hooks[a]==="function"){this.hooks[a](b)}else if(typeof this.hooks[a]==="array"){this.hooks[a][0][this.hooks[a][1]](b)}else if(window[this.hooks[a]]){window[this.hooks[a]](b)}return true}return false},set_api_url:function(a){this.api_url=a},set_swf_url:function(a){this.swf_url=a},get_html:function(a,b,c,d){if(!c){c=a}if(!d){d=b}var e="";var f="shutter_enabled="+(this.shutter_sound?1:0)+"&shutter_url="+encodeURIComponent(this.shutter_url)+"&width="+a+"&height="+b+"&server_width="+c+"&server_height="+d;if(this.ie){e+=''}else{e+=''}this.loaded=false;return e},get_movie:function(){if(!this.loaded){return false}var a=document.getElementById("webcam_movie");if(!a){return false}return a},set_stealth:function(a){this.stealth=a},snap:function(a,b,c){if(b){this.set_hook("onComplete",b)}if(a){this.set_api_url(a)}if(typeof c!=="undefined"){this.set_stealth(c)}this.get_movie()._snap(this.api_url,this.quality,this.shutter_sound?1:0,this.stealth?1:0)},freeze:function(){this.get_movie()._snap("",this.quality,this.shutter_sound?1:0,0)},upload:function(a,b){if(b){this.set_hook("onComplete",b)}if(a){this.set_api_url(a)}this.get_movie()._upload(this.api_url)},reset:function(){this.get_movie()._reset()},configure:function(a){if(!a){a="camera"}this.get_movie()._configure(a)},set_quality:function(a){this.quality=a},set_shutter_sound:function(a,b){this.shutter_sound=a;this.shutter_url=b?b:"shutter.mp3"},flash_notify:function(a,b){switch(a){case"security":var c=b=="Camera.Unmuted";this.fire_hook("onAllow",c);break;case"flashLoadComplete":this.loaded=true;this.fire_hook("onLoad",b);break;case"error":if(!this.fire_hook("onError",b)){}break;case"success":this.fire_hook("onComplete",b.toString());break;default:break}}} \ No newline at end of file diff --git a/lms/static/js/vendor/jpegcam/webcam.swf b/lms/static/js/vendor/jpegcam/webcam.swf deleted file mode 100755 index c21b715355..0000000000 Binary files a/lms/static/js/vendor/jpegcam/webcam.swf and /dev/null differ diff --git a/lms/static/js/verify_student/CameraCapture.as b/lms/static/js/verify_student/CameraCapture.as new file mode 100644 index 0000000000..0f5d5acae1 --- /dev/null +++ b/lms/static/js/verify_student/CameraCapture.as @@ -0,0 +1,103 @@ +/** + * Simple Camera Capture application meant to be used where WebRTC is not supported + * (e.g. Safari, Internet Explorer, Opera). All orchestration is assumed to happen + * in JavaScript. The only function this application has is to capture a snapshot + * and allow a 640x480 PNG of that snapshot to be made available to the JS as a + * base64 encoded data URL. + * + * There are really only three methods: + * snap() freezes the video and returns a PNG file as a data URL string. You can + * assign this return value to an img's src attribute. + * reset() restarts the the video. + * imageDataUrl() returns the same thing as snap() -- + */ + +package +{ + import flash.display.BitmapData; + import flash.display.PNGEncoderOptions; + import flash.display.Sprite; + import flash.events.Event; + import flash.external.ExternalInterface; + import flash.geom.Rectangle; + import flash.media.Camera; + import flash.media.Video; + import flash.utils.ByteArray; + import mx.utils.Base64Encoder; + + [SWF(width="640", height="480")] + public class CameraCapture extends Sprite + { + // We pick these values because that's captured by the WebRTC spec + private const VIDEO_WIDTH:int = 640; + private const VIDEO_HEIGHT:int = 480; + + private var camera:Camera; + private var video:Video; + private var b64EncodedImage:String = null; + + public function CameraCapture() + { + addEventListener(Event.ADDED_TO_STAGE, init); + } + + protected function init(e:Event):void { + camera = Camera.getCamera(); + camera.setMode(VIDEO_WIDTH, VIDEO_HEIGHT, 30); + + video = new Video(VIDEO_WIDTH, VIDEO_HEIGHT); + video.attachCamera(camera); + + addChild(video); + + ExternalInterface.addCallback("snap", snap); + ExternalInterface.addCallback("reset", reset); + ExternalInterface.addCallback("imageDataUrl", imageDataUrl); + + // Notify the container that the SWF is ready to be called. + ExternalInterface.call("setSWFIsReady"); + } + + public function snap():String { + // If we already have a b64 encoded image, just return that. The user + // is calling snap() multiple times in a row without reset() + if (b64EncodedImage) { + return imageDataUrl(); + } + + var bitmapData:BitmapData = new BitmapData(video.width, video.height); + bitmapData.draw(video); // Draw a snapshot of the video onto our bitmapData + video.attachCamera(null); // Stop capturing video + + // Convert to PNG + var pngBytes:ByteArray = new ByteArray(); + bitmapData.encode( + new Rectangle(0, 0, video.width, video.height), + new PNGEncoderOptions(), + pngBytes + ); + + // Convert to Base64 encoding of PNG + var b64Encoder:Base64Encoder = new Base64Encoder(); + b64Encoder.encodeBytes(pngBytes); + b64EncodedImage = b64Encoder.toString(); + + return imageDataUrl(); + } + + public function reset():String { + video.attachCamera(camera); + b64EncodedImage = null; + + return imageDataUrl(); + } + + public function imageDataUrl():String { + if (b64EncodedImage) { + return "data:image/png;base64," + b64EncodedImage; + } + return ""; + } + } +} + diff --git a/lms/static/js/verify_student/CameraCapture.swf b/lms/static/js/verify_student/CameraCapture.swf new file mode 100644 index 0000000000..d35e25fc26 Binary files /dev/null and b/lms/static/js/verify_student/CameraCapture.swf differ diff --git a/lms/static/js/verify_student/photocapture.js b/lms/static/js/verify_student/photocapture.js new file mode 100644 index 0000000000..1c609be5f3 --- /dev/null +++ b/lms/static/js/verify_student/photocapture.js @@ -0,0 +1,193 @@ +var onVideoFail = function(e) { + console.log('Failed to get camera access!', e); +}; + +// Returns true if we are capable of video capture (regardless of whether the +// user has given permission). +function initVideoCapture() { + window.URL = window.URL || window.webkitURL; + navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || navigator.msGetUserMedia; + return !(navigator.getUserMedia == undefined); +} + +var submitToPaymentProcessing = function() { + var contribution_input = $("input[name='contribution']:checked") + var contribution = 0; + if(contribution_input.attr('id') == 'contribution-other') + { + contribution = $("input[name='contribution-other-amt']").val(); + } + else + { + contribution = contribution_input.val(); + } + var xhr = $.post( + "create_order", + { + "course_id" : "${course_id}", + "contribution": contribution + }, + function(data) { + for (prop in data) { + $('').attr({ + type: 'hidden', + name: prop, + value: data[prop] + }).appendTo('#pay_form'); + } + } + ) + .done(function(data) { + $("#pay_form").submit(); + }) + .fail(function(jqXhr,text_status, error_thrown) { + alert(jqXhr.responseText); + }); +} + +function doResetButton(resetButton, captureButton, approveButton) { + approveButton.removeClass('approved'); + nextButton.addClass('disabled'); + + captureButton.show(); + resetButton.hide(); + approveButton.hide(); +} + +function doApproveButton(approveButton, nextButton) { + approveButton.addClass('approved'); + nextButton.removeClass('disabled'); +} + +function doSnapshotButton(captureButton, resetButton, approveButton) { + captureButton.hide(); + resetButton.show(); + approveButton.show(); +} + +function initSnapshotHandler(names, hasHtml5CameraSupport) { + var name = names.pop(); + if (name == undefined) { + return; + } + + var video = $('#' + name + '_video'); + var canvas = $('#' + name + '_canvas'); + var image = $('#' + name + "_image"); + var captureButton = $("#" + name + "_capture_button"); + var resetButton = $("#" + name + "_reset_button"); + var approveButton = $("#" + name + "_approve_button"); + var nextButton = $("#" + name + "_next_button"); + var flashCapture = $("#" + name + "_flash"); + + var ctx = null; + if (hasHtml5CameraSupport) { + ctx = canvas[0].getContext('2d'); + } + var localMediaStream = null; + + function snapshot(event) { + if (hasHtml5CameraSupport) { + if (localMediaStream) { + ctx.drawImage(video[0], 0, 0); + image[0].src = canvas[0].toDataURL('image/png'); + } + else { + return false; + } + video[0].pause(); + } + else { + image[0].src = flashCapture[0].snap(); + } + + doSnapshotButton(captureButton, resetButton, approveButton); + return false; + } + + function reset() { + image[0].src = ""; + + if (hasHtml5CameraSupport) { + video[0].play(); + } + else { + flashCapture[0].reset(); + } + + doResetButton(resetButton, captureButton, approveButton); + return false; + } + + function approve() { + doApproveButton(approveButton, nextButton) + return false; + } + + // Initialize state for this picture taker + captureButton.show(); + resetButton.hide(); + approveButton.hide(); + nextButton.addClass('disabled'); + + // Connect event handlers... + video.click(snapshot); + captureButton.click(snapshot); + resetButton.click(reset); + approveButton.click(approve); + + // If it's flash-based, we can just immediate initialize the next one. + // If it's HTML5 based, we have to do it in the callback from getUserMedia + // so that Firefox doesn't eat the second request. + if (hasHtml5CameraSupport) { + navigator.getUserMedia({video: true}, function(stream) { + video[0].src = window.URL.createObjectURL(stream); + localMediaStream = stream; + + // We do this in a recursive call on success because Firefox seems to + // simply eat the request if you stack up two on top of each other before + // the user has a chance to approve the first one. + initSnapshotHandler(names, hasHtml5CameraSupport); + }, onVideoFail); + } + else { + initSnapshotHandler(names, hasHtml5CameraSupport); + } + +} + +function objectTagForFlashCamera(name) { + return ''; +} + +$(document).ready(function() { + $(".carousel-nav").addClass('sr'); + $("#pay_button").click(submitToPaymentProcessing); + // $("#confirm_pics_good").click(function() { + // if (this.checked) { + // $("#pay_button_frame").removeClass('disabled'); + // } + // else { + // $("#pay_button_frame").addClass('disabled'); + // } + // }); + // + // $("#pay_button_frame").addClass('disabled'); + + var hasHtml5CameraSupport = initVideoCapture(); + + // If HTML5 WebRTC capture is not supported, we initialize jpegcam + if (!hasHtml5CameraSupport) { + $("#face_capture_div").html(objectTagForFlashCamera("face_flash")); + $("#photo_id_capture_div").html(objectTagForFlashCamera("photo_id_flash")); + } + + initSnapshotHandler(["photo_id", "face"], hasHtml5CameraSupport); + +}); diff --git a/lms/templates/verify_student/photo_verification.html b/lms/templates/verify_student/photo_verification.html index 5ffde8fced..c410331c4a 100644 --- a/lms/templates/verify_student/photo_verification.html +++ b/lms/templates/verify_student/photo_verification.html @@ -9,164 +9,7 @@ <%block name="js_extra"> - - + <%block name="content"> @@ -324,7 +167,7 @@
-
+