/* global BP_Uploader, _, Backbone */ window.bp = window.bp || {}; ( function( bp ) { // Bail if not set. if ( typeof BP_Uploader === 'undefined' ) { return; } bp.Models = bp.Models || {}; bp.Collections = bp.Collections || {}; bp.Views = bp.Views || {}; bp.WebCam = { start: function() { this.params = { video: null, videoStream: null, capture_enable: false, capture: null, canvas: null, warning: null, flipped: false }; bp.Avatar.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) ); }, setView: function( view ) { if ( 'camera' !== view ) { // Stop the camera if needed. if ( ! _.isNull( this.params.video ) ) { this.stop(); // Remove all warnings as we're changing the view. this.removeWarning(); } // Stop as this is not Camera area. return; } // Create the WebCam view. var cameraView = new bp.Views.WebCamAvatar( { model: new Backbone.Model( { user_media: false } ) } ); // Make sure the flipped param is reset. this.params.flipped = false; // Add it to views. bp.Avatar.views.add( { id: 'camera', view: cameraView } ); // Display it. cameraView.inject( '.bp-avatar' ); }, removeView: function() { var camera; if ( ! _.isUndefined( bp.Avatar.views.get( 'camera' ) ) ) { camera = bp.Avatar.views.get( 'camera' ); camera.get( 'view' ).remove(); bp.Avatar.views.remove( { id: 'camera', view: camera } ); } }, gotStream: function( stream ) { var video = bp.WebCam.params.video; bp.WebCam.params.videoStream = stream; // User Feedback. bp.WebCam.displayWarning( 'loaded' ); video.onerror = function () { // User Feedback. bp.WebCam.displayWarning( 'videoerror' ); if ( video ) { bp.WebCam.stop(); } }; stream.onended = bp.WebCam.noStream(); // Older browsers may not have srcObject. if ( 'srcObject' in video ) { video.srcObject = stream; } else { // Avoid using this in new browsers, as it is going away. video.src = window.URL.createObjectURL( stream ); } video.onloadedmetadata = function() { video.play(); }; bp.WebCam.params.capture_enable = true; }, stop: function() { bp.WebCam.params.capture_enable = false; if ( bp.WebCam.params.videoStream ) { if ( bp.WebCam.params.videoStream.stop ) { bp.WebCam.params.videoStream.stop(); } else if ( bp.WebCam.params.videoStream.msStop ) { bp.WebCam.params.videoStream.msStop(); } bp.WebCam.params.videoStream.onended = null; bp.WebCam.params.videoStream = null; } if ( bp.WebCam.params.video ) { bp.WebCam.params.video.onerror = null; bp.WebCam.params.video.pause(); if ( bp.WebCam.params.video.mozSrcObject ) { bp.WebCam.params.video.mozSrcObject = null; } bp.WebCam.params.video.src = ''; } }, noStream: function() { if ( _.isNull( bp.WebCam.params.videoStream ) ) { // User Feedback. bp.WebCam.displayWarning( 'noaccess' ); bp.WebCam.removeView(); } }, setAvatar: function( avatar ) { if ( ! avatar.get( 'url' ) ) { bp.WebCam.displayWarning( 'nocapture' ); } // Remove the view. bp.WebCam.removeView(); bp.Avatar.setAvatar( avatar ); }, removeWarning: function() { if ( ! _.isNull( this.params.warning ) ) { this.params.warning.remove(); } }, displayWarning: function( code ) { this.removeWarning(); this.params.warning = new bp.Views.uploaderWarning( { value: BP_Uploader.strings.camera_warnings[code] } ); this.params.warning.inject( '.bp-avatar-status' ); } }; // BuddyPress WebCam view. bp.Views.WebCamAvatar = bp.View.extend( { tagName: 'div', id: 'bp-webcam-avatar', template: bp.template( 'bp-avatar-webcam' ), events: { 'click .avatar-webcam-capture': 'captureStream', 'click .avatar-webcam-save': 'saveCapture' }, initialize: function() { var params; // Standardize getUserMedia browser call. navigator.getUserMedia = ( navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia ); if ( typeof navigator.getUserMedia !== 'undefined' ) { // We need to add some cropping stuff to use bp.Avatar.setAvatar(). params = _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params, 'object', 'item_id', 'nonces' ), { user_media: true, w: BP_Uploader.settings.crop.full_w, h: BP_Uploader.settings.crop.full_h, x: 0, y: 0, type: 'camera' } ); this.model.set( params ); } this.on( 'ready', this.useStream, this ); }, useStream:function() { // No support for user media... Stop! if ( ! this.model.get( 'user_media' ) ) { return; } this.options.video = new bp.Views.WebCamVideo(); this.options.canvas = new bp.Views.WebCamCanvas(); this.$el.find( '#avatar-to-crop' ).append( this.options.video.el ); this.$el.find( '#avatar-crop-pane' ).append( this.options.canvas.el ); bp.WebCam.params.video = this.options.video.el; bp.WebCam.params.canvas = this.options.canvas.el; // User Feedback. bp.WebCam.displayWarning( 'requesting' ); // Use deprecated getUserMedia call for browsers that require it. if ( typeof navigator.mediaDevices.getUserMedia === 'undefined' ) { navigator.getUserMedia({ audio: false, video: true }, bp.WebCam.gotStream, bp.WebCam.noStream); // Teh new hotness! } else { navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then(bp.WebCam.gotStream, bp.WebCam.noStream) // ES3 compatibility. ['catch'](function() { // User Feedback. bp.WebCam.displayWarning( 'errormsg' ); }); } }, captureStream: function( event ) { var sx, sc; event.preventDefault(); if ( ! bp.WebCam.params.capture_enable ) { // User Feedback. bp.WebCam.displayWarning( 'loading' ); return; } if ( this.model.get( 'h' ) > this.options.video.el.videoHeight || this.model.get( 'w' ) > this.options.video.el.videoWidth ) { bp.WebCam.displayWarning( 'videoerror' ); return; } // Set the offset. sc = this.options.video.el.videoHeight; sx = ( this.options.video.el.videoWidth - sc ) / 2; // Flip only once. if ( ! bp.WebCam.params.flipped ) { this.options.canvas.el.getContext( '2d' ).translate( this.model.get( 'w' ), 0 ); this.options.canvas.el.getContext( '2d' ).scale( -1, 1 ); bp.WebCam.params.flipped = true; } this.options.canvas.el.getContext( '2d' ).drawImage( this.options.video.el, sx, 0, sc, sc, 0, 0, this.model.get( 'w' ), this.model.get( 'h' ) ); bp.WebCam.params.capture = this.options.canvas.el.toDataURL( 'image/png' ); this.model.set( 'url', bp.WebCam.params.capture ); // User Feedback. bp.WebCam.displayWarning( 'ready' ); }, saveCapture: function( event ) { event.preventDefault(); if ( ! bp.WebCam.params.capture ) { // User Feedback. bp.WebCam.displayWarning( 'nocapture' ); return; } bp.WebCam.stop(); bp.WebCam.setAvatar( this.model ); } } ); // BuddyPress Video stream view. bp.Views.WebCamVideo = bp.View.extend( { tagName: 'video', id: 'bp-webcam-video', attributes: { autoplay: 'autoplay' } } ); // BuddyPress Canvas (capture) view. bp.Views.WebCamCanvas = bp.View.extend( { tagName: 'canvas', id: 'bp-webcam-canvas', attributes: { width: 150, height: 150 }, initialize: function() { // Make sure to take in account bp_core_avatar_full_height or bp_core_avatar_full_width php filters. if ( ! _.isUndefined( BP_Uploader.settings.crop.full_h ) && ! _.isUndefined( BP_Uploader.settings.crop.full_w ) ) { this.el.attributes.width.value = BP_Uploader.settings.crop.full_w; this.el.attributes.height.value = BP_Uploader.settings.crop.full_h; } } } ); bp.WebCam.start(); })( window.bp );