diff --git a/lam/lib/html.inc b/lam/lib/html.inc
index 21fb7b7d..051d88f1 100644
--- a/lam/lib/html.inc
+++ b/lam/lib/html.inc
@@ -4973,5 +4973,68 @@ class htmlResponsiveTable extends htmlElement {
}
+/**
+ * Renders a canvas.
+ *
+ * @author Roland Gruber
+ */
+class htmlCanvas extends htmlElement {
+
+ private $id;
+
+ /**
+ * Constructor
+ *
+ * @param string $id html id
+ */
+ public function __construct($id) {
+ $this->id = $id;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ function generateHTML($module, $input, $values, $restricted, &$tabindex, $scope) {
+ $classesValue = '';
+ if (!empty($this->cssClasses)) {
+ $classesValue = ' class="' . implode(' ', $this->cssClasses) . '"';
+ }
+ echo '';
+ return array();
+ }
+}
+
+/**
+ * Renders a video.
+ *
+ * @author Roland Gruber
+ */
+class htmlVideo extends htmlElement {
+
+ private $id;
+
+ /**
+ * Constructor
+ *
+ * @param string $id html id
+ */
+ public function __construct($id) {
+ $this->id = $id;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ function generateHTML($module, $input, $values, $restricted, &$tabindex, $scope) {
+ $classesValue = '';
+ if (!empty($this->cssClasses)) {
+ $classesValue = ' class="' . implode(' ', $this->cssClasses) . '"';
+ }
+ echo '';
+ return array();
+ }
+}
?>
diff --git a/lam/lib/modules/inetOrgPerson.inc b/lam/lib/modules/inetOrgPerson.inc
index 47fbeef2..f6439fab 100644
--- a/lam/lib/modules/inetOrgPerson.inc
+++ b/lam/lib/modules/inetOrgPerson.inc
@@ -1704,9 +1704,26 @@ class inetOrgPerson extends baseModule implements passwordService {
$container->add(new htmlSubTitle(_('Upload image')), 12);
$label = _('Photo file');
$container->add(new htmlResponsiveInputFileUpload('photoFile', $label, 'photoUpload'), 12);
+ $container->addVerticalSpacer('0.5rem');
+ $container->addLabel(new htmlOutputText(' ', false));
+ $container->addField(new htmlAccountPageButton(get_class($this), 'photo', 'upload', _('Upload')));
$container->addVerticalSpacer('1rem');
- $container->addLabel(new htmlAccountPageButton(get_class($this), 'photo', 'upload', _('Upload')));
- $container->addField(new htmlAccountPageButton(get_class($this), 'attributes', 'back', _('Back')));
+ $webcamContent = new htmlResponsiveRow();
+ $webcamContent->add(new htmlSubTitle(_('Get from webcam')), 12);
+ $webcamContent->addLabel(new htmlOutputText(_('Image')));
+ $webcamContent->addField(new htmlVideo('lam-webcam-video'));
+ $webcamContent->addLabel(new htmlOutputText(' ', false));
+ $webcamButtonGroup = new htmlGroup();
+ $captureButton = new htmlButton('lam-webcam-capture', _('Capture'));
+ $captureButton->setOnClick('window.lam.tools.startWebcamCapture(event);');
+ $webcamButtonGroup->addElement($captureButton);
+ $webcamButtonGroup->addElement(new htmlAccountPageButton(get_class($this), 'photo', 'upload', _('Upload')));
+ $webcamButtonGroup->addElement(new htmlCanvas('lam-webcam-canvas'));
+ $webcamContent->addField($webcamButtonGroup);
+ $webcamDiv = new htmlDiv('lam_webcam_div', $webcamContent, array('hidden'));
+ $container->add($webcamDiv, 12);
+ $container->addVerticalSpacer('1rem');
+ $container->add(new htmlAccountPageButton(get_class($this), 'attributes', 'back', _('Back')), 12);
}
else {
$container->add(new htmlSubTitle(_('Crop image')), 12);
diff --git a/lam/templates/lib/500_lam.js b/lam/templates/lib/500_lam.js
index d7839e40..4ec1ce52 100644
--- a/lam/templates/lib/500_lam.js
+++ b/lam/templates/lib/500_lam.js
@@ -934,6 +934,51 @@ window.lam.tools.setInitialFocus = function() {
jQuery('.lam-initial-focus').focus();
};
+/**
+ * Initializes the webcam capture.
+ */
+window.lam.tools.initWebcamCapture = function() {
+ var contentDiv = jQuery('#lam_webcam_div');
+ if (contentDiv.length === 0) {
+ return;
+ }
+ if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
+ navigator.mediaDevices.enumerateDevices()
+ .then(function(mediaDevices) {
+ mediaDevices.forEach(mediaDevice => {
+ if (mediaDevice.kind === 'videoinput') {
+ contentDiv.show();
+ }
+ });
+ });
+ }
+};
+
+/**
+ * Starts the webcam capture.
+ */
+window.lam.tools.startWebcamCapture = function(event) {
+ event.preventDefault();
+ var canvas = document.getElementById('lam-webcam-canvas');
+ var video = document.getElementById('lam-webcam-videofor');
+ navigator.mediaDevices.getUserMedia({
+ video: {
+ facingMode: 'user',
+ width: { min: 1024, ideal: 1280, max: 1920 },
+ height: { min: 576, ideal: 720, max: 1080 }
+ },
+ audio: false
+ })
+ .then(function(stream) {
+ video.srcObject = stream;
+ video.play();
+ })
+ .catch(function(err) {
+ console.log("An error occurred: " + err);
+ });
+ return false;
+}
+
window.lam.tools.schema = window.lam.tools.schema || {};
/**
@@ -1788,6 +1833,7 @@ jQuery(document).ready(function() {
window.lam.tools.addSavedSelectListener();
window.lam.tools.activateTab();
window.lam.tools.setInitialFocus();
+ window.lam.tools.initWebcamCapture();
window.lam.tools.schema.select();
window.lam.html.activateLightboxes();
window.lam.html.preventEnter();