From b9271c78c74c1909df80986e1bf1cea604ea7387 Mon Sep 17 00:00:00 2001 From: Geetanshu Mathur Date: Tue, 17 Jul 2018 21:47:23 +0530 Subject: [PATCH] Different focus selection for different widths (#12) * Adding more Fields to the front-end * Sending and receiveing Widths through ajax * updateing controller for requested widths * Added Multiple Focus Areas for diffrent widths * Added translatable strings * resolveing merge conflicts * phpcs * phpcs * added new lines * updated ajax for getFocusPoints * build * updateing ajax for all and build * removed data fields * codestyle * fix * codestyle fix * fix maxWidth and maxHeight * fix space * fix --- .../Controller/AdaptiveImageController.php | 34 ++-- .../en-GB.plg_media-action_smartcrop.ini | 1 + .../src/AdaptiveImage/FocusStoreInterface.php | 14 +- .../src/AdaptiveImage/JSONFocusStore.php | 79 ++++++-- .../css/smartcrop.css | 7 +- .../css/smartcrop.min.css | 1 + .../js/smartcrop.js | 182 ++++++++++-------- .../js/smartcrop.min.js | 2 +- .../media-action/smartcrop/form/smartcrop.xml | 16 ++ 9 files changed, 217 insertions(+), 119 deletions(-) create mode 100644 media/plg_media-action_smartcrop/css/smartcrop.min.css diff --git a/administrator/components/com_media/src/Controller/AdaptiveImageController.php b/administrator/components/com_media/src/Controller/AdaptiveImageController.php index e7643e6443fdb..191297879cb3f 100644 --- a/administrator/components/com_media/src/Controller/AdaptiveImageController.php +++ b/administrator/components/com_media/src/Controller/AdaptiveImageController.php @@ -42,30 +42,28 @@ public function execute($task) { case "setfocus" : $imgPath = $this->input->getString('path'); + $width = $this->input->getInt('width'); $dataFocus = array ( - "box-left" => $this->input->getInt('box-left'), - "box-top" => $this->input->getInt('box-top'), - "box-width" => $this->input->getInt('box-width'), - "box-height" => $this->input->getInt('box-height') + "box-left" => $this->input->getInt('box-left'), + "box-top" => $this->input->getInt('box-top'), + "box-width" => $this->input->getInt('box-width'), + "box-height" => $this->input->getInt('box-height') ); $storage = new JSONFocusStore; - $storage->setFocus($dataFocus, $imgPath); - $this->cropImage($imgPath); + $storage->setFocus($dataFocus, $width, $imgPath); return true; break; case "cropBoxData" : $this->app->setHeader('Content-Type', 'application/json'); $imgPath = $this->input->getString('path'); + $width = $this->input->getInt('width'); $storage = new JSONFocusStore; - echo $storage->getFocus($imgPath); + echo $storage->getFocus($imgPath, $width); $this->app->close(); return true; break; case "cropImage" : - // @TODO Resize image to any aspect ratio. - $imgPath = "/images/" . $this->input->getString('path'); - - // $finalWidth = $this->input->getFloat('width'); + $imgPath = $this->input->getString('path'); $this->cropImage($imgPath); return true; break; @@ -77,20 +75,24 @@ public function execute($task) * Crop the images around the focus area * * @param string $imgPath image path + * @param array $widths requested widths * * @return boolean * * @since 4.0.0 */ - public function cropImage($imgPath) + public function cropImage($imgPath, $widths = null) { $storage = new JSONFocusStore; - $dataFocus = json_decode($storage->getFocus($imgPath), true); - $width = array(240, 360, 480, 768, 940, 1024); - foreach ($width as $finalWidth) + if ($widths == null) + { + $widths = array(240, 360, 480, 768, 940, 1024); + } + foreach ($widths as $width) { + $dataFocus = json_decode($storage->getFocus($imgPath, $width), true); $image = new SmartCrop(".." . $imgPath); - $image->compute($dataFocus, $finalWidth); + $image->compute($dataFocus, $width); } return true; } diff --git a/administrator/language/en-GB/en-GB.plg_media-action_smartcrop.ini b/administrator/language/en-GB/en-GB.plg_media-action_smartcrop.ini index 934d2fbf86e2b..a9367b0ec40de 100644 --- a/administrator/language/en-GB/en-GB.plg_media-action_smartcrop.ini +++ b/administrator/language/en-GB/en-GB.plg_media-action_smartcrop.ini @@ -7,4 +7,5 @@ PLG_MEDIA-ACTION_SMARTCROP_PARAM_X="data focus x" PLG_MEDIA-ACTION_SMARTCROP_PARAM_X_PRE="Focus-X" PLG_MEDIA-ACTION_SMARTCROP_PARAM_Y="data focus top" PLG_MEDIA-ACTION_SMARTCROP_PARAM_Y_PRE="Focus-Y" +PLG_MEDIA-ACTION_SMARTCROP_REQUESTED_WIDTH="Choose focus for diffrent sizes (optional)." PLG_MEDIA-ACTION_SMARTCROP_QUALITY="Quality" diff --git a/libraries/src/AdaptiveImage/FocusStoreInterface.php b/libraries/src/AdaptiveImage/FocusStoreInterface.php index af4622477598f..6ab17a3317e6b 100644 --- a/libraries/src/AdaptiveImage/FocusStoreInterface.php +++ b/libraries/src/AdaptiveImage/FocusStoreInterface.php @@ -22,25 +22,27 @@ interface FocusStoreInterface * Pubic function for storeing the focus points * to the file system. * - * @param array $dataFocus Focus point selected - * @param string $filePath Path of the image + * @param array $dataFocus Focus point selected + * @param integer $width Width of the image + * @param string $filePath Path of the image * * @return void * * @since 4.0.0 */ - public function setFocus($dataFocus,$filePath); + public function setFocus($dataFocus, $width, $filePath); /** * Public function for getting the focus point * from the file system * - * @param string $imgSrc Path of the image - * + * @param string $imgSrc Path of the image + * @param integer $width Width of the image + * * @return string * * @since 4.0.0 */ - public function getFocus($imgSrc); + public function getFocus($imgSrc, $width); } diff --git a/libraries/src/AdaptiveImage/JSONFocusStore.php b/libraries/src/AdaptiveImage/JSONFocusStore.php index 10311534945ab..1036ba2054189 100644 --- a/libraries/src/AdaptiveImage/JSONFocusStore.php +++ b/libraries/src/AdaptiveImage/JSONFocusStore.php @@ -46,22 +46,24 @@ public function __construct() * * index.php?option=com_media&task=adaptiveimage.setfocus&path=/images/sampledata/fruitshop/bananas_1.jpg * - * @param array $dataFocus Array of the values of diffrent focus point - * - * @param string $imgPath Full path for the file + * @param array $dataFocus Array of the values of diffrent focus point + * @param integer $width Width of the image + * @param string $imgPath Full path for the file * * @return boolean * * @since 4.0.0 */ - public function setFocus($dataFocus,$imgPath) + public function setFocus($dataFocus, $width, $imgPath) { $newEntry = array( $imgPath => array( - "box-left" => $dataFocus['box-left'], - "box-top" => $dataFocus['box-top'], - "box-width" => $dataFocus['box-width'], - "box-height" => $dataFocus['box-height'] + $width => array( + "box-left" => $dataFocus['box-left'], + "box-top" => $dataFocus['box-top'], + "box-width" => $dataFocus['box-width'], + "box-height" => $dataFocus['box-height'] + ) ) ); @@ -71,15 +73,20 @@ public function setFocus($dataFocus,$imgPath) $prevData = json_decode($prevData, true); - $prevData[$imgPath]["box-left"] = $dataFocus['box-left']; - $prevData[$imgPath]["box-top"] = $dataFocus['box-top']; - $prevData[$imgPath]["box-width"] = $dataFocus['box-width']; - $prevData[$imgPath]["box-height"] = $dataFocus['box-height']; + $prevData[$imgPath][$width]["box-left"] = $dataFocus['box-left']; + $prevData[$imgPath][$width]["box-top"] = $dataFocus['box-top']; + $prevData[$imgPath][$width]["box-width"] = $dataFocus['box-width']; + $prevData[$imgPath][$width]["box-height"] = $dataFocus['box-height']; + + $max = $this->findMax($prevData[$imgPath]); + $prevData[$imgPath]["max"] = $max; file_put_contents(static::$dataLocation, json_encode($prevData)); } else { + $newEntry[$imgPath]["max"] = $newEntry[$imgPath][$width]; + file_put_contents(static::$dataLocation, json_encode($newEntry)); } @@ -90,13 +97,14 @@ public function setFocus($dataFocus,$imgPath) /** * Function to get the focus point * - * @param string $imgPath Image Path + * @param string $imgPath Image Path + * @param integer $width Width of the corresponding data focus point * * @return array * * @since 4.0.0 */ - public function getFocus($imgPath) + public function getFocus($imgPath, $width = null) { if (!filesize(static::$dataLocation)) { @@ -109,7 +117,14 @@ public function getFocus($imgPath) if (array_key_exists($imgPath, $prevData)) { - return json_encode($prevData[$imgPath]); + if (array_key_exists($width, $prevData[$imgPath])) + { + return json_encode($prevData[$imgPath][$width]); + } + else + { + return json_encode($prevData[$imgPath]["max"]); + } } else { @@ -134,4 +149,38 @@ private function checkStorage($dataLocation) return true; } + /** + * Fine the max value of all the focus area selected + * + * @param array $dataFocuses Collection of dataFocus for diffrent sizes. + * + * @return array + * + * @since 4.0.0 + */ + private function findMax($dataFocuses) + { + $minX = 9999; + $minY = 9999; + $maxX = 0; + $maxY = 0; + + foreach ($dataFocuses as $width => $focus) + { + if ($width != "max") + { + $minX = min($minX, $focus["box-left"]); + $minY = min($minY, $focus["box-top"]); + $maxX = max($maxX, $focus["box-left"] + $focus["box-width"]); + $maxY = max($maxY, $focus["box-top"] + $focus["box-height"]); + } + } + $maxFocus = array( + "box-left" => $minX, + "box-top" => $minY, + "box-width" => $maxX - $minX, + "box-height" => $maxY - $minY + ); + return $maxFocus; + } } diff --git a/media/plg_media-action_smartcrop/css/smartcrop.css b/media/plg_media-action_smartcrop/css/smartcrop.css index 3f4ea751584fe..3ab5eba4a07fa 100644 --- a/media/plg_media-action_smartcrop/css/smartcrop.css +++ b/media/plg_media-action_smartcrop/css/smartcrop.css @@ -1 +1,6 @@ -/* This is the CSS File for Smart Crop */ \ No newline at end of file +/* This is the CSS File for Smart Crop */ +#attrib-smartcrop +{ + overflow-y: auto +} + diff --git a/media/plg_media-action_smartcrop/css/smartcrop.min.css b/media/plg_media-action_smartcrop/css/smartcrop.min.css new file mode 100644 index 0000000000000..603ac33ecb27c --- /dev/null +++ b/media/plg_media-action_smartcrop/css/smartcrop.min.css @@ -0,0 +1 @@ +#attrib-smartcrop{overflow-y:auto} \ No newline at end of file diff --git a/media/plg_media-action_smartcrop/js/smartcrop.js b/media/plg_media-action_smartcrop/js/smartcrop.js index 39c37da1676ba..0f1f4a12eb8de 100644 --- a/media/plg_media-action_smartcrop/js/smartcrop.js +++ b/media/plg_media-action_smartcrop/js/smartcrop.js @@ -9,7 +9,95 @@ Joomla.MediaManager.Edit = Joomla.MediaManager.Edit || {}; (function () { "use strict"; - var initSmartCrop = function (mediaData) { + var path; + // resolveing the path + path = getQueryVariable('path').split(':'); + path = '/images' + path[1]; + + // Setting the focus area in the editor + var getFocusPoints = function(width){ + Joomla.request({ + url: resolveBaseUrl() +"/administrator/index.php?option=com_media&task=adaptiveimage.cropBoxData&path="+path+"&width="+width, + method: 'GET', + onSuccess: (response) => { + if(response!=''){ + var data = JSON.parse(response); + Joomla.MediaManager.Edit.smartcrop.cropper.setData({ + "x" : data["box-left"], + "y" : data["box-top"], + "width" : data["box-width"], + "height" : data["box-height"] + }); + } + }, + }); + } + + // Saveing the focus points to the storage + function saveFocusPoints(width) { + // Data to be saved in the storage + var data = "&box-left="+Joomla.MediaManager.Edit.smartcrop.cropper.boxLeft+ + "&box-top="+Joomla.MediaManager.Edit.smartcrop.cropper.boxTop+ + "&box-width="+Joomla.MediaManager.Edit.smartcrop.cropper.boxWidth+ + "&box-height="+Joomla.MediaManager.Edit.smartcrop.cropper.boxHeight+ + "&width="+width; + + Joomla.request({ + url: resolveBaseUrl() +"/administrator/index.php?option=com_media&task=adaptiveimage.setfocus&path="+path+data, + method: 'GET', + }); + } + + // At Deactivate crop the images and save to cache. + function cropImages(){ + Joomla.request({ + url: resolveBaseUrl() +"/administrator/index.php?option=com_media&task=adaptiveimage.cropImage&path="+path, + method: 'GET', + }); + } + + // Getting the value of any varible in the url + function getQueryVariable(variable) { + var query = window.location.search.substring(1); + var vars = query.split('&'); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split('='); + if (decodeURIComponent(pair[0]) == variable) { + return decodeURIComponent(pair[1]); + } + } + return false; + }; + + // Getting the perfect base path + function resolveBaseUrl() { + var basePath = window.location.origin; + var url = window.location.pathname.split('/'); + if (url[1]!='administrator') { + return basePath+"/"+url[1]; + } + return basePath; + } + + // Register the Events + Joomla.MediaManager.Edit.smartcrop = { + Activate: function (mediaData) { + // Initialize + initSmartCrop(mediaData); + }, + Deactivate: function () { + var width = document.getElementById("jform_requestedWidth").value; + saveFocusPoints(width); + cropImages(); + if (!Joomla.MediaManager.Edit.smartcrop.cropper) { + return; + } + // Destroy the instance + Joomla.MediaManager.Edit.smartcrop.cropper.destroy(); + } + }; + + var initSmartCrop = function (mediaData) { var image = document.getElementById('image-preview'); // Initiate the cropper for gathering the focus point @@ -25,17 +113,12 @@ Joomla.MediaManager.Edit = Joomla.MediaManager.Edit || {}; minContainerWidth: image.offsetWidth, minContainerHeight: image.offsetHeight, crop: function (e) { - var left, top, - canvas_width, canvas_height, - image_width, image_height; + var left, top,canvas_width, canvas_height; left = Math.round(e.detail.x); top = Math.round(e.detail.y); canvas_width = Math.round(e.detail.width); canvas_height = Math.round(e.detail.height); - - image_width = image.naturalWidth; - image_height = image.naturalHeight; // Saveing cropbox data for focus area Joomla.MediaManager.Edit.smartcrop.cropper.boxLeft = left; @@ -62,79 +145,18 @@ Joomla.MediaManager.Edit = Joomla.MediaManager.Edit || {}; Joomla.MediaManager.Edit.smartcrop.cropper.setAspectRatio(defaultCropFactor); }); + var width = document.getElementById("jform_requestedWidth"); + var preWidth = width.value; + + getFocusPoints(preWidth); - var setFocusData = function(){ - var data, path, - xhr, url; - path = getQueryVariable('path').split(':'); - path = '/images' + path[1]; - xhr = new XMLHttpRequest(); - url = resolveBaseUrl() +"/administrator/index.php?option=com_media&task=adaptiveimage.cropBoxData&path="+path; - xhr.open("GET", url, true); - xhr.onreadystatechange = function() { - if (this.readyState == 4 && this.status == 200) { - if(this.response!=''){ - data = JSON.parse(this.responseText); - Joomla.MediaManager.Edit.smartcrop.cropper.setData({ - "x" : data["box-left"], - "y" : data["box-top"], - "width" : data["box-width"], - "height": data["box-height"] - }); - } - } - }; - xhr.send(); - } - setFocusData(); - }; - - // Register the Events - Joomla.MediaManager.Edit.smartcrop = { - Activate: function (mediaData) { - // Initialize - initSmartCrop(mediaData); - }, - Deactivate: function () { - var path = getQueryVariable('path'); - path = path.split(':'); - path = '/images' + path[1]; - var data = "&box-left="+Joomla.MediaManager.Edit.smartcrop.cropper.boxLeft+ - "&box-top="+Joomla.MediaManager.Edit.smartcrop.cropper.boxTop+ - "&box-width="+Joomla.MediaManager.Edit.smartcrop.cropper.boxWidth+ - "&box-height="+Joomla.MediaManager.Edit.smartcrop.cropper.boxHeight; - var xhr = new XMLHttpRequest(); - var url = resolveBaseUrl() +"/administrator/index.php?option=com_media&task=AdaptiveImage.setfocus&path="+path; - url += data; - xhr.open("GET", url, true); - xhr.send(); - if (!Joomla.MediaManager.Edit.smartcrop.cropper) { - return; - } - // Destroy the instance - Joomla.MediaManager.Edit.smartcrop.cropper.destroy(); - } - }; - - function getQueryVariable(variable) { - var query = window.location.search.substring(1); - var vars = query.split('&'); - for (var i = 0; i < vars.length; i++) { - var pair = vars[i].split('='); - if (decodeURIComponent(pair[0]) == variable) { - return decodeURIComponent(pair[1]); - } - } - return false; + width.addEventListener('change', function(){ + saveFocusPoints(preWidth); + var newWidth = width.value + getFocusPoints(newWidth); + preWidth = newWidth; + }); + }; +})(); - function resolveBaseUrl() { - var basePath = window.location.origin; - var url = window.location.pathname.split('/'); - if (url[1]!='administrator') { - return basePath+"/"+url[1]; - } - return basePath; - } - -})(); \ No newline at end of file diff --git a/media/plg_media-action_smartcrop/js/smartcrop.min.js b/media/plg_media-action_smartcrop/js/smartcrop.min.js index 3db51dc60e731..426dc7554a958 100644 --- a/media/plg_media-action_smartcrop/js/smartcrop.min.js +++ b/media/plg_media-action_smartcrop/js/smartcrop.min.js @@ -1 +1 @@ -Joomla=window.Joomla||{},Joomla.MediaManager=Joomla.MediaManager||{},Joomla.MediaManager.Edit=Joomla.MediaManager.Edit||{},function(){"use strict";function a(a){for(var t=window.location.search.substring(1).split("&"),e=0;e{if(""!=a){var o=JSON.parse(a);Joomla.MediaManager.Edit.smartcrop.cropper.setData({x:o["box-left"],y:o["box-top"],width:o["box-width"],height:o["box-height"]})}}})};function e(o){var e="&box-left="+Joomla.MediaManager.Edit.smartcrop.cropper.boxLeft+"&box-top="+Joomla.MediaManager.Edit.smartcrop.cropper.boxTop+"&box-width="+Joomla.MediaManager.Edit.smartcrop.cropper.boxWidth+"&box-height="+Joomla.MediaManager.Edit.smartcrop.cropper.boxHeight+"&width="+o;Joomla.request({url:t()+"/administrator/index.php?option=com_media&task=adaptiveimage.setfocus&path="+a+e,method:"GET"})}function t(){var a=window.location.origin,o=window.location.pathname.split("/");return"administrator"!=o[1]?a+"/"+o[1]:a}Joomla.MediaManager.Edit.smartcrop={Activate:function(a){r(a)},Deactivate:function(){e(document.getElementById("jform_requestedWidth").value),Joomla.request({url:t()+"/administrator/index.php?option=com_media&task=adaptiveimage.cropImage&path="+a,method:"GET"}),Joomla.MediaManager.Edit.smartcrop.cropper&&Joomla.MediaManager.Edit.smartcrop.cropper.destroy()}};var r=function(a){var t=document.getElementById("image-preview");Joomla.MediaManager.Edit.smartcrop.cropper=new Cropper(t,{viewMode:1,responsive:!1,restore:!0,autoCrop:!0,movable:!0,zoomable:!1,rotatable:!1,autoCropArea:0,minContainerWidth:t.offsetWidth,minContainerHeight:t.offsetHeight,crop:function(a){var o,e,t,r;o=Math.round(a.detail.x),e=Math.round(a.detail.y),t=Math.round(a.detail.width),r=Math.round(a.detail.height),Joomla.MediaManager.Edit.smartcrop.cropper.boxLeft=o,Joomla.MediaManager.Edit.smartcrop.cropper.boxTop=e,Joomla.MediaManager.Edit.smartcrop.cropper.boxWidth=t,Joomla.MediaManager.Edit.smartcrop.cropper.boxHeight=r,document.getElementById("jform_data_focus_x").value=o,document.getElementById("jform_data_focus_y").value=e,document.getElementById("jform_data_focus_width").value=t,document.getElementById("jform_data_focus_height").value=r,window.dispatchEvent(new Event("mediaManager.history.point"))}}),t.addEventListener("load",function(){var a=t.naturalWidth/t.naturalHeight;Joomla.MediaManager.Edit.smartcrop.cropper.setAspectRatio(a)});var r=document.getElementById("jform_requestedWidth"),i=r.value;o(i),r.addEventListener("change",function(){e(i);var a=r.value;o(a),i=a})}}(); \ No newline at end of file diff --git a/plugins/media-action/smartcrop/form/smartcrop.xml b/plugins/media-action/smartcrop/form/smartcrop.xml index 7d5c83c37fdf1..bb4a9ecad5788 100644 --- a/plugins/media-action/smartcrop/form/smartcrop.xml +++ b/plugins/media-action/smartcrop/form/smartcrop.xml @@ -54,5 +54,21 @@ pattern="\d*\.?\d*" /> + + + + + + + + + +