<div class="efl-profile-left-popup" role="dialog" aria-modal="true" data-behavior="efl-profile-left-popup">
<button class="efl-profile-left-popup__close" aria-label="close add a profile picture popup window"></button>
<div class="efl-learner-profile-add-photo" data-behavior="efl-learner-profile-add-photo">
<h3>Add a profile picture</h3>
<div class="">
<div id="cropme">
<p class="instructions">
Position your face in the clear circle below
</p>
<img alt="myimage" id="myImage" />
<button class="crop-button" aria-label="crop photo" id="crop-image"></button>
</div>
<div data-camera="false" id="preview">
<p class="instructions retake">
Happy? Hit 'use this photo'. To try again, select 'retake photo'.
</p>
<p class="instructions another-photo">
Happy? Hit 'use this photo'. To try again, select 'Upload Another Photo'.
</p>
<img alt="preview image" id="preview-image" />
<button class="cta cta--efl " id="use-photo" aria-label="use this photo!">
<span>Use This Photo!</span>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="20px" viewBox="0 0 24 30" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<rect x="0" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
<rect x="8" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
<rect x="16" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
</svg>
</button>
<button class="cta cta--secondary " id="retake-photo" aria-label="retake photo">Retake Photo</button>
<div class="efl-profile-upload-another-photo">
<label for="efl-profile-upload-another-photo">Upload Another Photo</label>
<input type="file" id="efl-profile-upload-another-photo" role="button" aria-label="upload another photo">
</div>
<div class="upload-error hidden">
<div class="upload-error--alert" role="dialog" aria-modal="true" aria-atomic="true">
<h5>Error</h5>
<p></p>
<button class="cta cta--efl " id="upload-error-alert" aria-label="ok Upload error">Ok</button>
</div>
</div>
</div>
<div id="camera">
<div class="camera">
<video id="video">Video stream not available.</video>
</div>
<button class="cta cta--efl efl-profile-capture-photo" id="efl-profile-capture-photo" aria-label="capture photo">Capture photo</button>
<canvas id="cropme-canvas"></canvas>
</div>
<div id="default" class="active">
<p class="instructions">
Select from the options below.
</p>
<button class="cta cta--efl efl-profile-take-photo" id="efl-profile-take-photo" aria-label="take photo">Take photo</button>
<div class="efl-profile-add-photo">
<label for="efl-profile-upload-photo">Upload Photo</label>
<input type="file" id="efl-profile-upload-photo" tabindex="0" role="button" aria-label="upload photo">
</div>
</div>
</div>
<div class="efl-profile-left-popup__alert-modal" role="dialog" aria-modal="true">
<h5 class="efl-category-title">This Image is Not Appropriate</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ultricies, nibh sit amet varius faucibus, est ipsum commodo mi, a rutrum urna mauris ut.</p>
<button class="cta cta--efl " id="please-take-a-new-photo" aria-label="please take a new photo">Please Take a New Photo</button>
</div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cropme@latest/dist/cropme.min.css">
</div>
No notes defined.
{
"take-photo-button": {
"copy": "Take photo",
"modifier": "efl",
"id": "efl-profile-take-photo",
"additionalClass": "efl-profile-take-photo"
},
"capture-photo-button": {
"copy": "Capture photo",
"modifier": "efl",
"id": "efl-profile-capture-photo",
"additionalClass": "efl-profile-capture-photo"
},
"use-photo-button": {
"copy": "Use This Photo!",
"modifier": "efl",
"id": "use-photo"
},
"retake-button": {
"copy": "Retake Photo",
"modifier": "secondary",
"id": "retake-photo"
},
"upload-another-photo-button": {
"copy": "Retake Photo",
"modifier": "secondary",
"id": "upload-another-photo"
},
"please-take-a-new-photo-button": {
"copy": "Please Take a New Photo",
"modifier": "efl",
"id": "please-take-a-new-photo"
},
"error-ok-button": {
"copy": "Ok",
"modifier": "efl",
"id": "upload-error-alert"
}
}
import Cropme from 'cropme';
import { updateProfileCompletion } from '../efl-learner-profile/efl-learner-profile-update';
export default parentElement => {
const MOBILE_BREAKPOINT = 820;
const popUp = parentElement.closest('.efl-profile-left-popup');
const closeBtn = popUp.querySelector('.efl-profile-left-popup__close');
const modalcloseBtn = popUp.querySelector(
'.efl-profile-left-popup__close .large-modal'
);
const eflProfileLayout = document.querySelector('.efl-profile-layout');
const profilePic = document.querySelector(
'.efl-profile-hero-banner__content--profile__picture--dp img'
);
const editPicIcon = document.querySelector(
'.efl-profile-hero-banner__content--profile__picture .edit-pic'
);
const changePic = document.querySelector(
'.efl-profile-hero-banner__content--profile__picture .change-profile-pic'
);
let currentState;
const state = {
default: 'DEFAULT',
capturing: 'CAPTURING',
cropping: 'CROPPING',
saving: 'SAVING',
};
const defaultSection = parentElement.querySelector('#default');
const instructionText = parentElement.querySelector('.instructions');
let uploadImgName;
// Photo Cropping
let cropmeObj;
const uploadPhotoButton = parentElement.querySelector(
'#efl-profile-upload-photo'
);
const cropButton = parentElement.querySelector('#crop-image');
const imageTypes = ['gif', 'jpg', 'png', 'jpeg', 'jpe', 'jif', 'jfif', 'jfi'];
const cropmeSection = parentElement.querySelector('#cropme');
// Camera
let cameraStream;
const takePhotoBtn = parentElement.querySelector(
'.cta[id=efl-profile-take-photo]'
);
const cameraSection = parentElement.querySelector('#camera');
const canvas = cameraSection.querySelector('#cropme-canvas');
const video = cameraSection.querySelector('#video');
// const photo = document.getElementById('myImage');
const capturePhotoBtn = cameraSection.querySelector(
'.cta[id=efl-profile-capture-photo]'
);
const width = 697; // We will scale the photo width to this
let height = 0; // This will be computed based on the input stream
let streaming = false;
// Image Preview
const previewSection = parentElement.querySelector('#preview');
const previewImage = previewSection.querySelector('#preview-image');
const usePhotoButton = previewSection.querySelector('#use-photo');
const retakeButton = previewSection.querySelector('#retake-photo');
const uploadAnotherPhotoButton = previewSection.querySelector(
'#efl-profile-upload-another-photo'
);
const errorAlertButton = previewSection.querySelector('#upload-error-alert');
let imageIsAppropriate = false;
// Alert Modal
const alertModal = popUp.querySelector(
'.efl-profile-left-popup__alert-modal'
);
const closeModalBtn = alertModal.querySelector(
'.cta[id=please-take-a-new-photo]'
);
const createImageElement = () => {
const cropmeWrapper = cropmeSection.querySelector('.cropme-wrapper');
if (cropmeWrapper) {
cropmeObj.destroy();
cropmeWrapper.remove();
const image = document.createElement('img');
image.getAttribute('alt', 'my-image');
image.setAttribute('id', 'myImage');
cropmeSection.appendChild(image);
}
};
const createCropmeInstance = () => {
if (document.getElementById('myImage')) {
const element = document.getElementById('myImage');
defaultSection.classList.remove('active');
previewSection.classList.remove('active');
cropmeSection.classList.add('active');
instructionText.innerHTML = 'Position your face within the circle below.';
currentState = state.cropping;
let containerHeight;
if (window.innerWidth >= MOBILE_BREAKPOINT) {
containerHeight = 424;
} else {
containerHeight = window.innerHeight - 100;
}
cropmeObj = new Cropme(element, {
container: {
width: '100%',
height: containerHeight,
},
viewport: {
width: 311,
height: 311,
type: 'circle',
border: {
width: 6,
enable: true,
color: '#fff',
},
},
zoom: {
enable: true,
mouseWheel: true,
slider: false,
min: 0.05,
max: 5,
},
transformOrigin: 'viewport',
});
}
};
// Camera
function clearphoto() {
const photo = popUp.querySelector('#myImage');
const context = canvas.getContext('2d');
context.fillStyle = '#AAA';
context.fillRect(0, 0, canvas.width, canvas.height);
const data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
}
function takepicture() {
const photo = popUp.querySelector('#myImage');
const context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
const data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
uploadImgName = 'camera-photo.png';
// Turn off Camera Stream
if (cameraStream && cameraStream.active) {
cameraStream.getTracks().forEach(track => {
track.stop();
});
}
} else {
clearphoto();
}
}
const startupCamera = e => {
e.preventDefault();
cameraSection.classList.add('active');
defaultSection.classList.remove('active');
previewSection.classList.remove('active');
instructionText.innerHTML =
'Take a picture with your face clearly in the frame';
currentState = state.capturing;
navigator.mediaDevices
.getUserMedia({
video: true,
audio: false,
})
.then(stream => {
cameraStream = stream;
video.srcObject = cameraStream;
video.play();
defaultSection.classList.remove('active');
previewSection.setAttribute('data-camera', 'true');
cameraSection.classList.add('active');
popUp.classList.add('large-modal');
});
clearphoto();
setTimeout(() => {
capturePhotoBtn.focus();
}, 100);
};
async function uploadCroppedPhotoCallback(imageUploadData) {
const url = `/LearnerProfile/UploadPhoto`;
// eslint-disable-next-line compat/compat
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: imageUploadData,
});
return response.json();
}
function uploadCroppedPhoto(imageUploadData) {
// console.log(imageUploadData);
try {
// isAjaxRuning = true;
uploadCroppedPhotoCallback(imageUploadData).then(response => {
if (response) {
usePhotoButton.classList.remove('loading-bar');
usePhotoButton.setAttribute('aria-disabled', 'false');
if (response.Status && response.Status === 'Success') {
profilePic.src = previewImage.src;
profilePic.classList.remove('hidden');
if (editPicIcon) {
editPicIcon.classList.remove('hidden');
setTimeout(() => {
editPicIcon.focus();
}, 50);
}
if (changePic) {
changePic.classList.add('hidden');
}
popUp.classList.remove('add-animation');
document.body.classList.remove('efl-profile-dark-overlay');
eflProfileLayout.style.zIndex = null;
// Reset UI back to default
previewSection.classList.remove('active');
defaultSection.classList.add('active');
popUp.classList.remove('large-modal');
// profile completion notification
updateProfileCompletion(1);
} else if (response.ErrorCode) {
previewSection
.querySelector('.upload-error')
.classList.remove('hidden');
previewSection.querySelector('.upload-error p').innerText =
'response.ErrorDescription';
setTimeout(() => {
errorAlertButton.focus();
}, 10);
}
}
});
} catch (e) {
usePhotoButton.classList.remove('loading-bar');
usePhotoButton.setAttribute('aria-disabled', 'false');
throw new Error('Uable to upload the photo ::', e);
}
}
if (takePhotoBtn) {
takePhotoBtn.addEventListener('click', startupCamera, false);
}
const uploadPhoto = e => {
if (e.target.files.length === 0) {
return;
}
popUp.classList.add('large-modal');
previewSection.setAttribute('data-camera', 'false');
const pic = e.target.files[0];
const picName = pic.name;
uploadImgName = pic.name;
const filetype = picName
.substring(picName.lastIndexOf('.') + 1)
.toLowerCase();
// checking file type
if (imageTypes.indexOf(filetype) > -1) {
if (pic.size < 10000000) {
createImageElement();
const reader = new FileReader();
reader.onload = (() => {
return event => {
document.getElementById('myImage').src = event.target.result;
const img = new Image();
img.src = window.URL.createObjectURL(pic);
// eslint-disable-next-line no-undef
img.addEventListener('load', () => {
setTimeout(() => {
previewImage.removeAttribute('src');
createCropmeInstance();
cropButton.focus();
}, 100);
});
};
})(pic);
reader.readAsDataURL(pic);
e.target.files[0].value = '';
}
}
};
if (modalcloseBtn) {
// add photo functionality only
modalcloseBtn.addEventListener('click', () => {
defaultSection.classList.add('active');
previewSection.classList.remove('active');
previewSection.querySelector('.upload-error').classList.add('hidden');
cropmeSection.classList.remove('active');
cameraSection.classList.remove('active');
popUp.classList.remove('large-modal');
// Turn off Camera Stream
if (cameraStream && cameraStream.active) {
cameraStream.getTracks().forEach(track => {
track.stop();
});
}
createImageElement();
setTimeout(() => {
if (!editPicIcon.classList.contains('hidden')) {
editPicIcon.focus();
} else {
changePic.focus();
}
}, 50);
});
modalcloseBtn.addEventListener('keydown', event => {
if (event.shiftKey && event.keyCode === 9) {
event.preventDefault();
} else if (event.keyCode === 13) {
modalcloseBtn.click();
}
});
}
uploadPhotoButton.addEventListener('change', uploadPhoto);
uploadPhotoButton.addEventListener('click', e => {
e.target.value = null;
});
uploadPhotoButton.addEventListener('keydown', event => {
if (event.keyCode === 9) {
setTimeout(() => {
closeBtn.focus();
}, 50);
}
});
cropButton.addEventListener('click', () => {
if (currentState !== 'CROPPING') {
imageIsAppropriate = false;
return;
}
cropmeObj
.crop({
type: 'base64',
width: 311,
})
.then(output => {
previewSection.classList.add('active');
previewSection.querySelector('.upload-error').classList.add('hidden');
cropmeSection.classList.remove('active');
previewImage.src = output;
currentState = state.saving;
imageIsAppropriate = true;
createImageElement();
});
setTimeout(() => {
usePhotoButton.focus();
}, 10);
});
cropButton.addEventListener('keydown', event => {
if (event.keyCode === 13) {
event.preventDefault();
cropButton.click();
} else if (event.keyCode === 9) {
setTimeout(() => {
closeBtn.focus();
}, 10);
}
});
video.addEventListener(
'canplay',
() => {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
if (height === 0) {
height = width / (19 / 6);
}
video.setAttribute('width', width);
video.setAttribute('max-height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
},
false
);
capturePhotoBtn.addEventListener(
'click',
ev => {
ev.preventDefault();
takepicture();
cameraSection.classList.remove('active');
createCropmeInstance();
setTimeout(() => {
cropButton.focus();
}, 50);
},
false
);
capturePhotoBtn.addEventListener(
'keydown',
event => {
if (event.keyCode === 13) {
event.preventDefault();
takepicture();
cameraSection.classList.remove('active');
createCropmeInstance();
setTimeout(() => {
cropButton.focus();
}, 50);
} else if (event.keyCode === 9) {
setTimeout(() => {
closeBtn.focus();
}, 10);
}
},
false
);
// Saving Section
usePhotoButton.addEventListener('click', e => {
e.preventDefault();
usePhotoButton.classList.add('loading-bar');
usePhotoButton.setAttribute('aria-disabled', 'true');
// Close UI if successful, show alert modal if unsucessful.
if (imageIsAppropriate) {
const { fanid, individualProfilePhotoid } = document.querySelector(
'.efl-profile-hero-banner__content--profile__picture--dp'
).dataset;
const imageData = previewImage.src.replace('data:image/png;base64,', '');
let imageUploadData;
if (individualProfilePhotoid) {
imageUploadData = `{"FanCode": "${fanid}", "FileName": "${uploadImgName}", "PhotoTypeId": "1", "FileData": "${imageData}", "ApplicationName": "EFL" , "IndividualProfilePhotoId": "${individualProfilePhotoid}", "PhotoTypeDescription": "Individual"}`;
} else {
imageUploadData = `{"FanCode": "${fanid}", "FileName": "${uploadImgName}", "PhotoTypeId": "1", "FileData": "${imageData}", "ApplicationName": "EFL", "PhotoTypeDescription": "Individual"}`;
}
uploadCroppedPhoto(imageUploadData);
} else {
alertModal.classList.add('add-animation');
parentElement.classList.add('dark-overlay');
}
createImageElement();
});
usePhotoButton.addEventListener('keydown', event => {
if (event.keyCode === 13) {
usePhotoButton.click();
}
});
errorAlertButton.addEventListener('click', e => {
e.preventDefault();
previewSection.querySelector('.upload-error').classList.add('hidden');
setTimeout(() => {
usePhotoButton.focus();
}, 50);
});
errorAlertButton.addEventListener('keydown', event => {
if (event.keyCode === 13) {
errorAlertButton.click();
} else if (event.keyCode === 9) {
event.preventDefault();
}
});
retakeButton.addEventListener('click', e => {
e.preventDefault();
previewSection.classList.remove('active');
cameraSection.classList.add('active');
createImageElement();
startupCamera(e);
setTimeout(() => {
closeBtn.focus();
}, 50);
});
retakeButton.addEventListener('keydown', event => {
if (event.keyCode === 13) {
retakeButton.click();
} else if (event.keyCode === 9) {
setTimeout(() => {
closeBtn.focus();
}, 10);
}
});
uploadAnotherPhotoButton.addEventListener('change', e => {
createImageElement();
uploadPhoto(e);
});
uploadAnotherPhotoButton.addEventListener('click', e => {
e.target.value = null;
});
uploadAnotherPhotoButton.addEventListener('keydown', event => {
if (event.keyCode === 9) {
setTimeout(() => {
closeBtn.focus();
}, 50);
}
});
// Alert Modal
closeModalBtn.addEventListener('click', e => {
e.preventDefault();
alertModal.classList.remove('add-animation');
// Reset UI back to default
previewSection.classList.remove('active');
defaultSection.classList.add('active');
popUp.classList.remove('large-modal');
setTimeout(() => {
parentElement.classList.remove('dark-overlay');
}, 300);
});
};
.efl-learner-profile-add-photo {
position: relative;
padding: 0 2.9rem 0 2.8rem;
h3 {
@extend .efl-heading-3;
color: $black;
display: flex;
align-items: center;
margin-bottom: 2.8rem;
&::before {
content: '';
background: url('./assets/images/add-profile-photo-icon.svg') no-repeat
center;
width: 1.8rem;
height: 1.8rem;
display: flex;
margin-right: 0.8rem;
}
}
p {
@extend .efl-p-medium;
color: $color-interface-light;
margin-bottom: 2.4rem;
}
.cta {
margin-bottom: 1.6rem;
max-width: none;
&:hover {
background-color: $white;
border: 1px solid $red;
color: $red;
}
}
.efl-profile-add-photo,
.efl-profile-upload-another-photo {
position: relative;
max-width: 32.9rem;
margin-left: auto;
margin-right: auto;
input[type='file'] {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
label {
font-family: $text-font-ef;
letter-spacing: 0.01em;
font-size: 1.4rem;
line-height: 2.8rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
min-height: 4.4rem;
text-transform: uppercase;
text-decoration: none;
transition: background-color 0.2s ease-in;
border-radius: 2px;
position: relative;
white-space: nowrap;
padding: 0 2rem;
border: 1px solid;
}
}
.efl-profile-add-photo label {
background-color: $red;
border: none;
color: white;
&:hover {
background-color: $white;
border: 1px solid $red;
color: $red;
}
}
/* stylelint-disable-next-line no-descending-specificity */
.efl-profile-upload-another-photo label {
display: none;
border: 0.1rem solid $light-blue;
color: $blue;
font-weight: 500;
&:hover {
background-color: $light-blue;
}
}
.crop-button {
display: none;
justify-content: center;
align-items: center;
position: fixed;
z-index: 115;
left: 50%;
transform: translateX(-50%);
bottom: 5rem;
width: 9.6rem;
height: 9.6rem;
background-color: $red;
border-radius: 100%;
text-decoration: none;
border: none;
padding: 0;
&::before {
content: '';
display: block;
width: 4rem;
height: 3.6rem;
background-image: url('./assets/images/camera.svg');
background-size: cover;
}
}
#cropme {
display: none;
.instructions {
margin: 0 3.2rem 2.4rem 3.2rem;
transform: translateY(-30px);
}
&.active {
display: block;
position: absolute;
top: 10rem;
left: 0;
width: 100%;
height: 100%;
bottom: 0;
.crop-button {
display: flex;
}
.cropme-container {
&::before {
content: '';
border-top: 0.1rem solid white;
position: absolute;
display: block;
z-index: 116;
top: 0;
left: 0;
width: 100%;
height: 28.6rem;
pointer-events: none;
background: linear-gradient(
180deg,
#fff,
rgba(255, 255, 255, 0.95) 15.92%,
rgba(217, 217, 217, 0) 73.73%
);
}
}
// Hide Default CTA's while cropping
~ .cta,
~ .efl-profile-upload-photo {
display: none;
}
}
}
#camera {
canvas {
display: none;
}
video {
width: calc(100vw - 6.4rem);
}
}
#preview {
img[id='preview-image'] {
margin: 5rem auto;
max-width: 28.7rem;
max-height: 28.7rem;
}
.efl-profile-upload-another-photo {
margin-bottom: 1.6rem;
}
.cta--secondary[id='retake-photo'],
div.efl-profile-upload-another-photo label {
font-weight: 500;
color: $blue;
border-color: $light-blue;
border-width: 2px;
}
&[data-camera='true'] {
div.efl-profile-upload-another-photo label {
display: none;
}
.cta--secondary[id='retake-photo'] {
display: flex !important;
}
p.retake {
display: flex;
}
p.another-photo {
display: none;
}
}
&[data-camera='false'] {
div.efl-profile-upload-another-photo label {
display: flex !important;
}
.cta--secondary[id='retake-photo'] {
display: none;
}
p.retake {
display: none;
}
p.another-photo {
display: flex;
}
}
.upload-error {
position: absolute;
top: -16px;
left: 0;
height: calc(100% + 32px);
width: 100%;
background-color: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
z-index: 111;
&--alert {
padding: 2.4rem;
background-color: $white;
max-width: 30rem;
box-shadow: 0 0 16px rgba(0, 0, 0, 0.4);
border-radius: 8px;
h5 {
display: flex;
align-items: center;
font-family: $text-font-ef;
font-size: 1.6rem;
line-height: 2.4rem;
font-weight: 700;
letter-spacing: 0.16em;
color: $blue;
text-transform: uppercase;
margin-bottom: 0.8rem;
&::before {
content: '';
display: inline-block;
width: 2.7rem;
height: 2.4rem;
background: url('./assets/images/profile-icons/alert.svg') no-repeat
center;
margin-right: 0.8rem;
}
}
p {
padding-top: 0.6rem;
border-top: 1px solid $grey-light;
}
}
}
}
#cropme,
#preview,
#default,
#camera {
display: none;
&.active {
display: block;
}
.cta[id='efl-profile-take-photo'] {
display: none;
}
}
@media screen and (min-width: $mq-medium) {
#camera {
&.active {
display: grid;
grid-template-columns: 1fr;
.efl-learner-profile-add-photo {
grid-row: 2 / 2;
}
}
.camera {
display: flex;
justify-content: center;
grid-row: 1 / 1;
}
video {
width: initial;
max-height: 80vh;
}
}
#preview {
.instructions {
display: none !important;
}
}
#cropme {
.instructions {
display: none;
}
&.active {
display: grid;
}
grid-template-columns: 1fr;
position: initial;
height: fit-content !important;
.cropme-wrapper {
height: fit-content !important;
grid-row: 1 / 1;
}
.crop-button {
grid-row: 2 / 2;
transform: none;
position: initial;
height: 4.4rem;
min-width: 32.9rem;
border-radius: 0.2rem;
margin: 1.6rem auto 0 auto;
&::before {
content: 'Crop Photo';
text-transform: uppercase;
text-decoration: none;
color: $white;
display: inline;
background-image: none;
width: initial;
height: initial;
font-family: $text-font-ef;
font-style: normal;
font-weight: 400;
font-size: 1.4rem;
line-height: 1.8rem;
letter-spacing: 0.02em;
}
}
}
#default {
.cta[id='efl-profile-take-photo'] {
display: flex;
}
}
}
}
<div class="efl-profile-left-popup" role="dialog" aria-modal="true" data-behavior="efl-profile-left-popup">
<button class="efl-profile-left-popup__close" aria-label="close add a profile picture popup window"></button>
<div class="efl-learner-profile-add-photo" data-behavior="efl-learner-profile-add-photo">
<h3>Add a profile picture</h3>
<div class="">
<div id="cropme">
<p class="instructions">
Position your face in the clear circle below
</p>
<img alt="myimage" id="myImage" />
<button class="crop-button" aria-label="crop photo" id="crop-image"></button>
</div>
<div data-camera="false" id="preview">
<p class="instructions retake">
Happy? Hit 'use this photo'. To try again, select 'retake photo'.
</p>
<p class="instructions another-photo">
Happy? Hit 'use this photo'. To try again, select 'Upload Another Photo'.
</p>
<img alt="preview image" id="preview-image" />
<button class="cta cta--efl " id="use-photo" aria-label="use this photo!">
<span>Use This Photo!</span>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="20px" viewBox="0 0 24 30" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<rect x="0" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
<rect x="8" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
<rect x="16" y="10" width="4" height="10" fill="#fff" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite"></animate>
</rect>
</svg>
</button>
<button class="cta cta--secondary " id="retake-photo" aria-label="retake photo">Retake Photo</button>
<div class="efl-profile-upload-another-photo">
<label for="efl-profile-upload-another-photo">Upload Another Photo</label>
<input type="file" id="efl-profile-upload-another-photo" role="button" aria-label="upload another photo">
</div>
<div class="upload-error hidden">
<div class="upload-error--alert" role="dialog" aria-modal="true" aria-atomic="true">
<h5>Error</h5>
<p></p>
<button class="cta cta--efl " id="upload-error-alert" aria-label="ok Upload error">Ok</button>
</div>
</div>
</div>
<div id="camera">
<div class="camera">
<video id="video">Video stream not available.</video>
</div>
<button class="cta cta--efl efl-profile-capture-photo" id="efl-profile-capture-photo" aria-label="capture photo">Capture photo</button>
<canvas id="cropme-canvas"></canvas>
</div>
<div id="default" class="active">
<p class="instructions">
Select from the options below.
</p>
<button class="cta cta--efl efl-profile-take-photo" id="efl-profile-take-photo" aria-label="take photo">Take photo</button>
<div class="efl-profile-add-photo">
<label for="efl-profile-upload-photo">Upload Photo</label>
<input type="file" id="efl-profile-upload-photo" tabindex="0" role="button" aria-label="upload photo">
</div>
</div>
</div>
<div class="efl-profile-left-popup__alert-modal" role="dialog" aria-modal="true">
<h5 class="efl-category-title">This Image is Not Appropriate</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ultricies, nibh sit amet varius faucibus, est ipsum commodo mi, a rutrum urna mauris ut.</p>
<button class="cta cta--efl " id="please-take-a-new-photo" aria-label="please take a new photo">Please Take a New Photo</button>
</div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cropme@latest/dist/cropme.min.css">
</div>