Advertisement
Guest User

Untitled

a guest
Feb 2nd, 2017
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * @file
  3.  * Defines the behaviors needed for cropper integration.
  4.  */
  5.  
  6. (function ($, Drupal, drupalSettings) {
  7.     'use strict';
  8.  
  9.     var cropperSelector = '.crop-preview-wrapper__preview-image';
  10.     var cropperValuesSelector = '.crop-preview-wrapper__value';
  11.     var cropWrapperSelector = '.image-data__crop-wrapper';
  12.     var cropWrapperSummarySelector = '.panel-heading a';//'summary';
  13.     var verticalTabsSelector = '.vertical-tabs';
  14.     var verticalTabsMenuItemSelector = '.vertical-tab-button';//'.vertical-tabs__menu-item';
  15.     var resetSelector = '.crop-preview-wrapper__crop-reset';
  16.     var detailsWrapper = '.panel-body';//'.details-wrapper';
  17.     var detailsParentSelector = '.image-widget-data';
  18.     var table = '.responsive-enabled';
  19.     var cropperOptions = {
  20.         background: false,
  21.         zoomable: false,
  22.         viewMode: 1,
  23.         autoCropArea: 1,
  24.         responsive: false,
  25.         // Callback function, fires when crop is applied.
  26.         cropend: function (e) {
  27.             var $this = $(this);
  28.             var $values = $this.siblings(cropperValuesSelector);
  29.             var data = $this.cropper('getData');
  30.             // Calculate delta between original and thumbnail images.
  31.             var delta = $this.data('original-height') / $this.prop('naturalHeight');
  32.             /*
  33.              * All data returned by cropper plugin multiple with delta in order to get
  34.              * proper crop sizes for original image.
  35.              */
  36.             $values.find('.crop-x').val(Math.round(data.x * delta));
  37.             $values.find('.crop-y').val(Math.round(data.y * delta));
  38.             $values.find('.crop-width').val(Math.round(data.width * delta));
  39.             $values.find('.crop-height').val(Math.round(data.height * delta));
  40.             $values.find('.crop-applied').val(1);
  41.             Drupal.imageWidgetCrop.updateCropSummaries($this);
  42.         }
  43.     };
  44.  
  45.     Drupal.imageWidgetCrop = {};
  46.  
  47.     /**
  48.      * Initialize cropper on the ImageWidgetCrop widget.
  49.      *
  50.      * @param {Object} context - Element to initialize cropper on.
  51.      */
  52.     Drupal.imageWidgetCrop.initialize = function (context) {
  53.         var $cropWrapper = $(cropWrapperSelector, context);
  54.         var $cropWrapperSummary = $cropWrapper.children(detailsWrapper).find(cropWrapperSummarySelector);
  55.         var $verticalTabs = $(verticalTabsSelector, context);
  56.         var $verticalTabsMenuItem = $verticalTabs.find(verticalTabsMenuItemSelector);
  57.         var $reset = $(resetSelector, context);
  58.  
  59.         /*
  60.          * Cropper initialization on click events on vertical tabs and details
  61.          * summaries (for smaller screens).
  62.          */
  63.         $verticalTabsMenuItem.add($cropWrapperSummary).click(function () {
  64.             var tabId = $(this).find('a').attr('href');
  65.             var $cropper = $(this).parent().find(cropperSelector);
  66.             if (typeof tabId !== 'undefined') {
  67.                 $cropper = $(tabId).find(cropperSelector);
  68.             }
  69.             var ratio = Drupal.imageWidgetCrop.getRatio($cropper);
  70.             Drupal.imageWidgetCrop.initializeCropper($cropper, ratio);
  71.         });
  72.  
  73.         // Handling click event for opening/closing vertical tabs.
  74.         $cropWrapper.children(cropWrapperSummarySelector).once('imageWidgetCrop').click(function (evt) {
  75.             // Work only on bigger screens where $verticalTabsMenuItem is not empty.
  76.             if ($verticalTabsMenuItem.length !== 0) {
  77.                 // If detailsWrapper is not visible display it and initialize cropper.
  78.                 if (!$(this).siblings(detailsWrapper).is(':visible')) {
  79.                     evt.preventDefault();
  80.                     $(this).parent().attr('open', 'open');
  81.                     $(table).addClass('responsive-enabled--opened');
  82.                     $(this).parent().find(detailsWrapper).show();
  83.                     Drupal.imageWidgetCrop.initializeCropperOnChildren($(this).parent());
  84.                     evt.stopImmediatePropagation();
  85.                 }
  86.                 // If detailsWrapper is visible hide it.
  87.                 else {
  88.                     $(this).parent().removeAttr('open');
  89.                     $(table).removeClass('responsive-enabled--opened');
  90.                     $(this).parent().find(detailsWrapper).hide();
  91.                 }
  92.             }
  93.         });
  94.  
  95.         $reset.on('click', function (e) {
  96.             e.preventDefault();
  97.             var $element = $(this).siblings(cropperSelector);
  98.             Drupal.imageWidgetCrop.reset($element);
  99.             return false;
  100.         });
  101.  
  102.         // Handling cropping when viewport resizes.
  103.         $(window).resize(function () {
  104.             $(detailsParentSelector).each(function () {
  105.                 // Find only opened widgets.
  106.                 var cropperDetailsWrapper = $(this).children('details[open="open"]');
  107.                 cropperDetailsWrapper.each(function () {
  108.                     // Find all croppers for opened widgets.
  109.                     var $croppers = $(this).find(cropperSelector);
  110.                     $croppers.each(function () {
  111.                         var $this = $(this);
  112.                         if ($this.parent().parent().parent().css('display') !== 'none') {
  113.                             // Get previous data for cropper.
  114.                             var canvasDataOld = $this.cropper('getCanvasData');
  115.                             var cropBoxData = $this.cropper('getCropBoxData');
  116.  
  117.                             // Re-render cropper.
  118.                             $this.cropper('render');
  119.  
  120.                             // Get new data for cropper and calculate resize ratio.
  121.                             var canvasDataNew = $this.cropper('getCanvasData');
  122.                             var ratio = 1;
  123.                             if (canvasDataOld.width !== 0) {
  124.                                 ratio = canvasDataNew.width / canvasDataOld.width;
  125.                             }
  126.  
  127.                             // Set new data for crop box.
  128.                             $.each(cropBoxData, function (index, value) {
  129.                                 cropBoxData[index] = value * ratio;
  130.                             });
  131.                             $this.cropper('setCropBoxData', cropBoxData);
  132.  
  133.                             Drupal.imageWidgetCrop.updateHardLimits($this);
  134.                             Drupal.imageWidgetCrop.checkSoftLimits($this);
  135.                             Drupal.imageWidgetCrop.updateCropSummaries($this);
  136.                         }
  137.                     });
  138.                 });
  139.             });
  140.         });
  141.  
  142.         // Correctly updating messages of summaries.
  143.         Drupal.imageWidgetCrop.updateAllCropSummaries();
  144.     };
  145.  
  146.     /**
  147.      * Get ratio data and determine if an available ratio or free crop.
  148.      *
  149.      * @param {Object} $element - Element to initialize cropper on its children.
  150.      */
  151.     Drupal.imageWidgetCrop.getRatio = function ($element) {
  152.         var ratio = $element.data('ratio');
  153.         var regex = /:/;
  154.  
  155.         if ((regex.exec(ratio)) !== null) {
  156.             var int = ratio.split(":");
  157.             if ($.isArray(int) && ($.isNumeric(int[0]) && $.isNumeric(int[1]))) {
  158.                 return int[0] / int[1];
  159.             }
  160.             else {
  161.                 return "NaN";
  162.             }
  163.         }
  164.         else {
  165.             return ratio;
  166.         }
  167.     };
  168.  
  169.     /**
  170.      * Initialize cropper on an element.
  171.      *
  172.      * @param {Object} $element - Element to initialize cropper on.
  173.      * @param {number} ratio - The ratio of the image.
  174.      */
  175.     Drupal.imageWidgetCrop.initializeCropper = function ($element, ratio) {
  176.         var data = null;
  177.         var $values = $element.siblings(cropperValuesSelector);
  178.  
  179.         // Calculate minimal height for cropper container (minimal width is 200).
  180.         var minDelta = ($element.data('original-width') / 200);
  181.         cropperOptions['minContainerHeight'] = $element.data('original-height') / minDelta;
  182.  
  183.         var options = cropperOptions;
  184.         var delta = $element.data('original-height') / $element.prop('naturalHeight');
  185.  
  186.         // If 'Show default crop' is checked show crop box.
  187.         options.autoCrop = drupalSettings['crop_default'];
  188.  
  189.         if (parseInt($values.find('.crop-applied').val()) === 1) {
  190.             data = {
  191.                 x: Math.round(parseInt($values.find('.crop-x').val()) / delta),
  192.                 y: Math.round(parseInt($values.find('.crop-y').val()) / delta),
  193.                 width: Math.round(parseInt($values.find('.crop-width').val()) / delta),
  194.                 height: Math.round(parseInt($values.find('.crop-height').val()) / delta),
  195.                 rotate: 0,
  196.                 scaleX: 1,
  197.                 scaleY: 1
  198.             };
  199.             options.autoCrop = true;
  200.         }
  201.  
  202.         // React on crop move and check soft limits.
  203.         options.cropmove = function (e) {
  204.             Drupal.imageWidgetCrop.checkSoftLimits($(this));
  205.         };
  206.  
  207.         options.data = data;
  208.         options.aspectRatio = ratio;
  209.  
  210.         $element.cropper(options);
  211.  
  212.         // Hard and soft limits we need to check for fist time when cropper
  213.         // finished it initialization.
  214.         $element.on('built.cropper', function (e) {
  215.             var $this = $(this);
  216.             Drupal.imageWidgetCrop.updateHardLimits($this);
  217.             Drupal.imageWidgetCrop.checkSoftLimits($this);
  218.         });
  219.  
  220.         // If 'Show default crop' is checked apply default crop.
  221.         if (drupalSettings['crop_default']) {
  222.             var dataDefault = $element.cropper('getData');
  223.             // Calculate delta between original and thumbnail images.
  224.             var deltaDefault = $element.data('original-height') / $element.prop('naturalHeight');
  225.             /*
  226.              * All data returned by cropper plugin multiple with delta in order to get
  227.              * proper crop sizes for original image.
  228.              */
  229.             Drupal.imageWidgetCrop.updateCropValues($values, dataDefault, deltaDefault);
  230.             Drupal.imageWidgetCrop.updateCropSummaries($element);
  231.         }
  232.     };
  233.  
  234.     /**
  235.      * Update crop values in hidden inputs.
  236.      *
  237.      * @param {Object} $element - Cropper values selector.
  238.      * @param {Array} $data - Cropper data.
  239.      * @param {number} $delta - Delta between original and thumbnail images.
  240.      */
  241.     Drupal.imageWidgetCrop.updateCropValues = function ($element, $data, $delta) {
  242.         $element.find('.crop-x').val(Math.round($data.x * $delta));
  243.         $element.find('.crop-y').val(Math.round($data.y * $delta));
  244.         $element.find('.crop-width').val(Math.round($data.width * $delta));
  245.         $element.find('.crop-height').val(Math.round($data.height * $delta));
  246.         $element.find('.crop-applied').val(1);
  247.     };
  248.  
  249.     /**
  250.      * Converts horizontal and vertical dimensions to canvas dimensions.
  251.      *
  252.      * @param {Object} $element - Crop element.
  253.      * @param {Number} x - horizontal dimension in image space.
  254.      * @param {Number} y - vertical dimension in image space.
  255.      */
  256.     Drupal.imageWidgetCrop.toCanvasDimensions = function ($element, x, y) {
  257.         var imageData = $element.data('cropper').getImageData();
  258.         return {
  259.             width: imageData.width * (x / $element.data('original-width')),
  260.             height: imageData.height * (y / $element.data('original-height'))
  261.         }
  262.     };
  263.  
  264.     /**
  265.      * Converts horizontal and vertical dimensions to image dimensions.
  266.      *
  267.      * @param {Object} $element - Crop element.
  268.      * @param {Number} x - horizontal dimension in canvas space.
  269.      * @param {Number} y - vertical dimension in canvas space.
  270.      */
  271.     Drupal.imageWidgetCrop.toImageDimensions = function ($element, x, y) {
  272.         var imageData = $element.data('cropper').getImageData();
  273.         return {
  274.             width: x * ($element.data('original-width') / imageData.width),
  275.             height: y * ($element.data('original-height') / imageData.height)
  276.         }
  277.     };
  278.  
  279.     /**
  280.      * Update hard limits for given element.
  281.      *
  282.      * @param {Object} $element - Crop element.
  283.      */
  284.     Drupal.imageWidgetCrop.updateHardLimits = function ($element) {
  285.         var cropName = $element.data('name');
  286.  
  287.         // Check first that we have configuration for this crop.
  288.         if (!drupalSettings.image_widget_crop.hasOwnProperty(cropName)) {
  289.             return;
  290.         }
  291.  
  292.         var cropConfig = drupalSettings.image_widget_crop[cropName];
  293.         var cropper = $element.data('cropper');
  294.         var options = cropper.options;
  295.  
  296.         // Limits works in canvas so we need to convert dimensions.
  297.         var converted = Drupal.imageWidgetCrop.toCanvasDimensions($element, cropConfig.hard_limit.width, cropConfig.hard_limit.height);
  298.         options.minCropBoxWidth = converted.width;
  299.         options.minCropBoxHeight = converted.height;
  300.  
  301.         // After updating the options we need to limit crop box.
  302.         cropper.limitCropBox(true, false);
  303.     };
  304.  
  305.     /**
  306.      * Check soft limit for given crop element.
  307.      *
  308.      * @param {Object} $element - Crop element.
  309.      */
  310.     Drupal.imageWidgetCrop.checkSoftLimits = function ($element) {
  311.         var cropName = $element.data('name');
  312.  
  313.         // Check first that we have configuration for this crop.
  314.         if (!drupalSettings.image_widget_crop.hasOwnProperty(cropName)) {
  315.             return;
  316.         }
  317.  
  318.         var cropConfig = drupalSettings.image_widget_crop[cropName];
  319.  
  320.         var minSoftCropBox = {
  321.             'width': Number(cropConfig.soft_limit.width) || 0,
  322.             'height': Number(cropConfig.soft_limit.height) || 0
  323.         };
  324.  
  325.         // We do comparison in image dimensions so lets convert first.
  326.         var cropBoxData = $element.cropper('getCropBoxData');
  327.         var converted = Drupal.imageWidgetCrop.toImageDimensions($element, cropBoxData.width, cropBoxData.height);
  328.  
  329.         var dimensions = ['width', 'height'];
  330.  
  331.         for (var i = 0; i < dimensions.length; ++i) {
  332.             // @todo - setting up soft limit status in data attribute is not ideal
  333.             // but current architecture is like that. When we convert to proper
  334.             // one imageWidgetCrop object per crop widget we will be able to fix
  335.             // this also. @see https://www.drupal.org/node/2660788.
  336.             var softLimitReached = $element.data(dimensions[i] + '-soft-limit-reached');
  337.  
  338.             if (converted[dimensions[i]] < minSoftCropBox[dimensions[i]]) {
  339.                 if (!softLimitReached) {
  340.                     softLimitReached = true;
  341.                     Drupal.imageWidgetCrop.softLimitChanged($element, dimensions[i], softLimitReached);
  342.                 }
  343.             }
  344.             else if (softLimitReached) {
  345.                 softLimitReached = false;
  346.                 Drupal.imageWidgetCrop.softLimitChanged($element, dimensions[i], softLimitReached);
  347.             }
  348.         }
  349.     };
  350.  
  351.     /**
  352.      * React on soft limit change.
  353.      *
  354.      * @param {Object} $element - Crop element.
  355.      * @param {boolean} newSoftLimitState - new soft imit state, true if it
  356.      *   reached, or false.
  357.      */
  358.     Drupal.imageWidgetCrop.softLimitChanged = function ($element, dimension, newSoftLimitState) {
  359.         var $cropperWrapper = $element.siblings('.cropper-container');
  360.         if (newSoftLimitState) {
  361.             $cropperWrapper.addClass('cropper--' + dimension + '-soft-limit-reached');
  362.         }
  363.         else {
  364.             $cropperWrapper.removeClass('cropper--' + dimension + '-soft-limit-reached');
  365.         }
  366.  
  367.         // @todo - use temporary storage while we are waiting for [#2660788].
  368.         $element.data(dimension + '-soft-limit-reached', newSoftLimitState);
  369.  
  370.         Drupal.imageWidgetCrop.updateSingleCropSummary($element);
  371.     };
  372.  
  373.     /**
  374.      * Initialize cropper on all children of an element.
  375.      *
  376.      * @param {Object} $element - Element to initialize cropper on its children.
  377.      */
  378.     Drupal.imageWidgetCrop.initializeCropperOnChildren = function ($element) {
  379.         var visibleCropper = $element.find(cropperSelector + ':visible');
  380.         var ratio = Drupal.imageWidgetCrop.getRatio($(visibleCropper));
  381.         Drupal.imageWidgetCrop.initializeCropper($(visibleCropper), ratio);
  382.     };
  383.  
  384.     /**
  385.      * Update single crop summary of an element.
  386.      *
  387.      * @param {Object} $element - The element cropping on which has been changed.
  388.      */
  389.     Drupal.imageWidgetCrop.updateSingleCropSummary = function ($element) {
  390.         var $values = $element.siblings(cropperValuesSelector);
  391.         var croppingApplied = parseInt($values.find('.crop-applied').val());
  392.         var summaryMessages = [];
  393.  
  394.         $element.closest('details').drupalSetSummary(function (context) {
  395.             if (croppingApplied === 1) {
  396.                 summaryMessages.push(Drupal.t('Cropping applied.'));
  397.             }
  398.  
  399.             if ($element.data('height-soft-limit-reached') || $element.data('width-soft-limit-reached')) {
  400.                 summaryMessages.push(Drupal.t('Soft limit reached.'));
  401.             }
  402.  
  403.             return summaryMessages.join('<br>');
  404.         });
  405.     };
  406.  
  407.     /**
  408.      * Update common crop summary of an element.
  409.      *
  410.      * @param {Object} $element - The element cropping on which has been changed.
  411.      */
  412.     Drupal.imageWidgetCrop.updateCommonCropSummary = function ($element) {
  413.         var croppingApplied = parseInt($element.find('.crop-applied[value="1"]').length);
  414.         var wrapperText = Drupal.t('Crop image');
  415.         if (croppingApplied) {
  416.             wrapperText = Drupal.t('Crop image (cropping applied)');
  417.         }
  418.         $element.children('summary').text(wrapperText);
  419.     };
  420.  
  421.     /**
  422.      * Update crop summaries after cropping cas been set or reset.
  423.      *
  424.      * @param {Object} $element - The element cropping on which has been changed.
  425.      */
  426.     Drupal.imageWidgetCrop.updateCropSummaries = function ($element) {
  427.         var $details = $element.closest('details' + cropWrapperSelector);
  428.         Drupal.imageWidgetCrop.updateSingleCropSummary($element);
  429.         Drupal.imageWidgetCrop.updateCommonCropSummary($details);
  430.     };
  431.  
  432.     /**
  433.      * Update crop summaries of all elements.
  434.      */
  435.     Drupal.imageWidgetCrop.updateAllCropSummaries = function () {
  436.         var $croppers = $(cropperSelector);
  437.         $croppers.each(function () {
  438.             Drupal.imageWidgetCrop.updateSingleCropSummary($(this));
  439.         });
  440.         var $cropWrappers = $(cropWrapperSelector);
  441.         $cropWrappers.each(function () {
  442.             Drupal.imageWidgetCrop.updateCommonCropSummary($(this));
  443.         });
  444.     };
  445.  
  446.     /**
  447.      * Reset cropping for an element.
  448.      *
  449.      * @param {Object} $element - The element to reset cropping on.
  450.      */
  451.     Drupal.imageWidgetCrop.reset = function ($element) {
  452.         var $valuesDefault = $element.siblings(cropperValuesSelector);
  453.         var options = cropperOptions;
  454.         // If 'Show default crop' is not checked re-initialize cropper.
  455.         if (!drupalSettings['crop_default']) {
  456.             $element.cropper('destroy');
  457.             options.autoCrop = false;
  458.             $element.cropper(options);
  459.             $valuesDefault.find('.crop-applied').val(0);
  460.             $valuesDefault.find('.crop-x').val('');
  461.             $valuesDefault.find('.crop-y').val('');
  462.             $valuesDefault.find('.crop-width').val('');
  463.             $valuesDefault.find('.crop-height').val('');
  464.         }
  465.         else {
  466.             // Reset cropper.
  467.             $element.cropper('reset').cropper('options', options);
  468.             var dataDefault = $element.cropper('getData');
  469.             // Calculate delta between original and thumbnail images.
  470.             var deltaDefault = $element.data('original-height') / $element.prop('naturalHeight');
  471.             /*
  472.              * All data returned by cropper plugin multiple with delta in order to get
  473.              * proper crop sizes for original image.
  474.              */
  475.             Drupal.imageWidgetCrop.updateCropValues($valuesDefault, dataDefault, deltaDefault);
  476.         }
  477.         Drupal.imageWidgetCrop.updateCropSummaries($element);
  478.     };
  479.  
  480.     Drupal.behaviors.imageWidgetCrop = {
  481.         attach: function (context) {
  482.             Drupal.imageWidgetCrop.initialize(context);
  483.             Drupal.imageWidgetCrop.updateAllCropSummaries();
  484.         }
  485.     };
  486.  
  487. }(jQuery, Drupal, drupalSettings));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement