<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"
  }
}
  • Content:
    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);
      });
    };
    
  • URL: /components/raw/efl-learner-profile-add-photo/efl-learner-profile-add-photo.js
  • Filesystem Path: src/library/components/efl-learner-profile-add-photo/efl-learner-profile-add-photo.js
  • Size: 16.3 KB
  • Content:
    .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;
          }
        }
      }
    }
    
  • URL: /components/raw/efl-learner-profile-add-photo/efl-learner-profile-add-photo.scss
  • Filesystem Path: src/library/components/efl-learner-profile-add-photo/efl-learner-profile-add-photo.scss
  • Size: 7.6 KB
<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>