Skip to content
17 changes: 17 additions & 0 deletions administrator/language/en-GB/plg_media-action_crop.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
; Note : All ini files need to be saved as UTF-8

PLG_MEDIA-ACTION_CROP="Media Action - Crop"
PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_DESC="Configure custom aspect ratios for the crop tool. Each ratio needs a label (e.g. '16:9'), a value (e.g. '1.7777777777777777'), and optionally a group (landscape/portrait)."
PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_LABEL="Aspect Ratios"
PLG_MEDIA-ACTION_CROP_LABEL="Crop"
PLG_MEDIA-ACTION_CROP_PARAM_ASPECT="Aspect Ratio"
PLG_MEDIA-ACTION_CROP_PARAM_DEFAULT_RATIO="Default aspect ratio"
Expand All @@ -15,4 +17,19 @@ PLG_MEDIA-ACTION_CROP_PARAM_WIDTH="Width"
PLG_MEDIA-ACTION_CROP_PARAM_X="X-Axis"
PLG_MEDIA-ACTION_CROP_PARAM_Y="Y-Axis"
PLG_MEDIA-ACTION_CROP_QUALITY="Quality"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_COPY_DONE_LABEL="Copied"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_COPY_LABEL="Copy"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_DESC="Use this calculator to determine the decimal value for your aspect ratios. Enter width and height, then copy the calculated value."
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_HEIGHT_LABEL="Height"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_LABEL="Aspect Ratio Calculator"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_OUTPUT_LABEL="Calculated value:"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_OUTPUT_TITLE_LABEL="Click to copy"
PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_WIDTH_LABEL="Width"
PLG_MEDIA-ACTION_CROP_RATIO_GROUP="Group"
PLG_MEDIA-ACTION_CROP_RATIO_GROUP_DESC="Optionally group this ratio under landscape or portrait"
PLG_MEDIA-ACTION_CROP_RATIO_GROUP_NONE="No group"
PLG_MEDIA-ACTION_CROP_RATIO_LABEL="Label"
PLG_MEDIA-ACTION_CROP_RATIO_LABEL_DESC="The label to display for this ratio (e.g. '16:9', '4:3', etc.)"
PLG_MEDIA-ACTION_CROP_RATIO_VALUE="Value"
PLG_MEDIA-ACTION_CROP_RATIO_VALUE_DESC="The calculated aspect ratio value (width/height). For example, 16:9 = 1.7777777777777777, 4:3 = 1.3333333333333333, 1:1 = 1"
PLG_MEDIA-ACTION_CROP_XML_DESCRIPTION="Adds crop functionality for images."
17 changes: 17 additions & 0 deletions build/media_source/plg_media-action_crop/joomla.asset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "plg_media-action_crop",
"version": "6.1.0",
"description": "Web Assets for Media Action Crop Plugin",
"license": "GPL-2.0-or-later",
"assets": [
{
"name": "plg_media-action_crop.calculator",
"type": "script",
"uri": "plg_media-action_crop/calculator.js",
"attributes": {
"defer": true
}
}
]
}
84 changes: 84 additions & 0 deletions build/media_source/plg_media-action_crop/js/calculator.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @copyright (C) 2025 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

