$mid = $post['member_id'];
$fsize = $post['filesize'];
$fname = $post['filename'];
+ $cropping = null;
+ if ($post['cropping'] != false) {
+ $cropping = $post['cropping'];
+ }
$tmpname = GALETTE_TEMPIMAGES_PATH . 'ajax_upload_' . $fname;
$temp = explode('base64,', $post['file']);
'tmp_name' => $tmpname,
'size' => $fsize
),
- true
+ true,
+ $cropping
);
if ($res < 0) {
}
if (count($error_detected) === 0) {
- $files_res = $member->handleFiles($_FILES);
+ $cropping = null;
+ if ($this->preferences->pref_force_picture_ratio == 1) {
+ $cropping = [];
+ $cropping['ratio'] = isset($this->preferences->pref_member_picture_ratio) ? $this->preferences->pref_member_picture_ratio : 'square_ratio';
+ $cropping['focus'] = isset($post['crop_focus']) ? $post['crop_focus'] : 'center';
+ }
+ $files_res = $member->handleFiles($_FILES, $cropping);
if (is_array($files_res)) {
$error_detected = array_merge($error_detected, $files_res);
}
/**
* Stores an image on the disk and in the database
*
- * @param object $file the uploaded file
- * @param boolean $ajax If the image cames from an ajax call (dnd)
+ * @param object $file The uploaded file
+ * @param boolean $ajax If the image cames from an ajax call (dnd)
+ * @param array $cropping Cropping properties
*
* @return bool|int
*/
- public function store($file, $ajax = false)
+ public function store($file, $ajax = false, $cropping = null)
{
/** TODO: fix max size (by preferences ?) */
global $zdb;
);
}
+ // Source image must have minimum dimensions to match the cropping process requirements
+ // and ensure the final picture will fit the maximum allowed resizing dimensions.
+ if (isset($cropping['ratio']) && isset($cropping['focus'])) {
+ if ($current[0] < $this->mincropsize || $current[1] < $this->mincropsize) {
+ $min_current = min($current[0], $current[1]);
+ Analog::log(
+ '[' . $class . '] Image is too small. The minimum image side size allowed is ' .
+ $this->mincropsize . 'px, but current is ' . $min_current . 'px.',
+ Analog::ERROR
+ );
+ return self::IMAGE_TOO_SMALL;
+ } else {
+ Analog::log('[' . $class . '] Image dimensions are OK, proceed', Analog::DEBUG);
+ }
+ }
+
$this->delete();
$new_file = $this->store_path .
if ($current[0] > $this->max_width || $current[1] > $this->max_height) {
/** FIXME: what if image cannot be resized?
Should'nt we want to stop the process here? */
- $this->resizeImage($new_file, $extension);
+ $this->resizeImage($new_file, $extension, null, $cropping);
}
return $this->storeInDb($zdb, $this->db_id, $new_file, $extension);
}
/**
- * Resize the image if it exceeds max allowed sizes
+ * Resize and eventually crop the image if it exceeds max allowed sizes
*
- * @param string $source the source image
- * @param string $ext file's extension
- * @param string $dest the destination image.
- * If null, we'll use the source image. Defaults to null
+ * @param string $source The source image
+ * @param string $ext File's extension
+ * @param string $dest The destination image.
+ * If null, we'll use the source image. Defaults to null
+ * @param array $cropping Cropping properties
*
* @return void|false
*/
- private function resizeImage($source, $ext, $dest = null)
+ private function resizeImage($source, $ext, $dest = null, $cropping = null)
{
$class = get_class($this);
$ratio = $cur_width / $cur_height;
- // calculate image size according to ratio
- if ($cur_width > $cur_height) {
- $h = round($w / $ratio);
+ // Define cropping variables if necessary.
+ $thumb_cropped = false;
+ // Cropping is based on the smallest side of the source in order to
+ // provide as less focusing options as possible if the source doesn't
+ // fit the final ratio (center, top, bottom, left, right).
+ $min_size = min($cur_width, $cur_height);
+ // Cropping dimensions.
+ $crop_width = $min_size;
+ $crop_height = $min_size;
+ // Cropping focus.
+ $crop_x = 0;
+ $crop_y = 0;
+ if (isset($cropping['ratio']) && isset($cropping['focus'])) {
+ // Calculate cropping dimensions
+ switch ($cropping['ratio']) {
+ case 'portrait_ratio':
+ // Calculate cropping dimensions
+ if ($ratio < 1) {
+ $crop_height = ceil($crop_width * 4 / 3);
+ } else {
+ $crop_width = ceil($crop_height * 3 / 4);
+ }
+ // Calculate resizing dimensions
+ $w = ceil($h * 3 / 4);
+ break;
+ case 'landscape_ratio':
+ // Calculate cropping dimensions
+ if ($ratio > 1) {
+ $crop_width = ceil($crop_height * 4 / 3);
+ } else {
+ $crop_height = ceil($crop_width * 3 / 4);
+ }
+ // Calculate resizing dimensions
+ $h = ceil($w * 3 / 4);
+ break;
+ }
+ // Calculate focus coordinates
+ switch ($cropping['focus']) {
+ case 'center':
+ if ($ratio > 1) {
+ $crop_x = ceil(($cur_width - $crop_width) / 2);
+ } elseif ($ratio == 1) {
+ $crop_x = ceil(($cur_width - $crop_width) / 2);
+ $crop_y = ceil(($cur_height - $crop_height) / 2);
+ } else {
+ $crop_y = ceil(($cur_height - $crop_height) / 2);
+ }
+ break;
+ case 'top':
+ $crop_x = ceil(($cur_width - $crop_width) / 2);
+ break;
+ case 'bottom':
+ $crop_y = $cur_height - $crop_height;
+ break;
+ case 'right':
+ $crop_x = $cur_width - $crop_width;
+ break;
+ }
+ // Cropped image.
+ $thumb_cropped = imagecreatetruecolor($crop_width, $crop_height);
+ // Cropped ratio.
+ $ratio = $crop_width / $crop_height;
+ // Otherwise, calculate image size according to the source's ratio.
} else {
- $w = round($h * $ratio);
+ if ($cur_width > $cur_height) {
+ $h = round($w / $ratio);
+ } else {
+ $w = round($h * $ratio);
+ }
}
+ // Resized image.
$thumb = imagecreatetruecolor($w, $h);
+
+ $image = false;
switch ($ext) {
case 'jpg':
$image = imagecreatefromjpeg($source);
- imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ // Crop
+ if ($thumb_cropped !== false) {
+ // First, crop.
+ imagecopyresampled($thumb_cropped, $image, 0, 0, $crop_x, $crop_y, $cur_width, $cur_height, $cur_width, $cur_height);
+ // Then, resize.
+ imagecopyresampled($thumb, $thumb_cropped, 0, 0, 0, 0, $w, $h, $crop_width, $crop_height);
+ // Resize
+ } else {
+ imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ }
imagejpeg($thumb, $dest);
break;
case 'png':
$image = imagecreatefrompng($source);
// Turn off alpha blending and set alpha flag. That prevent alpha
// transparency to be saved as an arbitrary color (black in my tests)
- imagealphablending($thumb, false);
imagealphablending($image, false);
- imagesavealpha($thumb, true);
imagesavealpha($image, true);
- imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ imagealphablending($thumb, false);
+ imagesavealpha($thumb, true);
+ // Crop
+ if ($thumb_cropped !== false) {
+ imagealphablending($thumb_cropped, false);
+ imagesavealpha($thumb_cropped, true);
+ // First, crop.
+ imagecopyresampled($thumb_cropped, $image, 0, 0, $crop_x, $crop_y, $cur_width, $cur_height, $cur_width, $cur_height);
+ // Then, resize.
+ imagecopyresampled($thumb, $thumb_cropped, 0, 0, 0, 0, $w, $h, $crop_width, $crop_height);
+ // Resize
+ } else {
+ imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ }
imagepng($thumb, $dest);
break;
case 'gif':
$image = imagecreatefromgif($source);
- imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ // Crop
+ if ($thumb_cropped !== false) {
+ // First, crop.
+ imagecopyresampled($thumb_cropped, $image, 0, 0, $crop_x, $crop_y, $cur_width, $cur_height, $cur_width, $cur_height);
+ // Then, resize.
+ imagecopyresampled($thumb, $thumb_cropped, 0, 0, 0, 0, $w, $h, $crop_width, $crop_height);
+ // Resize
+ } else {
+ imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ }
imagegif($thumb, $dest);
break;
case 'webp':
$image = imagecreatefromwebp($source);
- imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ // Crop
+ if ($thumb_cropped !== false) {
+ // First, crop.
+ imagecopyresampled($thumb_cropped, $image, 0, 0, $crop_x, $crop_y, $cur_width, $cur_height, $cur_width, $cur_height);
+ // Then, resize.
+ imagecopyresampled($thumb, $thumb_cropped, 0, 0, 0, 0, $w, $h, $crop_width, $crop_height);
+ // Resize
+ } else {
+ imagecopyresampled($thumb, $image, 0, 0, 0, 0, $w, $h, $cur_width, $cur_height);
+ }
imagewebp($thumb, $dest);
break;
}
* @property string $pref_etiq_rows
* @property string $pref_etiq_corps
* @property boolean $pref_etiq_border
+ * @property boolean $pref_force_picture_ratio
+ * @property string $pref_member_picture_ratio
* @property string $pref_card_abrev
* @property string $pref_card_strip
* @property string $pref_card_tcol
'pref_etiq_corps' => 12,
'pref_etiq_border' => true,
/* Preferences for members cards */
+ 'pref_force_picture_ratio' => false,
+ 'pref_member_picture_ratio' => 'square_ratio',
'pref_card_abrev' => 'GALETTE',
'pref_card_strip' => 'Gestion d\'Adherents en Ligne Extrêmement Tarabiscotée',
'pref_card_tcol' => '#FFFFFF',
/**
* Handle files (photo and dynamics files)
*
- * @param array $files Files sent
+ * @param array $files Files sent
+ * @param array $cropping Cropping properties
*
* @return array|true
*/
- public function handleFiles(array $files)
+ public function handleFiles(array $files, array $cropping = null)
{
$this->errors = [];
// picture upload
if ($files['photo']['error'] === UPLOAD_ERR_OK) {
if ($files['photo']['tmp_name'] != '') {
if (is_uploaded_file($files['photo']['tmp_name'])) {
- $res = $this->picture->store($files['photo']);
+ if ($this->preferences->pref_force_picture_ratio == 1 && isset($cropping)) {
+ $res = $this->picture->store($files['photo'], false, $cropping);
+ } else {
+ $res = $this->picture->store($files['photo']);
+ }
if ($res < 0) {
$this->errors[]
= $this->picture->getErrorMessage($res);
public const INVALID_FILENAME = -1;
public const INVALID_EXTENSION = -2;
public const FILE_TOO_BIG = -3;
- public const MIME_NOT_ALLOWED = -4;
- public const NEW_FILE_EXISTS = -5;
- public const INVALID_FILE = -6;
- public const CANT_WRITE = -7;
+ public const IMAGE_TOO_SMALL = -4;
+ public const MIME_NOT_ALLOWED = -5;
+ public const NEW_FILE_EXISTS = -6;
+ public const INVALID_FILE = -7;
+ public const CANT_WRITE = -8;
public const MAX_FILE_SIZE = 2048;
+ public const MIN_CROP_SIZE = 267;
}
protected $allowed_extensions = array();
protected $allowed_mimes = array();
protected $maxlenght;
+ protected $mincropsize;
public static $mime_types = array(
'txt' => 'text/plain',
/**
* Initialization
*
- * @param string $dest File destination directory
- * @param array $extensions Array of permitted extensions
- * @param array $mimes Array of permitted mime types
- * @param int $maxlenght Maximum lenght for each file
+ * @param string $dest File destination directory
+ * @param array $extensions Array of permitted extensions
+ * @param array $mimes Array of permitted mime types
+ * @param int $maxlenght Maximum lenght for each file
+ * @param int $mincropsize Minimum image side size required for cropping
*
* @return void
*/
$dest,
$extensions = null,
$mimes = null,
- $maxlenght = null
+ $maxlenght = null,
+ $mincropsize = null
) {
if ($dest !== null && substr($dest, -1) !== '/') {
//normalize path
} else {
$this->maxlenght = self::MAX_FILE_SIZE;
}
+ if ($mincropsize !== null) {
+ $this->mincropsize = $mincropsize;
+ } else {
+ $this->mincropsize = self::MIN_CROP_SIZE;
+ }
}
/**
_T("File is too big. Maximum allowed size is %dKo")
);
break;
+ case self::IMAGE_TOO_SMALL:
+ $error = sprintf(
+ _T("Image is too small. The minimum image side size allowed is %spx"),
+ $this->mincropsize
+ );
+ break;
case self::MIME_NOT_ALLOWED:
/** FIXME: should be more descriptive */
$error = _T("Mime-Type not allowed");
<div class="field ui items">
<label>{{ _T("Picture:") }}</label>
<div class="item">
- {% if member.id %}
- <div class="image">
- {% set photo_id = member.id %}
- <img id="photo_adh" src="{{ url_for("photo", {"id": photo_id, "rand": time}) }}" class="picture" width="{{ member.picture.getOptimalWidth() }}" height="{{ member.picture.getOptimalHeight() }}" alt="{{ _T("Picture") }}"/>
- </div>
- {% endif %}
<div class="content">
+ {% if member.hasPicture() == 1 %}
+ <div class="extra ui basic fitted segment">
+ <div class="ui toggle checkbox">
+ <input type="checkbox" name="del_photo" id="del_photo" value="1"/>
+ <label for="del_photo" class="labelalign">{{ _T("Delete image") }}</label>
+ </div>
+ </div>
+ {% endif %}
<div class="description">
<div class="ui file action input">
- <input type="file" name="photo"/>
- <label for="photo" class="ui button{% if constant('GALETTE_MODE') == constant('\\Galette\\Core\\Galette::MODE_DEMO') %} disabled{% endif %}">
+ <input id="photo_new" type="file" name="photo"/>
+ <label for="photo_new" class="ui button{% if constant('GALETTE_MODE') == constant('\\Galette\\Core\\Galette::MODE_DEMO') %} disabled{% endif %}">
<i class="blue upload icon"></i>
{% if member.hasPicture() == 1 %}{{ _T("Choose another file") }}{% else %}{{ _T("Choose a file") }}{% endif %}
</label>
</div>
</div>
- <div class="extra ui basic fitted segment">
- {% if member.hasPicture() == 1 %}
- <div class="ui toggle checkbox">
- <input type="checkbox" name="del_photo" id="del_photo" value="1"/>
- <label for="del_photo" class="labelalign">{{ _T("Delete image") }}</label>
+ {% if preferences.pref_force_picture_ratio == 1 %}
+ {% set system_ratio = (preferences.pref_member_picture_ratio == 'square_ratio') ? _T("Square (1:1)") : (preferences.pref_member_picture_ratio == 'portrait_ratio') ? _T("Portrait (3:4)") : (preferences.pref_member_picture_ratio == 'landscape_ratio') ? _T("Landscape (4:3)") %}
+ <div id="crop_focus_field" class="extra ui basic fitted segment displaynone">
+ <div class="inline field">
+ <label for="crop_focus">{{ _T("Cropping focus") }}</label>
+ <select name="crop_focus" id="crop_focus" class="ui dropdown nochosen">
+ <option value="center">{{ _T("Center") }}</option>
+ <option value="top">{{ _T("Top") }}</option>
+ <option value="bottom">{{ _T("Bottom") }}</option>
+ <option value="left">{{ _T("Left") }}</option>
+ <option value="right">{{ _T("Right") }}</option>
+ </select>
+ <i class="tooltip circular inverted primary small icon info" data-html="{{ _T("Choose the area of the original image to preserve after cropping to the final ratio defined in the settings : %ratio")|replace({"%ratio": system_ratio}) }}"></i>
</div>
- {% endif %}
</div>
+ {% endif %}
</div>
</div>
</div>
- {% if member.id %}
- //Photo dnd
- // Check if window.FileReader exists to make
- // sure the browser supports file uploads
- if ( typeof(window.FileReader) ) {
- var _dz = $('#photo_adh');
+{% if member.id %}
+ //Photo dnd
+ // Check if window.FileReader exists to make
+ // sure the browser supports file uploads
+ if ( typeof(window.FileReader) ) {
+ var _dz = $('#photo_adh');
- // Add a nice drag effect
- _dz[0].ondragover = function() {
- _dz.addClass('dndhover');
- return false;
- };
+ if (_dz[0]) {
+ // Add a nice drag effect
+ _dz[0].ondragover = function() {
+ _dz.css({ opacity: 0.4 });
+ _dz.transition('pulsating');
+ return false;
+ };
- // Remove the drag effect when stopping our drag
- _dz[0].ondragend = function() {
- _dz.removeClass('dndhover');
- return false;
- };
+ // Remove the drag effect when leaving the dropping zone
+ _dz[0].ondragleave = function() {
+ _dz.css({ opacity: 1 });
+ _dz.transition('stop all');
+ return false;
+ };
- // The drop event handles the file sending
- _dz[0].ondrop = function(event) {
- // Stop the browser from opening the file in the window
- event.preventDefault();
- _dz.removeClass('dndhover');
+ // The drop event handles the file sending
+ _dz[0].ondrop = function(event) {
+ // Stop the browser from opening the file in the window
+ event.preventDefault();
+ _dz.css({ opacity: 1 });
+ _dz.transition('stop all');
+ $('.message').remove();
- var file = event.dataTransfer.files[0];
- var reader = new FileReader();
- reader.readAsDataURL(file);
+ var file = event.dataTransfer.files[0];
- reader.onload = function(evt) {
- $.ajax({
- type: 'POST',
- dataType: 'json',
- url : '{{ url_for("photoDnd") }}',
- data: {
- member_id: {{ member.id }},
- filename: file.name,
- filesize: file.size,
- file: evt.target.result
- },
- {% include "elements/js/loader.js.twig" %},
- success: function(res){
- if ( res.result == true ) {
- d = new Date();
- var _photo = $('#photo_adh');
- _photo.removeAttr('width').removeAttr('height');
- _photo.attr('src', $('#photo_adh')[0].src + '?' + d.getTime());
- }
+ {% if preferences.pref_force_picture_ratio == 1 %}
+ {% set system_ratio = (preferences.pref_member_picture_ratio == 'square_ratio') ? _T("Square (1:1)") : (preferences.pref_member_picture_ratio == 'portrait_ratio') ? _T("Portrait (3:4)") : (preferences.pref_member_picture_ratio == 'landscape_ratio') ? _T("Landscape (4:3)") %}
- //display message
- $.ajax({
- url: '{{ url_for("ajaxMessages") }}',
- method: "GET",
- success: function (message) {
- $('#asso_name').after(message);
- }
- });
- },
- error: function() {
- {% include "elements/js/modal.js.twig" with {
- modal_title_twig: _T("An error occurred sending photo :(")|e("js"),
- modal_without_content: true,
- modal_class: "mini",
- modal_deny_only: true,
- modal_cancel_text: _T("Close")|e("js"),
- modal_classname: "redalert",
- } %}
- }
- });
+ var cropping = { ratio: '{{ preferences.pref_member_picture_ratio }}' };
+ var focus_select = '<div class="ui basic horizontally fitted segment form"><div class="field">';
+ focus_select += '<select name="crop_focus_ajax" id="crop_focus_ajax" class="ui dropdown nochosen">';
+ focus_select += '<option value="center">{{ _T("Center") }}</option>';
+ focus_select += '<option value="top">{{ _T("Top") }}</option>';
+ focus_select += '<option value="bottom">{{ _T("Bottom") }}</option>';
+ focus_select += '<option value="left">{{ _T("Left") }}</option>';
+ focus_select += '<option value="right">{{ _T("Right") }}</option>';
+ focus_select += '</select>';
+ focus_select += '</div></div>';
+
+ {% include "elements/js/modal.js.twig" with {
+ modal_title_twig: _T("Cropping focus")|e("js"),
+ modal_content_twig: _T("Choose the area of the original image to preserve after cropping to the final ratio defined in the settings : %ratio")|replace({"%ratio": system_ratio})|e('js'),
+ modal_class: "tiny",
+ modal_other_options: {
+ closable: false
+ },
+ modal_onshow: "$(this).find('.content').append(focus_select);$('#crop_focus_ajax').dropdown();",
+ modal_onapprove: "cropping.focus=$(this).find('#crop_focus_ajax').val();_fileLoad(file, cropping);"
+ } %}
+ {% else %}
+ _fileLoad(file);
+ {% endif %}
+ }
+
+ var _fileLoad = function(file, cropping_settings) {
+ var reader = new FileReader();
+ reader.readAsDataURL(file);
+
+ var cropping = false;
+ if (cropping_settings) {
+ var cropping = cropping_settings;
+ }
+
+ reader.onload = function(evt) {
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ url : '{{ url_for("photoDnd") }}',
+ data: {
+ member_id: {{ member.id }},
+ filename: file.name,
+ filesize: file.size,
+ file: evt.target.result,
+ cropping: cropping
+ },
+ {% include "elements/js/loader.js.twig" with {
+ selector: '#member_card'
+ } %},
+ success: function(res){
+ window.location.reload(true);
+ },
+ error: function() {
+ {% include "elements/js/modal.js.twig" with {
+ modal_title_twig: _T("An error occurred sending photo :(")|e("js"),
+ modal_without_content: true,
+ modal_class: "tiny",
+ modal_deny_only: true,
+ modal_cancel_text: _T("Close")|e("js"),
+ modal_classname: "redalert",
+ } %}
}
- }
+ });
}
- {% endif %}
+ }
+ }
+ }
+{% endif %}
-<div class="ui horizontal fluid card">
+<div id="member_card" class="ui horizontal fluid card">
{% if not (member.picture.path ends with '/default/images/default.png') %}
<div class="image">
<img
+ id="photo_adh"
src="{{ url_for("photo", {"id": member.id, "rand": time}) }}"
width="{{ member.picture.getOptimalWidth() }}"
height="{{ member.picture.getOptimalHeight() }}"
- alt="{{ _T("Picture") }}">
+ alt="{{ _T("Picture") }}"
+ class="green no-touch tooltip"
+ {# Drag'n drop is disabled on member form #}
+ {% if (hidden_elements is not defined) %}
+ data-html="{{ _T("Drag and drop an image file to change the picture") }}">
+ <span class="ui bottom left corner tiny label">
+ <i class="download icon"></i>
+ </span>
+ {% else %}
+ >
+ {% endif %}
</div>
{% endif %}
<div class="content">
});
{% endif %}
{% endif %}
- {% include "elements/js/photo_dnd.js.twig" %}
$('#ddn_adh').on('blur', function() {
var _bdate = $(this).val();
$('#member_age').html('');
}
});
+
+ {% if preferences.pref_force_picture_ratio == 1 %}
+ // Show photo cropping preferences on file selection
+ let _photo_new = document.getElementById('photo_new');
+ _photo_new.addEventListener('change', function () {
+ if (_photo_new.files.length > 0) {
+ let _crop_focus = document.getElementById('crop_focus_field');
+ _crop_focus.classList.remove('displaynone');
+ $('#crop_focus_field').transition('glow');
+ return;
+ }
+ });
+ {% endif %}
{% endif %}
});
</script>
/>
</div>
<div class="content">
- <div class="header">{{ member.sfullname }}</div>
- {% if member.nickname != '' %}<div class="meta">{{ member.nickname|escape }}</div>{% endif %}
+ <div class="center aligned header">{{ member.sfullname }}</div>
+ {% if member.nickname != '' %}<div class="center aligned meta">{{ member.nickname|escape }}</div>{% endif %}
</div>
</div>
{% else %}
<label for="pref_bool_publicpages">{{ _T("Public pages enabled?") }}</label>
</div>
</div>
- <div class="field" id="publicpages_visibility"{% if not pref.pref_bool_publicpages %} class="displaynone"{% endif %}>
+ <div id="publicpages_visibility" class="field{% if not pref.pref_bool_publicpages %} displaynone{% endif %}">
<label for="pref_publicpages_visibility">{{ _T("Show public pages for") }}</label>
<select name="pref_publicpages_visibility" id="pref_publicpages_visibility" class="ui search dropdown nochosen">
<option value="{{ constant('Galette\\Core\\Preferences::PUBLIC_PAGES_VISIBILITY_PUBLIC') }}"{% if pref.pref_publicpages_visibility == constant('Galette\\Core\\Preferences::PUBLIC_PAGES_VISIBILITY_PUBLIC') %} selected="selected"{% endif %}>{{ _T("Everyone") }}</option>
<option value="{{ constant('Galette\\Core\\Preferences::PUBLIC_PAGES_VISIBILITY_PRIVATE') }}"{% if pref.pref_publicpages_visibility == constant('Galette\\Core\\Preferences::PUBLIC_PAGES_VISIBILITY_PRIVATE') %} selected="selected"{% endif %}>{{ _T("Admin and staff only") }}</option>
</select>
</div>
+ <div class="field inline">
+ <div class="ui right aligned toggle checkbox">
+ <input type="checkbox" name="pref_force_picture_ratio" id="pref_force_picture_ratio" value="1" {% if pref.pref_force_picture_ratio == 1 %}checked="checked"{% endif %}/>
+ <label for="pref_force_picture_ratio">{{ _T("Force member picture ratio") }}</label>
+ </div>
+ <i class="tooltip circular inverted primary small icon info" data-html="{{ _T("If checked, the members's picture will be resized and cropped to the ratio selected below.") }}" data-variation="inverted wide"></i>
+ </div>
+ <div id="pref_member_picture_ratio_field" class="inline field{% if pref.pref_force_picture_ratio != 1 %} displaynone{% endif %}">
+ <label for="pref_member_picture_ratio" title="{{ _T("Choose the") }}">{{ _T("Select a ratio") }}</label>
+ <select name="pref_member_picture_ratio" id="pref_member_picture_ratio" class="ui dropdown nochosen">
+ <option value="square_ratio"{% if pref.pref_member_picture_ratio == 'square_ratio' %} selected="selected"{% endif %}>{{ _T("Square (1:1)") }}</option>
+ <option value="portrait_ratio"{% if pref.pref_member_picture_ratio == 'portrait_ratio' %} selected="selected"{% endif %}>{{ _T("Portrait (3:4)") }}</option>
+ <option value="landscape_ratio"{% if pref.pref_member_picture_ratio == 'landscape_ratio' %} selected="selected"{% endif %}>{{ _T("Landscape (4:3)") }}</option>
+ </select>
+ </div>
<div class="field inline">
<div class="ui right aligned toggle checkbox">
<input type="checkbox" name="pref_bool_selfsubscribe" id="pref_bool_selfsubscribe" value="1"{% if pref.pref_bool_selfsubscribe %} checked="checked"{% endif %}/>
}
}
});
- /*$('#smtp, #gmail').checkbox({
- onChecked: function() {
- console.log($(this).closest('#smtp_parameters'));
- //$('#smtp_parameters, #smtp_auth').toggleClass('displaynone');
- }
- });*/
$('.pointing.menu .item').tab({
onVisible: function(tabPath) {
}
});
- $('#pref_bool_publicpages').change(function(){
- $('#publicpages_visibility').toggleClass('displaynone');
+ let _publicpages_status = document.getElementById('pref_bool_publicpages');
+ let _publicpages_visibility = document.getElementById('publicpages_visibility');
+ _publicpages_status.addEventListener('change', function () {
+ _publicpages_visibility.classList.toggle('displaynone');
+ return;
+ });
+
+ let _crop_status = document.getElementById('pref_force_picture_ratio');
+ let _crop_ratio = document.getElementById('pref_member_picture_ratio_field');
+ _crop_status.addEventListener('change', function () {
+ _crop_ratio.classList.toggle('displaynone');
+ return;
});
$('#btnmail').on('click', function(e) {
.edit-member {
.fieldset-1 .ui.items > .item {
- & > .image {
- display: none;
- }
& > .content {
padding: 0;
}