( function( $ ) { $.fn.CameraBrowser = function( options ) { Global.addCss( 'global/widgets/filebrowser/TImageBrowser.css' ); var opts = $.extend( {}, $.fn.CameraBrowser.defaults, options ); var $this = this; var field; var enabled = true; var video = null; var canvas = null; var local_stream = null; this.stopCamera = function() { if ( local_stream ) { if ( local_stream.stop ) { // This is the legacy method to stop video. local_stream.stop(); } else if ( local_stream.getTracks ) { // This is the modern approach for stopping the video. https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/stop local_stream.getTracks().forEach( track => track.stop() ); } } }; this.showCamera = function() { // check for getUserMedia support navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; if ( navigator.mediaDevices && navigator.mediaDevices.getUserMedia ) { // Most up to date as of May 2020 (Aside from using async and await) https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia // get webcam feed if available navigator.mediaDevices.getUserMedia( { video: true } ) .then(function(stream) { if ('srcObject' in video) { video.srcObject = stream; } else { // Fallback for older browsers. https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject#Supporting_fallback_to_the_src_property video.src = URL.createObjectURL( stream ); } video.play(); local_stream = stream; }) .catch(function(err) { errorBack(); }); } else if ( navigator.getUserMedia ) { // Semi-deprecated, legacy, but still works. https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia // get webcam feed if available navigator.getUserMedia( { video: true }, function( stream ) { if ('srcObject' in video) { video.srcObject = stream; } else { // Fallback for older browsers. https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject#Supporting_fallback_to_the_src_property video.src = URL.createObjectURL( stream ); } video.play(); local_stream = stream; }, errorBack ); } else if ( navigator.webkitGetUserMedia ) { // WebKit-prefixed navigator.webkitGetUserMedia( { video: true }, function( stream ) { video.src = window.webkitURL.createObjectURL( stream ); video.play(); local_stream = stream; }, errorBack ); } else if ( navigator.mozGetUserMedia ) { // Firefox-prefixed navigator.mozGetUserMedia( { video: true }, function( stream ) { video.src = window.URL.createObjectURL( stream ); video.play(); local_stream = stream; }, errorBack ); } else { errorBack(); } function errorBack() { TAlertManager.showAlert( $.i18n._( 'Unable to access Camera.

Please check your camera connections, permissions, and ensure you are using HTTPS. Alternatively, use the File upload method instead.' ) ); } }; this.setEnable = function( val ) { enabled = val; var btn = this.children().eq( 1 ); if ( !val ) { btn.attr( 'disabled', true ); btn.removeClass( 'disable-element' ).addClass( 'disable-element' ); } else { btn.removeAttr( 'disabled' ); btn.removeClass( 'disable-element' ); } }; this.clearErrorStyle = function() { }; this.getField = function() { return field; }; this.getValue = function() { return false; }; this.getFileName = function() { return 'camera_stream.png'; }; this.getImageSrc = function() { return canvas[0].toDataURL(); }; this.setImage = function( val ) { var image = $this.children().eq( 0 ); if ( !val ) { image.attr( 'src', '' ); image.hide(); return; } var d = new Date(); image.hide(); image.attr( 'src', val + '&t=' + d.getTime() ); image.css( 'height', 'auto' ); image.css( 'width', 'auto' ); }; this.onImageLoad = function( image ) { // var image_height = $( image ).height() > 0 ? $( image ).height() : image.naturalHeight; // var image_width = $( image ).width() > 0 ? $( image ).width() : image.naturalWidth; // // if ( image_height > default_height ) { // $( image ).css( 'height', default_height ); // // } // // if ( image_width > default_width ) { // $( image ).css( 'width', default_width ); // // $( image ).css( 'height', 'auto' ); // } // // $this.trigger( 'setSize' ); $( image ).show(); }; this.setValue = function( val ) { if ( !val ) { val = ''; } }; this.each( function() { var o = $.meta ? $.extend( {}, opts, $( this ).data() ) : opts; field = o.field; var $$this = this; video = $( this ).children().eq( 0 ).children().eq( 0 )[0]; canvas = $( this ).children().eq( 0 ).children().eq( 1 ); var take_picture = $( this ).children().eq( 1 ).children().eq( 0 ); var try_again = $( this ).children().eq( 1 ).children().eq( 1 ); // Set initial states of the buttons. take_picture.prop( 'disabled', false ); try_again.prop( 'disabled', true ); take_picture.bind( 'click', function() { take_picture.prop( 'disabled', true ); try_again.prop( 'disabled', false ); // Global.glowAnimation.start(); // not needed here as its triggered in UserPhotoWizardController.buildCurrentStepUI() // flash the photo area to indicate a picture has been taken. canvas.parent().addClass( 'flash' ); setTimeout( function(){ canvas.parent().removeClass( 'flash' ); }, 1000); // Timeout must be the same length as the CSS3 transition or longer (or you'll mess up the transition) // handle picture taking var ctx = canvas[0].getContext( '2d' ); ctx.drawImage( video, 0, 0, 400, 300 ); canvas.css( 'z-index', 51 ); $this.trigger( 'change', [$this] ); } ); try_again.bind( 'click', function() { take_picture.prop( 'disabled', false ); try_again.prop( 'disabled', true ); Global.glowAnimation.stop(); canvas.css( 'z-index', -1 ); $this.trigger( 'NoImageChange', [$this] ); } ); } ); return this; }; $.fn.CameraBrowser.defaults = {}; $.fn.CameraBrowser.html_template = `
`; } )( jQuery );