/**
* Aspect Ratio Calculator Module
*/
(() => {
const initCalculator = () => {
const widthInput = document.getElementById('calc-width');
const heightInput = document.getElementById('calc-height');
const output = document.getElementById('calc-output');
const copyBtn = document.getElementById('copy-calc-value');

if (!widthInput || !heightInput || !output || !copyBtn) {
return;
}

/**
* Calculate aspect ratio from width and height
*/
const calculateRatio = () => {
const width = parseFloat(widthInput.value);
const height = parseFloat(heightInput.value);

if (width > 0 && height > 0) {
const ratio = width / height;
output.textContent = ratio.toString();
} else {
output.textContent = '0';
}
};

/**
* Show copy feedback on button
*/
const showCopyFeedback = () => {
const originalHTML = copyBtn.innerHTML;
const copiedIcon = copyBtn.getAttribute('data-copied-icon');
const copiedText = copyBtn.getAttribute('data-copied-text');

copyBtn.innerHTML = Joomla.sanitizeHtml(copiedIcon + copiedText);
copyBtn.disabled = true;

setTimeout(() => {
copyBtn.innerHTML = originalHTML;
copyBtn.disabled = false;
}, 2000);
};

/**
* Copy the calculated value to clipboard
*/
const copyToClipboard = () => {
const value = output.textContent;

navigator.clipboard.writeText(value)
.then(() => {
showCopyFeedback();
})
.catch((err) => {
console.error('Clipboard copy failed:', err);
});
};

// Attach event listeners
widthInput.addEventListener('input', calculateRatio);
heightInput.addEventListener('input', calculateRatio);
copyBtn.addEventListener('click', copyToClipboard);
output.addEventListener('click', copyToClipboard);

// Calculate initial ratio
calculateRatio();
};

// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCalculator);
} else {
// DOM already loaded, run with slight delay for form rendering
setTimeout(initCalculator, 100);
}
})();
54 changes: 54 additions & 0 deletions plugins/media-action/crop/crop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,65 @@
<namespace path="src">Joomla\Plugin\MediaAction\Crop</namespace>
<files>
<folder>form</folder>
<folder>layouts</folder>
<folder plugin="crop">services</folder>
<folder>src</folder>
</files>
<languages>
<language tag="en-GB">language/en-GB/plg_media-action_crop.ini</language>
<language tag="en-GB">language/en-GB/plg_media-action_crop.sys.ini</language>
</languages>
<config>
<fields name="params" addfieldprefix="Joomla\Plugin\MediaAction\Crop\Field">
<fieldset name="basic">
<field
name="ratio_calculator"
type="calculator"
label="PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_LABEL"
/>
<field
name="aspect_ratios"
type="subform"
label="PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_LABEL"
description="PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_DESC"
multiple="true"
layout="joomla.form.field.subform.repeatable-table"
default='{"aspect_ratios0":{"label":"1:1","value":"1","group":""},"aspect_ratios1":{"label":"5:4","value":"1.25","group":"landscape"},"aspect_ratios2":{"label":"4:3","value":"1.3333333333333333","group":"landscape"},"aspect_ratios3":{"label":"3:2","value":"1.5","group":"landscape"},"aspect_ratios4":{"label":"16:9","value":"1.7777777777777777","group":"landscape"},"aspect_ratios5":{"label":"4:5","value":"0.8","group":"portrait"},"aspect_ratios6":{"label":"3:4","value":"0.75","group":"portrait"},"aspect_ratios7":{"label":"2:3","value":"0.6666666666666667","group":"portrait"},"aspect_ratios8":{"label":"9:16","value":"0.5625","group":"portrait"}}'
>
<form>
<field
name="label"
type="text"
label="PLG_MEDIA-ACTION_CROP_RATIO_LABEL"
description="PLG_MEDIA-ACTION_CROP_RATIO_LABEL_DESC"
required="true"
filter="string"
/>
<field
name="value"
type="text"
label="PLG_MEDIA-ACTION_CROP_RATIO_VALUE"
description="PLG_MEDIA-ACTION_CROP_RATIO_VALUE_DESC"
required="true"
pattern="\d*\.?\d+"
hint="1.7777777777777777"
validate="number"
class="input-small"
/>
<field
name="group"
type="list"
label="PLG_MEDIA-ACTION_CROP_RATIO_GROUP"
description="PLG_MEDIA-ACTION_CROP_RATIO_GROUP_DESC"
default=""
>
<option value="">PLG_MEDIA-ACTION_CROP_RATIO_GROUP_NONE</option>
<option value="landscape">PLG_MEDIA-ACTION_CROP_PARAM_LANDSCAPE</option>
<option value="portrait">PLG_MEDIA-ACTION_CROP_PARAM_PORTRAIT</option>
</field>
</form>
</field>
</fieldset>
</fields>
</config>
</extension>
75 changes: 75 additions & 0 deletions plugins/media-action/crop/layouts/field/calculator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/**
* @package Joomla.Plugin
* @subpackage Media-Action.crop
*
* @copyright (C) 2025 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

extract($displayData);

/**
* Layout variables
* -----------------
* @var string $id The field ID
*/

// Load the calculator JavaScript
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->getRegistry()->addExtensionRegistryFile('plg_media-action_crop');
$wa->useScript('plg_media-action_crop.calculator');

// Prepare data for JavaScript
$copiedIcon = LayoutHelper::render('joomla.icon.iconclass', ['icon' => 'icon-check']);
$copiedText = Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_COPY_DONE_LABEL');
?>
<div class="card mb-3">
<div class="card-header">
<h2 id="aspect-ratio-calculator" class="card-title mb-0">
<?php echo LayoutHelper::render('joomla.icon.iconclass', ['icon' => 'icon-wand']); ?>
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_LABEL'); ?>
</h2>
</div>
<div class="card-body">
<p class="mb-3">
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_DESC'); ?>
</p>
<div class="row g-3 mb-3">
<div class="col-md-6">
<label for="calc-width" class="form-label fw-bold">
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_WIDTH_LABEL'); ?>
</label>
<input type="number" id="calc-width" min="1" step="1" value="16" class="form-control" />
</div>
<div class="col-md-6">
<label for="calc-height" class="form-label fw-bold">
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_HEIGHT_LABEL'); ?>
</label>
<input type="number" id="calc-height" min="1" step="1" value="9" class="form-control" />
</div>
</div>
<div class="alert alert-success d-flex align-items-center justify-content-between" role="alert">
<div>
<strong class="me-2">
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_OUTPUT_LABEL'); ?>
</strong>
<output id="calc-output" for="aspect-ratio-calculator" class="font-monospace fs-5 text-success fw-bold user-select-all" style="cursor: pointer;" title="<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_OUTPUT_TITLE_LABEL'); ?>">1.7777777777777777</output>
</div>
<button type="button" id="copy-calc-value" class="btn btn-success btn-sm"
title="<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_COPY_LABEL'); ?>"
data-copied-icon="<?php echo htmlspecialchars($copiedIcon, ENT_QUOTES, 'UTF-8'); ?>"
data-copied-text="<?php echo htmlspecialchars($copiedText, ENT_QUOTES, 'UTF-8'); ?>">
<?php echo LayoutHelper::render('joomla.icon.iconclass', ['icon' => 'icon-copy']); ?>
<?php echo Text::_('PLG_MEDIA-ACTION_CROP_RATIO_CALCULATOR_COPY_LABEL'); ?>
</button>
</div>
</div>
</div>
Loading