Crop-Thumbnails - Version 1.0.3

Version Description

  • fix js error handling
  • add warning to the backend if the script cant connect the server
  • fix where escape of language-strings make no sense (exceptions in save.php)
Download this release

Release Info

Developer Volkmar Kantor
Plugin Icon Crop-Thumbnails
Version 1.0.3
Comparing to
See all releases

Code changes from version 1.0.2 to 1.0.3

Files changed (5) hide show
  1. crop-thumbnails.php +2 -2
  2. functions/editor.php +22 -17
  3. functions/save.php +12 -12
  4. js/app/app.js +25 -18
  5. readme.txt +6 -1
crop-thumbnails.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin URI: https://wordpress.org/extend/plugins/crop-thumbnails/
5
  * Author: Volkmar Kantor
6
  * Author URI: https://www.totalmedial.de
7
- * Version: 1.0.2
8
  * Description: The easy way to adjust your cropped image sizes.
9
  *
10
  *
@@ -26,7 +26,7 @@
26
  */
27
 
28
 
29
- define('CROP_THUMBNAILS_VERSION','1.0.2');
30
 
31
 
32
  function cptLoadLanguage() {
4
  * Plugin URI: https://wordpress.org/extend/plugins/crop-thumbnails/
5
  * Author: Volkmar Kantor
6
  * Author URI: https://www.totalmedial.de
7
+ * Version: 1.0.3
8
  * Description: The easy way to adjust your cropped image sizes.
9
  *
10
  *
26
  */
27
 
28
 
29
+ define('CROP_THUMBNAILS_VERSION','1.0.3');
30
 
31
 
32
  function cptLoadLanguage() {
functions/editor.php CHANGED
@@ -31,6 +31,10 @@ class CropPostThumbnailsEditor {
31
  }
32
  die();//to prevent to send back a "0"
33
  }
 
 
 
 
34
 
35
  public function getCropData() {
36
  if(!self::isUserPermitted()) {
@@ -54,23 +58,24 @@ class CropPostThumbnailsEditor {
54
  'postTypeFilter' => null,
55
  'imageSizes' => array_values($cptSettings->getImageSizes()),
56
  'lang' => array(
57
- 'warningOriginalToSmall' => esc_html__('Warning: the original image is too small to be cropped in good quality with this thumbnail size.','crop-thumbnails'),
58
- 'cropDisabled' => esc_html__('Cropping is disabled for this post-type.','crop-thumbnails'),
59
- 'waiting' => esc_html__('Please wait until the images are cropped.','crop-thumbnails'),
60
- 'rawImage' => esc_html__('Raw','crop-thumbnails'),
61
- 'pixel' => esc_html__('pixel','crop-thumbnails'),
62
- 'instructions_header' => esc_html__('Quick Instructions','crop-thumbnails'),
63
- 'instructions_step_1' => esc_html__('Step 1: Choose an image-size from the list.','crop-thumbnails'),
64
- 'instructions_step_2' => esc_html__('Step 2: Change the selection of the image above.','crop-thumbnails'),
65
- 'instructions_step_3' => str_replace('"','"', esc_html__('Step 3: Click on "Save Crop".','crop-thumbnails')),
66
- 'label_crop' => esc_html__('Save Crop','crop-thumbnails'),
67
- 'label_same_ratio' => esc_html__('Crop all images with same ratio at once','crop-thumbnails'),
68
- 'label_deselect_all' => esc_html__('deselect all','crop-thumbnails'),
69
- 'dimensions' => esc_html__('Dimensions:','crop-thumbnails'),
70
- 'ratio' => esc_html__('Ratio:','crop-thumbnails'),
71
- 'cropped' => esc_html__('cropped','crop-thumbnails'),
72
- 'lowResWarning' => esc_html__('Original image size too small for good crop quality!','crop-thumbnails'),
73
- 'message_image_orientation' => esc_html__('This image has an image orientation value in its exif-metadata. Be aware that this may result in rotatated or mirrored images on safari ipad / iphone.','crop-thumbnails')
 
74
  ),
75
  'nonce' => wp_create_nonce($cptSettings->getNonceBase())
76
  );
31
  }
32
  die();//to prevent to send back a "0"
33
  }
34
+
35
+ private function fixJsLangStrings($msg) {
36
+ return str_replace('"','"',esc_js($msg));
37
+ }
38
 
39
  public function getCropData() {
40
  if(!self::isUserPermitted()) {
58
  'postTypeFilter' => null,
59
  'imageSizes' => array_values($cptSettings->getImageSizes()),
60
  'lang' => array(
61
+ 'warningOriginalToSmall' => self::fixJsLangStrings(__('Warning: the original image is too small to be cropped in good quality with this thumbnail size.','crop-thumbnails')),
62
+ 'cropDisabled' => self::fixJsLangStrings(__('Cropping is disabled for this post-type.','crop-thumbnails')),
63
+ 'waiting' => self::fixJsLangStrings(__('Please wait until the images are cropped.','crop-thumbnails')),
64
+ 'rawImage' => self::fixJsLangStrings(__('Raw','crop-thumbnails')),
65
+ 'pixel' => self::fixJsLangStrings(__('pixel','crop-thumbnails')),
66
+ 'instructions_header' => self::fixJsLangStrings(__('Quick Instructions','crop-thumbnails')),
67
+ 'instructions_step_1' => self::fixJsLangStrings(__('Step 1: Choose an image-size from the list.','crop-thumbnails')),
68
+ 'instructions_step_2' => self::fixJsLangStrings(__('Step 2: Change the selection of the image above.','crop-thumbnails')),
69
+ 'instructions_step_3' => self::fixJsLangStrings(__('Step 3: Click on "Save Crop".','crop-thumbnails')),
70
+ 'label_crop' => self::fixJsLangStrings(__('Save Crop','crop-thumbnails')),
71
+ 'label_same_ratio' => self::fixJsLangStrings(__('Crop all images with same ratio at once','crop-thumbnails')),
72
+ 'label_deselect_all' => self::fixJsLangStrings(__('deselect all','crop-thumbnails')),
73
+ 'dimensions' => self::fixJsLangStrings(__('Dimensions:','crop-thumbnails')),
74
+ 'ratio' => self::fixJsLangStrings(__('Ratio:','crop-thumbnails')),
75
+ 'cropped' => self::fixJsLangStrings(__('cropped','crop-thumbnails')),
76
+ 'lowResWarning' => self::fixJsLangStrings(__('Original image size too small for good crop quality!','crop-thumbnails')),
77
+ 'message_image_orientation' => self::fixJsLangStrings(__('This image has an image orientation value in its exif-metadata. Be aware that this may result in rotatated or mirrored images on safari ipad / iphone.','crop-thumbnails')),
78
+ 'script_connection_error' => self::fixJsLangStrings(__('The plugin can not correctly connect to the server.','crop-thumbnails'))
79
  ),
80
  'nonce' => wp_create_nonce($cptSettings->getNonceBase())
81
  );
functions/save.php CHANGED
@@ -24,16 +24,16 @@ class CptSaveThumbnail {
24
  try {
25
  $input = $this->getValidatedInput();
26
 
27
-
28
  $sourceImgPath = get_attached_file( $input->sourceImageId );
29
  if(empty($sourceImgPath)) {
30
- throw new Exception(esc_html__("ERROR: Can't find original image file!",'crop-thumbnails'), 1);
31
  }
32
 
33
 
34
  $imageMetadata = wp_get_attachment_metadata($input->sourceImageId, true);//get the attachement metadata of the post
35
  if(empty($imageMetadata)) {
36
- throw new Exception(esc_html__("ERROR: Can't find original image metadata!",'crop-thumbnails'), 1);
37
  }
38
 
39
  //from DB
@@ -86,7 +86,7 @@ class CptSaveThumbnail {
86
 
87
  $_error = false;
88
  if(empty($result)) {
89
- $_processing_error[$activeImageSize->name][] = sprintf(esc_html__("Can't generate filesize '%s'.",'crop-thumbnails'),$activeImageSize->name);
90
  $_error = true;
91
  } else {
92
  if(!empty($oldFile_toDelete)) {
@@ -94,11 +94,11 @@ class CptSaveThumbnail {
94
  @unlink($currentFilePathInfo['dirname'].DIRECTORY_SEPARATOR.$oldFile_toDelete);
95
  }
96
  if(!@copy($result,$currentFilePath)) {
97
- $_processing_error[$activeImageSize->name][] = sprintf(esc_html__("Can't copy temporary file to media library.",'crop-thumbnails'));
98
  $_error = true;
99
  }
100
  if(!@unlink($result)) {
101
- $_processing_error[$activeImageSize->name][] = sprintf(esc_html__("Can't delete temporary file.",'crop-thumbnails'));
102
  $_error = true;
103
  }
104
  }
@@ -258,23 +258,23 @@ class CptSaveThumbnail {
258
  global $cptSettings;
259
 
260
  if(!check_ajax_referer($cptSettings->getNonceBase(),'_ajax_nonce',false)) {
261
- throw new Exception(esc_html__("ERROR: Security Check failed (maybe a timeout - please try again).",'crop-thumbnails'), 1);
262
  }
263
 
264
 
265
  if(empty($_REQUEST['crop_thumbnails'])) {
266
- throw new Exception(esc_html__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
267
  }
268
  $input = json_decode(stripcslashes($_REQUEST['crop_thumbnails']));
269
 
270
 
271
  if(empty($input->selection) || empty($input->sourceImageId) || !isset($input->activeImageSizes)) {
272
- throw new Exception(esc_html__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
273
  }
274
 
275
 
276
  if(!isset($input->selection->x) || !isset($input->selection->y) || !isset($input->selection->x2) || !isset($input->selection->y2)) {
277
- throw new Exception(esc_html__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
278
  }
279
 
280
 
@@ -284,14 +284,14 @@ class CptSaveThumbnail {
284
  $input->selection->y2 = intval($input->selection->y2);
285
 
286
  if($input->selection->x < 0 || $input->selection->y < 0) {
287
- throw new Exception(esc_html__('Cropping to these dimensions on this image is not possible.','crop-thumbnails'), 1);
288
  }
289
 
290
 
291
  $input->sourceImageId = intval($input->sourceImageId);
292
  $_tmp = get_post($input->sourceImageId);//need to be its own var - cause of old php versions
293
  if(empty($_tmp)) {
294
- throw new Exception(esc_html__("ERROR: Can't find original image in database!",'crop-thumbnails'), 1);
295
  }
296
 
297
  return $input;
24
  try {
25
  $input = $this->getValidatedInput();
26
 
27
+
28
  $sourceImgPath = get_attached_file( $input->sourceImageId );
29
  if(empty($sourceImgPath)) {
30
+ throw new Exception(__("ERROR: Can't find original image file!",'crop-thumbnails'), 1);
31
  }
32
 
33
 
34
  $imageMetadata = wp_get_attachment_metadata($input->sourceImageId, true);//get the attachement metadata of the post
35
  if(empty($imageMetadata)) {
36
+ throw new Exception(__("ERROR: Can't find original image metadata!",'crop-thumbnails'), 1);
37
  }
38
 
39
  //from DB
86
 
87
  $_error = false;
88
  if(empty($result)) {
89
+ $_processing_error[$activeImageSize->name][] = sprintf(__("Can't generate filesize '%s'.",'crop-thumbnails'), $activeImageSize->name);
90
  $_error = true;
91
  } else {
92
  if(!empty($oldFile_toDelete)) {
94
  @unlink($currentFilePathInfo['dirname'].DIRECTORY_SEPARATOR.$oldFile_toDelete);
95
  }
96
  if(!@copy($result,$currentFilePath)) {
97
+ $_processing_error[$activeImageSize->name][] = __("Can't copy temporary file to media library.", 'crop-thumbnails');
98
  $_error = true;
99
  }
100
  if(!@unlink($result)) {
101
+ $_processing_error[$activeImageSize->name][] = __("Can't delete temporary file.", 'crop-thumbnails');
102
  $_error = true;
103
  }
104
  }
258
  global $cptSettings;
259
 
260
  if(!check_ajax_referer($cptSettings->getNonceBase(),'_ajax_nonce',false)) {
261
+ throw new Exception(__("ERROR: Security Check failed (maybe a timeout - please try again).",'crop-thumbnails'), 1);
262
  }
263
 
264
 
265
  if(empty($_REQUEST['crop_thumbnails'])) {
266
+ throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
267
  }
268
  $input = json_decode(stripcslashes($_REQUEST['crop_thumbnails']));
269
 
270
 
271
  if(empty($input->selection) || empty($input->sourceImageId) || !isset($input->activeImageSizes)) {
272
+ throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
273
  }
274
 
275
 
276
  if(!isset($input->selection->x) || !isset($input->selection->y) || !isset($input->selection->x2) || !isset($input->selection->y2)) {
277
+ throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
278
  }
279
 
280
 
284
  $input->selection->y2 = intval($input->selection->y2);
285
 
286
  if($input->selection->x < 0 || $input->selection->y < 0) {
287
+ throw new Exception(__('Cropping to these dimensions on this image is not possible.','crop-thumbnails'), 1);
288
  }
289
 
290
 
291
  $input->sourceImageId = intval($input->sourceImageId);
292
  $_tmp = get_post($input->sourceImageId);//need to be its own var - cause of old php versions
293
  if(empty($_tmp)) {
294
+ throw new Exception(__("ERROR: Can't find original image in database!",'crop-thumbnails'), 1);
295
  }
296
 
297
  return $input;
js/app/app.js CHANGED
@@ -129,6 +129,21 @@ $(window).resize(function () {
129
  });
130
  ***************************/
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  CROP_THUMBNAILS_VUE.components.loadingcontainer = {
133
  template: "<div class=\"loadingcontainer\" :class=\"status\"> <img :src=\"image\" style=\"display:none;\"/><slot></slot><transition name=\"fade\"><div class=\"loadingMsg\" v-if=\"status===\'loading\'\"><div class=\"cptLoadingSpinner\"></div></div></transition></div>",
134
  props:{
@@ -180,21 +195,6 @@ CROP_THUMBNAILS_VUE.components.loadingcontainer = {
180
  }
181
  };
182
 
183
- CROP_THUMBNAILS_VUE.components.message = {
184
- template: "<div class=\"notice notice-warning is-dismissible cptMessage\" aria-role=\"alert\" v-if=\"!closed\"><p><slot></slot></p> <button type=\"button\" class=\"notice-dismiss\" @click=\"close()\" aria-label=\"close\"></button></div>",
185
- props:{},
186
- data:function() {
187
- return {
188
- closed:false
189
- };
190
- },
191
- methods:{
192
- close : function() {
193
- this.closed = true;
194
- }
195
- }
196
- };
197
-
198
  CROP_THUMBNAILS_VUE.components.cropeditor = {
199
  template: "<div class=\"cptEditorInner\" v-if=\"cropData && lang\" :class=\"{loading:loading,cropEditorActive:croppingApi}\"><div class=\"cptWaitingWindow\" v-if=\"loading\"><div class=\"msg\"> {{ lang.waiting }}<div><div class=\"cptLoadingSpinner\"></div></div></div></div><div class=\"mainWindow\"><div class=\"cptSelectionPane\"><div class=\"cptSelectionPaneInner\"><message v-if=\"sourceImageHasOrientation\">{{lang.message_image_orientation}}</message><p> <label class=\"cptSameRatioLabel\"><input type=\"checkbox\" v-model=\"selectSameRatio\"/> {{lang.label_same_ratio}}</label> <button type=\"button\" class=\"button\" @click=\"makeAllInactive()\">{{lang.label_deselect_all}}</button></p><ul class=\"cptImageSizelist\"><li v-for=\"i in filteredImageSizes\" :class=\"{active : i.active}\" @click=\"toggleActive(i)\"><section class=\"cptImageSizeInner\"><header>{{i.nameLabel}}</header><div class=\"lowResWarning\" v-if=\"isLowRes(i)\" :title=\"lang.lowResWarning\"><span>!</span></div><div class=\"dimensions\">{{ lang.dimensions }} {{i.width}} x {{i.height}} {{ lang.pixel }}</div><div class=\"ratio\">{{ lang.ratio }} {{i.printRatio}}</div><loadingcontainer :image=\"i.url+\'?cacheBreak=\'+i.cacheBreak\"><div class=\"cptImageBgContainer\" :style=\"{\'background-image\': \'url(\'+i.url+\'?cacheBreak=\'+i.cacheBreak+\')\'}\"></div></loadingcontainer></section></li></ul></div></div><div class=\"cptCropPane\"><div class=\"info\"><h3>{{ lang.rawImage }}</h3><div class=\"dimensions\">{{ lang.dimensions }} {{cropData.sourceImage.full.width}} x {{cropData.sourceImage.full.height}} {{ lang.pixel }}</div><div class=\"ratio\">{{ lang.ratio }} {{cropData.sourceImage.full.printRatio}}</div></div> <button type=\"button\" class=\"button cptGenerate\" :class=\"{\'button-primary\':croppingApi}\" @click=\"cropThumbnails()\" :disabled=\"!croppingApi\">{{ lang.label_crop }}</button><div class=\"cropContainer\"> <img class=\"cptCroppingImage\" :src=\"cropImage.url\"/></div><h4>{{ lang.instructions_header }}</h4><ul class=\"step-info\"><li>{{ lang.instructions_step_1 }}</li><li>{{ lang.instructions_step_2 }}</li><li>{{ lang.instructions_step_3 }}</li></ul><div> <button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_js\" @click=\"showDebugClick(\'js\')\">show JS-Debug</button> <button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_data && dataDebug!==null\" @click=\"showDebugClick(\'data\')\">show Data-Debug</button><pre v-if=\"showDebugType===\'data\'\">{{ dataDebug }}</pre><pre v-if=\"showDebugType===\'js\'\"><br/>cropImage:{{cropImage}}<br/>cropData:{{ cropData }}</pre></div></div></div></div>",
200
  props:{
@@ -458,7 +458,7 @@ CROP_THUMBNAILS_VUE.components.cropeditor = {
458
  if(!that.loading && that.croppingApi!==null) {
459
  that.loading = true;
460
 
461
- var params = {
462
  action : 'cptSaveThumbnail',
463
  _ajax_nonce : that.nonce,
464
  cookie : encodeURIComponent(document.cookie),
@@ -469,7 +469,7 @@ CROP_THUMBNAILS_VUE.components.cropeditor = {
469
  })
470
  };
471
 
472
- var request = jQuery.post(ajaxurl,params,null,'json');
473
  request
474
  .done(function(responseData) {
475
  if(that.cropData.options.debug_data) {
@@ -494,7 +494,14 @@ CROP_THUMBNAILS_VUE.components.cropeditor = {
494
  }
495
  })
496
  .fail(function(response) {
497
- console.error(error);
 
 
 
 
 
 
 
498
  })
499
  .always(function() {
500
  that.loading = false;
129
  });
130
  ***************************/
131
 
132
+ CROP_THUMBNAILS_VUE.components.message = {
133
+ template: "<div class=\"notice notice-warning is-dismissible cptMessage\" aria-role=\"alert\" v-if=\"!closed\"><p><slot></slot></p> <button type=\"button\" class=\"notice-dismiss\" @click=\"close()\" aria-label=\"close\"></button></div>",
134
+ props:{},
135
+ data:function() {
136
+ return {
137
+ closed:false
138
+ };
139
+ },
140
+ methods:{
141
+ close : function() {
142
+ this.closed = true;
143
+ }
144
+ }
145
+ };
146
+
147
  CROP_THUMBNAILS_VUE.components.loadingcontainer = {
148
  template: "<div class=\"loadingcontainer\" :class=\"status\"> <img :src=\"image\" style=\"display:none;\"/><slot></slot><transition name=\"fade\"><div class=\"loadingMsg\" v-if=\"status===\'loading\'\"><div class=\"cptLoadingSpinner\"></div></div></transition></div>",
149
  props:{
195
  }
196
  };
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  CROP_THUMBNAILS_VUE.components.cropeditor = {
199
  template: "<div class=\"cptEditorInner\" v-if=\"cropData && lang\" :class=\"{loading:loading,cropEditorActive:croppingApi}\"><div class=\"cptWaitingWindow\" v-if=\"loading\"><div class=\"msg\"> {{ lang.waiting }}<div><div class=\"cptLoadingSpinner\"></div></div></div></div><div class=\"mainWindow\"><div class=\"cptSelectionPane\"><div class=\"cptSelectionPaneInner\"><message v-if=\"sourceImageHasOrientation\">{{lang.message_image_orientation}}</message><p> <label class=\"cptSameRatioLabel\"><input type=\"checkbox\" v-model=\"selectSameRatio\"/> {{lang.label_same_ratio}}</label> <button type=\"button\" class=\"button\" @click=\"makeAllInactive()\">{{lang.label_deselect_all}}</button></p><ul class=\"cptImageSizelist\"><li v-for=\"i in filteredImageSizes\" :class=\"{active : i.active}\" @click=\"toggleActive(i)\"><section class=\"cptImageSizeInner\"><header>{{i.nameLabel}}</header><div class=\"lowResWarning\" v-if=\"isLowRes(i)\" :title=\"lang.lowResWarning\"><span>!</span></div><div class=\"dimensions\">{{ lang.dimensions }} {{i.width}} x {{i.height}} {{ lang.pixel }}</div><div class=\"ratio\">{{ lang.ratio }} {{i.printRatio}}</div><loadingcontainer :image=\"i.url+\'?cacheBreak=\'+i.cacheBreak\"><div class=\"cptImageBgContainer\" :style=\"{\'background-image\': \'url(\'+i.url+\'?cacheBreak=\'+i.cacheBreak+\')\'}\"></div></loadingcontainer></section></li></ul></div></div><div class=\"cptCropPane\"><div class=\"info\"><h3>{{ lang.rawImage }}</h3><div class=\"dimensions\">{{ lang.dimensions }} {{cropData.sourceImage.full.width}} x {{cropData.sourceImage.full.height}} {{ lang.pixel }}</div><div class=\"ratio\">{{ lang.ratio }} {{cropData.sourceImage.full.printRatio}}</div></div> <button type=\"button\" class=\"button cptGenerate\" :class=\"{\'button-primary\':croppingApi}\" @click=\"cropThumbnails()\" :disabled=\"!croppingApi\">{{ lang.label_crop }}</button><div class=\"cropContainer\"> <img class=\"cptCroppingImage\" :src=\"cropImage.url\"/></div><h4>{{ lang.instructions_header }}</h4><ul class=\"step-info\"><li>{{ lang.instructions_step_1 }}</li><li>{{ lang.instructions_step_2 }}</li><li>{{ lang.instructions_step_3 }}</li></ul><div> <button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_js\" @click=\"showDebugClick(\'js\')\">show JS-Debug</button> <button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_data && dataDebug!==null\" @click=\"showDebugClick(\'data\')\">show Data-Debug</button><pre v-if=\"showDebugType===\'data\'\">{{ dataDebug }}</pre><pre v-if=\"showDebugType===\'js\'\"><br/>cropImage:{{cropImage}}<br/>cropData:{{ cropData }}</pre></div></div></div></div>",
200
  props:{
458
  if(!that.loading && that.croppingApi!==null) {
459
  that.loading = true;
460
 
461
+ var cptRequestParams = {
462
  action : 'cptSaveThumbnail',
463
  _ajax_nonce : that.nonce,
464
  cookie : encodeURIComponent(document.cookie),
469
  })
470
  };
471
 
472
+ var request = jQuery.post(ajaxurl,cptRequestParams,null,'json');
473
  request
474
  .done(function(responseData) {
475
  if(that.cropData.options.debug_data) {
494
  }
495
  })
496
  .fail(function(response) {
497
+ alert(that.lang.script_connection_error);
498
+ var debug = {
499
+ status: response.status,
500
+ statusText: response.statusText,
501
+ requestUrl: ajaxurl,
502
+ requestParams: cptRequestParams
503
+ };
504
+ console.error('crop-thumbnails connection error', debug);
505
  })
506
  .always(function() {
507
  that.loading = false;
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: post-thumbnails, images, media library
5
  Requires at least: 4.6
6
  Requires PHP: 5.3.0
7
  Tested up to: 4.9
8
- Stable tag: 1.0.2
9
  License: GPL v3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -124,6 +124,11 @@ If you fork and planning to publish the forked plugin, please contact me.
124
 
125
  == Changelog ==
126
 
 
 
 
 
 
127
  = 1.0.2 =
128
  * improve i18n
129
  * change language text domain from 'cpt_lang' to 'crop-thumbnails'
5
  Requires at least: 4.6
6
  Requires PHP: 5.3.0
7
  Tested up to: 4.9
8
+ Stable tag: 1.0.3
9
  License: GPL v3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
124
 
125
  == Changelog ==
126
 
127
+ = 1.0.3 =
128
+ * fix js error handling
129
+ * add warning to the backend if the script cant connect the server
130
+ * fix where escape of language-strings make no sense (exceptions in save.php)
131
+
132
  = 1.0.2 =
133
  * improve i18n
134
  * change language text domain from 'cpt_lang' to 'crop-thumbnails'