Crop-Thumbnails - Version 1.0.0

Version Description

  • modal dialog rewritten
  • crop functionality refactored
  • changed the crop-library for improved touch support
  • the action "crop_thumbnails_modal_window_settings" is gone, you can adjust style by override admin-css
  • the filter "crop_post_thumbnail_window_css" is gone, you can adjust style by override admin-css
  • adjusting dialog style - make it more responsive
  • reviewed dynamic sizes: sizes with 9999 will no longer have ratio of the original image
  • reviewed dynamic sizes: filenames will no longer be changed
  • fix image-metadata polution
  • refactoring and cleanup a lot of the code
  • change from a language constant to 'cpt_lang' (as recommended by developer guide)
  • secure translations
Download this release

Release Info

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

Code changes from version 0.10.15 to 1.0.0

LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
1
+ GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
crop-thumbnails.php CHANGED
@@ -4,9 +4,10 @@
4
  * Plugin URI: http://wordpress.org/extend/plugins/crop-thumbnails/
5
  * Author: Volkmar Kantor
6
  * Author URI: http://www.totalmedial.de
7
- * Version: 0.10.15
8
- * Description: Crop your thumbnails, the easy way.
9
- * Text Domain: crop-thumbnails
 
10
  *
11
  * License: GPL v3
12
  * Copyright 2012 Volkmar Kantor (email : info@totalmedial.de)
@@ -25,14 +26,13 @@
25
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
26
  */
27
 
28
- //cpt - stands for crop-post-thumbnail
29
- define('CROP_THUMBS_LANG','cpt_lang');
30
- define('CROP_THUMBS_VERSION','0.10.15');
31
 
32
- function cpt_plugin_init() {
33
- load_plugin_textdomain( CROP_THUMBS_LANG, false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
34
 
35
- __('Crop your thumbnails, the easy way.');//have to be the same as the plugins-description - for automatic integration into poedit
 
 
36
  }
37
  add_action('plugins_loaded', 'cpt_plugin_init');
38
 
@@ -49,4 +49,3 @@ include_once(dirname(__FILE__).'/functions/settings.php');
49
  include_once(dirname(__FILE__).'/functions/editor.php');
50
  include_once(dirname(__FILE__).'/functions/backendpreparer.php');
51
  include_once(dirname(__FILE__).'/functions/save.php');
52
- ?>
4
  * Plugin URI: http://wordpress.org/extend/plugins/crop-thumbnails/
5
  * Author: Volkmar Kantor
6
  * Author URI: http://www.totalmedial.de
7
+ * Text Domain: cpt_lang
8
+ * Version: 1.0.0
9
+ * Description: The easy way to adjust your cropped image sizes.
10
+ *
11
  *
12
  * License: GPL v3
13
  * Copyright 2012 Volkmar Kantor (email : info@totalmedial.de)
26
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
 
 
 
29
 
30
+ define('CROP_THUMBS_VERSION','1.0.0');
31
+
32
 
33
+ //cpt - stands for crop-post-thumbnail
34
+ function cpt_plugin_init() {
35
+ load_plugin_textdomain( 'cpt_lang', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
36
  }
37
  add_action('plugins_loaded', 'cpt_plugin_init');
38
 
49
  include_once(dirname(__FILE__).'/functions/editor.php');
50
  include_once(dirname(__FILE__).'/functions/backendpreparer.php');
51
  include_once(dirname(__FILE__).'/functions/save.php');
 
css/cpt-backend.css ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cropThumbnailSettings .cpt_settings_paypal { border:1px solid #298CBA; border-radius:3px; background-color:#f6f6f6; max-width:30em; padding:0 0.5em; margin:2em 0; text-align:center; }
2
+ .cropThumbnailSettings .cpt_settings_submit { margin-top:2em; }
3
+
4
+ .cropThumbnailSettings #cpt_quicktest { white-space:nowrap; background:#fff; border:1px solid #ddd; margin: 1em auto; padding:1em; }
5
+ .cropThumbnailSettings #cpt_quicktest strong {display: inline-block; color:#fff; padding:3px 8px; margin-bottom: 1px; }
6
+ .cropThumbnailSettings #cpt_quicktest strong.success { background:#00cc00; }
7
+ .cropThumbnailSettings #cpt_quicktest strong.fails { background:#cc0000; }
8
+
9
+
10
+ /**** button icon ****/
11
+ a.cropThumbnailsLink .wp-media-buttons-icon::before { content: "\f165"; font: normal 12px/1 dashicons; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
12
+
13
+ /**** featured image box ****/
14
+ #postimagediv.closed .cropFeaturedImageWrap { display: none; }
15
+ #postimagediv .cropFeaturedImageWrap { padding:0 12px; margin-top:0; }
16
+
17
+ /**** button in media dialog ****/
18
+ .media-modal .compat-field-cropthumbnails th { width: 0; min-width: 0; margin:0; }
19
+ .media-modal .compat-field-cropthumbnails td { width: auto; }
20
+
21
+
22
+
23
+
24
+
25
+ /**** MODAL ****/
26
+ /* @see https://www.w3schools.com/howto/howto_css_modals.asp */
27
+ body.cpt_ModalIsOpen { overflow: hidden; }
28
+ #cpt_Modal { display: block; position: fixed; z-index: 99999999; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; padding:0; box-sizing: border-box; background-color: rgba(0,0,0,0.4); }
29
+ #cpt_Modal .cpt_ModalDialog { position: relative; background-color: #fff; overflow: hidden; margin: auto; padding: 0px; width: 100%; max-width: 100%; height: 100%; margin-top:0; box-shadow: 0 0 20px rgba(0,0,0,0.5); }
30
+ #cpt_Modal .cpt_ModalHeader { height: 40px; }
31
+ #cpt_Modal .cpt_ModalHeader .cpt_ModalTitle { font-size:20px; font-weight: 300; line-height: 1; padding: 10px 50px 10px 20px; background: #eee; color:#000; }
32
+ #cpt_Modal .cpt_ModalContent { width:100%; height: 100%; padding-top:30px; margin-top:-30px; box-sizing: border-box; }
33
+
34
+ /* The Close Button */
35
+ #cpt_Modal .cpt_ModalClose { color: #000; border:none; background: transparent; position: absolute; right:0; top:0; font-size: 38px; font-weight: 300; padding:0px 8px 10px 8px; line-height: 30px; }
36
+ #cpt_Modal .cpt_ModalClose:hover,
37
+ #cpt_Modal .cpt_ModalClose:focus { opacity: .6; text-decoration: none; cursor: pointer; }
38
+
39
+ @media(min-width:900px) {
40
+ #cpt_Modal { padding:40px; }
41
+ }
42
+
43
+ /* crop-editor-layout */
44
+ #cpt_crop_editor .mainWindow { width: 100%; height: 100%; }
45
+ #cpt_crop_editor .cptCropPane,
46
+ #cpt_crop_editor .cptSelectionPane { box-sizing: border-box; }
47
+
48
+ #cpt_crop_editor .cptCropPane { padding:0 20px 20px; }
49
+
50
+ @media(min-width:760px) {
51
+ #cpt_crop_editor .cptCropPane { position: absolute; right: 0; top:0; width:350px; height: 100%; overflow-y: auto; overflow-x: hidden; border:0; border-left:3px solid #eee; margin-top:0; padding:10px 20px; }
52
+ #cpt_crop_editor .cptSelectionPane { position: relative; width:100%; height: 100%; overflow:hidden; padding-right: 350px; }
53
+ #cpt_crop_editor .cptSelectionPaneInner { width: 100%; overflow-y: auto; height: 100%; }
54
+ }
55
+ @media(min-width:1000px) {
56
+ #cpt_crop_editor .cptCropPane { width: 500px; }
57
+ #cpt_crop_editor .cptSelectionPane { padding-right: 500px; }
58
+ }
59
+
60
+
61
+
62
+
63
+ #cpt_crop_editor .header {background-color:#efefef; padding:5px; position: relative; z-index: 1000;}
64
+
65
+ #cpt_crop_editor .cptEditorInner { position: relative; overflow-y: auto; height: 100%; }
66
+ #cpt_crop_editor .cptEditorInner.loading { overflow-y: hidden; }
67
+
68
+ #cpt_crop_editor .listEmptyMsg { font-size:1.5em; text-align:center; padding:2em;}
69
+ #cpt_crop_editor .image-list .entry.post-thumbnail { border-color:#aad6f4; background-color:#efefef; }
70
+ #cpt_crop_editor .image-list { margin:0;padding:0;}
71
+ #cpt_crop_editor .image-list .entry { width:140px; float:left; border:1px solid #efefef; margin:5px;}
72
+ #cpt_crop_editor .image-list .entry h3 { font-weight: normal; font-size:1em; margin:0 5px; }
73
+ #cpt_crop_editor .image-list .entry img { width:130px; height:130px; margin:5px; }
74
+ #cpt_crop_editor .image-list .cursor, .image-list .cursor * { cursor:pointer;}
75
+
76
+
77
+
78
+ #cpt_crop_editor .cptImageSizelist { border-top: 3px solid #efefef; padding-top:5px; margin-top:5px; }
79
+ #cpt_crop_editor .cptImageSizelist::after { content: ""; clear: both; display: block; }
80
+ #cpt_crop_editor .cptImageSizelist li { width: 50%; cursor:pointer; position: relative; float: left; padding: 8px; margin: 0; color: #444; cursor: pointer; list-style: none; text-align: center; box-sizing: border-box; -webkit-box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 7px transparent; box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 7px transparent; transition:box-shadow .5s ease; }
81
+ #cpt_crop_editor .cptImageSizelist li.active { -webkit-box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 7px #0073aa; box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 7px #0073aa; }
82
+ #cpt_crop_editor .cptImageSizelist li:hover,
83
+ #cpt_crop_editor .cptImageSizelist li:focus {background: #eee; }
84
+ @media(min-width:520px) { #cpt_crop_editor .cptImageSizelist li { width: 33.32%; } }
85
+ @media(min-width:760px) { #cpt_crop_editor .cptImageSizelist li { width: 50%; } }
86
+ @media(min-width:1100px) { #cpt_crop_editor .cptImageSizelist li { width: 33.32%; } }
87
+ @media(min-width:1400px) { #cpt_crop_editor .cptImageSizelist li { width: 25%; } }
88
+ @media(min-width:1600px) { #cpt_crop_editor .cptImageSizelist li { width: 20%; } }
89
+
90
+
91
+ #cpt_crop_editor .cptImageSizeInner header,
92
+ #cpt_crop_editor .cptImageSizeInner .dimensions,
93
+ #cpt_crop_editor .cptImageSizeInner .ratio { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
94
+
95
+ #cpt_crop_editor .cptImageSizeInner { line-height: 1.4; };
96
+ #cpt_crop_editor .cptImageSizeInner header { font-size:1em; font-weight: bold; }
97
+ #cpt_crop_editor .cptImageSizeInner .dimensions { font-size:0.8em; }
98
+ #cpt_crop_editor .cptImageSizeInner .ratio { font-size:0.8em; }
99
+ #cpt_crop_editor .cptImageSizeInner .lowResWarning { color: #fff; position: absolute; bottom: 12px; left: 12px; background: #ea6c00; width: 30px; height: 30px; line-height: 28px; font-size: 23px; font-weight: 600; z-index: 1; border: 2px solid #fff; box-shadow: 0 0 10px rgba(0,0,0,0.3); }
100
+ #cpt_crop_editor .cptImageSizeInner .cptImageBgContainer { width: 100%; padding-top:100%; background-size: contain; background-position: center; background-repeat: no-repeat; box-shadow: 0 0 1px rgba(0,0,0,0.5); box-sizing: border-box; }
101
+
102
+
103
+ #cpt_crop_editor .loadingcontainer { position: relative; }
104
+ #cpt_crop_editor .loadingcontainer .loadingMsg { opacity: 0; position: absolute; width: 100%; height: 100%; top:0; left:0; background: #fff; transition: opacity .4s linear; }
105
+ #cpt_crop_editor .loadingcontainer .cptLoadingSpinner { position: absolute; top:50%; left:50%; margin-left: -15px; margin-top: -15px; }
106
+ #cpt_crop_editor .loadingcontainer.loading .loadingMsg { opacity: 1; }
107
+ #cpt_crop_editor .loadingcontainer.loading .cptImageBgContainer { background: none !important; }
108
+ #cpt_crop_editor .loadingcontainer .fade-enter-active,
109
+ #cpt_crop_editor .loadingcontainer .fade-leave-active { transition: opacity .5s }
110
+ #cpt_crop_editor .loadingcontainer .fade-enter,
111
+ #cpt_crop_editor .loadingcontainer .fade-leave-to { opacity: 0; }
112
+
113
+ #cpt_crop_editor .cptSameRatioLabel { display: inline-block; margin:.3em 1em 0.3em 0; }
114
+
115
+ #cpt_crop_editor .cptSelectionPane>div>p { padding-left:1em; padding-right: 1em; margin:.3em; }
116
+
117
+ #cpt_crop_editor .cptCropPane .info { text-align: center; }
118
+ #cpt_crop_editor .cptCropPane h3 { margin:0;}
119
+ #cpt_crop_editor .cptCropPane button.cptGenerate { width: 100%; height:2em; font-size:1.4em; padding:0.5em 0; display:block; line-height: 0;}
120
+
121
+ #cpt_crop_editor .cropContainer { margin:.3em 0 .5em; opacity: .5; }
122
+ #cpt_crop_editor .cptEditorInner.cropEditorActive .cropContainer { opacity: 1; }
123
+ #cpt_crop_editor .cropContainer img.cptCroppingImage { max-width: 100%; height:auto; }
124
+
125
+ #cpt_crop_editor h4 { margin-bottom:0em;}
126
+ #cpt_crop_editor .step-info { font-size:0.9em; }
127
+
128
+ #cpt_crop_editor .jcrop-handle.ord-ne { margin-top: -8px; margin-right: -8px;}
129
+ #cpt_crop_editor .jcrop-handle.ord-nw { margin-top: -8px; margin-left: -8px;}
130
+ #cpt_crop_editor .jcrop-handle.ord-se { margin-bottom: -8px; margin-right: -8px;}
131
+ #cpt_crop_editor .jcrop-handle.ord-sw { margin-bottom: -8px; margin-left: -8px;}
132
+
133
+ #cpt_crop_editor .jcrop-handle.ord-ne,
134
+ #cpt_crop_editor .jcrop-handle.ord-nw,
135
+ #cpt_crop_editor .jcrop-handle.ord-se,
136
+ #cpt_crop_editor .jcrop-handle.ord-sw { width: 16px; height: 16px; }
137
+
138
+
139
+ #cpt_crop_editor .cpt-debug {clear: left; padding-left:5px;}
140
+ #cpt_crop_editor .cpt-debug .cpt-debug-handle { border:1px solid #aaa; background-color:#f1f1f1; padding:0.3em 1em;}
141
+ #cpt_crop_editor .cpt-debug.closed .content { display:none; }
142
+ #cpt_crop_editor .cpt-debug .content { font-family: monospace;margin-top:0.5em; }
143
+
144
+
145
+ #cpt_crop_editor .cptWaitingWindow { position: absolute; top:0; left:0; width: 100%; height: 100%; z-index: 10; background: rgba(255, 255, 255, 0.9); transition:all .5s ease; }
146
+ #cpt_crop_editor .cptWaitingWindow .msg { position: absolute; top:50%; width: 100%; margin-top:-4em; font-size: 2em; font-weight:bold; text-align: center; line-height: 1.3; padding: 0; }
147
+ #cpt_crop_editor .cptWaitingWindow .cptLoadingSpinner { height: 50px; width: 50px; margin-top:20px; }
148
+
149
+ .cptLoadingSpinner { height: 30px; width: 30px; border: 2px solid #0073aa; border-right-color: transparent; border-radius: 50%; display: inline-block;
150
+ -webkit-animation-duration: 0.75s;
151
+ animation-duration: 0.75s;
152
+ -webkit-animation-iteration-count: infinite;
153
+ animation-iteration-count: infinite;
154
+ -webkit-animation-name: cptRotateForever;
155
+ animation-name: cptRotateForever;
156
+ -webkit-animation-timing-function: linear;
157
+ animation-timing-function: linear;
158
+ }
159
+
160
+ @-webkit-keyframes cptRotateForever {
161
+ 0% {
162
+ -webkit-transform: rotate(0deg);
163
+ -ms-transform: rotate(0deg);
164
+ transform: rotate(0deg);
165
+ }
166
+ 100% {
167
+ -webkit-transform: rotate(360deg);
168
+ -ms-transform: rotate(360deg);
169
+ transform: rotate(360deg);
170
+ }
171
+ }
172
+ @-moz-keyframes cptRotateForever {
173
+ 0% {
174
+ -webkit-transform: rotate(0deg);
175
+ -ms-transform: rotate(0deg);
176
+ transform: rotate(0deg);
177
+ }
178
+ 100% {
179
+ -webkit-transform: rotate(360deg);
180
+ -ms-transform: rotate(360deg);
181
+ transform: rotate(360deg);
182
+ }
183
+ }
184
+ @keyframes cptRotateForever {
185
+ 0% {
186
+ -webkit-transform: rotate(0deg);
187
+ -ms-transform: rotate(0deg);
188
+ transform: rotate(0deg);
189
+ }
190
+ 100% {
191
+ -webkit-transform: rotate(360deg);
192
+ -ms-transform: rotate(360deg);
193
+ transform: rotate(360deg);
194
+ }
195
+ }
functions/backendpreparer.php CHANGED
@@ -1,4 +1,8 @@
1
- <?php
 
 
 
 
2
  class CropPostThumbnailsBackendPreparer {
3
 
4
  private $allowedMime = array('image/jpeg','image/png');
@@ -22,8 +26,10 @@ class CropPostThumbnailsBackendPreparer {
22
  || $pagenow == 'page.php'
23
  || $pagenow == 'page-new.php'
24
  || $pagenow == 'upload.php') {
25
- wp_enqueue_style("wp-jquery-ui-dialog");
26
- wp_enqueue_style('crop-thumbnails-options-style',plugins_url('css/options.css',dirname(__FILE__)));
 
 
27
  }
28
  }
29
 
@@ -38,11 +44,39 @@ class CropPostThumbnailsBackendPreparer {
38
  || $pagenow == 'page-new.php'
39
  || $pagenow == 'upload.php') {
40
 
41
- wp_enqueue_script('jquery-ui-dialog');
 
 
42
  add_action('admin_footer',array($this,'addLinksToAdmin'));
43
  }
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * adds the links into post-types and the media-library
48
  */
@@ -51,22 +85,6 @@ class CropPostThumbnailsBackendPreparer {
51
  ?>
52
  <script type="text/javascript">
53
  jQuery(document).ready(function($) {
54
- /**
55
- * Provide a global accessable cache-break-function (only available on backend-pages where crop-thumbnail is active --> post-editor, mediathek)
56
- * Calling this function will add a timestamp on the provided Image-Element.
57
- * ATTENTION: using this will also delete all other parameters on the images src-attribute.
58
- * @param {dom-element / jquery-selection} elem
59
- */
60
- CROP_THUMBNAILS_DO_CACHE_BREAK = function(elem) {
61
- var images = $(elem);
62
- for(var i = 0; i<images.length; i++) {
63
- var img = $(images[i]);//select image
64
- var imageUrl = img.attr('src');
65
- var imageUrlArray = imageUrl.split("?");
66
-
67
- img.attr('src',imageUrlArray[0]+'?&cacheBreak='+(new Date()).getTime());
68
- }
69
- };
70
 
71
  /**
72
  * Global accessable id of the current post (will be null if no post-element is present)
@@ -88,8 +106,8 @@ jQuery(document).ready(function($) {
88
 
89
  var featuredImageLinkButton = '';
90
  featuredImageLinkButton+= '<p class="cropFeaturedImageWrap hidden">';
91
- featuredImageLinkButton+= '<a class="button cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'+ parseInt(wp.media.featuredImage.get()) +',"viewmode":"single","posttype":"<?php echo get_post_type(); ?>"}\' title="<?php esc_attr_e('Crop Featured Image',CROP_THUMBS_LANG) ?>">';
92
- featuredImageLinkButton+= '<span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Featured Image',CROP_THUMBS_LANG); ?>';
93
  featuredImageLinkButton+= '</a>';
94
  baseElem.find('.inside').after( $(featuredImageLinkButton) );
95
 
@@ -116,10 +134,6 @@ jQuery(document).ready(function($) {
116
  updateCropFeaturedImageButton(-1);
117
  });
118
 
119
- baseElem.on('click', '.handlediv',function() {
120
-
121
- });
122
-
123
  updateCropFeaturedImageButton( parseInt(wp.media.featuredImage.get()) );
124
  }
125
 
@@ -131,15 +145,6 @@ jQuery(document).ready(function($) {
131
  post_id_hidden = parseInt(post_id_hidden.val());
132
  CROP_THUMBNAILS_CURRENT_POST_ID = post_id_hidden;
133
 
134
- /**
135
- * add link on top of editor *
136
- */
137
- var buttonContent = '';
138
- buttonContent+= '<a class="button cropThumbnailsLink" href="#" data-cropthumbnail=\'{"post_id":'+ post_id_hidden +'}\' title="<?php esc_attr_e('Crop Thumbnails',CROP_THUMBS_LANG) ?>">';
139
- buttonContent+= '<span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Thumbnails',CROP_THUMBS_LANG); ?>';
140
- buttonContent+= '</a>';
141
- $('#wp-content-media-buttons').append(buttonContent);
142
-
143
  handleFeaturedImageBox();
144
 
145
  $('body').on('cropThumbnailModalClosed',function() {
@@ -158,8 +163,8 @@ jQuery(document).ready(function($) {
158
  last_span.append(' | ');
159
 
160
  var buttonContent = '';
161
- buttonContent+= '<a class="cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'+ post_id +',"viewmode":"single"}\' title="<?php esc_attr_e('Crop Featured Image',CROP_THUMBS_LANG) ?>">';
162
- buttonContent+= '<span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Featured Image',CROP_THUMBS_LANG); ?>';
163
  buttonContent+= '</a>';
164
 
165
 
@@ -171,131 +176,9 @@ jQuery(document).ready(function($) {
171
  CROP_THUMBNAILS_DO_CACHE_BREAK($('#the-list tr .media-icon img'));
172
  });
173
  }
174
-
175
- /**
176
- * Create Listener for click-events with element-class ".cropThumbnailsLink".
177
- * Open the modal box.
178
- */
179
- $(document).on('click', '.cropThumbnailsLink', function(e) {
180
- e.preventDefault();
181
-
182
- <?php
183
- /*****************************************************************************/
184
- /**
185
- * Theme-Developers can adjust the size of the modal-dialog via filter.
186
- */
187
- $modal_window_settings = array(
188
- 'limitToWidth' => 800, //thats the maximum width the modal can be. On small screens it will be smaller (see offsets), set to FALSE if you want no limit
189
- 'maxWidthOffset' => 50, //window-width minus "width_offset" equals modal-width
190
- 'maxHeightOffset' => 100, //window-width minus "height_offset" equals modal-height
191
- );
192
- $modal_window_settings = apply_filters('crop_thumbnails_modal_window_settings',$modal_window_settings);
193
-
194
- $jsLimitOutput = '';
195
- if($modal_window_settings['limitToWidth']!==false) {
196
- $value = abs(intval($modal_window_settings['limitToWidth']));
197
-
198
- $jsLimitOutput.= 'if(boxViewportWidth>'.$value.') { boxViewportWidth = '.$value.'; }';
199
- }
200
- /*****************************************************************************/
201
- ?>
202
-
203
- //modal-box dimensions (will not adjust on viewport change)
204
- var boxViewportHeight = $(window).height() - <?php echo abs(intval($modal_window_settings['maxHeightOffset'])); ?>;
205
- var boxViewportWidth = $(window).outerWidth() - <?php echo abs(intval($modal_window_settings['maxWidthOffset'])); ?>;
206
-
207
- <?php echo $jsLimitOutput; ?>
208
-
209
-
210
-
211
- //get the data from the link
212
- var data = $(this).data('cropthumbnail');
213
-
214
- //construct the thickbox-parameter
215
- var url = ajaxurl+'?action=croppostthumb_ajax';
216
- for(var v in data) {
217
- url+='&amp;'+v+'='+data[v];
218
- }
219
- if(CROP_THUMBNAILS_CURRENT_POST_ID!==null) {
220
- url+='&amp;parent_post_id='+CROP_THUMBNAILS_CURRENT_POST_ID;
221
- }
222
-
223
- var content = $('<div><iframe src="'+url+'"></iframe></div>');
224
- var overlay;
225
- var isModalClassInitialSet = $('body').hasClass('modal-open');
226
-
227
- var dialogOptions = {
228
- dialogClass : 'cropThumbnailModal',
229
- modal : true,
230
- title : $(this).attr('title'),
231
- resizable : false,
232
- draggable : false,
233
- autoOpen : false,
234
- closeOnEscape : true,
235
- height : boxViewportHeight,
236
- width : boxViewportWidth,
237
- close : function(event, ui ) {
238
- if(overlay!==undefined) {
239
- overlay.unbind('click');
240
- }
241
-
242
- //remove modal-open class (disable the scrollbars)
243
- if(!isModalClassInitialSet) {
244
- $('body').removeClass('modal-open');
245
- }
246
- $(this).dialog('destroy');
247
-
248
- /**
249
- * We will trigger that the modal of the crop thumbnail is closed.
250
- * So everyone that is up to, could build a cache-breaker on their images.
251
- * HOW-TO cache-break:
252
- * $('body').on('cropThumbnailModalClosed',function() {
253
- * CROP_THUMBNAILS_DO_CACHE_BREAK( $('.your-image-selector') );
254
- * });
255
- */
256
- $('body').trigger('cropThumbnailModalClosed');
257
- },
258
- open : function(event, ui) {
259
- overlay = $('.ui-widget-overlay.ui-front');
260
- overlay.addClass('cropThumbnailModalOverlay');
261
- overlay.click(function() {
262
- content.dialog('close');
263
- });
264
-
265
- //add body class (disable the scrollbars)
266
- $('body').addClass('modal-open');
267
- }
268
- };
269
-
270
- content.dialog(dialogOptions).dialog('open');
271
- });
272
  });
273
  </script>
274
  <?php
275
  }
276
-
277
- /**
278
- * Add an field to the attachment edit dialog
279
- * @see http://code.tutsplus.com/tutorials/creating-custom-fields-for-attachments-in-wordpress--net-13076
280
- * @see https://make.wordpress.org/core/2012/12/12/attachment-editing-now-with-full-post-edit-ui/
281
- * @param array $form_fields
282
- * @param object $post
283
- */
284
- public function add_button_to_attachment_edit_view( $form_fields, $post ) {
285
-
286
- if(in_array($post->post_mime_type,$this->allowedMime)) {
287
- $html = '';
288
- $html.= '<a class="button cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'.$post->ID.',"viewmode":"single"}\' title="'.esc_attr__('Crop Featured Image',CROP_THUMBS_LANG).'">';
289
- $html.= '<span class="wp-media-buttons-icon"></span> '.esc_html__('Crop Featured Image',CROP_THUMBS_LANG);
290
- $html.= '</a>';
291
-
292
- $form_fields['cropthumbnails'] = array(
293
- 'label' => '&nbsp;',
294
- 'input' => 'html',
295
- 'html' => $html
296
- );
297
- }
298
- return $form_fields;
299
- }
300
  }
301
  $cpt_postView = new CropPostThumbnailsBackendPreparer();
1
+ <?php
2
+
3
+ /**
4
+ * Adds the Crop-Thumbnail-Editor to the Backend.
5
+ */
6
  class CropPostThumbnailsBackendPreparer {
7
 
8
  private $allowedMime = array('image/jpeg','image/png');
26
  || $pagenow == 'page.php'
27
  || $pagenow == 'page-new.php'
28
  || $pagenow == 'upload.php') {
29
+
30
+ wp_enqueue_style('jcrop');
31
+ wp_enqueue_style('crop-thumbnails-options-style',plugins_url('css/cpt-backend.css',dirname(__FILE__)),array('jcrop'),CROP_THUMBS_VERSION);
32
+
33
  }
34
  }
35
 
44
  || $pagenow == 'page-new.php'
45
  || $pagenow == 'upload.php') {
46
 
47
+ wp_enqueue_script( 'jcrop' );
48
+ wp_enqueue_script( 'vue', plugins_url('js/app/vendor/vue.min.js',dirname(__FILE__)), array(), CROP_THUMBS_VERSION);
49
+ wp_enqueue_script( 'cpt_crop_editor', plugins_url('js/app/app.js',dirname(__FILE__)), array('jquery','vue','imagesloaded','json2','jcrop'), CROP_THUMBS_VERSION);
50
  add_action('admin_footer',array($this,'addLinksToAdmin'));
51
  }
52
  }
53
 
54
+
55
+ /**
56
+ * Add an field to the attachment edit dialog
57
+ * @see http://code.tutsplus.com/tutorials/creating-custom-fields-for-attachments-in-wordpress--net-13076
58
+ * @see https://make.wordpress.org/core/2012/12/12/attachment-editing-now-with-full-post-edit-ui/
59
+ * @param array $form_fields
60
+ * @param object $post
61
+ */
62
+ public function add_button_to_attachment_edit_view( $form_fields, $post ) {
63
+
64
+ if(in_array($post->post_mime_type,$this->allowedMime)) {
65
+ $html = '';
66
+ $html.= '<a class="button cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'.$post->ID.',"viewmode":"single"}\' title="'.esc_attr__('Crop Featured Image','cpt_lang').'">';
67
+ $html.= '<span class="wp-media-buttons-icon"></span> '.esc_html__('Crop Featured Image','cpt_lang');
68
+ $html.= '</a>';
69
+
70
+ $form_fields['cropthumbnails'] = array(
71
+ 'label' => '&nbsp;',
72
+ 'input' => 'html',
73
+ 'html' => $html
74
+ );
75
+ }
76
+ return $form_fields;
77
+ }
78
+
79
+
80
  /**
81
  * adds the links into post-types and the media-library
82
  */
85
  ?>
86
  <script type="text/javascript">
87
  jQuery(document).ready(function($) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  /**
90
  * Global accessable id of the current post (will be null if no post-element is present)
106
 
107
  var featuredImageLinkButton = '';
108
  featuredImageLinkButton+= '<p class="cropFeaturedImageWrap hidden">';
109
+ featuredImageLinkButton+= '<a class="button cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'+ parseInt(wp.media.featuredImage.get()) +',"viewmode":"single","posttype":"<?php echo get_post_type(); ?>"}\' title="<?php esc_attr_e('Crop Featured Image','cpt_lang') ?>">';
110
+ featuredImageLinkButton+= '<span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Featured Image','cpt_lang'); ?>';
111
  featuredImageLinkButton+= '</a>';
112
  baseElem.find('.inside').after( $(featuredImageLinkButton) );
113
 
134
  updateCropFeaturedImageButton(-1);
135
  });
136
 
 
 
 
 
137
  updateCropFeaturedImageButton( parseInt(wp.media.featuredImage.get()) );
138
  }
139
 
145
  post_id_hidden = parseInt(post_id_hidden.val());
146
  CROP_THUMBNAILS_CURRENT_POST_ID = post_id_hidden;
147
 
 
 
 
 
 
 
 
 
 
148
  handleFeaturedImageBox();
149
 
150
  $('body').on('cropThumbnailModalClosed',function() {
163
  last_span.append(' | ');
164
 
165
  var buttonContent = '';
166
+ buttonContent+= '<a class="cropThumbnailsLink" href="#" data-cropthumbnail=\'{"image_id":'+ post_id +',"viewmode":"single"}\' title="<?php esc_attr_e('Crop Featured Image','cpt_lang') ?>">';
167
+ buttonContent+= '<span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Featured Image','cpt_lang'); ?>';
168
  buttonContent+= '</a>';
169
 
170
 
176
  CROP_THUMBNAILS_DO_CACHE_BREAK($('#the-list tr .media-icon img'));
177
  });
178
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  });
180
  </script>
181
  <?php
182
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
  $cpt_postView = new CropPostThumbnailsBackendPreparer();
functions/editor.php CHANGED
@@ -3,340 +3,187 @@
3
  /**
4
  * Contains all code inside the croping-window
5
  */
 
 
 
6
  class CropPostThumbnailsEditor {
7
 
8
  private $debugOutput = '';
9
 
10
- private $allowedMime = array('image/jpeg','image/png');
11
-
12
  function __construct() {
13
- /* for the html inside the thickbox */
14
- add_action('wp_ajax_croppostthumb_ajax', array($this,'ajaxWindow'));
15
  }
16
-
17
-
18
- /**
19
- * this function is called for/from the thickbox - returns ordanary html
20
- */
21
- function ajaxWindow() {
22
- $this->cleanWPHead();
23
- $failure_msg = '';
24
- if(!$this->isUserPermitted()) {
25
- $failure_msg = __('You are not allowed to do this.',CROP_THUMBS_LANG);
26
- } else {
27
- switch(true) {
28
- case isset($_REQUEST['post_id'])://full programm
29
- $this->listImages();
30
- break;
31
- case isset($_REQUEST['image_id'])://only one image
32
- $this->byImageId();
33
- break;
34
- case isset($_REQUEST['image_by_post_id'])://only one image
35
- $id = get_post_thumbnail_id(intval($_REQUEST['image_by_post_id']));
36
- if(!empty($id)) {
37
- $_REQUEST['image_id'] = $id;
38
- $_REQUEST['parent_post_id'] = intval($_REQUEST['image_by_post_id']);
39
- $this->byImageId();
40
- } else {
41
- $failure_msg = '<div class="listEmptyMsg">'.__('No featured image set for this post until now.',CROP_THUMBS_LANG).'</div>';
42
- }
43
- break;
44
- default:
45
- $failure_msg = __('An error occurred!',CROP_THUMBS_LANG);
46
- break;
47
- }
48
- }
49
-
50
- if(!empty($failure_msg)) {
51
- $windowCssPath = apply_filters('crop_post_thumbnail_window_css', plugins_url('css/cpt-window.css',dirname(__FILE__)));
52
- wp_enqueue_style( 'cpt-window',$windowCssPath,array('wp-admin'),CROP_THUMBS_VERSION);
53
- $cptContent = $failure_msg;
54
- include_once( dirname(__FILE__).'/../html/template.php' );
55
  }
56
  die();//to prevent to send back a "0"
57
  }
58
-
59
- /**
60
- * Display a list of images that are attached to this post_id.
61
- * Hightlight the post-thumbnail (if it is attached to this post_id)
62
- */
63
- function listImages() {
64
  global $cptSettings;
 
 
 
65
  $options = $cptSettings->getOptions();
66
-
67
- $data = $this->loadPostIdData(intval($_REQUEST['post_id']));
68
-
69
- $parent_post_type = '';
70
- $_tmp_post = get_post(intval($_REQUEST['post_id']));
71
- if(!empty($_tmp_post)) {
72
- $parent_post_type = $_tmp_post->post_type;
73
- }
74
-
75
- $cptContent = '';
76
-
77
- if($this->shouldBeHiddenOnPostType($options,$parent_post_type)) {
78
- $cptContent = '<div class="postTypeDisabledMsg">'.__('Cropping is disabled for this post-type.',CROP_THUMBS_LANG).'</div>';
79
- } elseif($data==false) {
80
- $cptContent = '<div class="listEmptyMsg">'.__('No images attached to this post yet. Please upload some via the upload dialog.',CROP_THUMBS_LANG).'</div>';
81
- } else {
82
- //the dynamic javascript
83
- ob_start(); ?>
84
- <script>
85
- jQuery(document).ready(function($) {
86
- $('.image-list .entry').click(function() {
87
- var image_id = $(this).attr('rel');
88
- var parent_post_id = <?php echo intval($_REQUEST['post_id']); ?>;
89
- document.location.href = ajaxurl+"?action=croppostthumb_ajax&image_id="+image_id+"&parent_post_id="+parent_post_id;
90
- return;
91
- });
92
- });
93
- </script>
94
- <?php
95
- $cptScript = ob_get_clean();
96
- //END the javascript
97
-
98
-
99
- //the content
100
- ob_start();?>
101
- <div class="header"><strong><?php _e('Choose the image you want to crop.',CROP_THUMBS_LANG); ?></strong></div>
102
- <ul class="image-list">
103
- <?php
104
- $counter = 1;
105
- foreach($data as $key=>$image) : ?>
106
- <li class="entry cursor<?php echo (isset($image->is_post_thumbnail) ? ' post-thumbnail' : ''); ?>" rel="<?php echo $image->ID;?>">
107
- <h3><?php echo (isset($image->is_post_thumbnail) ? __('Post Thumbnail',CROP_THUMBS_LANG) : sprintf(__('Image %d',CROP_THUMBS_LANG),$counter));?></h3>
108
- <?php $img_data = wp_get_attachment_image_src($image->ID, 'thumbnail');?>
109
- <img src="<?php echo $img_data[0].'?'.time(); ?>" />
110
- </li>
111
- <?php
112
- $counter++;
113
- endforeach; ?>
114
- </ul>
115
- <?php
116
- $cptContent = ob_get_clean();
117
- //END the content
118
  }
119
- wp_enqueue_script( 'jquery' );
120
-
121
- $windowCssPath = apply_filters('crop_post_thumbnail_window_css', plugins_url('css/cpt-window.css',dirname(__FILE__)));
122
- wp_enqueue_style( 'cpt-window',$windowCssPath,array('wp-admin'),CROP_THUMBS_VERSION);
123
- include_once( dirname(__FILE__).'/../html/template.php' );
124
- return true;
125
- }
126
-
127
-
128
- /**
129
- * Display the crop editor.
130
- * @param $_REQUEST['image_id'] - ID of the image to show
131
- * @param $_REQUEST['viewmode']=='single' - without the back-link
132
- * @param $_REQUEST['posttype']=='page' - (optional) will be used to hide certain image sizes (default: '')
133
- */
134
- function byImageId() {
135
- global $cptSettings,$content_width;
136
 
137
- //make sure $content_width is out of the way
138
- $_remember_content_width = $content_width;
139
- $content_width = null;
140
-
141
-
142
- $options = $cptSettings->getOptions();
143
- $this->addDebug('options', print_r($options,true));
144
- $image_obj = get_post(intval($_REQUEST['image_id']));
145
-
146
- //$post_id_attached holds the id of the post the image is attached to - can be null/empty
147
- $post_id_attached = -1;
148
- if(!empty($image_obj->post_parent)) {
149
- $post_id_attached=$image_obj->post_parent;
150
  }
 
151
 
152
- //$current_parent_post_type
153
- $current_parent_post_type = '';
154
- $current_parent_post_id = -1;
155
-
156
- if(!empty($_REQUEST['parent_post_id'])) {
157
- $_tmp = get_post(intval($_REQUEST['parent_post_id']));
158
- if(!empty($_tmp)) {
159
- $current_parent_post_type = $_tmp->post_type;
160
- $current_parent_post_id = $_tmp->ID;
161
- }
162
  }
163
 
164
- if(!empty($_REQUEST['posttype']) && post_type_exists($_REQUEST['posttype'])) {
165
- $current_parent_post_type = $_REQUEST['posttype'];
 
 
 
 
 
 
166
  }
167
-
168
- $all_image_sizes = $cptSettings->getImageSizes();
169
- $this->addDebug('all_image_sizes', print_r($all_image_sizes,true));
170
-
171
- $orig_img = wp_get_attachment_image_src($image_obj->ID, 'full');
172
- $orig_img['gcd'] = $this->gcd($orig_img[1],$orig_img[2]);
173
- $orig_img['ratio'] = ($orig_img[1]/$orig_img['gcd']) / ($orig_img[2]/$orig_img['gcd']);
174
- $orig_img['print_ratio'] = ($orig_img[1]/$orig_img['gcd']).':'.($orig_img[2]/$orig_img['gcd']);
175
-
176
- $cache_breaker = time();//a additional parameter that will be added to the image-urls to prevent the browser to show a cached image
177
-
178
- $this->addDebug('img-postmeta',print_r(wp_get_attachment_metadata($image_obj->ID, true),true));
179
-
180
- //the javascript
181
- ob_start(); ?>
182
- <script>
183
- jQuery(document).ready(function($) {
184
- cpt_lang = new Object();
185
- cpt_lang['bug'] = "<?php _e('Bug--this should not have occurred.',CROP_THUMBS_LANG);?>";
186
- cpt_lang['warningOriginalToSmall'] = "<?php _e('Warning: the original image is too small to be cropped in good quality with this thumbnail size.',CROP_THUMBS_LANG);?>";
187
- cpt_lang['selectOne'] = "<?php _e('First, select an image. Then, click once again.',CROP_THUMBS_LANG);?>";
188
- cpt_ajax_nonce = "<?php echo wp_create_nonce($cptSettings->getNonceBase()); ?>";
189
- cpt_debug_js = <?php echo (!empty($options['debug_js'])) ? 'true;' : 'false;'; ?>
190
- });
191
- </script>
192
- <?php
193
- $cptScript = ob_get_clean();
194
- //END the javascript
195
-
196
- /**
197
- * wether or not to show the "back button"
198
- */
199
- $headline = true;
200
- if(!empty($_REQUEST['viewmode']) && $_REQUEST['viewmode']=='single') {
201
- $headline = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
-
204
- //the content
205
- ob_start();
206
-
207
- if($this->shouldBeHiddenOnPostType($options,$current_parent_post_type)) : ?>
208
- <div class="cpt-crop-view">
209
- <div class="postTypeDisabledMsg"><?php _e('Cropping is disabled for this post-type.',CROP_THUMBS_LANG); ?></div>
210
- </div>
211
- <?php else : ?>
212
-
213
- <div class="cpt-crop-view">
214
- <?php if($headline) :?><div class="header"><a class="back" href="<?php echo admin_url( 'admin-ajax.php'); ?>?action=croppostthumb_ajax&post_id=<?php echo $current_parent_post_id; ?>"><?php _e('back to image list',CROP_THUMBS_LANG); ?></a></div><?php endif; ?>
215
- <div class="waitingWindow hidden"><?php _e('Please wait until the images are cropped.',CROP_THUMBS_LANG); ?></div>
216
- <div class="mainWindow">
217
- <div class="selectionArea cptLeftPane">
218
- <h3><?php _e('Raw',CROP_THUMBS_LANG); ?>: <?php echo $orig_img[1].' '.__('pixel',CROP_THUMBS_LANG)?> x <?php echo $orig_img[2].' '.__('pixel',CROP_THUMBS_LANG) ?> (<?php echo $orig_img['print_ratio']; ?>)</h3>
219
- <img src="<?php echo $orig_img[0]?>" data-values='{"id":<?php echo $image_obj->ID; ?>,"parentId":<?php echo $post_id_attached ?>,"width":<?php echo $orig_img[1]?>,"height":<?php echo $orig_img[2] ?>}' />
220
- <button id="cpt-generate" class="button"><?php _e('Save Crop',CROP_THUMBS_LANG);?></button>
221
- <h4><?php _e('Quick Instructions',CROP_THUMBS_LANG);?></h4>
222
- <ul class="step-info">
223
- <li><?php _e('Step 1: Choose an image from the right.',CROP_THUMBS_LANG); ?></li>
224
- <li><?php _e('Step 2: Use your mouse to change the size of the rectangle on the image above.',CROP_THUMBS_LANG); ?></li>
225
- <li><?php _e('Step 3: Click on "Save Crop".',CROP_THUMBS_LANG); ?></li>
226
- </ul>
227
- </div>
228
- <div class="cptRightPane">
229
- <input type="checkbox" name="cpt-same-ratio" value="1" id="cpt-same-ratio" checked="checked" />
230
- <label for="cpt-same-ratio" class="lbl-cpt-same-ratio"><?php _e('Crop all images with same ratio at once',CROP_THUMBS_LANG); ?></label>
231
- <button id="cpt-deselect" class="button"><?php _e('deselect all',CROP_THUMBS_LANG); ?></button>
232
- <ul class="thumbnail-list">
233
- <?php
234
- foreach($all_image_sizes as $img_size_name=>$value) :
235
-
236
- if ($value['height'] == 9999) {
237
- $value['height'] = 0;
238
- }
239
- if ($value['width'] == 9999) {
240
- $value['width'] = 0;
241
- }
242
-
243
- if(!$this->shouldSizeBeHidden($options,$img_size_name,$value,$current_parent_post_type)) :
244
- $ratio = null; //reset
245
- $gcd = null; //reset
246
- $print_ratio = null; //reset
247
- $print_cropped = ''; //reset
248
- $crop = 0; //reset
249
- $special_warning = ''; //reset
250
-
251
-
252
- /** define ratio **/
253
- if($value['width'] != 0 && $value['height']!=0) {
254
- $gcd = $this->gcd($value['width'],$value['height']);//get greatest common divisor
255
- $ratio = ($value['width']/$gcd) / ($value['height']/$gcd);//get ratio
256
- $print_ratio = $value['width']/$gcd.':'.$value['height']/$gcd;
257
- } else {
258
- //keep ratio same as original image
259
- $gcd = $orig_img['gcd'];
260
- $ratio = $orig_img['ratio'];
261
- $print_ratio = $orig_img['print_ratio'];
262
- }
263
-
264
-
265
- if(!empty($value['crop'])) {
266
- //cropped
267
- $print_cropped = ' ('.__('cropped',CROP_THUMBS_LANG).')';
268
- $crop = 1;
269
- } else {
270
- //not cropped
271
- /* -- maybe use this behaviour in a later version --
272
- $print_cropped = ' ('.__('maximum',CROP_THUMBS_LANG).')';
273
- $print_ratio = __('free choice',CROP_THUMBS_LANG);
274
- */
275
-
276
- $print_cropped = ' ('.__('maximum',CROP_THUMBS_LANG).')';
277
- $crop = 1;
278
- //keep ratio same as original image
279
- $gcd = $orig_img['gcd'];
280
- $ratio = $orig_img['ratio'];
281
- $print_ratio = $orig_img['print_ratio'];
282
- }
283
-
284
- $print_dimensions = $value['width'].' '.__('pixel',CROP_THUMBS_LANG).' x '.$value['height'].' '.__('pixel',CROP_THUMBS_LANG).$print_cropped;
285
-
286
- $img_data = wp_get_attachment_image_src($image_obj->ID, $img_size_name);
287
-
288
-
289
- $_lowResWarning = '';
290
- if($this->isLowRes($value,$orig_img)) {
291
- $_lowResWarning = ' <span class="lowResWarning">'.__('Original image size too small for good crop quality!',CROP_THUMBS_LANG).'</span>';
292
- }
293
-
294
- $jsonDataValues = array(
295
- 'name' => $img_size_name,
296
- 'width' => $value['width'],
297
- 'height' => $value['height'],
298
- 'ratio' => $ratio,
299
- 'crop' => $crop
300
- );
301
- $jsonDataValues = apply_filters('crop_thumbnails_editor_jsonDataValues', $jsonDataValues);
302
- $print_ratio = apply_filters('crop_thumbnails_editor_printratio', $print_ratio, $img_size_name);
303
-
304
- ?>
305
- <li rel="<?php echo $print_ratio; ?>">
306
- <strong title="<?php esc_attr_e($img_size_name) ?>"><?php echo $value['name'] ?><?php echo $_lowResWarning; ?></strong><?php echo $special_warning; ?>
307
- <span class="dimensions"><?php _e('Dimensions:',CROP_THUMBS_LANG) ?> <?php echo $print_dimensions; ?></span>
308
- <span class="ratio"><?php _e('Ratio:',CROP_THUMBS_LANG) ?> <?php echo $print_ratio; ?></span>
309
- <img src="<?php echo $img_data[0]?>?<?php echo $cache_breaker ?>" data-values="<?php esc_attr_e(json_encode($jsonDataValues)); ?>" />
310
- </li>
311
- <?php endif; ?>
312
- <?php endforeach; ?>
313
- </ul>
314
- </div>
315
- </div>
316
- </div>
317
- <?php
318
- endif;
319
- $cptContent = ob_get_clean();
320
- $cptContent.= $this->getDebugOutput($options);
321
- //END the content
322
-
323
-
324
- wp_enqueue_script( 'jquery' );
325
- wp_enqueue_script( 'my_jcrop', plugins_url('js/jcrop/js/jquery.Jcrop.min.js',dirname(__FILE__)), array(), CROP_THUMBS_VERSION);
326
- wp_enqueue_script( 'json2' );
327
- wp_enqueue_script( 'cpt-crop', plugins_url('js/cpt-crop.js',dirname(__FILE__)), array('jquery','my_jcrop','json2'), CROP_THUMBS_VERSION);
328
-
329
- $windowCssPath = apply_filters('crop_post_thumbnail_window_css', plugins_url('css/cpt-window.css',dirname(__FILE__)));
330
- wp_enqueue_style( 'cpt-window',$windowCssPath,array('wp-admin'),CROP_THUMBS_VERSION);
331
- wp_enqueue_style( 'my_jcrop', plugins_url('js/jcrop/css/jquery.Jcrop.min.css',dirname(__FILE__)), array(), CROP_THUMBS_VERSION);
332
-
333
- include_once( dirname(__FILE__).'/../html/template.php' );
334
-
335
- $content_width = $_remember_content_width;//reset the content-width
336
- return true;
337
  }
338
 
339
- function shouldBeHiddenOnPostType($options,$post_type) {
340
  if(empty($post_type)) {
341
  return false;
342
  }
@@ -349,17 +196,17 @@ jQuery(document).ready(function($) {
349
  /**
350
  * Check wether or not the image_size should be hidden for this post_type
351
  * @param array options array
352
- * @param string name of the image-size (i.e. post-thumbnail, ...)
353
  * @param string name post-type (i.e. post, page, ...)
354
  * @return boolean true if Image-size should be hidden
355
  */
356
- function shouldSizeBeHidden($options, $img_size_name, $img_size, $post_type='') {
357
  $_return = false;
358
  if(!empty($post_type)) {
359
  //we are NOT in the mediathek
360
 
361
  //-if hide_size
362
- if(!empty($options['hide_size'][$post_type][$img_size_name])) {
363
  $_return = true;
364
  }
365
 
@@ -379,48 +226,7 @@ jQuery(document).ready(function($) {
379
  }
380
 
381
 
382
- /**
383
- * load all image data of that $post_id
384
- * - adds "is_post_thumbnail" with value true into the entry, if it is the post_thumbnail
385
- */
386
- function loadPostIdData($post_id) {
387
- $args = array(
388
- 'post_type' => 'attachment',
389
- 'numberposts' => -1,
390
- 'post_parent' => intval($post_id)
391
- );
392
- $images = get_posts($args);
393
-
394
- $post_thumbnail_id = get_post_thumbnail_id( $post_id );
395
- if(!isset($post_thumbnail_id)) {
396
- $post_thumbnail_id = -1;
397
- }
398
-
399
- foreach($images as $key=>$value) {
400
- $mime = $value->post_mime_type;
401
- if( !in_array($mime,$this->allowedMime) ) {
402
- unset($images[$key]);
403
- } elseif($value->ID==$post_thumbnail_id) {
404
- $images[$key]->is_post_thumbnail = true;
405
- }
406
- }
407
- return $images;
408
- }
409
-
410
- /**
411
- * Checks if the thumb-image-dimensions are bigger than the actuall image.
412
- * @param array thumbnail-data from the add_image_size-funtion (width, height)
413
- * @param array original image-data-array (url, width, height)
414
- * @return true if the original is smaller than the thumbnail-size
415
- */
416
- function isLowRes($thumb,$orig) {
417
- if($thumb['width']>$orig[1] || $thumb['height']>$orig[2]) {
418
- return true;
419
- }
420
- return false;
421
- }
422
-
423
- function isUserPermitted() {
424
  $return = false;
425
  if(current_user_can('upload_files')) {
426
  $return = true;
@@ -430,52 +236,23 @@ jQuery(document).ready(function($) {
430
  }
431
 
432
 
433
- /**
434
- * This is for use inside the plugin only.
435
- * Removes all other styles and scripts, to make sure the crop-thumbnail is not compromited by other plugins
436
- */
437
- function cleanWPHead() {
438
- global $wp_scripts, $wp_styles;
439
- $wp_scripts = new WP_Scripts();
440
- $wp_styles = new WP_Styles();
441
- remove_all_actions('wp_print_styles');
442
- remove_all_actions('wp_print_scripts');
443
- }
444
-
445
  /**
446
  * Greatest cummon divisor
447
  */
448
- function gcd($a, $b) {
449
  if(function_exists('gmp_gcd')) {
450
  $gcd = gmp_strval(gmp_gcd($a,$b));
451
- $this->addDebug("gcd-version", "gmp_gcd:".$gcd);
452
  return ($gcd);
453
  } else {
454
- $gcd = $this->my_gcd($a,$b);
455
- $this->addDebug("gcd-version", "my_gcd:".$gcd);
456
  return $gcd;
457
  }
458
  }
459
 
460
- function my_gcd($a, $b) {
461
  $b = ( $a == 0 )? 0 : $b;
462
- return ( $a % $b )? $this->my_gcd($b, abs($a - $b)) : $b;
463
- }
464
-
465
-
466
- function addDebug($title, $output) {
467
- $this->debugOutput.= '---'.$title.'---<br />'.$output.'<br />';
468
- }
469
-
470
-
471
- function getDebugOutput($options) {
472
- if(!empty($options['debug_data'])) {
473
- return '<div class="cpt-debug closed"><a class="cpt-debug-handle" href="#">show debug</a><div class="content">'.nl2br(str_replace(" ","&nbsp;&nbsp;",$this->debugOutput)).'</div></div>';
474
- }
475
- return '';
476
  }
477
  }
478
 
479
-
480
-
481
  $cpte = new CropPostThumbnailsEditor();
3
  /**
4
  * Contains all code inside the croping-window
5
  */
6
+
7
+ class CPT_ForbiddenException extends Exception {}
8
+
9
  class CropPostThumbnailsEditor {
10
 
11
  private $debugOutput = '';
12
 
 
 
13
  function __construct() {
14
+ add_action('wp_ajax_cpt_cropdata', array($this, 'provideCropData') );
 
15
  }
16
+
17
+ public function provideCropData() {
18
+ try {
19
+ header('Content-Type: application/json; charset=UTF-8');
20
+ $result = $this->getCropData();
21
+ echo json_encode($result);
22
+ } catch(InvalidArgumentException $e) {
23
+ http_response_code(400);
24
+ echo 'FAILURE while processing request: '.$e->getMessage();
25
+ } catch(CPT_ForbiddenException $e) {
26
+ http_response_code(403);
27
+ echo 'ERROR not allowed.';
28
+ } catch(Exception $e) {
29
+ http_response_code(400);
30
+ echo 'FAILURE while processing request.';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
  die();//to prevent to send back a "0"
33
  }
34
+
35
+ public function getCropData() {
36
+ if(!self::isUserPermitted()) {
37
+ throw new CPT_ForbiddenException();
38
+ }
39
+
40
  global $cptSettings;
41
+ global $content_width;//include nasty content_width
42
+ $content_width = 9999;//override the idioty
43
+
44
  $options = $cptSettings->getOptions();
45
+ $result = array(
46
+ 'options' => $options,
47
+ 'sourceImageId' => null,
48
+ 'sourceImage' => array(
49
+ 'full' => null,
50
+ 'large' => null,
51
+ 'medium_large' => null,
52
+ ),
53
+ 'sourceImageMeta' => null,
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.','cpt_lang'),
58
+ 'cropDisabled' => esc_html__('Cropping is disabled for this post-type.','cpt_lang'),
59
+ 'waiting' => esc_html__('Please wait until the images are cropped.','cpt_lang'),
60
+ 'rawImage' => esc_html__('Raw','cpt_lang'),
61
+ 'pixel' => esc_html__('pixel','cpt_lang'),
62
+ 'instructions_header' => esc_html__('Quick Instructions','cpt_lang'),
63
+ 'instructions_step_1' => esc_html__('Step 1: Choose an image-size from the list.','cpt_lang'),
64
+ 'instructions_step_2' => esc_html__('Step 2: Change the selection of the image above.','cpt_lang'),
65
+ 'instructions_step_3' => str_replace('&quot;','"', esc_html__('Step 3: Click on "Save Crop".','cpt_lang')),
66
+ 'label_crop' => esc_html__('Save Crop','cpt_lang'),
67
+ 'label_same_ratio' => esc_html__('Crop all images with same ratio at once','cpt_lang'),
68
+ 'label_deselect_all' => esc_html__('deselect all','cpt_lang'),
69
+ 'dimensions' => esc_html__('Dimensions:','cpt_lang'),
70
+ 'ratio' => esc_html__('Ratio:','cpt_lang'),
71
+ 'cropped' => esc_html__('cropped','cpt_lang'),
72
+ 'lowResWarning' => esc_html__('Original image size too small for good crop quality!','cpt_lang'),
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.','cpt_lang')
74
+ ),
75
+ 'nonce' => wp_create_nonce($cptSettings->getNonceBase())
76
+ );
77
+
78
+ //simple validation
79
+ if(empty($_REQUEST['imageId'])) {
80
+ throw new InvalidArgumentException('Missing Parameter "imageId".');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ $imagePostObj = get_post(intval($_REQUEST['imageId']));
84
+ if(empty($imagePostObj) || $imagePostObj->post_type!=='attachment') {
85
+ throw new InvalidArgumentException('Image with ID:'.intval($_REQUEST['imageId']).' could not be found');
 
 
 
 
 
 
 
 
 
 
86
  }
87
+ $result['sourceImageId'] = $imagePostObj->ID;
88
 
89
+ if(!empty($_REQUEST['posttype']) && post_type_exists($_REQUEST['posttype'])) {
90
+ $result['postTypeFilter'] = $_REQUEST['posttype'];
 
 
 
 
 
 
 
 
91
  }
92
 
93
+ $result['sourceImage']['full'] = $this->getUncroppedImageData($imagePostObj->ID, 'full');
94
+ $result['sourceImage']['large'] = $this->getUncroppedImageData($imagePostObj->ID, 'large');
95
+ $result['sourceImage']['medium_large'] = $this->getUncroppedImageData($imagePostObj->ID, 'medium_large');
96
+
97
+ //image meta data
98
+ $meta_raw = wp_get_attachment_metadata($imagePostObj->ID);
99
+ if(!empty($meta_raw['image_meta'])) {
100
+ $result['sourceImageMeta'] = $meta_raw['image_meta'];
101
  }
102
+
103
+ $result['hiddenOnPostType'] = self::shouldBeHiddenOnPostType($options,$current_parent_post_type);
104
+
105
+ if(!$result['hiddenOnPostType']) {
106
+
107
+ foreach($result['imageSizes'] as $key => $imageSize) {
108
+
109
+ if(empty($imageSize['crop']) || $imageSize['width']<0 || $imageSize['height']<0) {
110
+ //we do not need uncropped image sizes
111
+ unset($result['imageSizes'][$key]);
112
+ continue;//to the next entry
113
+ }
114
+
115
+ //DEFINE RATIO AND GCD
116
+ if($imageSize['width'] ===0 || $imageSize['height']===0) {
117
+ $ratioData = $this->calculateRatioData($result['sourceImage']['full']['width'],$result['sourceImage']['full']['height']);
118
+ } else {
119
+ //DEFAULT RATIO - defined by the defined image-size
120
+ $ratioData = $this->calculateRatioData($imageSize['width'],$imageSize['height']);
121
+ }
122
+
123
+
124
+
125
+
126
+ //DYNAMIC RATIO
127
+ //the dynamic ratio is defined by the original image size and fix width OR height
128
+ //@eee https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
129
+ if($imageSize['width'] === 9999) {
130
+ //if you define width with 9999 - it crops for the exact defined height but the full width
131
+ $ratioData = $this->calculateRatioData($result['sourceImage']['full']['width'], $imageSize['height']);
132
+ } elseif($imageSize['height'] === 9999) {
133
+ //if you define height with 9999 - it crops for the exect defined width but the full height
134
+ $ratioData = $this->calculateRatioData($imageSize['width'], $result['sourceImage']['full']['height']);
135
+ }
136
+
137
+
138
+ $img_data = wp_get_attachment_image_src($imagePostObj->ID, $imageSize['name']);
139
+ $jsonDataValues = array(
140
+ 'name' => $imageSize['name'],
141
+ 'nameLabel' => $imageSize['name'],//if you want to change the label of this image-size
142
+ 'url' => $img_data[0],
143
+ 'width' => $imageSize['width'],
144
+ 'height' => $imageSize['height'],
145
+ 'gcd' => $ratioData['gcd'],
146
+ 'ratio' => $ratioData['ratio'],
147
+ 'printRatio' => apply_filters('crop_thumbnails_editor_printratio', $ratioData['printRatio'], $imageSize['name']),
148
+ 'hideByPostType' => self::shouldSizeBeHidden($options,$imageSize,$result['postTypeFilter']),
149
+ 'crop' => true//legacy
150
+ );
151
+
152
+ $result['imageSizes'][$key] = apply_filters('crop_thumbnails_editor_jsonDataValues', $jsonDataValues);
153
+
154
+ }//END froeach
155
  }
156
+
157
+ if(is_array($result['imageSizes'])) $result['imageSizes'] = array_values($result['imageSizes']);
158
+ return $result;
159
+ }
160
+
161
+ private function getUncroppedImageData($ID, $imageSize = 'full') {
162
+ $orig_img = wp_get_attachment_image_src($ID, $imageSize);
163
+ $orig_ima_gcd = $this->gcd($orig_img[1], $orig_img[2]);
164
+ $result = array(
165
+ 'url' => $orig_img[0],
166
+ 'width' => $orig_img[1],
167
+ 'height' => $orig_img[2],
168
+ 'gcd' => $orig_ima_gcd,
169
+ 'ratio' => ($orig_img[1]/$orig_ima_gcd) / ($orig_img[2]/$orig_ima_gcd),
170
+ 'printRatio' => ($orig_img[1]/$orig_ima_gcd).':'.($orig_img[2]/$orig_ima_gcd),
171
+ 'image_size' => $imageSize
172
+ );
173
+ return $result;
174
+ }
175
+
176
+ private function calculateRatioData($width,$height) {
177
+ $gcd = $this->gcd($width,$height);
178
+ $result = array(
179
+ 'gcd' => $gcd,
180
+ 'ratio' => ($width/$gcd) / ($height/$gcd),
181
+ 'printRatio' => $width/$gcd.':'.$height/$gcd
182
+ );
183
+ return $result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
 
186
+ private static function shouldBeHiddenOnPostType($options,$post_type) {
187
  if(empty($post_type)) {
188
  return false;
189
  }
196
  /**
197
  * Check wether or not the image_size should be hidden for this post_type
198
  * @param array options array
199
+ * @param array the image-size (i.e. post-thumbnail, ...)
200
  * @param string name post-type (i.e. post, page, ...)
201
  * @return boolean true if Image-size should be hidden
202
  */
203
+ private static function shouldSizeBeHidden($options, $img_size, $post_type='') {
204
  $_return = false;
205
  if(!empty($post_type)) {
206
  //we are NOT in the mediathek
207
 
208
  //-if hide_size
209
+ if(!empty($options['hide_size'][$post_type][ $img_size['name'] ])) {
210
  $_return = true;
211
  }
212
 
226
  }
227
 
228
 
229
+ private static function isUserPermitted() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  $return = false;
231
  if(current_user_can('upload_files')) {
232
  $return = true;
236
  }
237
 
238
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  /**
240
  * Greatest cummon divisor
241
  */
242
+ private function gcd($a, $b) {
243
  if(function_exists('gmp_gcd')) {
244
  $gcd = gmp_strval(gmp_gcd($a,$b));
 
245
  return ($gcd);
246
  } else {
247
+ $gcd = self::my_gcd($a,$b);
 
248
  return $gcd;
249
  }
250
  }
251
 
252
+ private static function my_gcd($a, $b) {
253
  $b = ( $a == 0 )? 0 : $b;
254
+ return ( $a % $b )? self::my_gcd($b, abs($a - $b)) : $b;
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  }
256
  }
257
 
 
 
258
  $cpte = new CropPostThumbnailsEditor();
functions/save.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
  $cptSave = new CptSaveThumbnail();
3
- add_action( 'wp_ajax_cptSaveThumbnail', array($cptSave, 'saveThumbnail') );
4
 
5
  class CptSaveThumbnail {
6
 
7
- private $debug = array();
8
 
9
  /**
10
  * Handle-function called via ajax request.
@@ -12,166 +12,220 @@ class CptSaveThumbnail {
12
  * Input parameters:
13
  * * $_REQUEST['selection'] - json-object - data of the selection/crop
14
  * * $_REQUEST['raw_values'] - json-object - data of the original image
15
- * * $_REQUEST['active_values'] - json-array - array with data of the images to crop
16
- * * $_REQUEST['same_ratio_active'] - boolean - was the same_ratio_checkbox checked or not
17
  * The main code is wraped via try-catch - the errorMessage will send back to JavaScript for displaying in an alert-box.
18
  * Called die() at the end.
19
  */
20
- function saveThumbnail() {
21
  global $cptSettings;
22
- $json_return = array();
 
23
 
24
  try {
25
- /** get data **/
26
- $options = $cptSettings->getOptions();
27
- //from $_REQUEST
28
- $selection = json_decode(stripcslashes($_REQUEST['selection']));
29
- $sourceImgData = json_decode(stripcslashes($_REQUEST['raw_values']));
30
- $targetImgData = json_decode(stripcslashes($_REQUEST['active_values']));
31
 
32
- //from DB
33
- $dbImageSizes = $cptSettings->getImageSizes();
34
 
35
- $obj = get_post($sourceImgData->id);
36
- $sourceImgPath = get_attached_file( $obj->ID );
37
- $post_metadata = wp_get_attachment_metadata($obj->ID, true);//get the attachement metadata of the post
 
38
 
39
- $this->validation($selection,$obj,$sourceImgPath,$post_metadata);
40
 
 
 
 
 
41
 
42
- #$debug.= "\nselection\n".print_r($selection,true);
43
- #$debug.= "\ntargetImgData\n".print_r($sourceImgData,true);
44
- #$debug.= "\ntargetImgData\n".print_r($targetImgData,true);
45
- #$debug.= "\nimageObject\n".print_r($obj,true);
46
- #$debug.= "\nsource:".$sourceImgPath."\n";
47
 
48
  /**
49
- * will be true if the image format isn't in the attachements metadata,
50
  * and Wordpress doesn't know about the image file
51
  */
52
- $_changed_image_format = false;
53
  $_processing_error = array();
54
- foreach($targetImgData as $_imageSize) {
55
- $this->addDebug('submitted image-data');
56
- $this->addDebug(print_r($_imageSize,true));
57
- $_delete_old_file = '';
58
- if(!$this->isImageSizeValid($_imageSize,$dbImageSizes)) {
59
- $this->addDebug("Image size not valid.");
60
  continue;
61
  }
62
- if(empty($post_metadata['sizes'][$_imageSize->name])) {
63
- $_changed_image_format = true;
 
 
64
  } else {
65
  //the old size hasent got the right image-size/image-ratio --> delete it or nobody will ever delete it correct
66
- if($post_metadata['sizes'][$_imageSize->name]['width'] != intval($_imageSize->width)
67
- || $post_metadata['sizes'][$_imageSize->name]['height'] != intval($_imageSize->height) ) {
68
-
69
- $_delete_old_file = $post_metadata['sizes'][$_imageSize->name]['file'];
70
- $_changed_image_format = true;
71
  }
72
  }
73
 
74
- $_filepath = $this->generateFilename($sourceImgPath, $_imageSize->width, $_imageSize->height);
75
- $_filepath_info = pathinfo($_filepath);
76
 
77
- $_tmp_filepath = $cptSettings->getUploadDir().DIRECTORY_SEPARATOR.$_filepath_info['basename'];
78
- $this->addDebug("filename:".$_filepath);
79
 
 
 
 
 
80
 
81
- $crop_width = $_imageSize->width;
82
- $crop_height = $_imageSize->height;
83
- if(!$_imageSize->crop || $_imageSize->width==0 || $_imageSize->height==0 || $_imageSize->width==9999 || $_imageSize->height==9999) {
84
- //handle images with soft-crop width/height value and crop set to "true"
85
- $crop_width = $selection->x2 - $selection->x;
86
- $crop_height = $selection->y2 - $selection->y;
87
- }
88
-
89
- $result = wp_crop_image( // * @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
90
- intval($sourceImgData->id), // * @param string|int $src The source file or Attachment ID.
91
- $selection->x, // * @param int $src_x The start x position to crop from.
92
- $selection->y, // * @param int $src_y The start y position to crop from.
93
- $selection->x2 - $selection->x, // * @param int $src_w The width to crop.
94
- $selection->y2 - $selection->y, // * @param int $src_h The height to crop.
95
- $crop_width, // * @param int $dst_w The destination width.
96
- $crop_height, // * @param int $dst_h The destination height.
97
- false, // * @param int $src_abs Optional. If the source crop points are absolute.
98
- $_tmp_filepath // * @param string $dst_file Optional. The destination file to write to.
99
  );
100
 
101
  $_error = false;
102
  if(empty($result)) {
103
- $_processing_error[] = sprintf(__("Can't generate filesize '%s'.",CROP_THUMBS_LANG),$_imageSize->name);
104
  $_error = true;
105
  } else {
106
- if(!empty($_delete_old_file)) {
107
- @unlink($_filepath_info['dirname'].DIRECTORY_SEPARATOR.$_delete_old_file);
 
108
  }
109
- if(!@copy($result,$_filepath)) {
110
- $_processing_error[] = sprintf(__("Can't copy temporary file to media library.",CROP_THUMBS_LANG));
111
  $_error = true;
112
  }
113
  if(!@unlink($result)) {
114
- $_processing_error[] = sprintf(__("Can't delete temporary file.",CROP_THUMBS_LANG));
115
  $_error = true;
116
  }
117
  }
118
 
119
  if(!$_error) {
120
  //update metadata --> otherwise new sizes will not be updated
121
- $filetype = wp_check_filetype( $_filepath );
122
- $_new_meta = array(
123
- 'file'=>$_filepath_info['basename'],
124
- 'width'=>intval($crop_width),
125
- 'height'=>intval($crop_height),
126
- 'mime-type' => $filetype['type']
127
- );
128
- if(!empty($dbImageSizes[$_imageSize->name]['crop'])) {
129
- $_new_meta['crop'] = $dbImageSizes[$_imageSize->name]['crop'];
130
- }
131
- $post_metadata['sizes'][$_imageSize->name] = $_new_meta;
132
-
133
- $_full_filepath = trailingslashit($_filepath_info['dirname']) . $_filepath_info['basename'];
134
- do_action('crop_thumbnails_after_save_new_thumb', $_full_filepath, $_imageSize->name, $_new_meta );
135
  } else {
136
- $this->addDebug('error on '.$_filepath_info['basename']);
137
- $this->addDebug(implode(' | ',$_processing_error));
138
  }
139
  }//END foreach
140
 
141
  //we have to update the posts metadate
142
  //otherwise new sizes will not be updated
143
- $post_metadata = apply_filters('crop_thumbnails_before_update_metadata', $post_metadata, $obj->ID);
144
- wp_update_attachment_metadata( $obj->ID, $post_metadata);
145
 
146
  //generate result;
147
- $json_return['debug'] = $this->getDebugOutput($options);
148
- if(!empty($_processing_error)) {
149
- //one or more errors happend when generating thumbnails
150
- $json_return['processingErrors'] = implode("\n",$_processing_error);
151
- }
152
- if($_changed_image_format) {
153
  //there was a change in the image-formats
154
- $json_return['changed_image_format'] = true;
 
 
 
 
 
 
 
155
  }
156
- $json_return['success'] = time();//time for cache-breaker
157
- echo json_encode($json_return);
 
 
 
158
  } catch (Exception $e) {
159
- $json_return['debug'] = $this->getDebugOutput($options);
160
- $json_return['error'] = $e->getMessage();
161
- echo json_encode($json_return);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
 
 
 
 
 
 
 
 
 
 
 
 
163
  die();
164
  }
165
 
166
- private function addDebug($text) {
167
- $this->debug[] = $text;
 
 
 
 
 
 
 
168
  }
169
 
170
- private function getDebugOutput($options) {
171
- if(!empty($this->debug)) {
172
- return join("\n",$this->debug);
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
- return '';
 
 
 
175
  }
176
 
177
  /**
@@ -179,7 +233,7 @@ class CptSaveThumbnail {
179
  * @param array all available ImageSizes
180
  * @return boolean true if the newImageSize is in the list of ImageSizes and dimensions are correct
181
  */
182
- function isImageSizeValid(&$submitted,$dbData) {
183
  if(empty($submitted->name)) {
184
  return false;
185
  }
@@ -194,44 +248,55 @@ class CptSaveThumbnail {
194
  //eventually we want to test some more later
195
  return true;
196
  }
197
-
198
  /**
199
- * some basic validations and value transformations
200
- * @param array the user submitted selection
201
- * @param object the loaded image-object loaded by $sourceImgData->id
202
- * @param string the server-path to the source-image
203
- * @param object metadata of the image-attachement
204
  * @throw Exception if the security validation fails
205
  */
206
- function validation($selection,$obj,$sourceImgPath,$post_metadata) {
207
  global $cptSettings;
 
208
  if(!check_ajax_referer($cptSettings->getNonceBase(),'_ajax_nonce',false)) {
209
- throw new Exception(__("ERROR: Security Check failed (maybe a timeout - please try again).",CROP_THUMBS_LANG), 1);
210
  }
211
 
212
- if(!isset($selection->x) || !isset($selection->y) || !isset($selection->x2) || !isset($selection->y2)) {
213
- throw new Exception(__('ERROR: Submitted data is incomplete.',CROP_THUMBS_LANG), 1);
 
214
  }
215
- $selection->x = intval($selection->x);
216
- $selection->y = intval($selection->y);
217
- $selection->x2 = intval($selection->x2);
218
- $selection->y2 = intval($selection->y2);
219
 
220
- if($selection->x < 0 || $selection->y < 0) {
221
- throw new Exception(__('Cropping to these dimensions on this image is not possible.',CROP_THUMBS_LANG), 1);
222
  }
223
 
224
- if(empty($obj)) {
225
- throw new Exception(__("ERROR: Can't find original image in database!",CROP_THUMBS_LANG), 1);
 
226
  }
227
- if(empty($sourceImgPath)) {
228
- throw new Exception(__("ERROR: Can't find original image file!",CROP_THUMBS_LANG), 1);
 
 
 
 
 
 
 
229
  }
230
- if(empty($post_metadata)) {
231
- throw new Exception(__("ERROR: Can't find original image metadata!",CROP_THUMBS_LANG), 1);
 
 
 
232
  }
 
 
233
  }
234
 
 
235
  /**
236
  * Generate the Filename (and path) of the thumbnail based on width and height the same way as wordpress do.
237
  * @see generate_filename in wp-includes/class-wp-image-editor.php
@@ -240,15 +305,13 @@ class CptSaveThumbnail {
240
  * @param int height of the new image
241
  * @return string path to the new image
242
  */
243
- function generateFilename( $file, $w, $h ){
244
  $info = pathinfo($file);
245
  $dir = $info['dirname'];
246
  $ext = $info['extension'];
247
  $name = wp_basename($file, '.'.$ext);
248
  $suffix = $w.'x'.$h;
249
  $destfilename = $dir.'/'.$name.'-'.$suffix.'.'.$ext;
250
-
251
  return $destfilename;
252
  }
253
- }
254
- ?>
1
  <?php
2
  $cptSave = new CptSaveThumbnail();
3
+ add_action( 'wp_ajax_cptSaveThumbnail', array($cptSave, 'saveThumbnailAjaxWrap') );
4
 
5
  class CptSaveThumbnail {
6
 
7
+ private static $debug = array();
8
 
9
  /**
10
  * Handle-function called via ajax request.
12
  * Input parameters:
13
  * * $_REQUEST['selection'] - json-object - data of the selection/crop
14
  * * $_REQUEST['raw_values'] - json-object - data of the original image
15
+ * * $_REQUEST['activeImageSizes'] - json-array - array with data of the images to crop
 
16
  * The main code is wraped via try-catch - the errorMessage will send back to JavaScript for displaying in an alert-box.
17
  * Called die() at the end.
18
  */
19
+ public function saveThumbnail() {
20
  global $cptSettings;
21
+ $jsonResult = array();
22
+ $settings = $cptSettings->getOptions();
23
 
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!",'cpt_lang'), 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!",'cpt_lang'), 1);
37
+ }
38
 
39
+ //from DB
40
+ $dbImageSizes = $cptSettings->getImageSizes();
 
 
 
41
 
42
  /**
43
+ * will be filled with the new image-url if the image format isn't in the attachements metadata,
44
  * and Wordpress doesn't know about the image file
45
  */
46
+ $changedImageName = array();
47
  $_processing_error = array();
48
+ foreach($input->activeImageSizes as $activeImageSize) {
49
+ self::addDebug('submitted image-data');
50
+ self::addDebug($activeImageSize);
51
+ if(!self::isImageSizeValid($activeImageSize,$dbImageSizes)) {
52
+ self::addDebug("Image size not valid.");
 
53
  continue;
54
  }
55
+
56
+ $oldFile_toDelete = '';
57
+ if(empty($imageMetadata['sizes'][$activeImageSize->name])) {
58
+ $changedImageName[ $activeImageSize->name ] = true;
59
  } else {
60
  //the old size hasent got the right image-size/image-ratio --> delete it or nobody will ever delete it correct
61
+ if($imageMetadata['sizes'][$activeImageSize->name]['width'] != intval($activeImageSize->width) || $imageMetadata['sizes'][$activeImageSize->name]['height'] != intval($activeImageSize->height) ) {
62
+ $oldFile_toDelete = $imageMetadata['sizes'][$activeImageSize->name]['file'];
63
+ $changedImageName[ $activeImageSize->name ] = true;
 
 
64
  }
65
  }
66
 
 
 
67
 
68
+ $croppedSize = self::getCroppedSize($activeImageSize,$imageMetadata,$input);
 
69
 
70
+ $currentFilePath = self::generateFilename($sourceImgPath, $croppedSize['width'], $croppedSize['height']);
71
+ self::addDebug("filename:".$currentFilePath);
72
+ $currentFilePathInfo = pathinfo($currentFilePath);
73
+ $temporaryCopyFile = $cptSettings->getUploadDir().DIRECTORY_SEPARATOR.$currentFilePathInfo['basename'];
74
 
75
+ $result = wp_crop_image( // * @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
76
+ $input->sourceImageId, // * @param string|int $src The source file or Attachment ID.
77
+ $input->selection->x, // * @param int $src_x The start x position to crop from.
78
+ $input->selection->y, // * @param int $src_y The start y position to crop from.
79
+ $input->selection->x2 - $input->selection->x, // * @param int $src_w The width to crop.
80
+ $input->selection->y2 - $input->selection->y, // * @param int $src_h The height to crop.
81
+ $croppedSize['width'], // * @param int $dst_w The destination width.
82
+ $croppedSize['height'], // * @param int $dst_h The destination height.
83
+ false, // * @param int $src_abs Optional. If the source crop points are absolute.
84
+ $temporaryCopyFile // * @param string $dst_file Optional. The destination file to write to.
 
 
 
 
 
 
 
 
85
  );
86
 
87
  $_error = false;
88
  if(empty($result)) {
89
+ $_processing_error[$activeImageSize->name][] = sprintf(esc_html__("Can't generate filesize '%s'.",'cpt_lang'),$activeImageSize->name);
90
  $_error = true;
91
  } else {
92
+ if(!empty($oldFile_toDelete)) {
93
+ self::addDebug("delete old image:".$oldFile_toDelete);
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.",'cpt_lang'));
98
  $_error = true;
99
  }
100
  if(!@unlink($result)) {
101
+ $_processing_error[$activeImageSize->name][] = sprintf(esc_html__("Can't delete temporary file.",'cpt_lang'));
102
  $_error = true;
103
  }
104
  }
105
 
106
  if(!$_error) {
107
  //update metadata --> otherwise new sizes will not be updated
108
+ $imageMetadata = self::updateMetadata($imageMetadata, $activeImageSize->name, $currentFilePathInfo, $croppedSize['width'], $croppedSize['height']);
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  } else {
110
+ self::addDebug('error on '.$currentFilePathInfo['basename']);
111
+ self::addDebug($_processing_error);
112
  }
113
  }//END foreach
114
 
115
  //we have to update the posts metadate
116
  //otherwise new sizes will not be updated
117
+ $imageMetadata = apply_filters('crop_thumbnails_before_update_metadata', $imageMetadata, $input->sourceImageId);
118
+ wp_update_attachment_metadata( $input->sourceImageId, $imageMetadata);
119
 
120
  //generate result;
121
+ if(!empty($changedImageName)) {
 
 
 
 
 
122
  //there was a change in the image-formats
123
+ foreach($changedImageName as $key=>$value) {
124
+ $newImageLocation = wp_get_attachment_image_src($input->sourceImageId, $key);
125
+ $changedImageName[ $key ] = $newImageLocation[0];
126
+ }
127
+ $jsonResult['changedImageName'] = $changedImageName;
128
+ }
129
+ if(!empty($_processing_error)) {//one or more errors happend when generating thumbnails
130
+ $jsonResult['processingErrors'] = $_processing_error;
131
  }
132
+ if(!empty($settings['debug_data'])) {
133
+ $jsonResult['debug'] = self::getDebug();
134
+ }
135
+ $jsonResult['success'] = time();//time for cache-breaker
136
+ echo json_encode($jsonResult);
137
  } catch (Exception $e) {
138
+ if(!empty($settings['debug_data'])) {
139
+ $jsonResult['debug'] = self::getDebug();
140
+ }
141
+ $jsonResult['error'] = $e->getMessage();
142
+ echo json_encode($jsonResult);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Get the end-size of the cropped image in pixels.
148
+ * Attention: these sizes are used to name the file.
149
+ * @param object $activeImageSize The image size that should be used
150
+ * @param [type] $imageMetadata [description]
151
+ * @param [type] $input [description]
152
+ * @return {[type] [description]
153
+ */
154
+ public static function getCroppedSize($activeImageSize,$imageMetadata,$input) {
155
+ //set target size of the cropped image
156
+ $croppedWidth = $activeImageSize->width;
157
+ $croppedHeight = $activeImageSize->height;
158
+ try {
159
+ if($activeImageSize->width===9999) {
160
+ $croppedWidth = intval($imageMetadata['width']);
161
+ } elseif($activeImageSize->height===9999) {
162
+ $croppedHeight = intval($imageMetadata['height']);
163
+ } elseif(intval($activeImageSize->width)===0 && intval($activeImageSize->height)===0) {
164
+ $croppedWidth = $input->selection->x2 - $input->selection->x;
165
+ $croppedHeight = $input->selection->y2 - $input->selection->y;
166
+ } elseif(intval($activeImageSize->width)===0) {
167
+ $croppedWidth = intval(( intval($imageMetadata['width']) / intval($imageMetadata['height']) ) * $activeImageSize->height);
168
+ $croppedHeight = $activeImageSize->height;
169
+ } elseif(intval($activeImageSize->height)===0) {
170
+ $croppedWidth = $activeImageSize->width;
171
+ $croppedHeight = intval(( intval($imageMetadata['height']) / intval($imageMetadata['width']) ) * $activeImageSize->width);
172
+ }
173
+
174
+ /* --- no need to use that ---
175
+ if(!$activeImageSize->crop) {
176
+ $croppedWidth = $input->selection->x2 - $input->selection->x;
177
+ $croppedHeight = $input->selection->y2 - $input->selection->y;
178
+ }*/
179
+ } catch(Exception $e) {
180
+ $croppedWidth = 10;
181
+ $croppedHeight = 10;
182
  }
183
+
184
+ return array('width' => $croppedWidth, 'height'=> $croppedHeight);
185
+ }
186
+
187
+ /**
188
+ * This function is called by the wordpress-ajax-callback. Its only purpose is to call the
189
+ * saveThumbnail function and die().
190
+ * All wordpress ajax-functions should call the "die()" function in the end. But this makes
191
+ * phpunit tests impossible - so we have to wrap it.
192
+ */
193
+ public function saveThumbnailAjaxWrap() {
194
+ $this->saveThumbnail();
195
  die();
196
  }
197
 
198
+ private static function addDebug($text) {
199
+ self::$debug[] = $text;
200
+ }
201
+
202
+ private static function getDebug() {
203
+ if(!empty(self::$debug)) {
204
+ return self::$debug;
205
+ }
206
+ return [];
207
  }
208
 
209
+ private static function updateMetadata($imageMetadata, $imageSizeName, $currentFilePathInfo, $croppedWidth, $croppedHeight) {
210
+ $fullFilePath = trailingslashit($currentFilePathInfo['dirname']) . $currentFilePathInfo['basename'];
211
+
212
+ $newValues = array();
213
+ $newValues['file'] = $currentFilePathInfo['basename'];
214
+ $newValues['width'] = intval($croppedWidth);
215
+ $newValues['height'] = intval($croppedHeight);
216
+ $newValues['mime-type'] = mime_content_type($fullFilePath);
217
+
218
+ $oldValues = array();
219
+ if(empty($imageMetadata['sizes'])) {
220
+ $imageMetadata['sizes'] = array();
221
+ }
222
+ if(!empty($imageMetadata['sizes'][$imageSizeName])) {
223
+ $oldValues = $imageMetadata['sizes'][$imageSizeName];
224
  }
225
+ $imageMetadata['sizes'][$imageSizeName] = array_merge($oldValues,$newValues);
226
+
227
+ do_action('crop_thumbnails_after_save_new_thumb', $fullFilePath, $imageSizeName, $imageMetadata['sizes'][$imageSizeName] );
228
+ return $imageMetadata;
229
  }
230
 
231
  /**
233
  * @param array all available ImageSizes
234
  * @return boolean true if the newImageSize is in the list of ImageSizes and dimensions are correct
235
  */
236
+ private static function isImageSizeValid(&$submitted,$dbData) {
237
  if(empty($submitted->name)) {
238
  return false;
239
  }
248
  //eventually we want to test some more later
249
  return true;
250
  }
251
+
252
  /**
253
+ * Some basic validations and value transformations
254
+ * @return object JSON-Object with submitted data
 
 
 
255
  * @throw Exception if the security validation fails
256
  */
257
+ private function getValidatedInput() {
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).",'cpt_lang'), 1);
262
  }
263
 
264
+
265
+ if(empty($_REQUEST['crop_thumbnails'])) {
266
+ throw new Exception(esc_html__('ERROR: Submitted data is incomplete.','cpt_lang'), 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.','cpt_lang'), 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.','cpt_lang'), 1);
278
  }
279
+
280
+
281
+ $input->selection->x = intval($input->selection->x);
282
+ $input->selection->y = intval($input->selection->y);
283
+ $input->selection->x2 = intval($input->selection->x2);
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.','cpt_lang'), 1);
288
  }
289
+
290
+
291
+ $input->sourceImageId = intval($input->sourceImageId);
292
+ if(empty(get_post($input->sourceImageId))) {
293
+ throw new Exception(esc_html__("ERROR: Can't find original image in database!",'cpt_lang'), 1);
294
  }
295
+
296
+ return $input;
297
  }
298
 
299
+
300
  /**
301
  * Generate the Filename (and path) of the thumbnail based on width and height the same way as wordpress do.
302
  * @see generate_filename in wp-includes/class-wp-image-editor.php
305
  * @param int height of the new image
306
  * @return string path to the new image
307
  */
308
+ private static function generateFilename( $file, $w, $h ){
309
  $info = pathinfo($file);
310
  $dir = $info['dirname'];
311
  $ext = $info['extension'];
312
  $name = wp_basename($file, '.'.$ext);
313
  $suffix = $w.'x'.$h;
314
  $destfilename = $dir.'/'.$name.'-'.$suffix.'.'.$ext;
 
315
  return $destfilename;
316
  }
317
+ }
 
functions/settings.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  class CropThumbnailsSettings {
3
- private $uniqeSettingsId = 'cpt-settings';
4
- private $optionsKey = 'crop-post-thumbs';
5
- private $cssPrefix = 'cpt_settings_';
6
- private $defaultSizes = array('thumbnail','medium','medium_large','large');
7
 
8
- function __construct() {
9
  add_action('admin_menu', array($this,'addOptionsPage'));
10
  if(is_admin()) {
11
  add_filter('plugin_action_links', array($this,'addSettingsLinkToPluginPage'), 10, 2);
@@ -16,41 +16,41 @@ class CropThumbnailsSettings {
16
  }
17
  }
18
 
19
- function optionsPageStyle() {
20
- if(!empty($_REQUEST['page']) && $_REQUEST['page']=='page-cpt') {
21
- wp_enqueue_style('crop-thumbnails-options-style',plugins_url('css/options.css',dirname(__FILE__)));
22
  }
23
  }
24
 
25
- function addSettingsLinkToPluginPage($links, $file) {
26
  if ($file === 'crop-thumbnails/crop-thumbnails.php'){
27
- $settings_link = '<a href="options-general.php?page=page-cpt" title="">'.__('Settings',CROP_THUMBS_LANG).'</a>';
28
  array_unshift( $links, $settings_link );
29
  }
30
  return $links;
31
  }
32
 
33
- function addOptionsPage() {
34
- add_options_page(__('Crop Post Thumbnail Page',CROP_THUMBS_LANG), 'Crop-Thumbnails', 'manage_options', 'page-cpt', array($this,'optionsPage'));
35
  add_action('admin_init', array($this,'settingsInitialisation'));
36
  }
37
 
38
- function optionsPage() { ?>
39
- <div class="wrap">
40
  <div id="icon-options-general" class="icon32"><br /></div>
41
- <h2>Crop-Thumbnails <?php esc_attr_e('Settings',CROP_THUMBS_LANG); ?></h2>
42
  <form action="options.php" method="post">
43
- <?php settings_fields($this->uniqeSettingsId); ?>
44
  <?php do_settings_sections('page1'); ?>
45
 
46
- <div class="<?php echo $this->cssPrefix ?>submit">
47
- <input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes',CROP_THUMBS_LANG); ?>" class="button-primary" />
48
  </div>
49
  </form>
50
 
51
- <div class="<?php echo $this->cssPrefix; ?>paypal">
52
- <h3><?php _e('Support the plugin author',CROP_THUMBS_LANG) ?></h3>
53
- <p><?php _e('You can support the plugin author <br />(and let him know you love this plugin) <br />by donating via Paypal. Thanks a lot!',CROP_THUMBS_LANG); ?></p>
54
  <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
55
  <input type="hidden" name="cmd" value="_donations">
56
  <input type="hidden" name="business" value="volkmar.kantor@gmx.de">
@@ -68,38 +68,38 @@ class CropThumbnailsSettings {
68
  <?php
69
  }
70
 
71
- function settingsInitialisation(){
72
- register_setting( $this->uniqeSettingsId, $this->optionsKey, array($this,'validateSettings') );
73
 
74
  $_sectionID = 'choose_sizes_section';
75
- add_settings_section($_sectionID, __('Sizes and Post Types',CROP_THUMBS_LANG), array($this,'sectionDescriptionChooseSizes'), 'page1');
76
- add_settings_field('sizes', __('Choose the image size options you want to hide for each post type.',CROP_THUMBS_LANG), array($this,'callback_choose_size'), 'page1', $_sectionID);
77
 
78
  $_sectionID = 'quick_test';
79
- add_settings_section($_sectionID, __('Plugin Test',CROP_THUMBS_LANG), array($this,'sectionDescriptionTest'), 'page1');
80
 
81
  $_sectionID = 'developer';
82
- add_settings_section($_sectionID, __('Developer Settings',CROP_THUMBS_LANG), array($this,'emptySectionDescription'), 'page1');
83
  $_tmpID = 'debug_js';
84
- add_settings_field($_tmpID, __('Enable JS-Debug.',CROP_THUMBS_LANG), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => $this->cssPrefix.$_tmpID ));
85
  $_tmpID = 'debug_data';
86
- add_settings_field($_tmpID, __('Enable Data-Debug.',CROP_THUMBS_LANG), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => $this->cssPrefix.$_tmpID ));
87
  }
88
 
89
- function sectionDescriptionChooseSizes() {?>
90
  <p>
91
- <?php _e('Crop-Thumbnails is designed to make cropping images easy. For some post types, not all crop sizes are needed, but the plugin will automatically create all the crop sizes. Here you can select which crop sizes are available in the cropping interface for each post type..',CROP_THUMBS_LANG) ?>
92
- <br /><strong><?php _e('Crop-Thumbnails will only show cropped images. Sizes with no crop will always be hidden.',CROP_THUMBS_LANG); ?></strong>
93
  </p>
94
  <?php
95
  }
96
 
97
- function emptySectionDescription() {/*empty*/ }
98
 
99
 
100
- function callback_choose_size() {
101
  //get all the data
102
- $options = get_option($this->optionsKey);
103
  #echo '<pre>'.print_r($options,true).'</pre>';
104
  $post_types = $this->getPostTypes();
105
  $image_sizes = $this->getImageSizes();
@@ -109,8 +109,8 @@ class CropThumbnailsSettings {
109
  <ul>
110
  <?php foreach($post_types as $post_type=>$value) : ?>
111
  <li>
112
- <label for="<?php echo $this->cssPrefix.$post_type; ?>">
113
- <input id="<?php echo $this->cssPrefix.$post_type;?>" type="checkbox" name="<?php echo $this->optionsKey; ?>[hide_post_type][<?php echo $post_type;?>]" value="1" <?php checked(isset($options['hide_post_type'][$post_type]),true); ?> />
114
  <strong><?php echo $value->labels->name; ?></strong>
115
  </label>
116
  <ul style="margin:1em;">
@@ -122,8 +122,8 @@ class CropThumbnailsSettings {
122
  }
123
  if($data['crop']=='1') : ?>
124
  <li>
125
- <label for="<?php echo $this->cssPrefix.$post_type;?>-<?php echo $thumb_name;?>">
126
- <input id="<?php echo $this->cssPrefix.$post_type;?>-<?php echo $thumb_name;?>" type="checkbox" name="<?php echo $this->optionsKey; ?>[hide_size][<?php echo $post_type; ?>][<?php echo $thumb_name; ?>]" value="1" <?php echo checked($_checked); ?> />
127
  <?php echo $thumb_name;?> - <?php echo $data['width'];?>x<?php echo $data['height'];?> <?php /* echo ($data['crop'] == '1' ? '(cropped)' : '') */?>
128
  </label>
129
  </li>
@@ -138,21 +138,21 @@ class CropThumbnailsSettings {
138
  <?php
139
  }
140
 
141
- function callback_debug_js() {
142
- $options = get_option($this->optionsKey);
143
  $_id = 'debug_js';
144
  if(empty($options[$_id])) { $options[$_id] = ''; }
145
- echo '<input name="'.$this->optionsKey.'['.$_id.']" id="'.$this->cssPrefix.$_id.'" type="checkbox" value="1" ' . checked( 1, $options[$_id], false) . ' />';
146
  }
147
 
148
- function callback_debug_data() {
149
- $options = get_option($this->optionsKey);
150
  $_id = 'debug_data';
151
  if(empty($options[$_id])) { $options[$_id] = ''; }
152
- echo '<input name="'.$this->optionsKey.'['.$_id.']" id="'.$this->cssPrefix.$_id.'" type="checkbox" value="1" ' . checked( 1, $options[$_id], false ) . ' />';
153
  }
154
 
155
- function validateSettings($input) {
156
  $sizes = $this->getImageSizes();
157
 
158
  $post_types = $this->getPostTypes();
@@ -195,7 +195,7 @@ class CropThumbnailsSettings {
195
  return $storeInDb;
196
  }
197
 
198
- function sectionDescriptionTest() {?>
199
  <button type="button" class="button-secondary cpt_quicktest">Do plugin quick-test.</button>
200
 
201
  <script>
@@ -238,7 +238,7 @@ class CropThumbnailsSettings {
238
 
239
  /* helper functions **********************************************************************************************/
240
 
241
- function ajax_callback_admin_quicktest() {
242
  //security
243
  if(!current_user_can('manage_options')) die('forbidden');
244
  check_ajax_referer('cpt_quicktest-ajax-nonce','security');//only for quicktest
@@ -298,7 +298,7 @@ class CropThumbnailsSettings {
298
  120, // * @param int $src_h The height to crop.
299
  200, // * @param int $dst_w The destination width.
300
  25, // * @param int $dst_h The destination height.
301
- false, // * @param int $src_abs Optional. If the source crop points are absolute.
302
  $tempFile // * @param string $dst_file Optional. The destination file to write to.
303
  );
304
  if ( is_wp_error( $cropResult ) ) {
@@ -361,7 +361,7 @@ class CropThumbnailsSettings {
361
  exit();
362
  }
363
 
364
- function getUploadDir() {
365
  $upload_dir = wp_upload_dir();
366
  return $upload_dir['basedir'].DIRECTORY_SEPARATOR.'tmp';
367
  }
@@ -370,7 +370,7 @@ class CropThumbnailsSettings {
370
  /**
371
  * get the post types and delete some prebuild post types that we dont need
372
  */
373
- function getPostTypes() {
374
  $post_types = get_post_types(array(),'objects');
375
  unset($post_types['nav_menu_item']);
376
  unset($post_types['revision']);
@@ -389,7 +389,7 @@ class CropThumbnailsSettings {
389
  * array[<sizename>]['name'] = string --> readable name if provided in "image_size_names_choose", else sizename
390
  * </pre>
391
  */
392
- function getImageSizes() {
393
  global $_wp_additional_image_sizes;//array with the available image sizes
394
  $image_size_names = array_flip(get_intermediate_image_sizes());
395
  foreach($image_size_names as $key=>$value) {
@@ -402,7 +402,7 @@ class CropThumbnailsSettings {
402
  $sizes = array();
403
  foreach( $image_size_names as $_size=>$theName ) {
404
 
405
- if ( in_array( $_size, $this->defaultSizes ) ) {
406
  $sizes[ $_size ]['width'] = intval(get_option( $_size . '_size_w' ));
407
  $sizes[ $_size ]['height'] = intval(get_option( $_size . '_size_h' ));
408
  $sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
@@ -419,11 +419,11 @@ class CropThumbnailsSettings {
419
  return $sizes;
420
  }
421
 
422
- function getOptions() {
423
- return get_option($this->optionsKey);
424
  }
425
 
426
- function getNonceBase() {
427
  return 'crop-post-thumbnails-nonce-base';
428
  }
429
  }
1
  <?php
2
  class CropThumbnailsSettings {
3
+ private static $uniqeSettingsId = 'cpt-settings';
4
+ private static $optionsKey = 'crop-post-thumbs';
5
+ private static $cssPrefix = 'cpt_settings_';
6
+ private static $defaultSizes = array('thumbnail','medium','medium_large','large');
7
 
8
+ public function __construct() {
9
  add_action('admin_menu', array($this,'addOptionsPage'));
10
  if(is_admin()) {
11
  add_filter('plugin_action_links', array($this,'addSettingsLinkToPluginPage'), 10, 2);
16
  }
17
  }
18
 
19
+ public function optionsPageStyle() {
20
+ if(!empty($_REQUEST['page']) && $_REQUEST['page']==='page-cpt') {
21
+ wp_enqueue_style('crop-thumbnails-options-style',plugins_url('css/cpt-backend.css',dirname(__FILE__)));
22
  }
23
  }
24
 
25
+ public function addSettingsLinkToPluginPage($links, $file) {
26
  if ($file === 'crop-thumbnails/crop-thumbnails.php'){
27
+ $settings_link = '<a href="options-general.php?page=page-cpt" title="">'.esc_html__('Settings','cpt_lang').'</a>';
28
  array_unshift( $links, $settings_link );
29
  }
30
  return $links;
31
  }
32
 
33
+ public function addOptionsPage() {
34
+ add_options_page(esc_html__('Crop Post Thumbnail Page','cpt_lang'), 'Crop-Thumbnails', 'manage_options', 'page-cpt', array($this,'optionsPage'));
35
  add_action('admin_init', array($this,'settingsInitialisation'));
36
  }
37
 
38
+ public function optionsPage() { ?>
39
+ <div class="wrap cropThumbnailSettings">
40
  <div id="icon-options-general" class="icon32"><br /></div>
41
+ <h2>Crop-Thumbnails <?php esc_attr_e('Settings','cpt_lang'); ?></h2>
42
  <form action="options.php" method="post">
43
+ <?php settings_fields( self::$uniqeSettingsId ); ?>
44
  <?php do_settings_sections('page1'); ?>
45
 
46
+ <div class="<?php echo self::$cssPrefix ?>submit">
47
+ <input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes','cpt_lang'); ?>" class="button-primary" />
48
  </div>
49
  </form>
50
 
51
+ <div class="<?php echo self::$cssPrefix; ?>paypal">
52
+ <h3><?php esc_html_e('Support the plugin author','cpt_lang') ?></h3>
53
+ <p><?php esc_html_e('You can support the plugin author (and let him know you love this plugin) by donating via Paypal. Thanks a lot!','cpt_lang'); ?></p>
54
  <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
55
  <input type="hidden" name="cmd" value="_donations">
56
  <input type="hidden" name="business" value="volkmar.kantor@gmx.de">
68
  <?php
69
  }
70
 
71
+ public function settingsInitialisation(){
72
+ register_setting( self::$uniqeSettingsId, self::$optionsKey, array($this,'validateSettings') );
73
 
74
  $_sectionID = 'choose_sizes_section';
75
+ add_settings_section($_sectionID, esc_html__('Sizes and Post Types','cpt_lang'), array($this,'sectionDescriptionChooseSizes'), 'page1');
76
+ add_settings_field('sizes', esc_html__('Choose the image size options you want to hide for each post type.','cpt_lang'), array($this,'callback_choose_size'), 'page1', $_sectionID);
77
 
78
  $_sectionID = 'quick_test';
79
+ add_settings_section($_sectionID, esc_html__('Plugin Test','cpt_lang'), array($this,'sectionDescriptionTest'), 'page1');
80
 
81
  $_sectionID = 'developer';
82
+ add_settings_section($_sectionID, esc_html__('Developer Settings','cpt_lang'), array($this,'emptySectionDescription'), 'page1');
83
  $_tmpID = 'debug_js';
84
+ add_settings_field($_tmpID, esc_html__('Enable JS-Debug.','cpt_lang'), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => self::$cssPrefix.$_tmpID ));
85
  $_tmpID = 'debug_data';
86
+ add_settings_field($_tmpID, esc_html__('Enable Data-Debug.','cpt_lang'), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => self::$cssPrefix.$_tmpID ));
87
  }
88
 
89
+ public function sectionDescriptionChooseSizes() {?>
90
  <p>
91
+ <?php esc_html_e('Crop-Thumbnails is designed to make cropping images easy. For some post types, not all crop sizes are needed, but the plugin will automatically create all the crop sizes. Here you can select which crop sizes are available in the cropping interface for each post type..','cpt_lang') ?>
92
+ <br /><strong><?php esc_html_e('Crop-Thumbnails will only show cropped images. Sizes with no crop will always be hidden.','cpt_lang'); ?></strong>
93
  </p>
94
  <?php
95
  }
96
 
97
+ public function emptySectionDescription() {/*empty*/ }
98
 
99
 
100
+ public function callback_choose_size() {
101
  //get all the data
102
+ $options = get_option(self::$optionsKey);
103
  #echo '<pre>'.print_r($options,true).'</pre>';
104
  $post_types = $this->getPostTypes();
105
  $image_sizes = $this->getImageSizes();
109
  <ul>
110
  <?php foreach($post_types as $post_type=>$value) : ?>
111
  <li>
112
+ <label for="<?php echo self::$cssPrefix.$post_type; ?>">
113
+ <input id="<?php echo self::$cssPrefix.$post_type;?>" type="checkbox" name="<?php echo self::$optionsKey; ?>[hide_post_type][<?php echo $post_type;?>]" value="1" <?php checked(isset($options['hide_post_type'][$post_type]),true); ?> />
114
  <strong><?php echo $value->labels->name; ?></strong>
115
  </label>
116
  <ul style="margin:1em;">
122
  }
123
  if($data['crop']=='1') : ?>
124
  <li>
125
+ <label for="<?php echo self::$cssPrefix.$post_type;?>-<?php echo $thumb_name;?>">
126
+ <input id="<?php echo self::$cssPrefix.$post_type;?>-<?php echo $thumb_name;?>" type="checkbox" name="<?php echo self::$optionsKey; ?>[hide_size][<?php echo $post_type; ?>][<?php echo $thumb_name; ?>]" value="1" <?php echo checked($_checked); ?> />
127
  <?php echo $thumb_name;?> - <?php echo $data['width'];?>x<?php echo $data['height'];?> <?php /* echo ($data['crop'] == '1' ? '(cropped)' : '') */?>
128
  </label>
129
  </li>
138
  <?php
139
  }
140
 
141
+ public function callback_debug_js() {
142
+ $options = get_option(self::$optionsKey);
143
  $_id = 'debug_js';
144
  if(empty($options[$_id])) { $options[$_id] = ''; }
145
+ echo '<input name="'.self::$optionsKey.'['.$_id.']" id="'.self::$cssPrefix.$_id.'" type="checkbox" value="1" ' . checked( 1, $options[$_id], false) . ' />';
146
  }
147
 
148
+ public function callback_debug_data() {
149
+ $options = get_option(self::$optionsKey);
150
  $_id = 'debug_data';
151
  if(empty($options[$_id])) { $options[$_id] = ''; }
152
+ echo '<input name="'.self::$optionsKey.'['.$_id.']" id="'.self::$cssPrefix.$_id.'" type="checkbox" value="1" ' . checked( 1, $options[$_id], false ) . ' />';
153
  }
154
 
155
+ public function validateSettings($input) {
156
  $sizes = $this->getImageSizes();
157
 
158
  $post_types = $this->getPostTypes();
195
  return $storeInDb;
196
  }
197
 
198
+ public function sectionDescriptionTest() {?>
199
  <button type="button" class="button-secondary cpt_quicktest">Do plugin quick-test.</button>
200
 
201
  <script>
238
 
239
  /* helper functions **********************************************************************************************/
240
 
241
+ public function ajax_callback_admin_quicktest() {
242
  //security
243
  if(!current_user_can('manage_options')) die('forbidden');
244
  check_ajax_referer('cpt_quicktest-ajax-nonce','security');//only for quicktest
298
  120, // * @param int $src_h The height to crop.
299
  200, // * @param int $dst_w The destination width.
300
  25, // * @param int $dst_h The destination height.
301
+ false, // * @param int $src_abs Optional. If the source crop points are absolute.
302
  $tempFile // * @param string $dst_file Optional. The destination file to write to.
303
  );
304
  if ( is_wp_error( $cropResult ) ) {
361
  exit();
362
  }
363
 
364
+ public function getUploadDir() {
365
  $upload_dir = wp_upload_dir();
366
  return $upload_dir['basedir'].DIRECTORY_SEPARATOR.'tmp';
367
  }
370
  /**
371
  * get the post types and delete some prebuild post types that we dont need
372
  */
373
+ public function getPostTypes() {
374
  $post_types = get_post_types(array(),'objects');
375
  unset($post_types['nav_menu_item']);
376
  unset($post_types['revision']);
389
  * array[<sizename>]['name'] = string --> readable name if provided in "image_size_names_choose", else sizename
390
  * </pre>
391
  */
392
+ public function getImageSizes() {
393
  global $_wp_additional_image_sizes;//array with the available image sizes
394
  $image_size_names = array_flip(get_intermediate_image_sizes());
395
  foreach($image_size_names as $key=>$value) {
402
  $sizes = array();
403
  foreach( $image_size_names as $_size=>$theName ) {
404
 
405
+ if ( in_array( $_size, self::$defaultSizes ) ) {
406
  $sizes[ $_size ]['width'] = intval(get_option( $_size . '_size_w' ));
407
  $sizes[ $_size ]['height'] = intval(get_option( $_size . '_size_h' ));
408
  $sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
419
  return $sizes;
420
  }
421
 
422
+ public function getOptions() {
423
+ return get_option(self::$optionsKey);
424
  }
425
 
426
+ public function getNonceBase() {
427
  return 'crop-post-thumbnails-nonce-base';
428
  }
429
  }
js/app/app.js ADDED
@@ -0,0 +1,586 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var CROP_THUMBNAILS_VUE = {
2
+ app:null,//will be initialized in modal/modal.js
3
+ components : {}
4
+ };
5
+
6
+
7
+ /**
8
+ * Provide a global accessable cache-break-function (only available on backend-pages where crop-thumbnail is active --> post-editor, mediathek)
9
+ * Calling this function will add a timestamp on the provided Image-Element.
10
+ * ATTENTION: using this will also delete all other parameters on the images src-attribute.
11
+ * @param {dom-element / jquery-selection} elem
12
+ */
13
+ CROP_THUMBNAILS_DO_CACHE_BREAK = function(elem) {
14
+ var $ = jQuery;
15
+ var images = $(elem);
16
+ for(var i = 0; i<images.length; i++) {
17
+ var img = $(images[i]);//select image
18
+ var imageUrl = img.attr('src');
19
+ var imageUrlArray = imageUrl.split("?");
20
+
21
+ img.attr('src',imageUrlArray[0]+'?&cacheBreak='+(new Date()).getTime());
22
+ }
23
+ };
24
+
25
+ /**
26
+ * Create Listener for click-events with element-class ".cropThumbnailsLink".
27
+ * Open the modal box.
28
+ */
29
+ jQuery(document).ready(function($) {
30
+ $(document).on('click', '.cropThumbnailsLink', function(e) {
31
+ e.preventDefault();
32
+
33
+ //get the data from the link
34
+ var data = $(this).data('cropthumbnail');
35
+
36
+ var title = $(this).attr('title');
37
+ var posttype = null;
38
+ if(data.posttype!==undefined) {
39
+ posttype = data.posttype;
40
+ }
41
+
42
+ var modal = new CROP_THUMBNAILS_VUE.modal();
43
+ modal.open(data.image_id, posttype, title);
44
+ });
45
+ });
46
+
47
+ if (!Array.prototype.filter) {
48
+ Array.prototype.filter = function(fun/*, thisArg*/) {
49
+ 'use strict';
50
+
51
+ if (this === void 0 || this === null) {
52
+ throw new TypeError();
53
+ }
54
+
55
+ var t = Object(this);
56
+ var len = t.length >>> 0;
57
+ if (typeof fun !== 'function') {
58
+ throw new TypeError();
59
+ }
60
+
61
+ var res = [];
62
+ var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
63
+ for (var i = 0; i < len; i++) {
64
+ if (i in t) {
65
+ var val = t[i];
66
+
67
+ // NOTE: Technically this should Object.defineProperty at
68
+ // the next index, as push can be affected by
69
+ // properties on Object.prototype and Array.prototype.
70
+ // But that method's new, and collisions should be
71
+ // rare, so use the more-compatible alternative.
72
+ if (fun.call(thisArg, val, i, t)) {
73
+ res.push(val);
74
+ }
75
+ }
76
+ }
77
+
78
+ return res;
79
+ };
80
+ }
81
+
82
+ if (!Array.prototype.find) {
83
+ Array.prototype.find = function(predicate) {
84
+ 'use strict';
85
+ if (this == null) {
86
+ throw new TypeError('Array.prototype.find called on null or undefined');
87
+ }
88
+ if (typeof predicate !== 'function') {
89
+ throw new TypeError('predicate must be a function');
90
+ }
91
+ var list = Object(this);
92
+ var length = list.length >>> 0;
93
+ var thisArg = arguments[1];
94
+ var value;
95
+
96
+ for (var i = 0; i < length; i++) {
97
+ value = list[i];
98
+ if (predicate.call(thisArg, value, i, list)) {
99
+ return value;
100
+ }
101
+ }
102
+ return undefined;
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Waiting x milliseconds for a final event than call the callback.
108
+ * @see http://stackoverflow.com/a/4541963
109
+ */
110
+ var CPT_waitForFinalEvent = (function () {
111
+ var timers = {};
112
+ return function (callback, ms, uniqueId) {
113
+ if (!uniqueId) {
114
+ uniqueId = "Don't call this twice without a uniqueId";
115
+ }
116
+ if (timers[uniqueId]) {
117
+ clearTimeout (timers[uniqueId]);
118
+ }
119
+ timers[uniqueId] = setTimeout(callback, ms);
120
+ };
121
+ })();
122
+
123
+
124
+ /** USAGE ******************
125
+ $(window).resize(function () {
126
+ CPT_waitForFinalEvent(function(){
127
+ alert('Resize...');
128
+ }, 500, "some unique string");
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:{
135
+ image : {
136
+ required: true,
137
+ type:String
138
+ }
139
+ },
140
+ data:function() {
141
+ return {
142
+ status:null
143
+ };
144
+ },
145
+ watch:{
146
+ image:function() {
147
+ this.setup();
148
+ }
149
+ },
150
+ mounted:function() {
151
+ this.setup();
152
+ },
153
+ methods:{
154
+ setup : function() {
155
+ var that = this;
156
+ that.setStart();
157
+ setTimeout(function() {
158
+ var imgLoad = imagesLoaded( that.$el );
159
+ imgLoad
160
+ .once('done',function() {
161
+ if(that.status!=='failed') {
162
+ that.setComplete();
163
+ }
164
+ })
165
+ .once('fail',function() {
166
+ that.setFailed();
167
+ })
168
+ ;
169
+ },300);
170
+ },
171
+ setComplete : function() {
172
+ this.status = 'completed';
173
+ },
174
+ setStart : function() {
175
+ this.status = 'loading';
176
+ },
177
+ setFailed : function() {
178
+ this.status = 'failed';
179
+ }
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:{
201
+ imageId : {
202
+ required: true,
203
+ type:Number
204
+ },
205
+ posttype : {
206
+ required:false,
207
+ type:String,
208
+ default:null
209
+ }
210
+ },
211
+ components: {
212
+ loadingcontainer : CROP_THUMBNAILS_VUE.components.loadingcontainer,
213
+ message : CROP_THUMBNAILS_VUE.components.message
214
+ },
215
+ data:function() {
216
+ return {
217
+ cropData : null,//
218
+ loading : false,//will be true as long as the crop-request is running
219
+ selectSameRatio : true,//boolean value if same ratio image-sizes should be selected at once
220
+ croppingApi : null,//the object of the crop-library
221
+ currentCropSize : null,//the size of the cropp region (needed for lowResWarning)
222
+ lang : null,//language-variable (filled after initial request)
223
+ nonce : null,//the nonce for the crop-request
224
+ showDebugType : null,//the type of the debug to show: null-> no debug open, 'js' -> show jsDebug, 'data' -> show dataDebug
225
+ dataDebug : null//will be filled after the crop request finished
226
+ };
227
+ },
228
+ mounted:function() {
229
+ this.loadCropData();
230
+ },
231
+ computed:{
232
+ cropImage : function() {
233
+ if(this.cropData!==undefined) {
234
+ var result = this.cropData.sourceImage.full;
235
+ var targetRatio = Math.round(result.ratio * 10);
236
+ if(this.cropData.sourceImage.large!==null
237
+ && this.cropData.sourceImage.large.width>745
238
+ && targetRatio === Math.round(this.cropData.sourceImage.large.ratio * 10)
239
+ && this.cropData.sourceImage.full.url !== this.cropData.sourceImage.large.url
240
+ ) {
241
+ result = this.cropData.sourceImage.large;
242
+ }
243
+ if(this.cropData.sourceImage.medium_large!==null
244
+ && this.cropData.sourceImage.medium_large.width>745
245
+ && targetRatio === Math.round(this.cropData.sourceImage.medium_large.ratio * 10)
246
+ && this.cropData.sourceImage.full.url !== this.cropData.sourceImage.medium_large.url
247
+ ) {
248
+ result = this.cropData.sourceImage.medium_large;
249
+ }
250
+ return result;
251
+ }
252
+ },
253
+ filteredImageSizes : function() {
254
+ return this.cropData.imageSizes
255
+ .filter(function(elem) {
256
+ return !elem.hideByPostType;
257
+ });
258
+ },
259
+ activeImageSizes : function() {
260
+ return this.cropData.imageSizes
261
+ .filter(function(elem) {
262
+ return elem.active;
263
+ });
264
+ },
265
+ sourceImageHasOrientation : function() {
266
+ try {
267
+ if(typeof this.cropData.sourceImageMeta.orientation === 'string' && this.cropData.sourceImageMeta.orientation !== '1' && this.cropData.sourceImageMeta.orientation !== '0') {
268
+ return true;
269
+ }
270
+ } catch(e) {}
271
+ return false;
272
+ }
273
+ },
274
+ methods:{
275
+ loadCropData : function() {
276
+ var that = this;
277
+ var getParameter = {
278
+ action : 'cpt_cropdata',
279
+ imageId : this.imageId,
280
+ posttype : this.posttype
281
+ };
282
+ that.loading = true;
283
+ jQuery.get(ajaxurl,getParameter,function(responseData) {
284
+ that.makeAllInactive(responseData.imageSizes);
285
+ that.addCacheBreak(responseData.imageSizes);
286
+ that.cropData = responseData;
287
+ that.lang = that.cropData.lang;
288
+ that.nonce = that.cropData.nonce;
289
+ delete that.cropData.nonce;
290
+ }).always(function() {
291
+ that.loading = false;
292
+ });
293
+ },
294
+ isLowRes : function(image) {
295
+ if(!image.active || this.currentCropSize===null) {
296
+ return false;
297
+ }
298
+ if(image.width===0 && this.currentCropSize.height < image.height) {
299
+ return true;
300
+ }
301
+ if(image.height===0 && this.currentCropSize.width < image.width) {
302
+ return true;
303
+ }
304
+ if(image.height===9999) {
305
+ if(this.currentCropSize.width < image.width) {
306
+ return true;
307
+ }
308
+ return false;
309
+ }
310
+ if(image.width===9999) {
311
+ if(this.currentCropSize.height < image.height) {
312
+ return true;
313
+ }
314
+ return false;
315
+ }
316
+ if(this.currentCropSize.width < image.width || this.currentCropSize.height < image.height) {
317
+ return true;
318
+ }
319
+ return false;
320
+ },
321
+ toggleActive : function(image) {
322
+ var newValue = !image.active;
323
+
324
+ if(image.active===false) {
325
+ this.makeAllInactive();
326
+ }
327
+
328
+ if(this.selectSameRatio) {
329
+ this.cropData.imageSizes.forEach(function(i) {
330
+ if(i.printRatio === image.printRatio) {
331
+ i.active = newValue;
332
+ }
333
+ });
334
+ } else {
335
+ image.active = newValue;
336
+ }
337
+
338
+ if(this.activeImageSizes.length>0) {
339
+ this.activateCropArea();
340
+ } else {
341
+ this.deactivateCropArea();
342
+ }
343
+ },
344
+ makeAllInactive : function(imageSizes) {
345
+ if(imageSizes===undefined) {
346
+ imageSizes = this.cropData.imageSizes;
347
+ }
348
+ imageSizes.forEach(function(i) {
349
+ i.active = false;
350
+ i.lowResWarning = false;
351
+ });
352
+ this.deactivateCropArea();
353
+ },
354
+ addCacheBreak : function(imageSizes) {
355
+ if(imageSizes===undefined) {
356
+ imageSizes = this.cropData.imageSizes;
357
+ }
358
+ imageSizes.forEach(function(i) {
359
+ i.cacheBreak = Date.now();
360
+ });
361
+ },
362
+ updateCurrentCrop : function() {
363
+ var result = null;
364
+ if(this.croppingApi!==null) {
365
+ var size = this.croppingApi.tellSelect();
366
+ result = {
367
+ width : Math.round(size.w),
368
+ height : Math.round(size.h)
369
+ };
370
+ }
371
+ this.currentCropSize = result;
372
+ },
373
+ activateCropArea : function() {
374
+ var that = this;
375
+ that.deactivateCropArea();
376
+
377
+ function getPreselect(width,height,targetRatio) {
378
+ var x0 = 0;
379
+ var y0 = 0;
380
+ var x1 = width;
381
+ var y1 = height;
382
+ var sourceRatio = width/height;
383
+
384
+ if(sourceRatio <= targetRatio) {
385
+ y0 = (height / 2) - ((width / targetRatio) / 2);
386
+ y1 = height-y0;
387
+ } else {
388
+ x0 = (width / 2) - ((height * targetRatio) / 2);
389
+ x1 = width-x0;
390
+ }
391
+ var result = [x0,y0,x1,y1];
392
+ return result;
393
+ }
394
+
395
+ var options = {
396
+ trueSize: [ that.cropData.sourceImage.full.width , that.cropData.sourceImage.full.height ],
397
+ aspectRatio: 0,
398
+ setSelect: [],
399
+ onSelect:that.updateCurrentCrop
400
+ };
401
+
402
+ //get the options
403
+ that.activeImageSizes.forEach(function(i) {
404
+ if(options.aspectRatio === 0) {
405
+ options.aspectRatio = i.ratio;//initial
406
+ }
407
+ if(options.aspectRatio !== i.ratio) {
408
+ console.info('Crop Thumbnails: print ratio is different from normal ratio on image size "'+i.name+'".');
409
+ }
410
+ });
411
+
412
+ options.setSelect = getPreselect(that.cropData.sourceImage.full.width , that.cropData.sourceImage.full.height, options.aspectRatio);
413
+
414
+ //debug
415
+ if(that.cropData.options.debug_js) {
416
+ console.info('Cropping options',options);
417
+ }
418
+
419
+ jQuery(that.$el).find('img.cptCroppingImage').Jcrop(options,function(){
420
+ that.croppingApi = this;
421
+ that.updateCurrentCrop();
422
+ });
423
+ },
424
+ deactivateCropArea : function() {
425
+ if(this.croppingApi!==null) {
426
+ this.croppingApi.destroy();
427
+ this.croppingApi = null;
428
+ this.currentCropSize = null;
429
+ }
430
+ },
431
+ showDebugClick : function(type) {
432
+ if(this.showDebugType === type) {
433
+ this.showDebugType = null;
434
+ } else {
435
+ this.showDebugType = type;
436
+ }
437
+ },
438
+ cropThumbnails : function() {
439
+ var that = this;
440
+
441
+ function getDataOfActiveImageSizes() {
442
+ var result = [];
443
+ that.activeImageSizes.forEach(function(i) {
444
+ if(i.active) {
445
+ var tmp = {
446
+ name: i.name,
447
+ width:i.width,
448
+ height:i.height,
449
+ ratio:i.ratio,
450
+ crop:i.crop
451
+ };
452
+ result.push(tmp);
453
+ }
454
+ });
455
+ return result;
456
+ }
457
+
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),
465
+ crop_thumbnails : JSON.stringify({
466
+ 'selection' : that.croppingApi.tellSelect(),
467
+ 'sourceImageId' : that.cropData.sourceImageId,
468
+ 'activeImageSizes' : getDataOfActiveImageSizes()
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) {
476
+ that.dataDebug = responseData.debug;
477
+ console.log('Save Function Debug',responseData.debug);
478
+ }
479
+ if(responseData.error!==undefined) {
480
+ alert(responseData.error);
481
+ return;
482
+ }
483
+ if(responseData.success!==undefined) {
484
+ if(responseData.changedImageName!==undefined) {
485
+ //update activeImageSizes with the new URLs
486
+ that.activeImageSizes.forEach(function(value,key) {
487
+ if(responseData.changedImageName[value.name]!==undefined) {
488
+ value.url = responseData.changedImageName[value.name];
489
+ }
490
+ });
491
+ }
492
+ that.addCacheBreak(that.activeImageSizes);
493
+ return;
494
+ }
495
+ })
496
+ .fail(function(response) {
497
+ console.error(error);
498
+ })
499
+ .always(function() {
500
+ that.loading = false;
501
+ });
502
+ }
503
+ }
504
+ }
505
+ };
506
+
507
+ CROP_THUMBNAILS_VUE.modal = function() {
508
+ var $ = jQuery;
509
+ var that = this;
510
+
511
+ function removeModal() {
512
+ $('#cpt_Modal .cpt_ModalClose, #cpt_Modal').unbind('click');
513
+ $('#cpt_Modal').remove();
514
+ $('body').removeClass('cpt_ModalIsOpen');
515
+ }
516
+
517
+ /**
518
+ * Should be called when the close-button is clicked.
519
+ * Will trigger the "cropThumbnailModalClosed"-event to the body on close,
520
+ * so everyone that is up to, could build a cache-breaker on their images.
521
+ * HOW-TO cache-break:
522
+ * $('body').on('cropThumbnailModalClosed',function() {
523
+ * CROP_THUMBNAILS_DO_CACHE_BREAK( $('.your-image-selector') );
524
+ * });
525
+ * @var Event
526
+ */
527
+ that.close = function(event) {
528
+ CROP_THUMBNAILS_VUE.app.$destroy();
529
+ CROP_THUMBNAILS_VUE.app = null;
530
+ removeModal();
531
+ $('body').trigger('cropThumbnailModalClosed');
532
+ document.removeEventListener('keydown', that.closeByEscKey, true);
533
+ };
534
+
535
+ /**
536
+ * Should be called when the background is clicked
537
+ * @var Event
538
+ */
539
+ that.closeByBackground = function(event) {
540
+ if(event.target==document.getElementById('cpt_Modal')) {
541
+ that.close(event);
542
+ }
543
+ };
544
+
545
+ that.closeByEscKey = function(event) {
546
+ if ( !event.keyCode || event.keyCode === 27 ) {
547
+ event.stopPropagation();
548
+ that.close(event);
549
+ }
550
+ }
551
+
552
+ that.open = function(imageId,posttype,title) {
553
+
554
+
555
+ var id = imageId;
556
+ var modalHtml = '';
557
+ modalHtml+= '<div id="cpt_Modal" class="cpt_Modal">';
558
+ modalHtml+= '<div class="cpt_ModalDialog" role="dialog" aria-label="'+$('<div>').text(title).html()+'">';
559
+ modalHtml+= '<button type="button" class="cpt_ModalClose" aria-label="close">&times;</button>';
560
+ modalHtml+= '<div class="cpt_ModalHeader"><div class="cpt_ModalTitle">'+title+'</div></div>';
561
+
562
+ modalHtml+= '<div class="cpt_ModalContent" id="cpt_crop_editor">';
563
+ modalHtml+= '<cropeditor image-id="'+id+'"';
564
+ if(typeof posttype === 'string') {
565
+ modalHtml+= ' posttype="'+posttype+'"';
566
+ }
567
+ modalHtml+= '></cropeditor>'
568
+ modalHtml+= '</div>';//end cpt_ModalContent
569
+ modalHtml+= '</div>';//end cpt_ModalDialog
570
+ modalHtml+= '</div>';//end cpt_Modal;
571
+
572
+
573
+ $('body').prepend(modalHtml).addClass('cpt_ModalIsOpen');
574
+ $('#cpt_Modal .cpt_ModalClose').click(that.close);
575
+ $('#cpt_Modal').on('touchstart mousedown',that.closeByBackground);
576
+ document.addEventListener('keydown', that.closeByEscKey, true);
577
+
578
+ CROP_THUMBNAILS_VUE.app = new Vue({
579
+ el:'#cpt_crop_editor',
580
+ mounted:function() {
581
+ console.log('cpt_crop_editor mounted');
582
+ },
583
+ components: CROP_THUMBNAILS_VUE.components
584
+ });
585
+ };
586
+ };
js/app/vendor/cropper.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Cropper.js v1.0.0-rc
3
+ * https://github.com/fengyuanchen/cropperjs
4
+ *
5
+ * Copyright (c) 2017 Fengyuan Chen
6
+ * Released under the MIT license
7
+ *
8
+ * Date: 2017-03-25T12:02:21.062Z
9
+ */
10
+
11
+ .cropper-container{font-size:0;line-height:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;direction:ltr;-ms-touch-action:none;touch-action:none}.cropper-container img{display:block;min-width:0!important;max-width:none!important;min-height:0!important;max-height:none!important;width:100%;height:100%;image-orientation:0deg}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{position:absolute;top:0;right:0;bottom:0;left:0}.cropper-wrap-box{overflow:hidden}.cropper-drag-box{opacity:0;background-color:#fff}.cropper-modal{opacity:.5;background-color:#000}.cropper-view-box{display:block;overflow:hidden;width:100%;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75)}.cropper-dashed{position:absolute;display:block;opacity:.5;border:0 dashed #eee}.cropper-dashed.dashed-h{top:33.33333%;left:0;width:100%;height:33.33333%;border-top-width:1px;border-bottom-width:1px}.cropper-dashed.dashed-v{top:0;left:33.33333%;width:33.33333%;height:100%;border-right-width:1px;border-left-width:1px}.cropper-center{position:absolute;top:50%;left:50%;display:block;width:0;height:0;opacity:.75}.cropper-center:after,.cropper-center:before{position:absolute;display:block;content:" ";background-color:#eee}.cropper-center:before{top:0;left:-3px;width:7px;height:1px}.cropper-center:after{top:-3px;left:0;width:1px;height:7px}.cropper-face,.cropper-line,.cropper-point{position:absolute;display:block;width:100%;height:100%;opacity:.1}.cropper-face{top:0;left:0;background-color:#fff}.cropper-line{background-color:#39f}.cropper-line.line-e{top:0;right:-3px;width:5px;cursor:e-resize}.cropper-line.line-n{top:-3px;left:0;height:5px;cursor:n-resize}.cropper-line.line-w{top:0;left:-3px;width:5px;cursor:w-resize}.cropper-line.line-s{bottom:-3px;left:0;height:5px;cursor:s-resize}.cropper-point{width:5px;height:5px;opacity:.75;background-color:#39f}.cropper-point.point-e{top:50%;right:-3px;margin-top:-3px;cursor:e-resize}.cropper-point.point-n{top:-3px;left:50%;margin-left:-3px;cursor:n-resize}.cropper-point.point-w{top:50%;left:-3px;margin-top:-3px;cursor:w-resize}.cropper-point.point-s{bottom:-3px;left:50%;margin-left:-3px;cursor:s-resize}.cropper-point.point-ne{top:-3px;right:-3px;cursor:ne-resize}.cropper-point.point-nw{top:-3px;left:-3px;cursor:nw-resize}.cropper-point.point-sw{bottom:-3px;left:-3px;cursor:sw-resize}.cropper-point.point-se{right:-3px;bottom:-3px;width:20px;height:20px;cursor:se-resize;opacity:1}@media (min-width:768px){.cropper-point.point-se{width:15px;height:15px}}@media (min-width:992px){.cropper-point.point-se{width:10px;height:10px}}@media (min-width:1200px){.cropper-point.point-se{width:5px;height:5px;opacity:.75}}.cropper-point.point-se:before{position:absolute;right:-50%;bottom:-50%;display:block;width:200%;height:200%;content:" ";opacity:0;background-color:#39f}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{position:absolute;display:block;width:0;height:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
js/app/vendor/cropper.min.js ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Cropper.js v1.0.0-rc
3
+ * https://github.com/fengyuanchen/cropperjs
4
+ *
5
+ * Copyright (c) 2017 Fengyuan Chen
6
+ * Released under the MIT license
7
+ *
8
+ * Date: 2017-03-25T12:02:21.062Z
9
+ */
10
+
11
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Cropper=e()}(this,function(){"use strict";function t(t){return rt.call(t).slice(8,-1).toLowerCase()}function e(t){return"number"==typeof t&&!isNaN(t)}function a(t){return"undefined"==typeof t}function i(t){return"object"===("undefined"==typeof t?"undefined":Z(t))&&null!==t}function o(t){if(!i(t))return!1;try{var e=t.constructor,a=e.prototype;return e&&a&&ht.call(a,"isPrototypeOf")}catch(t){return!1}}function n(e){return"function"===t(e)}function r(e){return Array.isArray?Array.isArray(e):"array"===t(e)}function h(t){return"string"==typeof t&&(t=t.trim?t.trim():t.replace(et,"$1")),t}function c(t,a){if(t&&n(a)){var o=void 0;if(r(t)||e(t.length)){var h=t.length;for(o=0;o<h&&a.call(t,t[o],o,t)!==!1;o++);}else i(t)&&Object.keys(t).forEach(function(e){a.call(t,t[e],e,t)})}return t}function s(t){for(var e=arguments.length,a=Array(e>1?e-1:0),o=1;o<e;o++)a[o-1]=arguments[o];if(i(t)&&a.length>0){if(Object.assign)return Object.assign.apply(Object,[t].concat(a));a.forEach(function(e){i(e)&&Object.keys(e).forEach(function(a){t[a]=e[a]})})}return t}function d(t,e){for(var a=arguments.length,i=Array(a>2?a-2:0),o=2;o<a;o++)i[o-2]=arguments[o];return function(){for(var a=arguments.length,o=Array(a),n=0;n<a;n++)o[n]=arguments[n];return t.apply(e,i.concat(o))}}function l(t,a){var i=t.style;c(a,function(t,a){tt.test(a)&&e(t)&&(t+="px"),i[a]=t})}function p(t,e){return t.classList?t.classList.contains(e):t.className.indexOf(e)>-1}function u(t,a){if(a){if(e(t.length))return void c(t,function(t){u(t,a)});if(t.classList)return void t.classList.add(a);var i=h(t.className);i?i.indexOf(a)<0&&(t.className=i+" "+a):t.className=a}}function m(t,a){if(a)return e(t.length)?void c(t,function(t){m(t,a)}):t.classList?void t.classList.remove(a):void(t.className.indexOf(a)>=0&&(t.className=t.className.replace(a,"")))}function f(t,a,i){if(a)return e(t.length)?void c(t,function(t){f(t,a,i)}):void(i?u(t,a):m(t,a))}function g(t){return t.replace(J,"$1-$2").toLowerCase()}function v(t,e){return i(t[e])?t[e]:t.dataset?t.dataset[e]:t.getAttribute("data-"+g(e))}function w(t,e,a){i(a)?t[e]=a:t.dataset?t.dataset[e]=a:t.setAttribute("data-"+g(e),a)}function b(t,e){if(i(t[e]))delete t[e];else if(t.dataset)try{delete t.dataset[e]}catch(a){t.dataset[e]=null}else t.removeAttribute("data-"+g(e))}function x(t,e,a){var i=h(e).split(_);return i.length>1?void c(i,function(e){x(t,e,a)}):void(t.removeEventListener?t.removeEventListener(e,a,!1):t.detachEvent&&t.detachEvent("on"+e,a))}function y(t,e,a,i){var o=h(e).split(_),n=a;return o.length>1?void c(o,function(e){y(t,e,a)}):(i&&(a=function(){for(var i=arguments.length,o=Array(i),r=0;r<i;r++)o[r]=arguments[r];return x(t,e,a),n.apply(t,o)}),void(t.addEventListener?t.addEventListener(e,a,!1):t.attachEvent&&t.attachEvent("on"+e,a)))}function M(t,e,i){if(t.dispatchEvent){var o=void 0;return n(Event)&&n(CustomEvent)?o=a(i)?new Event(e,{bubbles:!0,cancelable:!0}):new CustomEvent(e,{detail:i,bubbles:!0,cancelable:!0}):a(i)?(o=document.createEvent("Event"),o.initEvent(e,!0,!0)):(o=document.createEvent("CustomEvent"),o.initCustomEvent(e,!0,!0,i)),t.dispatchEvent(o)}return!t.fireEvent||t.fireEvent("on"+e)}function C(t){var a=t||window.event;if(a.target||(a.target=a.srcElement||document),!e(a.pageX)&&e(a.clientX)){var i=t.target.ownerDocument||document,o=i.documentElement,n=i.body;a.pageX=a.clientX+((o&&o.scrollLeft||n&&n.scrollLeft||0)-(o&&o.clientLeft||n&&n.clientLeft||0)),a.pageY=a.clientY+((o&&o.scrollTop||n&&n.scrollTop||0)-(o&&o.clientTop||n&&n.clientTop||0))}return a}function D(t){var e=document.documentElement,a=t.getBoundingClientRect();return{left:a.left+((window.scrollX||e&&e.scrollLeft||0)-(e&&e.clientLeft||0)),top:a.top+((window.scrollY||e&&e.scrollTop||0)-(e&&e.clientTop||0))}}function B(t,e){return t.getElementsByTagName(e)}function k(t,e){return t.getElementsByClassName?t.getElementsByClassName(e):t.querySelectorAll("."+e)}function T(t){return document.createElement(t)}function L(t,e){t.appendChild(e)}function W(t){t.parentNode&&t.parentNode.removeChild(t)}function X(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function Y(t){var e=t.match(Q);return e&&(e[1]!==location.protocol||e[2]!==location.hostname||e[3]!==location.port)}function E(t){var e="timestamp="+(new Date).getTime();return t+(t.indexOf("?")===-1?"?":"&")+e}function H(t,e){if(t.naturalWidth&&!ot)return void e(t.naturalWidth,t.naturalHeight);var a=T("img");a.onload=function(){e(this.width,this.height)},a.src=t.src}function N(t){var a=[],i=t.translateX,o=t.translateY,n=t.rotate,r=t.scaleX,h=t.scaleY;e(i)&&0!==i&&a.push("translateX("+i+"px)"),e(o)&&0!==o&&a.push("translateY("+o+"px)"),e(n)&&0!==n&&a.push("rotate("+n+"deg)"),e(r)&&1!==r&&a.push("scaleX("+r+")"),e(h)&&1!==h&&a.push("scaleY("+h+")");var c=a.length?a.join(" "):"none";return{WebkitTransform:c,msTransform:c,transform:c}}function O(t,e){var a=Math.abs(t.degree)%180,i=(a>90?180-a:a)*Math.PI/180,o=Math.sin(i),n=Math.cos(i),r=t.width,h=t.height,c=t.aspectRatio,s=void 0,d=void 0;return e?(s=r/(n+o/c),d=s/c):(s=r*n+h*o,d=r*o+h*n),{width:s,height:d}}function z(t,a){var i=T("canvas"),o=i.getContext("2d"),n=0,r=0,h=a.naturalWidth,c=a.naturalHeight,s=a.rotate,d=a.scaleX,l=a.scaleY,p=e(d)&&e(l)&&(1!==d||1!==l),u=e(s)&&0!==s,m=u||p,f=h*Math.abs(d||1),g=c*Math.abs(l||1),v=void 0,w=void 0,b=void 0;return p&&(v=f/2,w=g/2),u&&(b=O({width:f,height:g,degree:s}),f=b.width,g=b.height,v=f/2,w=g/2),i.width=f,i.height=g,m&&(n=-h/2,r=-c/2,o.save(),o.translate(v,w)),u&&o.rotate(s*Math.PI/180),p&&o.scale(d,l),o.drawImage(t,Math.floor(n),Math.floor(r),Math.floor(h),Math.floor(c)),m&&o.restore(),i}function A(t,e,a){var i="",o=e;for(a+=e;o<a;o++)i+=ct(t.getUint8(o));return i}function R(t){var e=new DataView(t),a=e.byteLength,i=void 0,o=void 0,n=void 0,r=void 0,h=void 0,c=void 0,s=void 0,d=void 0,l=void 0,p=void 0;if(255===e.getUint8(0)&&216===e.getUint8(1))for(l=2;l<a;){if(255===e.getUint8(l)&&225===e.getUint8(l+1)){s=l;break}l++}if(s&&(o=s+4,n=s+10,"Exif"===A(e,o,4)&&(c=e.getUint16(n),h=18761===c,(h||19789===c)&&42===e.getUint16(n+2,h)&&(r=e.getUint32(n+4,h),r>=8&&(d=n+r)))),d)for(a=e.getUint16(d,h),p=0;p<a;p++)if(l=d+12*p+2,274===e.getUint16(l,h)){l+=8,i=e.getUint16(l,h),ot&&e.setUint16(l,1,h);break}return i}function S(t){var e=t.replace(G,""),a=atob(e),i=a.length,o=new ArrayBuffer(i),n=new Uint8Array(o),r=void 0;for(r=0;r<i;r++)n[r]=a.charCodeAt(r);return o}function I(t){var e=new Uint8Array(t),a=e.length,i="",o=void 0;for(o=0;o<a;o++)i+=ct(e[o]);return"data:image/jpeg;base64,"+btoa(i)}function U(t,e){var a=t.pageX,i=t.pageY,o={endX:a,endY:i};return e?o:s({startX:a,startY:i},o)}function j(t){var e=s({},t),a=[];return c(t,function(t,i){delete e[i],c(e,function(e){var i=Math.abs(t.startX-e.startX),o=Math.abs(t.startY-e.startY),n=Math.abs(t.endX-e.endX),r=Math.abs(t.endY-e.endY),h=Math.sqrt(i*i+o*o),c=Math.sqrt(n*n+r*r),s=(c-h)/h;a.push(s)})}),a.sort(function(t,e){return Math.abs(t)<Math.abs(e)}),a[0]}function P(t){var e=0,a=0,i=0;return c(t,function(t){var o=t.startX,n=t.startY;e+=o,a+=n,i+=1}),e/=i,a/=i,{pageX:e,pageY:a}}var q={viewMode:0,dragMode:"crop",aspectRatio:NaN,data:null,preview:"",responsive:!0,restore:!0,checkCrossOrigin:!0,checkOrientation:!0,modal:!0,guides:!0,center:!0,highlight:!0,background:!0,autoCrop:!0,autoCropArea:.8,movable:!0,rotatable:!0,scalable:!0,zoomable:!0,zoomOnTouch:!0,zoomOnWheel:!0,wheelZoomRatio:.1,cropBoxMovable:!0,cropBoxResizable:!0,toggleDragModeOnDblclick:!0,minCanvasWidth:0,minCanvasHeight:0,minCropBoxWidth:0,minCropBoxHeight:0,minContainerWidth:200,minContainerHeight:100,ready:null,cropstart:null,cropmove:null,cropend:null,crop:null,zoom:null},$='<div class="cropper-container"><div class="cropper-wrap-box"><div class="cropper-canvas"></div></div><div class="cropper-drag-box"></div><div class="cropper-crop-box"><span class="cropper-view-box"></span><span class="cropper-dashed dashed-h"></span><span class="cropper-dashed dashed-v"></span><span class="cropper-center"></span><span class="cropper-face"></span><span class="cropper-line line-e" data-action="e"></span><span class="cropper-line line-n" data-action="n"></span><span class="cropper-line line-w" data-action="w"></span><span class="cropper-line line-s" data-action="s"></span><span class="cropper-point point-e" data-action="e"></span><span class="cropper-point point-n" data-action="n"></span><span class="cropper-point point-w" data-action="w"></span><span class="cropper-point point-s" data-action="s"></span><span class="cropper-point point-ne" data-action="ne"></span><span class="cropper-point point-nw" data-action="nw"></span><span class="cropper-point point-sw" data-action="sw"></span><span class="cropper-point point-se" data-action="se"></span></div></div>',Z="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},K=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},V=function(){function t(t,e){for(var a=0;a<e.length;a++){var i=e[a];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,a,i){return a&&t(e.prototype,a),i&&t(e,i),e}}(),F=function(t){if(Array.isArray(t)){for(var e=0,a=Array(t.length);e<t.length;e++)a[e]=t[e];return a}return Array.from(t)},G=/^data:.*,/,J=/([a-z\d])([A-Z])/g,Q=/^(https?:)\/\/([^:\/?#]+):?(\d*)/i,_=/\s+/,tt=/^(width|height|left|top|marginLeft|marginTop)$/,et=/^\s+(.*)\s+$/,at=/(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i,it="undefined"!=typeof window?window.navigator:null,ot=it&&at.test(it.userAgent),nt=Object.prototype,rt=nt.toString,ht=nt.hasOwnProperty,ct=(Array.prototype.slice,String.fromCharCode),st={render:function(){var t=this;t.initContainer(),t.initCanvas(),t.initCropBox(),t.renderCanvas(),t.cropped&&t.renderCropBox()},initContainer:function(){var t=this,e=t.options,a=t.element,i=t.container,o=t.cropper,n="cropper-hidden",r=void 0;u(o,n),m(a,n),t.containerData=r={width:Math.max(i.offsetWidth,Number(e.minContainerWidth)||200),height:Math.max(i.offsetHeight,Number(e.minContainerHeight)||100)},l(o,{width:r.width,height:r.height}),u(a,n),m(o,n)},initCanvas:function(){var t=this,e=t.options.viewMode,a=t.containerData,i=t.imageData,o=90===Math.abs(i.rotate),n=o?i.naturalHeight:i.naturalWidth,r=o?i.naturalWidth:i.naturalHeight,h=n/r,c=a.width,d=a.height;a.height*h>a.width?3===e?c=a.height*h:d=a.width/h:3===e?d=a.width/h:c=a.height*h;var l={naturalWidth:n,naturalHeight:r,aspectRatio:h,width:c,height:d};l.oldLeft=l.left=(a.width-c)/2,l.oldTop=l.top=(a.height-d)/2,t.canvasData=l,t.limited=1===e||2===e,t.limitCanvas(!0,!0),t.initialImageData=s({},i),t.initialCanvasData=s({},l)},limitCanvas:function(t,e){var a=this,i=a.options,o=i.viewMode,n=a.containerData,r=a.canvasData,h=r.aspectRatio,c=a.cropBoxData,s=a.cropped&&c;if(t){var d=Number(i.minCanvasWidth)||0,l=Number(i.minCanvasHeight)||0;o>1?(d=Math.max(d,n.width),l=Math.max(l,n.height),3===o&&(l*h>d?d=l*h:l=d/h)):o>0&&(d?d=Math.max(d,s?c.width:0):l?l=Math.max(l,s?c.height:0):s&&(d=c.width,l=c.height,l*h>d?d=l*h:l=d/h)),d&&l?l*h>d?l=d/h:d=l*h:d?l=d/h:l&&(d=l*h),r.minWidth=d,r.minHeight=l,r.maxWidth=1/0,r.maxHeight=1/0}if(e)if(o){var p=n.width-r.width,u=n.height-r.height;r.minLeft=Math.min(0,p),r.minTop=Math.min(0,u),r.maxLeft=Math.max(0,p),r.maxTop=Math.max(0,u),s&&a.limited&&(r.minLeft=Math.min(c.left,c.left+(c.width-r.width)),r.minTop=Math.min(c.top,c.top+(c.height-r.height)),r.maxLeft=c.left,r.maxTop=c.top,2===o&&(r.width>=n.width&&(r.minLeft=Math.min(0,p),r.maxLeft=Math.max(0,p)),r.height>=n.height&&(r.minTop=Math.min(0,u),r.maxTop=Math.max(0,u))))}else r.minLeft=-r.width,r.minTop=-r.height,r.maxLeft=n.width,r.maxTop=n.height},renderCanvas:function(t){var e=this,a=e.canvasData,i=e.imageData,o=i.rotate;if(e.rotated){e.rotated=!1;var n=O({width:i.width,height:i.height,degree:o}),r=n.width/n.height,h=1===i.aspectRatio;if(h||r!==a.aspectRatio){if(a.left-=(n.width-a.width)/2,a.top-=(n.height-a.height)/2,a.width=n.width,a.height=n.height,a.aspectRatio=r,a.naturalWidth=i.naturalWidth,a.naturalHeight=i.naturalHeight,h&&o%90||o%180){var c=O({width:i.naturalWidth,height:i.naturalHeight,degree:o});a.naturalWidth=c.width,a.naturalHeight=c.height}e.limitCanvas(!0,!1)}}(a.width>a.maxWidth||a.width<a.minWidth)&&(a.left=a.oldLeft),(a.height>a.maxHeight||a.height<a.minHeight)&&(a.top=a.oldTop),a.width=Math.min(Math.max(a.width,a.minWidth),a.maxWidth),a.height=Math.min(Math.max(a.height,a.minHeight),a.maxHeight),e.limitCanvas(!1,!0),a.oldLeft=a.left=Math.min(Math.max(a.left,a.minLeft),a.maxLeft),a.oldTop=a.top=Math.min(Math.max(a.top,a.minTop),a.maxTop),l(e.canvas,s({width:a.width,height:a.height},N({translateX:a.left,translateY:a.top}))),e.renderImage(),e.cropped&&e.limited&&e.limitCropBox(!0,!0),t&&e.output()},renderImage:function(t){var e=this,a=e.canvasData,i=e.imageData,o=void 0,n=void 0,r=void 0,h=void 0;i.rotate&&(n=O({width:a.width,height:a.height,degree:i.rotate,aspectRatio:i.aspectRatio},!0),r=n.width,h=n.height,o={width:r,height:h,left:(a.width-r)/2,top:(a.height-h)/2}),s(i,o||{width:a.width,height:a.height,left:0,top:0}),l(e.image,s({width:i.width,height:i.height},N(s({translateX:i.left,translateY:i.top},i)))),t&&e.output()},initCropBox:function(){var t=this,e=t.options,a=e.aspectRatio,i=Number(e.autoCropArea)||.8,o=t.canvasData,n={width:o.width,height:o.height};a&&(o.height*a>o.width?n.height=n.width/a:n.width=n.height*a),t.cropBoxData=n,t.limitCropBox(!0,!0),n.width=Math.min(Math.max(n.width,n.minWidth),n.maxWidth),n.height=Math.min(Math.max(n.height,n.minHeight),n.maxHeight),n.width=Math.max(n.minWidth,n.width*i),n.height=Math.max(n.minHeight,n.height*i),n.oldLeft=n.left=o.left+(o.width-n.width)/2,n.oldTop=n.top=o.top+(o.height-n.height)/2,t.initialCropBoxData=s({},n)},limitCropBox:function(t,e){var a=this,i=a.options,o=i.aspectRatio,n=a.containerData,r=a.canvasData,h=a.cropBoxData,c=a.limited;if(t){var s=Number(i.minCropBoxWidth)||0,d=Number(i.minCropBoxHeight)||0,l=Math.min(n.width,c?r.width:n.width),p=Math.min(n.height,c?r.height:n.height);s=Math.min(s,n.width),d=Math.min(d,n.height),o&&(s&&d?d*o>s?d=s/o:s=d*o:s?d=s/o:d&&(s=d*o),p*o>l?p=l/o:l=p*o),h.minWidth=Math.min(s,l),h.minHeight=Math.min(d,p),h.maxWidth=l,h.maxHeight=p}e&&(c?(h.minLeft=Math.max(0,r.left),h.minTop=Math.max(0,r.top),h.maxLeft=Math.min(n.width,r.left+r.width)-h.width,h.maxTop=Math.min(n.height,r.top+r.height)-h.height):(h.minLeft=0,h.minTop=0,h.maxLeft=n.width-h.width,h.maxTop=n.height-h.height))},renderCropBox:function(){var t=this,e=t.options,a=t.containerData,i=t.cropBoxData;(i.width>i.maxWidth||i.width<i.minWidth)&&(i.left=i.oldLeft),(i.height>i.maxHeight||i.height<i.minHeight)&&(i.top=i.oldTop),i.width=Math.min(Math.max(i.width,i.minWidth),i.maxWidth),i.height=Math.min(Math.max(i.height,i.minHeight),i.maxHeight),t.limitCropBox(!1,!0),i.oldLeft=i.left=Math.min(Math.max(i.left,i.minLeft),i.maxLeft),i.oldTop=i.top=Math.min(Math.max(i.top,i.minTop),i.maxTop),e.movable&&e.cropBoxMovable&&w(t.face,"action",i.width===a.width&&i.height===a.height?"move":"all"),l(t.cropBox,s({width:i.width,height:i.height},N({translateX:i.left,translateY:i.top}))),t.cropped&&t.limited&&t.limitCanvas(!0,!0),t.disabled||t.output()},output:function(){var t=this;t.preview(),t.complete&&M(t.element,"crop",t.getData())}},dt="preview",lt={initPreview:function(){var t=this,e=t.options.preview,a=T("img"),i=t.crossOrigin,o=i?t.crossOriginUrl:t.url;if(i&&(a.crossOrigin=i),a.src=o,L(t.viewBox,a),t.image2=a,e){var n=e.querySelector?[e]:document.querySelectorAll(e);t.previews=n,c(n,function(t){var e=T("img");w(t,dt,{width:t.offsetWidth,height:t.offsetHeight,html:t.innerHTML}),i&&(e.crossOrigin=i),e.src=o,e.style.cssText='display:block;width:100%;height:auto;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;image-orientation:0deg!important;"',X(t),L(t,e)})}},resetPreview:function(){c(this.previews,function(t){var e=v(t,dt);l(t,{width:e.width,height:e.height}),t.innerHTML=e.html,b(t,dt)})},preview:function(){var t=this,e=t.imageData,a=t.canvasData,i=t.cropBoxData,o=i.width,n=i.height,r=e.width,h=e.height,d=i.left-a.left-e.left,p=i.top-a.top-e.top;t.cropped&&!t.disabled&&(l(t.image2,s({width:r,height:h},N(s({translateX:-d,translateY:-p},e)))),c(t.previews,function(t){var a=v(t,dt),i=a.width,c=a.height,u=i,m=c,f=1;o&&(f=i/o,m=n*f),n&&m>c&&(f=c/n,u=o*f,m=c),l(t,{width:u,height:m}),l(B(t,"img")[0],s({width:r*f,height:h*f},N(s({translateX:-d*f,translateY:-p*f},e))))}))}},pt="undefined"!=typeof window?window.PointerEvent:null,ut=pt?"pointerdown":"touchstart mousedown",mt=pt?"pointermove":"touchmove mousemove",ft=pt?" pointerup pointercancel":"touchend touchcancel mouseup",gt="wheel mousewheel DOMMouseScroll",vt="dblclick",wt="resize",bt="cropstart",xt="cropmove",yt="cropend",Mt="crop",Ct="zoom",Dt={bind:function(){var t=this,e=t.options,a=t.element,i=t.cropper;n(e.cropstart)&&y(a,bt,e.cropstart),n(e.cropmove)&&y(a,xt,e.cropmove),n(e.cropend)&&y(a,yt,e.cropend),n(e.crop)&&y(a,Mt,e.crop),n(e.zoom)&&y(a,Ct,e.zoom),y(i,ut,t.onCropStart=d(t.cropStart,t)),e.zoomable&&e.zoomOnWheel&&y(i,gt,t.onWheel=d(t.wheel,t)),e.toggleDragModeOnDblclick&&y(i,vt,t.onDblclick=d(t.dblclick,t)),y(document,mt,t.onCropMove=d(t.cropMove,t)),y(document,ft,t.onCropEnd=d(t.cropEnd,t)),e.responsive&&y(window,wt,t.onResize=d(t.resize,t))},unbind:function(){var t=this,e=t.options,a=t.element,i=t.cropper;n(e.cropstart)&&x(a,bt,e.cropstart),n(e.cropmove)&&x(a,xt,e.cropmove),n(e.cropend)&&x(a,yt,e.cropend),n(e.crop)&&x(a,Mt,e.crop),n(e.zoom)&&x(a,Ct,e.zoom),x(i,ut,t.onCropStart),e.zoomable&&e.zoomOnWheel&&x(i,gt,t.onWheel),e.toggleDragModeOnDblclick&&x(i,vt,t.onDblclick),x(document,mt,t.onCropMove),x(document,ft,t.onCropEnd),e.responsive&&x(window,wt,t.onResize)}},Bt=/^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/,kt={resize:function(){var t=this,e=t.options,a=t.container,i=t.containerData,o=Number(e.minContainerWidth)||200,n=Number(e.minContainerHeight)||100;if(!t.disabled&&i.width!==o&&i.height!==n){var r=a.offsetWidth/i.width;1===r&&a.offsetHeight===i.height||!function(){var a=void 0,i=void 0;e.restore&&(a=t.getCanvasData(),i=t.getCropBoxData()),t.render(),e.restore&&(t.setCanvasData(c(a,function(t,e){a[e]=t*r})),t.setCropBoxData(c(i,function(t,e){i[e]=t*r})))}()}},dblclick:function(){var t=this;t.disabled||"none"===t.options.dragMode||t.setDragMode(p(t.dragBox,"cropper-crop")?"move":"crop")},wheel:function(t){var e=this,a=C(t),i=Number(e.options.wheelZoomRatio)||.1,o=1;e.disabled||(a.preventDefault(),e.wheeling||(e.wheeling=!0,setTimeout(function(){e.wheeling=!1},50),a.deltaY?o=a.deltaY>0?1:-1:a.wheelDelta?o=-a.wheelDelta/120:a.detail&&(o=a.detail>0?1:-1),e.zoom(-o*i,a)))},cropStart:function(t){var e=this;if(!e.disabled){var a=e.options,i=e.pointers,o=C(t),n=void 0;o.changedTouches?c(o.changedTouches,function(t){i[t.identifier]=U(t)}):i[o.pointerId||0]=U(o),n=Object.keys(i).length>1&&a.zoomable&&a.zoomOnTouch?"zoom":v(o.target,"action"),Bt.test(n)&&M(e.element,"cropstart",{originalEvent:o,action:n})!==!1&&(o.preventDefault(),e.action=n,e.cropping=!1,"crop"===n&&(e.cropping=!0,u(e.dragBox,"cropper-modal")))}},cropMove:function(t){var e=this,a=e.action;if(!e.disabled&&a){var i=e.pointers,o=C(t);o.preventDefault(),M(e.element,"cropmove",{originalEvent:o,action:a})!==!1&&(o.changedTouches?c(o.changedTouches,function(t){s(i[t.identifier],U(t,!0))}):s(i[o.pointerId||0],U(o,!0)),e.change(o))}},cropEnd:function(t){var e=this;if(!e.disabled){var a=e.action,i=e.pointers,o=C(t);o.changedTouches?c(o.changedTouches,function(t){delete i[t.identifier]}):delete i[o.pointerId||0],a&&(o.preventDefault(),Object.keys(i).length||(e.action=""),e.cropping&&(e.cropping=!1,f(e.dragBox,"cropper-modal",e.cropped&&this.options.modal)),M(e.element,"cropend",{originalEvent:o,action:a}))}}},Tt="e",Lt="w",Wt="s",Xt="n",Yt="se",Et="sw",Ht="ne",Nt="nw",Ot={change:function(t){var e=this,a=e.options,i=e.containerData,o=e.canvasData,n=e.cropBoxData,r=a.aspectRatio,h=e.action,s=n.width,d=n.height,l=n.left,p=n.top,u=l+s,f=p+d,g=0,v=0,w=i.width,b=i.height,x=!0,y=void 0;!r&&t.shiftKey&&(r=s&&d?s/d:1),e.limited&&(g=n.minLeft,v=n.minTop,w=g+Math.min(i.width,o.width,o.left+o.width),b=v+Math.min(i.height,o.height,o.top+o.height));var M=e.pointers,C=M[Object.keys(M)[0]],B={x:C.endX-C.startX,y:C.endY-C.startY};switch(r&&(B.X=B.y*r,B.Y=B.x/r),h){case"all":l+=B.x,p+=B.y;break;case Tt:if(B.x>=0&&(u>=w||r&&(p<=v||f>=b))){x=!1;break}s+=B.x,r&&(d=s/r,p-=B.Y/2),s<0&&(h=Lt,s=0);break;case Xt:if(B.y<=0&&(p<=v||r&&(l<=g||u>=w))){x=!1;break}d-=B.y,p+=B.y,r&&(s=d*r,l+=B.X/2),d<0&&(h=Wt,d=0);break;case Lt:if(B.x<=0&&(l<=g||r&&(p<=v||f>=b))){x=!1;break}s-=B.x,l+=B.x,r&&(d=s/r,p+=B.Y/2),s<0&&(h=Tt,s=0);break;case Wt:if(B.y>=0&&(f>=b||r&&(l<=g||u>=w))){x=!1;break}d+=B.y,r&&(s=d*r,l-=B.X/2),d<0&&(h=Xt,d=0);break;case Ht:if(r){if(B.y<=0&&(p<=v||u>=w)){x=!1;break}d-=B.y,p+=B.y,s=d*r}else B.x>=0?u<w?s+=B.x:B.y<=0&&p<=v&&(x=!1):s+=B.x,B.y<=0?p>v&&(d-=B.y,p+=B.y):(d-=B.y,p+=B.y);s<0&&d<0?(h=Et,d=0,s=0):s<0?(h=Nt,s=0):d<0&&(h=Yt,d=0);break;case Nt:if(r){if(B.y<=0&&(p<=v||l<=g)){x=!1;break}d-=B.y,p+=B.y,s=d*r,l+=B.X}else B.x<=0?l>g?(s-=B.x,l+=B.x):B.y<=0&&p<=v&&(x=!1):(s-=B.x,l+=B.x),B.y<=0?p>v&&(d-=B.y,p+=B.y):(d-=B.y,p+=B.y);s<0&&d<0?(h=Yt,d=0,s=0):s<0?(h=Ht,s=0):d<0&&(h=Et,d=0);break;case Et:if(r){if(B.x<=0&&(l<=g||f>=b)){x=!1;break}s-=B.x,l+=B.x,d=s/r}else B.x<=0?l>g?(s-=B.x,l+=B.x):B.y>=0&&f>=b&&(x=!1):(s-=B.x,l+=B.x),B.y>=0?f<b&&(d+=B.y):d+=B.y;s<0&&d<0?(h=Ht,d=0,s=0):s<0?(h=Yt,s=0):d<0&&(h=Nt,d=0);break;case Yt:if(r){if(B.x>=0&&(u>=w||f>=b)){x=!1;break}s+=B.x,d=s/r}else B.x>=0?u<w?s+=B.x:B.y>=0&&f>=b&&(x=!1):s+=B.x,B.y>=0?f<b&&(d+=B.y):d+=B.y;s<0&&d<0?(h=Nt,d=0,s=0):s<0?(h=Et,s=0):d<0&&(h=Ht,d=0);break;case"move":e.move(B.x,B.y),x=!1;break;case"zoom":e.zoom(j(M),t),x=!1;break;case"crop":if(!B.x||!B.y){x=!1;break}y=D(e.cropper),l=C.startX-y.left,p=C.startY-y.top,s=n.minWidth,d=n.minHeight,B.x>0?h=B.y>0?Yt:Ht:B.x<0&&(l-=s,h=B.y>0?Et:Nt),B.y<0&&(p-=d),e.cropped||(m(e.cropBox,"cropper-hidden"),e.cropped=!0,e.limited&&e.limitCropBox(!0,!0))}x&&(n.width=s,n.height=d,n.left=l,n.top=p,e.action=h,e.renderCropBox()),c(M,function(t){t.startX=t.endX,t.startY=t.endY})}},zt={crop:function(){var t=this;return t.ready&&!t.disabled&&(t.cropped||(t.cropped=!0,t.limitCropBox(!0,!0),t.options.modal&&u(t.dragBox,"cropper-modal"),m(t.cropBox,"cropper-hidden")),t.setCropBoxData(t.initialCropBoxData)),t},reset:function(){var t=this;return t.ready&&!t.disabled&&(t.imageData=s({},t.initialImageData),t.canvasData=s({},t.initialCanvasData),t.cropBoxData=s({},t.initialCropBoxData),t.renderCanvas(),t.cropped&&t.renderCropBox()),t},clear:function(){var t=this;return t.cropped&&!t.disabled&&(s(t.cropBoxData,{left:0,top:0,width:0,height:0}),t.cropped=!1,t.renderCropBox(),t.limitCanvas(),t.renderCanvas(),m(t.dragBox,"cropper-modal"),u(t.cropBox,"cropper-hidden")),t},replace:function(t,e){var a=this;return!a.disabled&&t&&(a.isImg&&(a.element.src=t),e?(a.url=t,a.image.src=t,a.ready&&(a.image2.src=t,c(a.previews,function(e){B(e,"img")[0].src=t}))):(a.isImg&&(a.replaced=!0),a.options.data=null,a.load(t))),a},enable:function(){var t=this;return t.ready&&(t.disabled=!1,m(t.cropper,"cropper-disabled")),t},disable:function(){var t=this;return t.ready&&(t.disabled=!0,u(t.cropper,"cropper-disabled")),t},destroy:function(){var t=this,e=t.element,a=t.image;return t.loaded?(t.isImg&&t.replaced&&(e.src=t.originalUrl),t.unbuild(),m(e,"cropper-hidden")):t.isImg?x(e,"load",t.onStart):a&&W(a),b(e,"cropper"),t},move:function(t,e){var i=this,o=i.canvasData;return i.moveTo(a(t)?t:o.left+Number(t),a(e)?e:o.top+Number(e))},moveTo:function(t,i){var o=this,n=o.canvasData,r=!1;return a(i)&&(i=t),t=Number(t),i=Number(i),o.ready&&!o.disabled&&o.options.movable&&(e(t)&&(n.left=t,r=!0),e(i)&&(n.top=i,r=!0),r&&o.renderCanvas(!0)),o},zoom:function(t,e){var a=this,i=a.canvasData;return t=Number(t),t=t<0?1/(1-t):1+t,a.zoomTo(i.width*t/i.naturalWidth,e)},zoomTo:function(t,e){var a=this,i=a.options,o=a.canvasData,n=o.width,r=o.height,h=o.naturalWidth,c=o.naturalHeight;if(t=Number(t),t>=0&&a.ready&&!a.disabled&&i.zoomable){var s=h*t,d=c*t;if(M(a.element,"zoom",{originalEvent:e,oldRatio:n/h,ratio:s/h})===!1)return a;if(e){var l=a.pointers,p=D(a.cropper),u=l&&Object.keys(l).length?P(l):{pageX:e.pageX,pageY:e.pageY};o.left-=(s-n)*((u.pageX-p.left-o.left)/n),o.top-=(d-r)*((u.pageY-p.top-o.top)/r)}else o.left-=(s-n)/2,o.top-=(d-r)/2;o.width=s,o.height=d,a.renderCanvas(!0)}return a},rotate:function(t){var e=this;return e.rotateTo((e.imageData.rotate||0)+Number(t))},rotateTo:function(t){var a=this;return t=Number(t),e(t)&&a.ready&&!a.disabled&&a.options.rotatable&&(a.imageData.rotate=t%360,a.rotated=!0,a.renderCanvas(!0)),a},scale:function(t,i){var o=this,n=o.imageData,r=!1;return a(i)&&(i=t),t=Number(t),i=Number(i),o.ready&&!o.disabled&&o.options.scalable&&(e(t)&&(n.scaleX=t,r=!0),e(i)&&(n.scaleY=i,r=!0),r&&o.renderImage(!0)),o},scaleX:function(t){var a=this,i=a.imageData.scaleY;return a.scale(t,e(i)?i:1)},scaleY:function(t){var a=this,i=a.imageData.scaleX;return a.scale(e(i)?i:1,t)},getData:function(t){var e=this,a=e.options,i=e.imageData,o=e.canvasData,n=e.cropBoxData,r=void 0,h=void 0;return e.ready&&e.cropped?(h={x:n.left-o.left,y:n.top-o.top,width:n.width,height:n.height},r=i.width/i.naturalWidth,c(h,function(e,a){e/=r,h[a]=t?Math.round(e):e})):h={x:0,y:0,width:0,height:0},a.rotatable&&(h.rotate=i.rotate||0),a.scalable&&(h.scaleX=i.scaleX||1,h.scaleY=i.scaleY||1),h},setData:function(t){var a=this,i=a.options,r=a.imageData,h=a.canvasData,c={},s=void 0,d=void 0,l=void 0;return n(t)&&(t=t.call(a.element)),a.ready&&!a.disabled&&o(t)&&(i.rotatable&&e(t.rotate)&&t.rotate!==r.rotate&&(r.rotate=t.rotate,a.rotated=s=!0),i.scalable&&(e(t.scaleX)&&t.scaleX!==r.scaleX&&(r.scaleX=t.scaleX,d=!0),e(t.scaleY)&&t.scaleY!==r.scaleY&&(r.scaleY=t.scaleY,d=!0)),s?a.renderCanvas():d&&a.renderImage(),l=r.width/r.naturalWidth,e(t.x)&&(c.left=t.x*l+h.left),e(t.y)&&(c.top=t.y*l+h.top),e(t.width)&&(c.width=t.width*l),e(t.height)&&(c.height=t.height*l),a.setCropBoxData(c)),a},getContainerData:function(){var t=this;return t.ready?t.containerData:{}},getImageData:function(){var t=this;return t.loaded?t.imageData:{}},getCanvasData:function(){var t=this,e=t.canvasData,a={};return t.ready&&c(["left","top","width","height","naturalWidth","naturalHeight"],function(t){a[t]=e[t]}),a},setCanvasData:function(t){var a=this,i=a.canvasData,r=i.aspectRatio;return n(t)&&(t=t.call(a.element)),a.ready&&!a.disabled&&o(t)&&(e(t.left)&&(i.left=t.left),e(t.top)&&(i.top=t.top),e(t.width)?(i.width=t.width,i.height=t.width/r):e(t.height)&&(i.height=t.height,i.width=t.height*r),a.renderCanvas(!0)),a},getCropBoxData:function(){var t=this,e=t.cropBoxData,a=void 0;return t.ready&&t.cropped&&(a={left:e.left,top:e.top,width:e.width,height:e.height}),a||{}},setCropBoxData:function(t){var a=this,i=a.cropBoxData,r=a.options.aspectRatio,h=void 0,c=void 0;return n(t)&&(t=t.call(a.element)),a.ready&&a.cropped&&!a.disabled&&o(t)&&(e(t.left)&&(i.left=t.left),e(t.top)&&(i.top=t.top),e(t.width)&&t.width!==i.width&&(h=!0,i.width=t.width),e(t.height)&&t.height!==i.height&&(c=!0,i.height=t.height),r&&(h?i.height=i.width/r:c&&(i.width=i.height*r)),a.renderCropBox()),a},getCroppedCanvas:function(t){var e=this;if(!e.ready||!window.HTMLCanvasElement)return null;if(!e.cropped)return z(e.image,e.imageData);o(t)||(t={});var a=e.getData(),i=a.width,n=a.height,r=i/n,h=void 0,c=void 0,s=void 0;o(t)&&(h=t.width,c=t.height,h?(c=h/r,s=h/i):c&&(h=c*r,s=c/n));var d=Math.floor(h||i),l=Math.floor(c||n),p=T("canvas"),u=p.getContext("2d");p.width=d,p.height=l,t.fillColor&&(u.fillStyle=t.fillColor,u.fillRect(0,0,d,l));var m=function(){var t=z(e.image,e.imageData),o=t.width,r=t.height,h=e.canvasData,c=[t],d=a.x+h.naturalWidth*(Math.abs(a.scaleX||1)-1)/2,l=a.y+h.naturalHeight*(Math.abs(a.scaleY||1)-1)/2,p=void 0,u=void 0,m=void 0,f=void 0,g=void 0,v=void 0;return d<=-i||d>o?d=p=m=g=0:d<=0?(m=-d,d=0,p=g=Math.min(o,i+d)):d<=o&&(m=0,p=g=Math.min(i,o-d)),p<=0||l<=-n||l>r?l=u=f=v=0:l<=0?(f=-l,l=0,u=v=Math.min(r,n+l)):l<=r&&(f=0,u=v=Math.min(n,r-l)),c.push(Math.floor(d),Math.floor(l),Math.floor(p),Math.floor(u)),s&&(m*=s,f*=s,g*=s,v*=s),g>0&&v>0&&c.push(Math.floor(m),Math.floor(f),Math.floor(g),Math.floor(v)),c}();return u.drawImage.apply(u,F(m)),p},setAspectRatio:function(t){var e=this,i=e.options;return e.disabled||a(t)||(i.aspectRatio=Math.max(0,t)||NaN,e.ready&&(e.initCropBox(),e.cropped&&e.renderCropBox())),e},setDragMode:function(t){var e=this,a=e.options,i=e.dragBox,o=e.face,n=void 0,r=void 0;return e.loaded&&!e.disabled&&(n="crop"===t,r=a.movable&&"move"===t,t=n||r?t:"none",w(i,"action",t),f(i,"cropper-crop",n),f(i,"cropper-move",r),a.cropBoxMovable||(w(o,"action",t),f(o,"cropper-crop",n),f(o,"cropper-move",r))),e}},At="cropper",Rt=At+"-hidden",St="error",It="load",Ut="ready",jt="crop",Pt=/^data:/,qt=/^data:image\/jpeg;base64,/,$t=void 0,Zt=function(){function t(e,a){K(this,t);var i=this;i.element=e,i.options=s({},q,o(a)&&a),i.loaded=!1,i.ready=!1,i.complete=!1,i.rotated=!1,i.cropped=!1,i.disabled=!1,i.replaced=!1,i.limited=!1,i.wheeling=!1,i.isImg=!1,i.originalUrl="",i.canvasData=null,i.cropBoxData=null,i.previews=null,i.pointers={},i.init()}return V(t,[{key:"init",value:function(){var t=this,e=t.element,a=e.tagName.toLowerCase(),i=void 0;if(!v(e,At)){if(w(e,At,t),"img"===a){if(t.isImg=!0,t.originalUrl=i=e.getAttribute("src"),!i)return;i=e.src}else"canvas"===a&&window.HTMLCanvasElement&&(i=e.toDataURL());t.load(i)}}},{key:"load",value:function(t){var e=this,a=e.options,i=e.element;if(t){if(e.url=t,e.imageData={},!a.checkOrientation||!window.ArrayBuffer)return void e.clone();if(Pt.test(t))return void(qt?e.read(S(t)):e.clone());var o=new XMLHttpRequest;o.onerror=o.onabort=function(){e.clone()},o.onload=function(){e.read(o.response)},a.checkCrossOrigin&&Y(t)&&i.crossOrigin&&(t=E(t)),o.open("get",t),o.responseType="arraybuffer",o.withCredentials="use-credentials"===i.crossOrigin,o.send()}}},{key:"read",value:function(t){var e=this,a=e.options,i=R(t),o=e.imageData,n=0,r=1,h=1;if(i>1)switch(e.url=I(t),i){case 2:r=-1;break;case 3:n=-180;break;case 4:h=-1;break;case 5:n=90,h=-1;break;case 6:n=90;break;case 7:n=90,r=-1;break;case 8:n=-90}a.rotatable&&(o.rotate=n),a.scalable&&(o.scaleX=r,o.scaleY=h),e.clone()}},{key:"clone",value:function(){var t=this,e=t.element,a=t.url,i=void 0,o=void 0,n=void 0,r=void 0;t.options.checkCrossOrigin&&Y(a)&&(i=e.crossOrigin,i?o=a:(i="anonymous",o=E(a))),t.crossOrigin=i,t.crossOriginUrl=o;var h=T("img");i&&(h.crossOrigin=i),h.src=o||a,t.image=h,t.onStart=n=d(t.start,t),t.onStop=r=d(t.stop,t),t.isImg?e.complete?t.start():y(e,It,n):(y(h,It,n),y(h,St,r),u(h,"cropper-hide"),e.parentNode.insertBefore(h,e.nextSibling))}},{key:"start",value:function(t){var e=this,a=e.isImg?e.element:e.image;t&&(x(a,It,e.onStart),x(a,St,e.onStop)),H(a,function(t,a){s(e.imageData,{naturalWidth:t,naturalHeight:a,aspectRatio:t/a}),e.loaded=!0,e.build()})}},{key:"stop",value:function(){var t=this,e=t.image;x(e,It,t.onStart),x(e,St,t.onStop),W(e),t.image=null}},{key:"build",value:function(){var t=this,e=t.options,a=t.element,i=t.image,o=void 0,r=void 0,h=void 0,c=void 0,s=void 0,d=void 0;if(t.loaded){t.ready&&t.unbuild();var l=T("div");l.innerHTML=$,t.container=o=a.parentNode,t.cropper=r=k(l,"cropper-container")[0],t.canvas=h=k(r,"cropper-canvas")[0],t.dragBox=c=k(r,"cropper-drag-box")[0],t.cropBox=s=k(r,"cropper-crop-box")[0],t.viewBox=k(r,"cropper-view-box")[0],t.face=d=k(s,"cropper-face")[0],L(h,i),u(a,Rt),o.insertBefore(r,a.nextSibling),t.isImg||m(i,"cropper-hide"),t.initPreview(),t.bind(),e.aspectRatio=Math.max(0,e.aspectRatio)||NaN,e.viewMode=Math.max(0,Math.min(3,Math.round(e.viewMode)))||0,t.cropped=e.autoCrop,
12
+ e.autoCrop?e.modal&&u(c,"cropper-modal"):u(s,Rt),e.guides||u(k(s,"cropper-dashed"),Rt),e.center||u(k(s,"cropper-center"),Rt),e.background&&u(r,"cropper-bg"),e.highlight||u(d,"cropper-invisible"),e.cropBoxMovable&&(u(d,"cropper-move"),w(d,"action","all")),e.cropBoxResizable||(u(k(s,"cropper-line"),Rt),u(k(s,"cropper-point"),Rt)),t.setDragMode(e.dragMode),t.render(),t.ready=!0,t.setData(e.data),t.completing=setTimeout(function(){n(e.ready)&&y(a,Ut,e.ready,!0),M(a,Ut),M(a,jt,t.getData()),t.complete=!0},0)}}},{key:"unbuild",value:function(){var t=this;t.ready&&(t.complete||clearTimeout(t.completing),t.ready=!1,t.complete=!1,t.initialImageData=null,t.initialCanvasData=null,t.initialCropBoxData=null,t.containerData=null,t.canvasData=null,t.cropBoxData=null,t.unbind(),t.resetPreview(),t.previews=null,t.viewBox=null,t.cropBox=null,t.dragBox=null,t.canvas=null,t.container=null,W(t.cropper),t.cropper=null)}}],[{key:"noConflict",value:function(){return window.Cropper=$t,t}},{key:"setDefaults",value:function(t){s(q,o(t)&&t)}}]),t}();return s(Zt.prototype,st),s(Zt.prototype,lt),s(Zt.prototype,Dt),s(Zt.prototype,kt),s(Zt.prototype,Ot),s(Zt.prototype,zt),"undefined"!=typeof window&&($t=window.Cropper,window.Cropper=Zt),Zt});
js/app/vendor/vue.min.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Vue.js v2.2.6
3
+ * (c) 2014-2017 Evan You
4
+ * Released under the MIT License.
5
+ */
6
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function t(e){var t=parseFloat(e);return isNaN(t)?e:t}function n(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function r(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function i(e,t){return $i.call(e,t)}function o(e){return"string"==typeof e||"number"==typeof e}function a(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function s(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function c(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function u(e,t){for(var n in t)e[n]=t[n];return e}function l(e){return null!==e&&"object"==typeof e}function f(e){return ki.call(e)===Ai}function p(e){for(var t={},n=0;n<e.length;n++)e[n]&&u(t,e[n]);return t}function d(){}function v(e,t){var n=l(e),r=l(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{return JSON.stringify(e)===JSON.stringify(t)}catch(n){return e===t}}function h(e,t){for(var n=0;n<e.length;n++)if(v(e[n],t))return n;return-1}function m(e){var t=!1;return function(){t||(t=!0,e())}}function g(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function y(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function _(e){if(!ji.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function b(e){return/native code/.test(e.toString())}function $(e){qi.target&&Wi.push(qi.target),qi.target=e}function w(){qi.target=Wi.pop()}function x(e,t){e.__proto__=t}function C(e,t,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];y(e,o,t[o])}}function k(e,t){if(l(e)){var n;return i(e,"__ob__")&&e.__ob__ instanceof Xi?n=e.__ob__:Qi.shouldConvert&&!Ui()&&(Array.isArray(e)||f(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new Xi(e)),t&&n&&n.vmCount++,n}}function A(e,t,n,r){var i=new qi,o=Object.getOwnPropertyDescriptor(e,t);if(!o||o.configurable!==!1){var a=o&&o.get,s=o&&o.set,c=k(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=a?a.call(e):n;return qi.target&&(i.depend(),c&&c.dep.depend(),Array.isArray(t)&&S(t)),t},set:function(t){var r=a?a.call(e):n;t===r||t!==t&&r!==r||(s?s.call(e,t):n=t,c=k(t),i.notify())}})}}function O(e,t,n){if(Array.isArray(e)&&"number"==typeof t)return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(i(e,t))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?(A(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function T(e,t){if(Array.isArray(e)&&"number"==typeof t)return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||i(e,t)&&(delete e[t],n&&n.dep.notify())}function S(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Array.isArray(t)&&S(t)}function E(e,t){if(!t)return e;for(var n,r,o,a=Object.keys(t),s=0;s<a.length;s++)n=a[s],r=e[n],o=t[n],i(e,n)?f(r)&&f(o)&&E(r,o):O(e,n,o);return e}function j(e,t){return t?e?e.concat(t):Array.isArray(t)?t:[t]:e}function N(e,t){var n=Object.create(e||null);return t?u(n,t):n}function I(e){var t=e.props;if(t){var n,r,i,o={};if(Array.isArray(t))for(n=t.length;n--;)"string"==typeof(r=t[n])&&(i=wi(r),o[i]={type:null});else if(f(t))for(var a in t)r=t[a],i=wi(a),o[i]=f(r)?r:{type:r};e.props=o}}function L(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function D(e,t,n){function r(r){var i=eo[r]||to;l[r]=i(e[r],t[r],n,r)}I(t),L(t);var o=t.extends;if(o&&(e="function"==typeof o?D(e,o.options,n):D(e,o,n)),t.mixins)for(var a=0,s=t.mixins.length;a<s;a++){var c=t.mixins[a];c.prototype instanceof nt&&(c=c.options),e=D(e,c,n)}var u,l={};for(u in e)r(u);for(u in t)i(e,u)||r(u);return l}function M(e,t,n,r){if("string"==typeof n){var o=e[t];if(i(o,n))return o[n];var a=wi(n);if(i(o,a))return o[a];var s=xi(a);if(i(o,s))return o[s];var c=o[n]||o[a]||o[s];return c}}function P(e,t,n,r){var o=t[e],a=!i(n,e),s=n[e];if(H(Boolean,o.type)&&(a&&!i(o,"default")?s=!1:H(String,o.type)||""!==s&&s!==Ci(e)||(s=!0)),void 0===s){s=R(r,o,e);var c=Qi.shouldConvert;Qi.shouldConvert=!0,k(s),Qi.shouldConvert=c}return s}function R(e,t,n){if(i(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==F(t.type)?r.call(e):r}}function F(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t&&t[1]}function H(e,t){if(!Array.isArray(t))return F(t)===F(e);for(var n=0,r=t.length;n<r;n++)if(F(t[n])===F(e))return!0;return!1}function U(e,t,n){if(Si.errorHandler)Si.errorHandler.call(null,e,t,n);else{if(!Ii||"undefined"==typeof console)throw e;console.error(e)}}function B(e){return new no(void 0,void 0,void 0,String(e))}function V(e){var t=new no(e.tag,e.data,e.children,e.text,e.elm,e.context,e.componentOptions);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isCloned=!0,t}function z(e){for(var t=e.length,n=new Array(t),r=0;r<t;r++)n[r]=V(e[r]);return n}function J(e){function t(){var e=arguments,n=t.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=0;r<n.length;r++)n[r].apply(null,e)}return t.fns=e,t}function K(e,t,n,r,i){var o,a,s,c;for(o in e)a=e[o],s=t[o],c=ao(o),a&&(s?a!==s&&(s.fns=a,e[o]=s):(a.fns||(a=e[o]=J(a)),n(c.name,a,c.once,c.capture)));for(o in t)e[o]||(c=ao(o),r(c.name,t[o],c.capture))}function q(e,t,n){function i(){n.apply(this,arguments),r(o.fns,i)}var o,a=e[t];a?a.fns&&a.merged?(o=a,o.fns.push(i)):o=J([a,i]):o=J([i]),o.merged=!0,e[t]=o}function W(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function Z(e){return o(e)?[B(e)]:Array.isArray(e)?G(e):void 0}function G(e,t){var n,r,i,a=[];for(n=0;n<e.length;n++)null!=(r=e[n])&&"boolean"!=typeof r&&(i=a[a.length-1],Array.isArray(r)?a.push.apply(a,G(r,(t||"")+"_"+n)):o(r)?i&&i.text?i.text+=String(r):""!==r&&a.push(B(r)):r.text&&i&&i.text?a[a.length-1]=B(i.text+r.text):(r.tag&&null==r.key&&null!=t&&(r.key="__vlist"+t+"_"+n+"__"),a.push(r)));return a}function Y(e){return e&&e.filter(function(e){return e&&e.componentOptions})[0]}function Q(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&te(e,t)}function X(e,t,n){n?io.$once(e,t):io.$on(e,t)}function ee(e,t){io.$off(e,t)}function te(e,t,n){io=e,K(t,n||{},X,ee,e)}function ne(e,t){var n={};if(!e)return n;for(var r,i,o=[],a=0,s=e.length;a<s;a++)if(i=e[a],(i.context===t||i.functionalContext===t)&&i.data&&(r=i.data.slot)){var c=n[r]||(n[r]=[]);"template"===i.tag?c.push.apply(c,i.children):c.push(i)}else o.push(i);return o.every(re)||(n.default=o),n}function re(e){return e.isComment||" "===e.text}function ie(e){for(var t={},n=0;n<e.length;n++)t[e[n][0]]=e[n][1];return t}function oe(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}function ae(e,t,n){e.$el=t,e.$options.render||(e.$options.render=oo),fe(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},e._watcher=new ho(e,r,d),n=!1,null==e.$vnode&&(e._isMounted=!0,fe(e,"mounted")),e}function se(e,t,n,r,i){var o=!!(i||e.$options._renderChildren||r.data.scopedSlots||e.$scopedSlots!==Ei);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=i,t&&e.$options.props){Qi.shouldConvert=!1;for(var a=e._props,s=e.$options._propKeys||[],c=0;c<s.length;c++){var u=s[c];a[u]=P(u,e.$options.props,t,e)}Qi.shouldConvert=!0,e.$options.propsData=t}if(n){var l=e.$options._parentListeners;e.$options._parentListeners=n,te(e,n,l)}o&&(e.$slots=ne(i,r.context),e.$forceUpdate())}function ce(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function ue(e,t){if(t){if(e._directInactive=!1,ce(e))return}else if(e._directInactive)return;if(e._inactive||null==e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)ue(e.$children[n]);fe(e,"activated")}}function le(e,t){if(!(t&&(e._directInactive=!0,ce(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)le(e.$children[n]);fe(e,"deactivated")}}function fe(e,t){var n=e.$options[t];if(n)for(var r=0,i=n.length;r<i;r++)try{n[r].call(e)}catch(n){U(n,e,t+" hook")}e._hasHookEvent&&e.$emit("hook:"+t)}function pe(){co.length=0,uo={},lo=fo=!1}function de(){fo=!0;var e,t,n;for(co.sort(function(e,t){return e.id-t.id}),po=0;po<co.length;po++)e=co[po],t=e.id,uo[t]=null,e.run();var r=co.slice();for(pe(),po=r.length;po--;)e=r[po],n=e.vm,n._watcher===e&&n._isMounted&&fe(n,"updated");Bi&&Si.devtools&&Bi.emit("flush")}function ve(e){var t=e.id;if(null==uo[t]){if(uo[t]=!0,fo){for(var n=co.length-1;n>=0&&co[n].id>e.id;)n--;co.splice(Math.max(n,po)+1,0,e)}else co.push(e);lo||(lo=!0,zi(de))}}function he(e){mo.clear(),me(e,mo)}function me(e,t){var n,r,i=Array.isArray(e);if((i||l(e))&&Object.isExtensible(e)){if(e.__ob__){var o=e.__ob__.dep.id;if(t.has(o))return;t.add(o)}if(i)for(n=e.length;n--;)me(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)me(e[r[n]],t)}}function ge(e,t,n){go.get=function(){return this[t][n]},go.set=function(e){this[t][n]=e},Object.defineProperty(e,n,go)}function ye(e){e._watchers=[];var t=e.$options;t.props&&_e(e,t.props),t.methods&&ke(e,t.methods),t.data?be(e):k(e._data={},!0),t.computed&&we(e,t.computed),t.watch&&Ae(e,t.watch)}function _e(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[],o=!e.$parent;Qi.shouldConvert=o;for(var a in t)!function(o){i.push(o);var a=P(o,t,n,e);A(r,o,a),o in e||ge(e,"_props",o)}(a);Qi.shouldConvert=!0}function be(e){var t=e.$options.data;t=e._data="function"==typeof t?$e(t,e):t||{},f(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,o=n.length;o--;)r&&i(r,n[o])||g(n[o])||ge(e,"_data",n[o]);k(t,!0)}function $e(e,t){try{return e.call(t)}catch(e){return U(e,t,"data()"),{}}}function we(e,t){var n=e._computedWatchers=Object.create(null);for(var r in t){var i=t[r],o="function"==typeof i?i:i.get;n[r]=new ho(e,o,d,yo),r in e||xe(e,r,i)}}function xe(e,t,n){"function"==typeof n?(go.get=Ce(t),go.set=d):(go.get=n.get?n.cache!==!1?Ce(t):n.get:d,go.set=n.set?n.set:d),Object.defineProperty(e,t,go)}function Ce(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),qi.target&&t.depend(),t.value}}function ke(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?d:s(t[n],e)}function Ae(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i<r.length;i++)Oe(e,n,r[i]);else Oe(e,n,r)}}function Oe(e,t,n){var r;f(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function Te(e,t,n,r,i){if(e){var o=n.$options._base;if(l(e)&&(e=o.extend(e)),"function"==typeof e){if(!e.cid)if(e.resolved)e=e.resolved;else if(!(e=je(e,o,function(){n.$forceUpdate()})))return;Xe(e),t=t||{},t.model&&Me(e.options,t);var a=Ne(t,e,i);if(e.options.functional)return Se(e,a,t,n,r);var s=t.on;t.on=t.nativeOn,e.options.abstract&&(t={}),Le(t);var c=e.options.name||i;return new no("vue-component-"+e.cid+(c?"-"+c:""),t,void 0,void 0,void 0,n,{Ctor:e,propsData:a,listeners:s,tag:i,children:r})}}}function Se(e,t,n,r,i){var o={},a=e.options.props;if(a)for(var s in a)o[s]=P(s,a,t);var c=Object.create(r),u=function(e,t,n,r){return Pe(c,e,t,n,r,!0)},l=e.options.render.call(null,u,{props:o,data:n,parent:r,children:i,slots:function(){return ne(i,r)}});return l instanceof no&&(l.functionalContext=r,n.slot&&((l.data||(l.data={})).slot=n.slot)),l}function Ee(e,t,n,r){var i=e.componentOptions,o={_isComponent:!0,parent:t,propsData:i.propsData,_componentTag:i.tag,_parentVnode:e,_parentListeners:i.listeners,_renderChildren:i.children,_parentElm:n||null,_refElm:r||null},a=e.data.inlineTemplate;return a&&(o.render=a.render,o.staticRenderFns=a.staticRenderFns),new i.Ctor(o)}function je(e,t,n){if(!e.requested){e.requested=!0;var r=e.pendingCallbacks=[n],i=!0,o=function(n){if(l(n)&&(n=t.extend(n)),e.resolved=n,!i)for(var o=0,a=r.length;o<a;o++)r[o](n)},a=function(e){},s=e(o,a);return s&&"function"==typeof s.then&&!e.resolved&&s.then(o,a),i=!1,e.resolved}e.pendingCallbacks.push(n)}function Ne(e,t,n){var r=t.options.props;if(r){var i={},o=e.attrs,a=e.props,s=e.domProps;if(o||a||s)for(var c in r){var u=Ci(c);Ie(i,a,c,u,!0)||Ie(i,o,c,u)||Ie(i,s,c,u)}return i}}function Ie(e,t,n,r,o){if(t){if(i(t,n))return e[n]=t[n],o||delete t[n],!0;if(i(t,r))return e[n]=t[r],o||delete t[r],!0}return!1}function Le(e){e.hook||(e.hook={});for(var t=0;t<bo.length;t++){var n=bo[t],r=e.hook[n],i=_o[n];e.hook[n]=r?De(i,r):i}}function De(e,t){return function(n,r,i,o){e(n,r,i,o),t(n,r,i,o)}}function Me(e,t){var n=e.model&&e.model.prop||"value",r=e.model&&e.model.event||"input";(t.props||(t.props={}))[n]=t.model.value;var i=t.on||(t.on={});i[r]?i[r]=[t.model.callback].concat(i[r]):i[r]=t.model.callback}function Pe(e,t,n,r,i,a){return(Array.isArray(n)||o(n))&&(i=r,r=n,n=void 0),a&&(i=wo),Re(e,t,n,r,i)}function Re(e,t,n,r,i){if(n&&n.__ob__)return oo();if(!t)return oo();Array.isArray(r)&&"function"==typeof r[0]&&(n=n||{},n.scopedSlots={default:r[0]},r.length=0),i===wo?r=Z(r):i===$o&&(r=W(r));var o,a;if("string"==typeof t){var s;a=Si.getTagNamespace(t),o=Si.isReservedTag(t)?new no(Si.parsePlatformTagName(t),n,r,void 0,void 0,e):(s=M(e.$options,"components",t))?Te(s,n,e,r,t):new no(t,n,r,void 0,void 0,e)}else o=Te(t,n,e,r);return o?(a&&Fe(o,a),o):oo()}function Fe(e,t){if(e.ns=t,"foreignObject"!==e.tag&&e.children)for(var n=0,r=e.children.length;n<r;n++){var i=e.children[n];i.tag&&!i.ns&&Fe(i,t)}}function He(e,t){var n,r,i,o,a;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),r=0,i=e.length;r<i;r++)n[r]=t(e[r],r);else if("number"==typeof e)for(n=new Array(e),r=0;r<e;r++)n[r]=t(r+1,r);else if(l(e))for(o=Object.keys(e),n=new Array(o.length),r=0,i=o.length;r<i;r++)a=o[r],n[r]=t(e[a],a,r);return n}function Ue(e,t,n,r){var i=this.$scopedSlots[e];if(i)return n=n||{},r&&u(n,r),i(n)||t;var o=this.$slots[e];return o||t}function Be(e){return M(this.$options,"filters",e,!0)||Ti}function Ve(e,t,n){var r=Si.keyCodes[t]||n;return Array.isArray(r)?r.indexOf(e)===-1:r!==e}function ze(e,t,n,r){if(n)if(l(n)){Array.isArray(n)&&(n=p(n));var i;for(var o in n){if("class"===o||"style"===o)i=e;else{var a=e.attrs&&e.attrs.type;i=r||Si.mustUseProp(t,a,o)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}o in i||(i[o]=n[o])}}else;return e}function Je(e,t){var n=this._staticTrees[e];return n&&!t?Array.isArray(n)?z(n):V(n):(n=this._staticTrees[e]=this.$options.staticRenderFns[e].call(this._renderProxy),qe(n,"__static__"+e,!1),n)}function Ke(e,t,n){return qe(e,"__once__"+t+(n?"_"+n:""),!0),e}function qe(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&We(e[r],t+"_"+r,n);else We(e,t,n)}function We(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function Ze(e){e.$vnode=null,e._vnode=null,e._staticTrees=null;var t=e.$options._parentVnode,n=t&&t.context;e.$slots=ne(e.$options._renderChildren,n),e.$scopedSlots=Ei,e._c=function(t,n,r,i){return Pe(e,t,n,r,i,!1)},e.$createElement=function(t,n,r,i){return Pe(e,t,n,r,i,!0)}}function Ge(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function Ye(e){var t=e.$options.inject;if(t)for(var n=Array.isArray(t),r=n?t:Vi?Reflect.ownKeys(t):Object.keys(t),i=0;i<r.length;i++)!function(i){for(var o=r[i],a=n?o:t[o],s=e;s;){if(s._provided&&a in s._provided){A(e,o,s._provided[a]);break}s=s.$parent}}(i)}function Qe(e,t){var n=e.$options=Object.create(e.constructor.options);n.parent=t.parent,n.propsData=t.propsData,n._parentVnode=t._parentVnode,n._parentListeners=t._parentListeners,n._renderChildren=t._renderChildren,n._componentTag=t._componentTag,n._parentElm=t._parentElm,n._refElm=t._refElm,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}function Xe(e){var t=e.options;if(e.super){var n=Xe(e.super);if(n!==e.superOptions){e.superOptions=n;var r=et(e);r&&u(e.extendOptions,r),t=e.options=D(n,e.extendOptions),t.name&&(t.components[t.name]=e)}}return t}function et(e){var t,n=e.options,r=e.sealedOptions;for(var i in n)n[i]!==r[i]&&(t||(t={}),t[i]=tt(n[i],r[i]));return t}function tt(e,t){if(Array.isArray(e)){var n=[];t=Array.isArray(t)?t:[t];for(var r=0;r<e.length;r++)t.indexOf(e[r])<0&&n.push(e[r]);return n}return e}function nt(e){this._init(e)}function rt(e){e.use=function(e){if(!e.installed){var t=c(arguments,1);return t.unshift(this),"function"==typeof e.install?e.install.apply(e,t):"function"==typeof e&&e.apply(null,t),e.installed=!0,this}}}function it(e){e.mixin=function(e){this.options=D(this.options,e)}}function ot(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=D(n.options,e),a.super=n,a.options.props&&at(a),a.options.computed&&st(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Si._assetTypes.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=u({},a.options),i[r]=a,a}}function at(e){var t=e.options.props;for(var n in t)ge(e.prototype,"_props",n)}function st(e){var t=e.options.computed;for(var n in t)xe(e.prototype,n,t[n])}function ct(e){Si._assetTypes.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&f(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function ut(e){return e&&(e.Ctor.options.name||e.tag)}function lt(e,t){return"string"==typeof e?e.split(",").indexOf(t)>-1:e instanceof RegExp&&e.test(t)}function ft(e,t){for(var n in e){var r=e[n];if(r){var i=ut(r.componentOptions);i&&!t(i)&&(pt(r),e[n]=null)}}}function pt(e){e&&(e.componentInstance._inactive||fe(e.componentInstance,"deactivated"),e.componentInstance.$destroy())}function dt(e){for(var t=e.data,n=e,r=e;r.componentInstance;)r=r.componentInstance._vnode,r.data&&(t=vt(r.data,t));for(;n=n.parent;)n.data&&(t=vt(t,n.data));return ht(t)}function vt(e,t){return{staticClass:mt(e.staticClass,t.staticClass),class:e.class?[e.class,t.class]:t.class}}function ht(e){var t=e.class,n=e.staticClass;return n||t?mt(n,gt(t)):""}function mt(e,t){return e?t?e+" "+t:e:t||""}function gt(e){var t="";if(!e)return t;if("string"==typeof e)return e;if(Array.isArray(e)){for(var n,r=0,i=e.length;r<i;r++)e[r]&&(n=gt(e[r]))&&(t+=n+" ");return t.slice(0,-1)}if(l(e)){for(var o in e)e[o]&&(t+=o+" ");return t.slice(0,-1)}return t}function yt(e){return Ko(e)?"svg":"math"===e?"math":void 0}function _t(e){if(!Ii)return!0;if(Wo(e))return!1;if(e=e.toLowerCase(),null!=Zo[e])return Zo[e];var t=document.createElement(e);return e.indexOf("-")>-1?Zo[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Zo[e]=/HTMLUnknownElement/.test(t.toString())}function bt(e){if("string"==typeof e){var t=document.querySelector(e);return t?t:document.createElement("div")}return e}function $t(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function wt(e,t){return document.createElementNS(zo[e],t)}function xt(e){return document.createTextNode(e)}function Ct(e){return document.createComment(e)}function kt(e,t,n){e.insertBefore(t,n)}function At(e,t){e.removeChild(t)}function Ot(e,t){e.appendChild(t)}function Tt(e){return e.parentNode}function St(e){return e.nextSibling}function Et(e){return e.tagName}function jt(e,t){e.textContent=t}function Nt(e,t,n){e.setAttribute(t,n)}function It(e,t){var n=e.data.ref;if(n){var i=e.context,o=e.componentInstance||e.elm,a=i.$refs;t?Array.isArray(a[n])?r(a[n],o):a[n]===o&&(a[n]=void 0):e.data.refInFor?Array.isArray(a[n])&&a[n].indexOf(o)<0?a[n].push(o):a[n]=[o]:a[n]=o}}function Lt(e){return void 0===e||null===e}function Dt(e){return void 0!==e&&null!==e}function Mt(e){return e===!0}function Pt(e,t){return e.key===t.key&&e.tag===t.tag&&e.isComment===t.isComment&&Dt(e.data)===Dt(t.data)&&Rt(e,t)}function Rt(e,t){if("input"!==e.tag)return!0;var n;return(Dt(n=e.data)&&Dt(n=n.attrs)&&n.type)===(Dt(n=t.data)&&Dt(n=n.attrs)&&n.type)}function Ft(e,t,n){var r,i,o={};for(r=t;r<=n;++r)i=e[r].key,Dt(i)&&(o[i]=r);return o}function Ht(e,t){(e.data.directives||t.data.directives)&&Ut(e,t)}function Ut(e,t){var n,r,i,o=e===Qo,a=t===Qo,s=Bt(e.data.directives,e.context),c=Bt(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,zt(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(zt(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n<u.length;n++)zt(u[n],"inserted",t,e)};o?q(t.data.hook||(t.data.hook={}),"insert",f):f()}if(l.length&&q(t.data.hook||(t.data.hook={}),"postpatch",function(){for(var n=0;n<l.length;n++)zt(l[n],"componentUpdated",t,e)}),!o)for(n in s)c[n]||zt(s[n],"unbind",e,e,a)}function Bt(e,t){var n=Object.create(null);if(!e)return n;var r,i;for(r=0;r<e.length;r++)i=e[r],i.modifiers||(i.modifiers=ta),n[Vt(i)]=i,i.def=M(t.$options,"directives",i.name,!0);return n}function Vt(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function zt(e,t,n,r,i){var o=e.def&&e.def[t];o&&o(n.elm,e,n,r,i)}function Jt(e,t){if(e.data.attrs||t.data.attrs){var n,r,i=t.elm,o=e.data.attrs||{},a=t.data.attrs||{};a.__ob__&&(a=t.data.attrs=u({},a));for(n in a)r=a[n],o[n]!==r&&Kt(i,n,r);Mi&&a.value!==o.value&&Kt(i,"value",a.value);for(n in o)null==a[n]&&(Uo(n)?i.removeAttributeNS(Ho,Bo(n)):Ro(n)||i.removeAttribute(n))}}function Kt(e,t,n){Fo(t)?Vo(n)?e.removeAttribute(t):e.setAttribute(t,t):Ro(t)?e.setAttribute(t,Vo(n)||"false"===n?"false":"true"):Uo(t)?Vo(n)?e.removeAttributeNS(Ho,Bo(t)):e.setAttributeNS(Ho,t,n):Vo(n)?e.removeAttribute(t):e.setAttribute(t,n)}function qt(e,t){var n=t.elm,r=t.data,i=e.data;if(r.staticClass||r.class||i&&(i.staticClass||i.class)){var o=dt(t),a=n._transitionClasses;a&&(o=mt(o,gt(a))),o!==n._prevClass&&(n.setAttribute("class",o),n._prevClass=o)}}function Wt(e){function t(){(a||(a=[])).push(e.slice(v,i).trim()),v=i+1}var n,r,i,o,a,s=!1,c=!1,u=!1,l=!1,f=0,p=0,d=0,v=0;for(i=0;i<e.length;i++)if(r=n,n=e.charCodeAt(i),s)39===n&&92!==r&&(s=!1);else if(c)34===n&&92!==r&&(c=!1);else if(u)96===n&&92!==r&&(u=!1);else if(l)47===n&&92!==r&&(l=!1);else if(124!==n||124===e.charCodeAt(i+1)||124===e.charCodeAt(i-1)||f||p||d){switch(n){case 34:c=!0;break;case 39:s=!0;break;case 96:u=!0;break;case 40:d++;break;case 41:d--;break;case 91:p++;break;case 93:p--;break;case 123:f++;break;case 125:f--}if(47===n){for(var h=i-1,m=void 0;h>=0&&" "===(m=e.charAt(h));h--);m&&oa.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=e.slice(0,i).trim()):t();if(void 0===o?o=e.slice(0,i).trim():0!==v&&t(),a)for(i=0;i<a.length;i++)o=Zt(o,a[i]);return o}function Zt(e,t){var n=t.indexOf("(");return n<0?'_f("'+t+'")('+e+")":'_f("'+t.slice(0,n)+'")('+e+","+t.slice(n+1)}function Gt(e){console.error("[Vue compiler]: "+e)}function Yt(e,t){return e?e.map(function(e){return e[t]}).filter(function(e){return e}):[]}function Qt(e,t,n){(e.props||(e.props=[])).push({name:t,value:n})}function Xt(e,t,n){(e.attrs||(e.attrs=[])).push({name:t,value:n})}function en(e,t,n,r,i,o){(e.directives||(e.directives=[])).push({name:t,rawName:n,value:r,arg:i,modifiers:o})}function tn(e,t,n,r,i){r&&r.capture&&(delete r.capture,t="!"+t),r&&r.once&&(delete r.once,t="~"+t);var o;r&&r.native?(delete r.native,o=e.nativeEvents||(e.nativeEvents={})):o=e.events||(e.events={});var a={value:n,modifiers:r},s=o[t];Array.isArray(s)?i?s.unshift(a):s.push(a):o[t]=s?i?[a,s]:[s,a]:a}function nn(e,t,n){var r=rn(e,":"+t)||rn(e,"v-bind:"+t);if(null!=r)return Wt(r);if(n!==!1){var i=rn(e,t);if(null!=i)return JSON.stringify(i)}}function rn(e,t){var n;if(null!=(n=e.attrsMap[t]))for(var r=e.attrsList,i=0,o=r.length;i<o;i++)if(r[i].name===t){r.splice(i,1);break}return n}function on(e,t,n){var r=n||{},i=r.number,o=r.trim,a="$$v";o&&(a="(typeof $$v === 'string'? $$v.trim(): $$v)"),i&&(a="_n("+a+")");var s=an(t,a);e.model={value:"("+t+")",expression:'"'+t+'"',callback:"function ($$v) {"+s+"}"}}function an(e,t){var n=sn(e);return null===n.idx?e+"="+t:"var $$exp = "+n.exp+", $$idx = "+n.idx+";if (!Array.isArray($$exp)){"+e+"="+t+"}else{$$exp.splice($$idx, 1, "+t+")}"}function sn(e){if(To=e,Oo=To.length,Eo=jo=No=0,e.indexOf("[")<0||e.lastIndexOf("]")<Oo-1)return{exp:e,idx:null};for(;!un();)So=cn(),ln(So)?pn(So):91===So&&fn(So);return{exp:e.substring(0,jo),idx:e.substring(jo+1,No)}}function cn(){return To.charCodeAt(++Eo)}function un(){return Eo>=Oo}function ln(e){return 34===e||39===e}function fn(e){var t=1;for(jo=Eo;!un();)if(e=cn(),ln(e))pn(e);else if(91===e&&t++,93===e&&t--,0===t){No=Eo;break}}function pn(e){for(var t=e;!un()&&(e=cn())!==t;);}function dn(e,t,n){Io=n;var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if("select"===o)mn(e,r,i);else if("input"===o&&"checkbox"===a)vn(e,r,i);else if("input"===o&&"radio"===a)hn(e,r,i);else if("input"===o||"textarea"===o)gn(e,r,i);else if(!Si.isReservedTag(o))return on(e,r,i),!1;return!0}function vn(e,t,n){var r=n&&n.number,i=nn(e,"value")||"null",o=nn(e,"true-value")||"true",a=nn(e,"false-value")||"false";Qt(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),tn(e,sa,"var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$c){$$i<0&&("+t+"=$$a.concat($$v))}else{$$i>-1&&("+t+"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}}else{"+t+"=$$c}",null,!0)}function hn(e,t,n){var r=n&&n.number,i=nn(e,"value")||"null";i=r?"_n("+i+")":i,Qt(e,"checked","_q("+t+","+i+")"),tn(e,sa,an(t,i),null,!0)}function mn(e,t,n){var r=n&&n.number,i='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",o="var $$selectedVal = "+i+";";o=o+" "+an(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),tn(e,"change",o,null,!0)}function gn(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?aa:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=an(t,l);c&&(f="if($event.target.composing)return;"+f),Qt(e,"value","("+t+")"),tn(e,u,f,null,!0),(s||a||"number"===r)&&tn(e,"blur","$forceUpdate()")}function yn(e){var t;e[aa]&&(t=Di?"change":"input",e[t]=[].concat(e[aa],e[t]||[]),delete e[aa]),e[sa]&&(t=Hi?"click":"change",e[t]=[].concat(e[sa],e[t]||[]),delete e[sa])}function _n(e,t,n,r){if(n){var i=t,o=Lo;t=function(n){null!==(1===arguments.length?i(n):i.apply(null,arguments))&&bn(e,t,r,o)}}Lo.addEventListener(e,t,r)}function bn(e,t,n,r){(r||Lo).removeEventListener(e,t,n)}function $n(e,t){if(e.data.on||t.data.on){var n=t.data.on||{},r=e.data.on||{};Lo=t.elm,yn(n),K(n,r,_n,bn,t.context)}}function wn(e,t){if(e.data.domProps||t.data.domProps){var n,r,i=t.elm,o=e.data.domProps||{},a=t.data.domProps||{};a.__ob__&&(a=t.data.domProps=u({},a));for(n in o)null==a[n]&&(i[n]="");for(n in a)if(r=a[n],"textContent"!==n&&"innerHTML"!==n||(t.children&&(t.children.length=0),r!==o[n]))if("value"===n){i._value=r;var s=null==r?"":String(r);xn(i,t,s)&&(i.value=s)}else i[n]=r}}function xn(e,t,n){return!e.composing&&("option"===t.tag||Cn(e,n)||kn(e,n))}function Cn(e,t){return document.activeElement!==e&&e.value!==t}function kn(e,n){var r=e.value,i=e._vModifiers;return i&&i.number||"number"===e.type?t(r)!==t(n):i&&i.trim?r.trim()!==n.trim():r!==n}function An(e){var t=On(e.style);return e.staticStyle?u(e.staticStyle,t):t}function On(e){return Array.isArray(e)?p(e):"string"==typeof e?la(e):e}function Tn(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)i=i.componentInstance._vnode,i.data&&(n=An(i.data))&&u(r,n);(n=An(e.data))&&u(r,n);for(var o=e;o=o.parent;)o.data&&(n=An(o.data))&&u(r,n);return r}function Sn(e,t){var n=t.data,r=e.data;if(n.staticStyle||n.style||r.staticStyle||r.style){var i,o,a=t.elm,s=e.data.staticStyle,c=e.data.style||{},l=s||c,f=On(t.data.style)||{};t.data.style=f.__ob__?u({},f):f;var p=Tn(t,!0);for(o in l)null==p[o]&&da(a,o,"");for(o in p)(i=p[o])!==l[o]&&da(a,o,null==i?"":i)}}function En(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function jn(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t);else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");e.setAttribute("class",n.trim())}}function Nn(e){if(e){if("object"==typeof e){var t={};return e.css!==!1&&u(t,ga(e.name||"v")),u(t,e),t}return"string"==typeof e?ga(e):void 0}}function In(e){ka(function(){ka(e)})}function Ln(e,t){(e._transitionClasses||(e._transitionClasses=[])).push(t),En(e,t)}function Dn(e,t){e._transitionClasses&&r(e._transitionClasses,t),jn(e,t)}function Mn(e,t,n){var r=Pn(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===_a?wa:Ca,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c<a&&u()},o+1),e.addEventListener(s,l)}function Pn(e,t){var n,r=window.getComputedStyle(e),i=r[$a+"Delay"].split(", "),o=r[$a+"Duration"].split(", "),a=Rn(i,o),s=r[xa+"Delay"].split(", "),c=r[xa+"Duration"].split(", "),u=Rn(s,c),l=0,f=0;return t===_a?a>0&&(n=_a,l=a,f=o.length):t===ba?u>0&&(n=ba,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?_a:ba:null,f=n?n===_a?o.length:c.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===_a&&Aa.test(r[$a+"Property"])}}function Rn(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max.apply(null,t.map(function(t,n){return Fn(t)+Fn(e[n])}))}function Fn(e){return 1e3*Number(e.slice(0,-1))}function Hn(e,n){var r=e.elm;r._leaveCb&&(r._leaveCb.cancelled=!0,r._leaveCb());var i=Nn(e.data.transition);if(i&&!r._enterCb&&1===r.nodeType){for(var o=i.css,a=i.type,s=i.enterClass,c=i.enterToClass,u=i.enterActiveClass,f=i.appearClass,p=i.appearToClass,d=i.appearActiveClass,v=i.beforeEnter,h=i.enter,g=i.afterEnter,y=i.enterCancelled,_=i.beforeAppear,b=i.appear,$=i.afterAppear,w=i.appearCancelled,x=i.duration,C=so,k=so.$vnode;k&&k.parent;)k=k.parent,C=k.context;var A=!C._isMounted||!e.isRootInsert;if(!A||b||""===b){var O=A&&f?f:s,T=A&&d?d:u,S=A&&p?p:c,E=A?_||v:v,j=A&&"function"==typeof b?b:h,N=A?$||g:g,I=A?w||y:y,L=t(l(x)?x.enter:x),D=o!==!1&&!Mi,M=Vn(j),P=r._enterCb=m(function(){D&&(Dn(r,S),Dn(r,T)),P.cancelled?(D&&Dn(r,O),I&&I(r)):N&&N(r),r._enterCb=null});e.data.show||q(e.data.hook||(e.data.hook={}),"insert",function(){var t=r.parentNode,n=t&&t._pending&&t._pending[e.key];n&&n.tag===e.tag&&n.elm._leaveCb&&n.elm._leaveCb(),j&&j(r,P)}),E&&E(r),D&&(Ln(r,O),Ln(r,T),In(function(){Ln(r,S),Dn(r,O),P.cancelled||M||(Bn(L)?setTimeout(P,L):Mn(r,a,P))})),e.data.show&&(n&&n(),j&&j(r,P)),D||M||P()}}}function Un(e,n){function r(){w.cancelled||(e.data.show||((i.parentNode._pending||(i.parentNode._pending={}))[e.key]=e),p&&p(i),_&&(Ln(i,c),Ln(i,f),In(function(){Ln(i,u),Dn(i,c),w.cancelled||b||(Bn($)?setTimeout(w,$):Mn(i,s,w))})),d&&d(i,w),_||b||w())}var i=e.elm;i._enterCb&&(i._enterCb.cancelled=!0,i._enterCb());var o=Nn(e.data.transition);if(!o)return n();if(!i._leaveCb&&1===i.nodeType){
7
+ var a=o.css,s=o.type,c=o.leaveClass,u=o.leaveToClass,f=o.leaveActiveClass,p=o.beforeLeave,d=o.leave,v=o.afterLeave,h=o.leaveCancelled,g=o.delayLeave,y=o.duration,_=a!==!1&&!Mi,b=Vn(d),$=t(l(y)?y.leave:y),w=i._leaveCb=m(function(){i.parentNode&&i.parentNode._pending&&(i.parentNode._pending[e.key]=null),_&&(Dn(i,u),Dn(i,f)),w.cancelled?(_&&Dn(i,c),h&&h(i)):(n(),v&&v(i)),i._leaveCb=null});g?g(r):r()}}function Bn(e){return"number"==typeof e&&!isNaN(e)}function Vn(e){if(!e)return!1;var t=e.fns;return t?Vn(Array.isArray(t)?t[0]:t):(e._length||e.length)>1}function zn(e,t){t.data.show||Hn(t)}function Jn(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],i)o=h(r,qn(a))>-1,a.selected!==o&&(a.selected=o);else if(v(qn(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Kn(e,t){for(var n=0,r=t.length;n<r;n++)if(v(qn(t[n]),e))return!1;return!0}function qn(e){return"_value"in e?e._value:e.value}function Wn(e){e.target.composing=!0}function Zn(e){e.target.composing=!1,Gn(e.target,"input")}function Gn(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Yn(e){return!e.componentInstance||e.data&&e.data.transition?e:Yn(e.componentInstance._vnode)}function Qn(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Qn(Y(t.children)):e}function Xn(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[wi(o)]=i[o];return t}function er(e,t){return/\d-keep-alive$/.test(t.tag)?e("keep-alive"):null}function tr(e){for(;e=e.parent;)if(e.data.transition)return!0}function nr(e,t){return t.key===e.key&&t.tag===e.tag}function rr(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function ir(e){e.data.newPos=e.elm.getBoundingClientRect()}function or(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}function ar(e){return Fa=Fa||document.createElement("div"),Fa.innerHTML=e,Fa.textContent}function sr(e,t){var n=t?ws:$s;return e.replace(n,function(e){return bs[e]})}function cr(e,t){function n(t){l+=t,e=e.substring(t)}function r(e,n,r){var i,s;if(null==n&&(n=l),null==r&&(r=l),e&&(s=e.toLowerCase()),e)for(i=a.length-1;i>=0&&a[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(var c=a.length-1;c>=i;c--)t.end&&t.end(a[c].tag,n,r);a.length=i,o=i&&a[i-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,r):"p"===s&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var i,o,a=[],s=t.expectHTML,c=t.isUnaryTag||Oi,u=t.canBeLeftOpenTag||Oi,l=0;e;){if(i=e,o&&ys(o)){var f=o.toLowerCase(),p=_s[f]||(_s[f]=new RegExp("([\\s\\S]*?)(</"+f+"[^>]*>)","i")),d=0,v=e.replace(p,function(e,n,r){return d=r.length,ys(f)||"noscript"===f||(n=n.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),t.chars&&t.chars(n),""});l+=e.length-v.length,e=v,r(f,l-d,l)}else{var h=e.indexOf("<");if(0===h){if(Ya.test(e)){var m=e.indexOf("-->");if(m>=0){n(m+3);continue}}if(Qa.test(e)){var g=e.indexOf("]>");if(g>=0){n(g+2);continue}}var y=e.match(Ga);if(y){n(y[0].length);continue}var _=e.match(Za);if(_){var b=l;n(_[0].length),r(_[1],b,l);continue}var $=function(){var t=e.match(qa);if(t){var r={tagName:t[1],attrs:[],start:l};n(t[0].length);for(var i,o;!(i=e.match(Wa))&&(o=e.match(Ja));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=l,r}}();if($){!function(e){var n=e.tagName,i=e.unarySlash;s&&("p"===o&&Va(n)&&r(o),u(n)&&o===n&&r(n));for(var l=c(n)||"html"===n&&"head"===o||!!i,f=e.attrs.length,p=new Array(f),d=0;d<f;d++){var v=e.attrs[d];Xa&&v[0].indexOf('""')===-1&&(""===v[3]&&delete v[3],""===v[4]&&delete v[4],""===v[5]&&delete v[5]);var h=v[3]||v[4]||v[5]||"";p[d]={name:v[1],value:sr(h,t.shouldDecodeNewlines)}}l||(a.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:p}),o=n),t.start&&t.start(n,p,l,e.start,e.end)}($);continue}}var w=void 0,x=void 0,C=void 0;if(h>=0){for(x=e.slice(h);!(Za.test(x)||qa.test(x)||Ya.test(x)||Qa.test(x)||(C=x.indexOf("<",1))<0);)h+=C,x=e.slice(h);w=e.substring(0,h),n(h)}h<0&&(w=e,e=""),t.chars&&w&&t.chars(w)}if(e===i){t.chars&&t.chars(e);break}}r()}function ur(e,t){var n=t?Cs(t):xs;if(n.test(e)){for(var r,i,o=[],a=n.lastIndex=0;r=n.exec(e);){i=r.index,i>a&&o.push(JSON.stringify(e.slice(a,i)));var s=Wt(r[1].trim());o.push("_s("+s+")"),a=i+r[0].length}return a<e.length&&o.push(JSON.stringify(e.slice(a))),o.join("+")}}function lr(e,t){function n(e){e.pre&&(s=!1),os(e.tag)&&(c=!1)}es=t.warn||Gt,ss=t.getTagNamespace||Oi,as=t.mustUseProp||Oi,os=t.isPreTag||Oi,rs=Yt(t.modules,"preTransformNode"),ns=Yt(t.modules,"transformNode"),is=Yt(t.modules,"postTransformNode"),ts=t.delimiters;var r,i,o=[],a=t.preserveWhitespace!==!1,s=!1,c=!1;return cr(e,{warn:es,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,start:function(e,a,u){var l=i&&i.ns||ss(e);Di&&"svg"===l&&(a=Tr(a));var f={type:1,tag:e,attrsList:a,attrsMap:Ar(a),parent:i,children:[]};l&&(f.ns=l),Or(f)&&!Ui()&&(f.forbidden=!0);for(var p=0;p<rs.length;p++)rs[p](f,t);if(s||(fr(f),f.pre&&(s=!0)),os(f.tag)&&(c=!0),s)pr(f);else{hr(f),mr(f),br(f),dr(f),f.plain=!f.key&&!a.length,vr(f),$r(f),wr(f);for(var d=0;d<ns.length;d++)ns[d](f,t);xr(f)}if(r?o.length||r.if&&(f.elseif||f.else)&&_r(r,{exp:f.elseif,block:f}):r=f,i&&!f.forbidden)if(f.elseif||f.else)gr(f,i);else if(f.slotScope){i.plain=!1;var v=f.slotTarget||'"default"';(i.scopedSlots||(i.scopedSlots={}))[v]=f}else i.children.push(f),f.parent=i;u?n(f):(i=f,o.push(f));for(var h=0;h<is.length;h++)is[h](f,t)},end:function(){var e=o[o.length-1],t=e.children[e.children.length-1];t&&3===t.type&&" "===t.text&&!c&&e.children.pop(),o.length-=1,i=o[o.length-1],n(e)},chars:function(e){if(i&&(!Di||"textarea"!==i.tag||i.attrsMap.placeholder!==e)){var t=i.children;if(e=c||e.trim()?Ns(e):a&&t.length?" ":""){var n;!s&&" "!==e&&(n=ur(e,ts))?t.push({type:2,expression:n,text:e}):" "===e&&t.length&&" "===t[t.length-1].text||t.push({type:3,text:e})}}}}),r}function fr(e){null!=rn(e,"v-pre")&&(e.pre=!0)}function pr(e){var t=e.attrsList.length;if(t)for(var n=e.attrs=new Array(t),r=0;r<t;r++)n[r]={name:e.attrsList[r].name,value:JSON.stringify(e.attrsList[r].value)};else e.pre||(e.plain=!0)}function dr(e){var t=nn(e,"key");t&&(e.key=t)}function vr(e){var t=nn(e,"ref");t&&(e.ref=t,e.refInFor=Cr(e))}function hr(e){var t;if(t=rn(e,"v-for")){var n=t.match(Os);if(!n)return;e.for=n[2].trim();var r=n[1].trim(),i=r.match(Ts);i?(e.alias=i[1].trim(),e.iterator1=i[2].trim(),i[3]&&(e.iterator2=i[3].trim())):e.alias=r}}function mr(e){var t=rn(e,"v-if");if(t)e.if=t,_r(e,{exp:t,block:e});else{null!=rn(e,"v-else")&&(e.else=!0);var n=rn(e,"v-else-if");n&&(e.elseif=n)}}function gr(e,t){var n=yr(t.children);n&&n.if&&_r(n,{exp:e.elseif,block:e})}function yr(e){for(var t=e.length;t--;){if(1===e[t].type)return e[t];e.pop()}}function _r(e,t){e.ifConditions||(e.ifConditions=[]),e.ifConditions.push(t)}function br(e){null!=rn(e,"v-once")&&(e.once=!0)}function $r(e){if("slot"===e.tag)e.slotName=nn(e,"name");else{var t=nn(e,"slot");t&&(e.slotTarget='""'===t?'"default"':t),"template"===e.tag&&(e.slotScope=rn(e,"scope"))}}function wr(e){var t;(t=nn(e,"is"))&&(e.component=t),null!=rn(e,"inline-template")&&(e.inlineTemplate=!0)}function xr(e){var t,n,r,i,o,a,s,c=e.attrsList;for(t=0,n=c.length;t<n;t++)if(r=i=c[t].name,o=c[t].value,As.test(r))if(e.hasBindings=!0,a=kr(r),a&&(r=r.replace(js,"")),Es.test(r))r=r.replace(Es,""),o=Wt(o),s=!1,a&&(a.prop&&(s=!0,"innerHtml"===(r=wi(r))&&(r="innerHTML")),a.camel&&(r=wi(r))),s||as(e.tag,e.attrsMap.type,r)?Qt(e,r,o):Xt(e,r,o);else if(ks.test(r))r=r.replace(ks,""),tn(e,r,o,a);else{r=r.replace(As,"");var u=r.match(Ss),l=u&&u[1];l&&(r=r.slice(0,-(l.length+1))),en(e,r,i,o,l,a)}else Xt(e,r,JSON.stringify(o))}function Cr(e){for(var t=e;t;){if(void 0!==t.for)return!0;t=t.parent}return!1}function kr(e){var t=e.match(js);if(t){var n={};return t.forEach(function(e){n[e.slice(1)]=!0}),n}}function Ar(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n].name]=e[n].value;return t}function Or(e){return"style"===e.tag||"script"===e.tag&&(!e.attrsMap.type||"text/javascript"===e.attrsMap.type)}function Tr(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];Is.test(r.name)||(r.name=r.name.replace(Ls,""),t.push(r))}return t}function Sr(e,t){e&&(cs=Ds(t.staticKeys||""),us=t.isReservedTag||Oi,jr(e),Nr(e,!1))}function Er(e){return n("type,tag,attrsList,attrsMap,plain,parent,children,attrs"+(e?","+e:""))}function jr(e){if(e.static=Lr(e),1===e.type){if(!us(e.tag)&&"slot"!==e.tag&&null==e.attrsMap["inline-template"])return;for(var t=0,n=e.children.length;t<n;t++){var r=e.children[t];jr(r),r.static||(e.static=!1)}}}function Nr(e,t){if(1===e.type){if((e.static||e.once)&&(e.staticInFor=t),e.static&&e.children.length&&(1!==e.children.length||3!==e.children[0].type))return void(e.staticRoot=!0);if(e.staticRoot=!1,e.children)for(var n=0,r=e.children.length;n<r;n++)Nr(e.children[n],t||!!e.for);e.ifConditions&&Ir(e.ifConditions,t)}}function Ir(e,t){for(var n=1,r=e.length;n<r;n++)Nr(e[n].block,t)}function Lr(e){return 2!==e.type&&(3===e.type||!(!e.pre&&(e.hasBindings||e.if||e.for||bi(e.tag)||!us(e.tag)||Dr(e)||!Object.keys(e).every(cs))))}function Dr(e){for(;e.parent;){if(e=e.parent,"template"!==e.tag)return!1;if(e.for)return!0}return!1}function Mr(e,t){var n=t?"nativeOn:{":"on:{";for(var r in e)n+='"'+r+'":'+Pr(r,e[r])+",";return n.slice(0,-1)+"}"}function Pr(e,t){if(!t)return"function(){}";if(Array.isArray(t))return"["+t.map(function(t){return Pr(e,t)}).join(",")+"]";var n=Ps.test(t.value),r=Ms.test(t.value);if(t.modifiers){var i="",o="",a=[];for(var s in t.modifiers)Hs[s]?(o+=Hs[s],Rs[s]&&a.push(s)):a.push(s);a.length&&(i+=Rr(a)),o&&(i+=o);return"function($event){"+i+(n?t.value+"($event)":r?"("+t.value+")($event)":t.value)+"}"}return n||r?t.value:"function($event){"+t.value+"}"}function Rr(e){return"if(!('button' in $event)&&"+e.map(Fr).join("&&")+")return null;"}function Fr(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Rs[e];return"_k($event.keyCode,"+JSON.stringify(e)+(n?","+JSON.stringify(n):"")+")"}function Hr(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+(t.modifiers&&t.modifiers.prop?",true":"")+")"}}function Ur(e,t){var n=hs,r=hs=[],i=ms;ms=0,gs=t,ls=t.warn||Gt,fs=Yt(t.modules,"transformCode"),ps=Yt(t.modules,"genData"),ds=t.directives||{},vs=t.isReservedTag||Oi;var o=e?Br(e):'_c("div")';return hs=n,ms=i,{render:"with(this){return "+o+"}",staticRenderFns:r}}function Br(e){if(e.staticRoot&&!e.staticProcessed)return Vr(e);if(e.once&&!e.onceProcessed)return zr(e);if(e.for&&!e.forProcessed)return qr(e);if(e.if&&!e.ifProcessed)return Jr(e);if("template"!==e.tag||e.slotTarget){if("slot"===e.tag)return oi(e);var t;if(e.component)t=ai(e.component,e);else{var n=e.plain?void 0:Wr(e),r=e.inlineTemplate?null:Xr(e,!0);t="_c('"+e.tag+"'"+(n?","+n:"")+(r?","+r:"")+")"}for(var i=0;i<fs.length;i++)t=fs[i](e,t);return t}return Xr(e)||"void 0"}function Vr(e){return e.staticProcessed=!0,hs.push("with(this){return "+Br(e)+"}"),"_m("+(hs.length-1)+(e.staticInFor?",true":"")+")"}function zr(e){if(e.onceProcessed=!0,e.if&&!e.ifProcessed)return Jr(e);if(e.staticInFor){for(var t="",n=e.parent;n;){if(n.for){t=n.key;break}n=n.parent}return t?"_o("+Br(e)+","+ms+++(t?","+t:"")+")":Br(e)}return Vr(e)}function Jr(e){return e.ifProcessed=!0,Kr(e.ifConditions.slice())}function Kr(e){function t(e){return e.once?zr(e):Br(e)}if(!e.length)return"_e()";var n=e.shift();return n.exp?"("+n.exp+")?"+t(n.block)+":"+Kr(e):""+t(n.block)}function qr(e){var t=e.for,n=e.alias,r=e.iterator1?","+e.iterator1:"",i=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,"_l(("+t+"),function("+n+r+i+"){return "+Br(e)+"})"}function Wr(e){var t="{",n=Zr(e);n&&(t+=n+","),e.key&&(t+="key:"+e.key+","),e.ref&&(t+="ref:"+e.ref+","),e.refInFor&&(t+="refInFor:true,"),e.pre&&(t+="pre:true,"),e.component&&(t+='tag:"'+e.tag+'",');for(var r=0;r<ps.length;r++)t+=ps[r](e);if(e.attrs&&(t+="attrs:{"+si(e.attrs)+"},"),e.props&&(t+="domProps:{"+si(e.props)+"},"),e.events&&(t+=Mr(e.events)+","),e.nativeEvents&&(t+=Mr(e.nativeEvents,!0)+","),e.slotTarget&&(t+="slot:"+e.slotTarget+","),e.scopedSlots&&(t+=Yr(e.scopedSlots)+","),e.model&&(t+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var i=Gr(e);i&&(t+=i+",")}return t=t.replace(/,$/,"")+"}",e.wrapData&&(t=e.wrapData(t)),t}function Zr(e){var t=e.directives;if(t){var n,r,i,o,a="directives:[",s=!1;for(n=0,r=t.length;n<r;n++){i=t[n],o=!0;var c=ds[i.name]||Us[i.name];c&&(o=!!c(e,i,ls)),o&&(s=!0,a+='{name:"'+i.name+'",rawName:"'+i.rawName+'"'+(i.value?",value:("+i.value+"),expression:"+JSON.stringify(i.value):"")+(i.arg?',arg:"'+i.arg+'"':"")+(i.modifiers?",modifiers:"+JSON.stringify(i.modifiers):"")+"},")}return s?a.slice(0,-1)+"]":void 0}}function Gr(e){var t=e.children[0];if(1===t.type){var n=Ur(t,gs);return"inlineTemplate:{render:function(){"+n.render+"},staticRenderFns:["+n.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}function Yr(e){return"scopedSlots:_u(["+Object.keys(e).map(function(t){return Qr(t,e[t])}).join(",")+"])"}function Qr(e,t){return"["+e+",function("+String(t.attrsMap.scope)+"){return "+("template"===t.tag?Xr(t)||"void 0":Br(t))+"}]"}function Xr(e,t){var n=e.children;if(n.length){var r=n[0];if(1===n.length&&r.for&&"template"!==r.tag&&"slot"!==r.tag)return Br(r);var i=t?ei(n):0;return"["+n.map(ri).join(",")+"]"+(i?","+i:"")}}function ei(e){for(var t=0,n=0;n<e.length;n++){var r=e[n];if(1===r.type){if(ti(r)||r.ifConditions&&r.ifConditions.some(function(e){return ti(e.block)})){t=2;break}(ni(r)||r.ifConditions&&r.ifConditions.some(function(e){return ni(e.block)}))&&(t=1)}}return t}function ti(e){return void 0!==e.for||"template"===e.tag||"slot"===e.tag}function ni(e){return!vs(e.tag)}function ri(e){return 1===e.type?Br(e):ii(e)}function ii(e){return"_v("+(2===e.type?e.expression:ci(JSON.stringify(e.text)))+")"}function oi(e){var t=e.slotName||'"default"',n=Xr(e),r="_t("+t+(n?","+n:""),i=e.attrs&&"{"+e.attrs.map(function(e){return wi(e.name)+":"+e.value}).join(",")+"}",o=e.attrsMap["v-bind"];return!i&&!o||n||(r+=",null"),i&&(r+=","+i),o&&(r+=(i?"":",null")+","+o),r+")"}function ai(e,t){var n=t.inlineTemplate?null:Xr(t,!0);return"_c("+e+","+Wr(t)+(n?","+n:"")+")"}function si(e){for(var t="",n=0;n<e.length;n++){var r=e[n];t+='"'+r.name+'":'+ci(r.value)+","}return t.slice(0,-1)}function ci(e){return e.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function ui(e,t){var n=lr(e.trim(),t);Sr(n,t);var r=Ur(n,t);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}}function li(e,t){try{return new Function(e)}catch(n){return t.push({err:n,code:e}),d}}function fi(e,t){var n=(t.warn,rn(e,"class"));n&&(e.staticClass=JSON.stringify(n));var r=nn(e,"class",!1);r&&(e.classBinding=r)}function pi(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}function di(e,t){var n=(t.warn,rn(e,"style"));n&&(e.staticStyle=JSON.stringify(la(n)));var r=nn(e,"style",!1);r&&(e.styleBinding=r)}function vi(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}function hi(e,t){t.value&&Qt(e,"textContent","_s("+t.value+")")}function mi(e,t){t.value&&Qt(e,"innerHTML","_s("+t.value+")")}function gi(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}var yi,_i,bi=n("slot,component",!0),$i=Object.prototype.hasOwnProperty,wi=a(function(e){return e.replace(/-(\w)/g,function(e,t){return t?t.toUpperCase():""})}),xi=a(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),Ci=a(function(e){return e.replace(/([^-])([A-Z])/g,"$1-$2").replace(/([^-])([A-Z])/g,"$1-$2").toLowerCase()}),ki=Object.prototype.toString,Ai="[object Object]",Oi=function(){return!1},Ti=function(e){return e},Si={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:Oi,isUnknownElement:Oi,getTagNamespace:d,parsePlatformTagName:Ti,mustUseProp:Oi,_assetTypes:["component","directive","filter"],_lifecycleHooks:["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated"],_maxUpdateCount:100},Ei=Object.freeze({}),ji=/[^\w.$]/,Ni="__proto__"in{},Ii="undefined"!=typeof window,Li=Ii&&window.navigator.userAgent.toLowerCase(),Di=Li&&/msie|trident/.test(Li),Mi=Li&&Li.indexOf("msie 9.0")>0,Pi=Li&&Li.indexOf("edge/")>0,Ri=Li&&Li.indexOf("android")>0,Fi=Li&&/iphone|ipad|ipod|ios/.test(Li),Hi=Li&&/chrome\/\d+/.test(Li)&&!Pi,Ui=function(){return void 0===yi&&(yi=!Ii&&"undefined"!=typeof global&&"server"===global.process.env.VUE_ENV),yi},Bi=Ii&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,Vi="undefined"!=typeof Symbol&&b(Symbol)&&"undefined"!=typeof Reflect&&b(Reflect.ownKeys),zi=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t<e.length;t++)e[t]()}var t,n=[],r=!1;if("undefined"!=typeof Promise&&b(Promise)){var i=Promise.resolve(),o=function(e){console.error(e)};t=function(){i.then(e).catch(o),Fi&&setTimeout(d)}}else if("undefined"==typeof MutationObserver||!b(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())t=function(){setTimeout(e,0)};else{var a=1,s=new MutationObserver(e),c=document.createTextNode(String(a));s.observe(c,{characterData:!0}),t=function(){a=(a+1)%2,c.data=String(a)}}return function(e,i){var o;if(n.push(function(){e&&e.call(i),o&&o(i)}),r||(r=!0,t()),!e&&"undefined"!=typeof Promise)return new Promise(function(e){o=e})}}();_i="undefined"!=typeof Set&&b(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return this.set[e]===!0},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var Ji=d,Ki=0,qi=function(){this.id=Ki++,this.subs=[]};qi.prototype.addSub=function(e){this.subs.push(e)},qi.prototype.removeSub=function(e){r(this.subs,e)},qi.prototype.depend=function(){qi.target&&qi.target.addDep(this)},qi.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},qi.target=null;var Wi=[],Zi=Array.prototype,Gi=Object.create(Zi);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=Zi[e];y(Gi,e,function(){for(var n=arguments,r=arguments.length,i=new Array(r);r--;)i[r]=n[r];var o,a=t.apply(this,i),s=this.__ob__;switch(e){case"push":o=i;break;case"unshift":o=i;break;case"splice":o=i.slice(2)}return o&&s.observeArray(o),s.dep.notify(),a})});var Yi=Object.getOwnPropertyNames(Gi),Qi={shouldConvert:!0,isSettingProps:!1},Xi=function(e){if(this.value=e,this.dep=new qi,this.vmCount=0,y(e,"__ob__",this),Array.isArray(e)){(Ni?x:C)(e,Gi,Yi),this.observeArray(e)}else this.walk(e)};Xi.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)A(e,t[n],e[t[n]])},Xi.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)k(e[t])};var eo=Si.optionMergeStrategies;eo.data=function(e,t,n){return n?e||t?function(){var r="function"==typeof t?t.call(n):t,i="function"==typeof e?e.call(n):void 0;return r?E(r,i):i}:void 0:t?"function"!=typeof t?e:e?function(){return E(t.call(this),e.call(this))}:t:e},Si._lifecycleHooks.forEach(function(e){eo[e]=j}),Si._assetTypes.forEach(function(e){eo[e+"s"]=N}),eo.watch=function(e,t){if(!t)return Object.create(e||null);if(!e)return t;var n={};u(n,e);for(var r in t){var i=n[r],o=t[r];i&&!Array.isArray(i)&&(i=[i]),n[r]=i?i.concat(o):[o]}return n},eo.props=eo.methods=eo.computed=function(e,t){if(!t)return Object.create(e||null);if(!e)return t;var n=Object.create(null);return u(n,e),u(n,t),n};var to=function(e,t){return void 0===t?e:t},no=function(e,t,n,r,i,o,a){this.tag=e,this.data=t,this.children=n,this.text=r,this.elm=i,this.ns=void 0,this.context=o,this.functionalContext=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1},ro={child:{}};ro.child.get=function(){return this.componentInstance},Object.defineProperties(no.prototype,ro);var io,oo=function(){var e=new no;return e.text="",e.isComment=!0,e},ao=a(function(e){var t="~"===e.charAt(0);e=t?e.slice(1):e;var n="!"===e.charAt(0);return e=n?e.slice(1):e,{name:e,once:t,capture:n}}),so=null,co=[],uo={},lo=!1,fo=!1,po=0,vo=0,ho=function(e,t,n,r){this.vm=e,e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++vo,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new _i,this.newDepIds=new _i,this.expression="","function"==typeof t?this.getter=t:(this.getter=_(t),this.getter||(this.getter=function(){})),this.value=this.lazy?void 0:this.get()};ho.prototype.get=function(){$(this);var e,t=this.vm;if(this.user)try{e=this.getter.call(t,t)}catch(e){U(e,t,'getter for watcher "'+this.expression+'"')}else e=this.getter.call(t,t);return this.deep&&he(e),w(),this.cleanupDeps(),e},ho.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},ho.prototype.cleanupDeps=function(){for(var e=this,t=this.deps.length;t--;){var n=e.deps[t];e.newDepIds.has(n.id)||n.removeSub(e)}var r=this.depIds;this.depIds=this.newDepIds,this.newDepIds=r,this.newDepIds.clear(),r=this.deps,this.deps=this.newDeps,this.newDeps=r,this.newDeps.length=0},ho.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():ve(this)},ho.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||l(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){U(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},ho.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},ho.prototype.depend=function(){for(var e=this,t=this.deps.length;t--;)e.deps[t].depend()},ho.prototype.teardown=function(){var e=this;if(this.active){this.vm._isBeingDestroyed||r(this.vm._watchers,this);for(var t=this.deps.length;t--;)e.deps[t].removeSub(e);this.active=!1}};var mo=new _i,go={enumerable:!0,configurable:!0,get:d,set:d},yo={lazy:!0},_o={init:function(e,t,n,r){if(!e.componentInstance||e.componentInstance._isDestroyed){(e.componentInstance=Ee(e,so,n,r)).$mount(t?e.elm:void 0,t)}else if(e.data.keepAlive){var i=e;_o.prepatch(i,i)}},prepatch:function(e,t){var n=t.componentOptions;se(t.componentInstance=e.componentInstance,n.propsData,n.listeners,t,n.children)},insert:function(e){e.componentInstance._isMounted||(e.componentInstance._isMounted=!0,fe(e.componentInstance,"mounted")),e.data.keepAlive&&ue(e.componentInstance,!0)},destroy:function(e){e.componentInstance._isDestroyed||(e.data.keepAlive?le(e.componentInstance,!0):e.componentInstance.$destroy())}},bo=Object.keys(_o),$o=1,wo=2,xo=0;!function(e){e.prototype._init=function(e){var t=this;t._uid=xo++,t._isVue=!0,e&&e._isComponent?Qe(t,e):t.$options=D(Xe(t.constructor),e||{},t),t._renderProxy=t,t._self=t,oe(t),Q(t),Ze(t),fe(t,"beforeCreate"),Ye(t),ye(t),Ge(t),fe(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(nt),function(e){var t={};t.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=O,e.prototype.$delete=T,e.prototype.$watch=function(e,t,n){var r=this;n=n||{},n.user=!0;var i=new ho(r,e,t,n);return n.immediate&&t.call(r,i.value),function(){i.teardown()}}}(nt),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this,i=this;if(Array.isArray(e))for(var o=0,a=e.length;o<a;o++)r.$on(e[o],n);else(i._events[e]||(i._events[e]=[])).push(n),t.test(e)&&(i._hasHookEvent=!0);return i},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(r,arguments)}var r=this;return n.fn=t,r.$on(e,n),r},e.prototype.$off=function(e,t){var n=this,r=this;if(!arguments.length)return r._events=Object.create(null),r;if(Array.isArray(e)){for(var i=0,o=e.length;i<o;i++)n.$off(e[i],t);return r}var a=r._events[e];if(!a)return r;if(1===arguments.length)return r._events[e]=null,r;for(var s,c=a.length;c--;)if((s=a[c])===t||s.fn===t){a.splice(c,1);break}return r},e.prototype.$emit=function(e){var t=this,n=t._events[e];if(n){n=n.length>1?c(n):n;for(var r=c(arguments,1),i=0,o=n.length;i<o;i++)n[i].apply(t,r)}return t}}(nt),function(e){e.prototype._update=function(e,t){var n=this;n._isMounted&&fe(n,"beforeUpdate");var r=n.$el,i=n._vnode,o=so;so=n,n._vnode=e,n.$el=i?n.__patch__(i,e):n.__patch__(n.$el,e,t,!1,n.$options._parentElm,n.$options._refElm),so=o,r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){var e=this;e._watcher&&e._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){fe(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||r(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),fe(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null),e.$options._parentElm=e.$options._refElm=null}}}(nt),function(n){n.prototype.$nextTick=function(e){return zi(e,this)},n.prototype._render=function(){var e=this,t=e.$options,n=t.render,r=t.staticRenderFns,i=t._parentVnode;if(e._isMounted)for(var o in e.$slots)e.$slots[o]=z(e.$slots[o]);e.$scopedSlots=i&&i.data.scopedSlots||Ei,r&&!e._staticTrees&&(e._staticTrees=[]),e.$vnode=i;var a;try{a=n.call(e._renderProxy,e.$createElement)}catch(t){U(t,e,"render function"),a=e._vnode}return a instanceof no||(a=oo()),a.parent=i,a},n.prototype._o=Ke,n.prototype._n=t,n.prototype._s=e,n.prototype._l=He,n.prototype._t=Ue,n.prototype._q=v,n.prototype._i=h,n.prototype._m=Je,n.prototype._f=Be,n.prototype._k=Ve,n.prototype._b=ze,n.prototype._v=B,n.prototype._e=oo,n.prototype._u=ie}(nt);var Co=[String,RegExp],ko={name:"keep-alive",abstract:!0,props:{include:Co,exclude:Co},created:function(){this.cache=Object.create(null)},destroyed:function(){var e=this;for(var t in e.cache)pt(e.cache[t])},watch:{include:function(e){ft(this.cache,function(t){return lt(e,t)})},exclude:function(e){ft(this.cache,function(t){return!lt(e,t)})}},render:function(){var e=Y(this.$slots.default),t=e&&e.componentOptions;if(t){var n=ut(t);if(n&&(this.include&&!lt(this.include,n)||this.exclude&&lt(this.exclude,n)))return e;var r=null==e.key?t.Ctor.cid+(t.tag?"::"+t.tag:""):e.key;this.cache[r]?e.componentInstance=this.cache[r].componentInstance:this.cache[r]=e,e.data.keepAlive=!0}return e}},Ao={KeepAlive:ko};!function(e){var t={};t.get=function(){return Si},Object.defineProperty(e,"config",t),e.util={warn:Ji,extend:u,mergeOptions:D,defineReactive:A},e.set=O,e.delete=T,e.nextTick=zi,e.options=Object.create(null),Si._assetTypes.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,u(e.options.components,Ao),rt(e),it(e),ot(e),ct(e)}(nt),Object.defineProperty(nt.prototype,"$isServer",{get:Ui}),nt.version="2.2.6";var Oo,To,So,Eo,jo,No,Io,Lo,Do,Mo=n("input,textarea,option,select"),Po=function(e,t,n){return"value"===n&&Mo(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Ro=n("contenteditable,draggable,spellcheck"),Fo=n("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Ho="http://www.w3.org/1999/xlink",Uo=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Bo=function(e){return Uo(e)?e.slice(6,e.length):""},Vo=function(e){return null==e||e===!1},zo={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},Jo=n("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template"),Ko=n("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),qo=function(e){return"pre"===e},Wo=function(e){return Jo(e)||Ko(e)},Zo=Object.create(null),Go=Object.freeze({createElement:$t,createElementNS:wt,createTextNode:xt,createComment:Ct,insertBefore:kt,removeChild:At,appendChild:Ot,parentNode:Tt,nextSibling:St,tagName:Et,setTextContent:jt,setAttribute:Nt}),Yo={create:function(e,t){It(t)},update:function(e,t){e.data.ref!==t.data.ref&&(It(e,!0),It(t))},destroy:function(e){It(e,!0)}},Qo=new no("",{},[]),Xo=["create","activate","update","remove","destroy"],ea={create:Ht,update:Ht,destroy:function(e){Ht(e,Qo)}},ta=Object.create(null),na=[Yo,ea],ra={create:Jt,update:Jt},ia={create:qt,update:qt},oa=/[\w).+\-_$\]]/,aa="__r",sa="__c",ca={create:$n,update:$n},ua={create:wn,update:wn},la=a(function(e){var t={};return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var n=e.split(/:(.+)/);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}),fa=/^--/,pa=/\s*!important$/,da=function(e,t,n){fa.test(t)?e.style.setProperty(t,n):pa.test(n)?e.style.setProperty(t,n.replace(pa,""),"important"):e.style[ha(t)]=n},va=["Webkit","Moz","ms"],ha=a(function(e){if(Do=Do||document.createElement("div"),"filter"!==(e=wi(e))&&e in Do.style)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<va.length;n++){var r=va[n]+t;if(r in Do.style)return r}}),ma={create:Sn,update:Sn},ga=a(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),ya=Ii&&!Mi,_a="transition",ba="animation",$a="transition",wa="transitionend",xa="animation",Ca="animationend";ya&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&($a="WebkitTransition",wa="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(xa="WebkitAnimation",Ca="webkitAnimationEnd"));var ka=Ii&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout,Aa=/\b(transform|all)(,|$)/,Oa=Ii?{create:zn,activate:zn,remove:function(e,t){e.data.show?t():Un(e,t)}}:{},Ta=[ra,ia,ca,ua,ma,Oa],Sa=Ta.concat(na),Ea=function(e){function t(e){return new no(O.tagName(e).toLowerCase(),{},[],void 0,e)}function r(e,t){function n(){0==--n.listeners&&i(e)}return n.listeners=t,n}function i(e){var t=O.parentNode(e);Dt(t)&&O.removeChild(t,e)}function a(e,t,n,r,i){if(e.isRootInsert=!i,!s(e,t,n,r)){var o=e.data,a=e.children,c=e.tag;Dt(c)?(e.elm=e.ns?O.createElementNS(e.ns,c):O.createElement(c,e),v(e),f(e,a,t),Dt(o)&&d(e,t),l(n,e.elm,r)):Mt(e.isComment)?(e.elm=O.createComment(e.text),
8
+ l(n,e.elm,r)):(e.elm=O.createTextNode(e.text),l(n,e.elm,r))}}function s(e,t,n,r){var i=e.data;if(Dt(i)){var o=Dt(e.componentInstance)&&i.keepAlive;if(Dt(i=i.hook)&&Dt(i=i.init)&&i(e,!1,n,r),Dt(e.componentInstance))return c(e,t),Mt(o)&&u(e,t,n,r),!0}}function c(e,t){Dt(e.data.pendingInsert)&&t.push.apply(t,e.data.pendingInsert),e.elm=e.componentInstance.$el,p(e)?(d(e,t),v(e)):(It(e),t.push(e))}function u(e,t,n,r){for(var i,o=e;o.componentInstance;)if(o=o.componentInstance._vnode,Dt(i=o.data)&&Dt(i=i.transition)){for(i=0;i<k.activate.length;++i)k.activate[i](Qo,o);t.push(o);break}l(n,e.elm,r)}function l(e,t,n){Dt(e)&&(Dt(n)?O.insertBefore(e,t,n):O.appendChild(e,t))}function f(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)a(t[r],n,e.elm,null,!0);else o(e.text)&&O.appendChild(e.elm,O.createTextNode(e.text))}function p(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return Dt(e.tag)}function d(e,t){for(var n=0;n<k.create.length;++n)k.create[n](Qo,e);x=e.data.hook,Dt(x)&&(Dt(x.create)&&x.create(Qo,e),Dt(x.insert)&&t.push(e))}function v(e){for(var t,n=e;n;)Dt(t=n.context)&&Dt(t=t.$options._scopeId)&&O.setAttribute(e.elm,t,""),n=n.parent;Dt(t=so)&&t!==e.context&&Dt(t=t.$options._scopeId)&&O.setAttribute(e.elm,t,"")}function h(e,t,n,r,i,o){for(;r<=i;++r)a(n[r],o,e,t)}function m(e){var t,n,r=e.data;if(Dt(r))for(Dt(t=r.hook)&&Dt(t=t.destroy)&&t(e),t=0;t<k.destroy.length;++t)k.destroy[t](e);if(Dt(t=e.children))for(n=0;n<e.children.length;++n)m(e.children[n])}function g(e,t,n,r){for(;n<=r;++n){var o=t[n];Dt(o)&&(Dt(o.tag)?(y(o),m(o)):i(o.elm))}}function y(e,t){if(Dt(t)||Dt(e.data)){var n=k.remove.length+1;for(Dt(t)?t.listeners+=n:t=r(e.elm,n),Dt(x=e.componentInstance)&&Dt(x=x._vnode)&&Dt(x.data)&&y(x,t),x=0;x<k.remove.length;++x)k.remove[x](e,t);Dt(x=e.data.hook)&&Dt(x=x.remove)?x(e,t):t()}else i(e.elm)}function _(e,t,n,r,i){for(var o,s,c,u,l=0,f=0,p=t.length-1,d=t[0],v=t[p],m=n.length-1,y=n[0],_=n[m],$=!i;l<=p&&f<=m;)Lt(d)?d=t[++l]:Lt(v)?v=t[--p]:Pt(d,y)?(b(d,y,r),d=t[++l],y=n[++f]):Pt(v,_)?(b(v,_,r),v=t[--p],_=n[--m]):Pt(d,_)?(b(d,_,r),$&&O.insertBefore(e,d.elm,O.nextSibling(v.elm)),d=t[++l],_=n[--m]):Pt(v,y)?(b(v,y,r),$&&O.insertBefore(e,v.elm,d.elm),v=t[--p],y=n[++f]):(Lt(o)&&(o=Ft(t,l,p)),s=Dt(y.key)?o[y.key]:null,Lt(s)?(a(y,r,e,d.elm),y=n[++f]):(c=t[s],Pt(c,y)?(b(c,y,r),t[s]=void 0,$&&O.insertBefore(e,y.elm,d.elm),y=n[++f]):(a(y,r,e,d.elm),y=n[++f])));l>p?(u=Lt(n[m+1])?null:n[m+1].elm,h(e,u,n,f,m,r)):f>m&&g(e,t,l,p)}function b(e,t,n,r){if(e!==t){if(Mt(t.isStatic)&&Mt(e.isStatic)&&t.key===e.key&&(Mt(t.isCloned)||Mt(t.isOnce)))return t.elm=e.elm,void(t.componentInstance=e.componentInstance);var i,o=t.data;Dt(o)&&Dt(i=o.hook)&&Dt(i=i.prepatch)&&i(e,t);var a=t.elm=e.elm,s=e.children,c=t.children;if(Dt(o)&&p(t)){for(i=0;i<k.update.length;++i)k.update[i](e,t);Dt(i=o.hook)&&Dt(i=i.update)&&i(e,t)}Lt(t.text)?Dt(s)&&Dt(c)?s!==c&&_(a,s,c,n,r):Dt(c)?(Dt(e.text)&&O.setTextContent(a,""),h(a,null,c,0,c.length-1,n)):Dt(s)?g(a,s,0,s.length-1):Dt(e.text)&&O.setTextContent(a,""):e.text!==t.text&&O.setTextContent(a,t.text),Dt(o)&&Dt(i=o.hook)&&Dt(i=i.postpatch)&&i(e,t)}}function $(e,t,n){if(Mt(n)&&Dt(e.parent))e.parent.data.pendingInsert=t;else for(var r=0;r<t.length;++r)t[r].data.hook.insert(t[r])}function w(e,t,n){t.elm=e;var r=t.tag,i=t.data,o=t.children;if(Dt(i)&&(Dt(x=i.hook)&&Dt(x=x.init)&&x(t,!0),Dt(x=t.componentInstance)))return c(t,n),!0;if(Dt(r)){if(Dt(o))if(e.hasChildNodes()){for(var a=!0,s=e.firstChild,u=0;u<o.length;u++){if(!s||!w(s,o[u],n)){a=!1;break}s=s.nextSibling}if(!a||s)return!1}else f(t,o,n);if(Dt(i))for(var l in i)if(!T(l)){d(t,n);break}}else e.data!==t.text&&(e.data=t.text);return!0}var x,C,k={},A=e.modules,O=e.nodeOps;for(x=0;x<Xo.length;++x)for(k[Xo[x]]=[],C=0;C<A.length;++C)Dt(A[C][Xo[x]])&&k[Xo[x]].push(A[C][Xo[x]]);var T=n("attrs,style,class,staticClass,staticStyle,key");return function(e,n,r,i,o,s){if(Lt(n))return void(Dt(e)&&m(e));var c=!1,u=[];if(Lt(e))c=!0,a(n,u,o,s);else{var l=Dt(e.nodeType);if(!l&&Pt(e,n))b(e,n,u,i);else{if(l){if(1===e.nodeType&&e.hasAttribute("server-rendered")&&(e.removeAttribute("server-rendered"),r=!0),Mt(r)&&w(e,n,u))return $(n,u,!0),e;e=t(e)}var f=e.elm,d=O.parentNode(f);if(a(n,u,f._leaveCb?null:d,O.nextSibling(f)),Dt(n.parent)){for(var v=n.parent;v;)v.elm=n.elm,v=v.parent;if(p(n))for(var h=0;h<k.create.length;++h)k.create[h](Qo,n.parent)}Dt(d)?g(d,[e],0,0):Dt(e.tag)&&m(e)}}return $(n,u,c),n.elm}}({nodeOps:Go,modules:Sa});Mi&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&Gn(e,"input")});var ja={inserted:function(e,t,n){if("select"===n.tag){var r=function(){Jn(e,t,n.context)};r(),(Di||Pi)&&setTimeout(r,0)}else"textarea"!==n.tag&&"text"!==e.type&&"password"!==e.type||(e._vModifiers=t.modifiers,t.modifiers.lazy||(Ri||(e.addEventListener("compositionstart",Wn),e.addEventListener("compositionend",Zn)),Mi&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Jn(e,t,n.context);(e.multiple?t.value.some(function(t){return Kn(t,e.options)}):t.value!==t.oldValue&&Kn(t.value,e.options))&&Gn(e,"change")}}},Na={bind:function(e,t,n){var r=t.value;n=Yn(n);var i=n.data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i&&!Mi?(n.data.show=!0,Hn(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;r!==t.oldValue&&(n=Yn(n),n.data&&n.data.transition&&!Mi?(n.data.show=!0,r?Hn(n,function(){e.style.display=e.__vOriginalDisplay}):Un(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}},Ia={model:ja,show:Na},La={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]},Da={name:"transition",props:La,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(function(e){return e.tag}),n.length)){var r=this.mode,i=n[0];if(tr(this.$vnode))return i;var a=Qn(i);if(!a)return i;if(this._leaving)return er(e,i);var s="__transition-"+this._uid+"-";a.key=null==a.key?s+a.tag:o(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=Xn(this),l=this._vnode,f=Qn(l);if(a.data.directives&&a.data.directives.some(function(e){return"show"===e.name})&&(a.data.show=!0),f&&f.data&&!nr(a,f)){var p=f&&(f.data.transition=u({},c));if("out-in"===r)return this._leaving=!0,q(p,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),er(e,i);if("in-out"===r){var d,v=function(){d()};q(c,"afterEnter",v),q(c,"enterCancelled",v),q(p,"delayLeave",function(e){d=e})}}return i}}},Ma=u({tag:String,moveClass:String},La);delete Ma.mode;var Pa={props:Ma,render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=Xn(this),s=0;s<i.length;s++){var c=i[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(o.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],l=[],f=0;f<r.length;f++){var p=r[f];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?u.push(p):l.push(p)}this.kept=e(t,null,u),this.removed=l}return e(t,null,o)},beforeUpdate:function(){this.__patch__(this._vnode,this.kept,!1,!0),this._vnode=this.kept},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";if(e.length&&this.hasMove(e[0].elm,t)){e.forEach(rr),e.forEach(ir),e.forEach(or);var n=document.body;n.offsetHeight;e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;Ln(n,t),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(wa,n._moveCb=function e(r){r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(wa,e),n._moveCb=null,Dn(n,t))})}})}},methods:{hasMove:function(e,t){if(!ya)return!1;if(null!=this._hasMove)return this._hasMove;var n=e.cloneNode();e._transitionClasses&&e._transitionClasses.forEach(function(e){jn(n,e)}),En(n,t),n.style.display="none",this.$el.appendChild(n);var r=Pn(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}},Ra={Transition:Da,TransitionGroup:Pa};nt.config.mustUseProp=Po,nt.config.isReservedTag=Wo,nt.config.getTagNamespace=yt,nt.config.isUnknownElement=_t,u(nt.options.directives,Ia),u(nt.options.components,Ra),nt.prototype.__patch__=Ii?Ea:d,nt.prototype.$mount=function(e,t){return e=e&&Ii?bt(e):void 0,ae(this,e,t)},setTimeout(function(){Si.devtools&&Bi&&Bi.emit("init",nt)},0);var Fa,Ha=!!Ii&&function(e,t){var n=document.createElement("div");return n.innerHTML='<div a="'+e+'">',n.innerHTML.indexOf(t)>0}("\n","&#10;"),Ua=n("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),Ba=n("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),Va=n("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),za=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^\s"'=<>`]+)/.source],Ja=new RegExp("^\\s*"+/([^\s"'<>\/=]+)/.source+"(?:\\s*("+/(?:=)/.source+")\\s*(?:"+za.join("|")+"))?"),Ka="[a-zA-Z_][\\w\\-\\.]*",qa=new RegExp("^<((?:"+Ka+"\\:)?"+Ka+")"),Wa=/^\s*(\/?)>/,Za=new RegExp("^<\\/((?:"+Ka+"\\:)?"+Ka+")[^>]*>"),Ga=/^<!DOCTYPE [^>]+>/i,Ya=/^<!--/,Qa=/^<!\[/,Xa=!1;"x".replace(/x(.)?/g,function(e,t){Xa=""===t});var es,ts,ns,rs,is,os,as,ss,cs,us,ls,fs,ps,ds,vs,hs,ms,gs,ys=n("script,style,textarea",!0),_s={},bs={"&lt;":"<","&gt;":">","&quot;":'"',"&amp;":"&","&#10;":"\n"},$s=/&(?:lt|gt|quot|amp);/g,ws=/&(?:lt|gt|quot|amp|#10);/g,xs=/\{\{((?:.|\n)+?)\}\}/g,Cs=a(function(e){var t=e[0].replace(/[-.*+?^${}()|[\]\/\\]/g,"\\$&"),n=e[1].replace(/[-.*+?^${}()|[\]\/\\]/g,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")}),ks=/^@|^v-on:/,As=/^v-|^@|^:/,Os=/(.*?)\s+(?:in|of)\s+(.*)/,Ts=/\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/,Ss=/:(.*)$/,Es=/^:|^v-bind:/,js=/\.[^.]+/g,Ns=a(ar),Is=/^xmlns:NS\d+/,Ls=/^NS\d+:/,Ds=a(Er),Ms=/^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/,Ps=/^\s*[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?']|\[".*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*\s*$/,Rs={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},Fs=function(e){return"if("+e+")return null;"},Hs={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Fs("$event.target !== $event.currentTarget"),ctrl:Fs("!$event.ctrlKey"),shift:Fs("!$event.shiftKey"),alt:Fs("!$event.altKey"),meta:Fs("!$event.metaKey"),left:Fs("'button' in $event && $event.button !== 0"),middle:Fs("'button' in $event && $event.button !== 1"),right:Fs("'button' in $event && $event.button !== 2")},Us={bind:Hr,cloak:d},Bs={staticKeys:["staticClass"],transformNode:fi,genData:pi},Vs={staticKeys:["staticStyle"],transformNode:di,genData:vi},zs=[Bs,Vs],Js={model:dn,text:hi,html:mi},Ks={expectHTML:!0,modules:zs,directives:Js,isPreTag:qo,isUnaryTag:Ua,mustUseProp:Po,canBeLeftOpenTag:Ba,isReservedTag:Wo,getTagNamespace:yt,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(zs)},qs=function(e){function t(t,n){var r=Object.create(e),i=[],o=[];if(r.warn=function(e,t){(t?o:i).push(e)},n){n.modules&&(r.modules=(e.modules||[]).concat(n.modules)),n.directives&&(r.directives=u(Object.create(e.directives),n.directives));for(var a in n)"modules"!==a&&"directives"!==a&&(r[a]=n[a])}var s=ui(t,r);return s.errors=i,s.tips=o,s}function n(e,n,i){n=n||{};var o=n.delimiters?String(n.delimiters)+e:e;if(r[o])return r[o];var a=t(e,n),s={},c=[];s.render=li(a.render,c);var u=a.staticRenderFns.length;s.staticRenderFns=new Array(u);for(var l=0;l<u;l++)s.staticRenderFns[l]=li(a.staticRenderFns[l],c);return r[o]=s}var r=Object.create(null);return{compile:t,compileToFunctions:n}}(Ks),Ws=qs.compileToFunctions,Zs=a(function(e){var t=bt(e);return t&&t.innerHTML}),Gs=nt.prototype.$mount;return nt.prototype.$mount=function(e,t){if((e=e&&bt(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=Zs(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=gi(e));if(r){var i=Ws(r,{shouldDecodeNewlines:Ha,delimiters:n.delimiters},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return Gs.call(this,e,t)},nt.compile=Ws,nt});
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=volkm
4
  Tags: post-thumbnails, images, media library
5
  Requires at least: 4.6
6
  Tested up to: 4.7
7
- Stable tag: 0.10.15
8
  License: GPL v3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -12,33 +12,30 @@ License URI: http://www.gnu.org/licenses/gpl-3.0.html
12
 
13
  == Description ==
14
 
15
- The plugin enhance functionality to crop your automatic cropped images individuell and simple. It add buttons to the edit-pages and media-dialog to access a crop-editor.
16
  In the crop-editor you can choose one or more (if they have the same ratio) imagesizes and cut-off the part of the image you want.
17
 
18
- = Further Features =
19
 
20
- * It is possible to filter the list of available image-sizes (in dependency to post-types) in the settings (Settings > Crop-Thumbnails).
21
- * You could provide your users a custom style for the Editor-Window (see F.A.Q.).
22
 
23
- == Installation ==
24
-
25
- You can use the built in installer and upgrader, or you can install the plugin manually.
26
-
27
- 1. You can either use the automatic plugin installer or your FTP program to upload it to your wp-content/plugins directory the top-level folder. Don't just upload all the php files and put them in /wp-content/plugins/.
28
- 2. Activate the plugin through the 'Plugins' menu in WordPress
29
- 3. Configure any settings from "Settings > Crop-Thumbnails".
30
- 4. Use it.
31
-
32
- == Frequently Asked Questions ==
33
-
34
- = How do i add custom image sizes? =
35
- The plugin do not add additional image sizes, it only make it possible to edit the crop area. You can add image sizes with normal wordpress functions (see: https://developer.wordpress.org/reference/functions/add_image_size/).
36
-
37
- Simply add the code to the functions.php of your theme, i.e.:
38
  `add_action( 'after_setup_theme', 'my_adjust_image_sizes' );
39
  function my_adjust_image_sizes() {
40
  //add an cropped image-size with 800 x 250 Pixels
41
  add_image_size( 'my-custom-image-size', 800, 250, true );
 
 
 
 
 
 
 
 
 
 
 
 
42
  }`
43
 
44
  After you add the image-size any futher image uploads will produce a cropped image "my-custom-image-size" which you can use in post-loop:
@@ -46,13 +43,27 @@ After you add the image-size any futher image uploads will produce a cropped ima
46
  the_post_thumbnail( 'my-custom-image-size' );
47
  }`
48
 
49
- = What internal rules use the plugin for cropping? =
 
 
 
 
 
 
 
 
 
 
 
50
  * The plugin will only crop image-sizes where crop is set to "true" (hard crop mode - see: http://codex.wordpress.org/Function_Reference/add_image_size).
51
- * If you had set one of image dimension in add_image_size to "0" or "9999" (an set crop to true) the plugin will crop it in the ratio of the original image.
 
52
  * You are able to crop all images with the same ratio at once (default) or and any imagesize (and ratio) seperate.
53
 
54
- = I have cropped the image but the old one is used on the page. =
55
- If you had viewed your image on the site before, your browser has cached the image. Go tell them to reload the fresh image from the server by hitting "F5".
 
 
56
 
57
  = Is it possible to crop an non-cropped image-size? =
58
  No. The purpose of this plugin is to provide control for the wordpress automatic crop. If you want to crop let's say the full-size image you should
@@ -60,16 +71,6 @@ No. The purpose of this plugin is to provide control for the wordpress automatic
60
  * a) upload it in a better format in the first place
61
  * OR b) use the Standard Wordpress-Image editor to crop the image.
62
 
63
- = Is it possible to adjust the css-style of the crop-thumbnail window? =
64
- Yes, for a simple test, copy the css/cpt-window.css file into your template_directory and make some change.
65
- Then add this code into the functions.php of your template.
66
-
67
- `add_filter('crop_post_thumbnail_window_css','myCustomStyle');
68
- function myCustomStyle($content) {
69
- $content = get_bloginfo('template_directory').'/cpt-window.css';
70
- return $content;
71
- }`
72
-
73
  = I have two image-sizes that have nearly the same ratio. I want to make use of the feature "Crop all images with same ratio at once", but cause the ratios are slightly different they wont be selected together. =
74
  You can add the following filter in the functions.php of your theme to adjust the ratio of one or more specified image-sizes.
75
  CAUTION: use only when the ratios are really close.
@@ -81,17 +82,7 @@ function my_crop_thumbnails_editor_printratio( $printRatio, $imageSizeName) {
81
  return $printRatio;
82
  }`
83
 
84
- = Can i make the modal-dialog fullscreen? =
85
- Yes, i added a filter with some settings for the modal-dialog, so you can adjust the size:
86
- `add_filter('crop_thumbnails_modal_window_settings','crop_thumbnails_modal_window_settings_override');
87
- function crop_thumbnails_modal_window_settings_override($param) {
88
- $param['limitToWidth'] = false; //You may set a number, then thats the maximum width the modal can be. On small screens it will be smaller (see offsets). Set to FALSE if you want no limit.
89
- $param['maxWidthOffset'] = 0; //window-width minus "width_offset" equals modal-width
90
- $param['maxHeightOffset'] = 0; //window-width minus "height_offset" equals modal-height
91
- return $param;
92
- }`
93
-
94
- = I have show the cropped image in the backend in an custom meta-box. It does not update after the modal-dialog closed. Is there a way to fix this =
95
  Yeah, there is a way. After the crop-thumbnails-modal closed it triggeres a javascript event on the body element. You could use jQuery to cache-break your cropped thumbnail (in backend-view).
96
  The event called "cropThumbnailModalClosed". The plugin also provides a global function that could be called (only in post-edit-view and mediathek) to do the cache-break.
97
  Example-Code:
@@ -120,27 +111,42 @@ If you fork and planning to publish the forked plugin, please contact me.
120
  5. Choose what image-sizes should be hidden (for what post-types), for better usability.
121
  6. Quicktest on settings-page, to check if your system is correct setup.
122
 
123
- == Changelog ==
124
- = 0.10.15 =
125
- * bugfix: use wordpress-function to determine mime-type, as some servers do not define "mime_content_type" (Thank you Eskil Keskikangas for the submission)
126
-
127
- = 0.10.14 =
128
- * bugfix: add mime-type to image-metadata (the mime-type was deleted by crop-thumbnails before unintentional)
129
-
130
- = 0.10.13 =
131
- * bugfix: filter-settings will work again in media-dialog
132
-
133
- = 0.10.12 =
134
- * add italian translation (thanks to akteon18)
135
-
136
- = 0.10.11 =
137
- * bugfix: hide disabled image-sizes in the crop-editor again
138
-
139
- = 0.10.10 =
140
- * bugfix: Checks if the current page have a featured image box in the first place
141
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  = 0.10.9 =
143
- * bugfix: click on the button in the featured image box (WP 4.6 and above)
144
  * button in featured image box is no longer visible if no image is choosed
145
  * minor style improvements
146
 
@@ -207,7 +213,6 @@ If you fork and planning to publish the forked plugin, please contact me.
207
  * fix warning: when settings are saved
208
 
209
  = 0.8.0 =
210
- * change Constant from CPT_LANG to CROP_THUMBS_LANG
211
  * change Constant from CPT_VERSION to CROP_THUMBS_VERSION
212
  * bug fix: wrong calculated scale in the cpt-crop.js (selection will again always fill the maximum space)
213
  * change behavior: on landscape-ratio-images the selection will be initial in the middle of the image (portrait-ratio-images stay the same - i asume that portrait-ratio images are mostly portraits)
4
  Tags: post-thumbnails, images, media library
5
  Requires at least: 4.6
6
  Tested up to: 4.7
7
+ Stable tag: 1.0.0
8
  License: GPL v3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
12
 
13
  == Description ==
14
 
15
+ The plugin provides the functionality to adjust the crop region of cropped images. It add buttons to the edit-pages and media-dialog to access a crop-editor.
16
  In the crop-editor you can choose one or more (if they have the same ratio) imagesizes and cut-off the part of the image you want.
17
 
18
+ = How to define cropped image sizes?
19
 
20
+ The plugin do not add additional image sizes, it only provides functionality to edit the crop area.
 
21
 
22
+ You can use "add_image_size" inside your functions.php to add additional cropped image sizes (see: https://developer.wordpress.org/reference/functions/add_image_size/).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  `add_action( 'after_setup_theme', 'my_adjust_image_sizes' );
24
  function my_adjust_image_sizes() {
25
  //add an cropped image-size with 800 x 250 Pixels
26
  add_image_size( 'my-custom-image-size', 800, 250, true );
27
+
28
+
29
+ /**
30
+ * The following image sizes use a dynamic value.
31
+ * USE WITH CARE
32
+ * Also the plugin supports these image-sizes, i do not recommend them!
33
+ **/
34
+ //a dynamic cropped image size with 500 pixel height and the width of the original image
35
+ add_image_size( 'my-dynamic-width-1', 9999, 500, true );
36
+
37
+ //a dynamic cropped image with the same ratio as the original image and 500 pixel width
38
+ add_image_size( 'my-dynamic-zero-height-1', 500, 0, true );
39
  }`
40
 
41
  After you add the image-size any futher image uploads will produce a cropped image "my-custom-image-size" which you can use in post-loop:
43
  the_post_thumbnail( 'my-custom-image-size' );
44
  }`
45
 
46
+ == Installation ==
47
+
48
+ You can use the built in installer and upgrader, or you can install the plugin manually.
49
+
50
+ 1. You can either use the automatic plugin installer or your FTP program to upload it to your wp-content/plugins directory the top-level folder. Don't just upload all the php files and put them in /wp-content/plugins/.
51
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
52
+ 3. Configure any settings from "Settings > Crop-Thumbnails".
53
+ 4. Use it.
54
+
55
+ == Frequently Asked Questions ==
56
+
57
+ = What internal rules the plugin use for cropping? =
58
  * The plugin will only crop image-sizes where crop is set to "true" (hard crop mode - see: http://codex.wordpress.org/Function_Reference/add_image_size).
59
+ * If you had set one image dimension in add_image_size() to "0", the plugin will crop it in the ratio of the original image.
60
+ * If you had set one image dimension in add_image_size() to "9999", the plugin will change the 9999 to the actual size of the current original image.
61
  * You are able to crop all images with the same ratio at once (default) or and any imagesize (and ratio) seperate.
62
 
63
+ = I've cropped the image, but the new version do not appear in the frontend. =
64
+ If you had viewed your image on the site before, your browser has cached the image. You can hard refresh the page by hitting:
65
+ * "CTRL + F5" (on Windows)
66
+ * "Apple + R" or "command + R" (on Mac/Apple)
67
 
68
  = Is it possible to crop an non-cropped image-size? =
69
  No. The purpose of this plugin is to provide control for the wordpress automatic crop. If you want to crop let's say the full-size image you should
71
  * a) upload it in a better format in the first place
72
  * OR b) use the Standard Wordpress-Image editor to crop the image.
73
 
 
 
 
 
 
 
 
 
 
 
74
  = I have two image-sizes that have nearly the same ratio. I want to make use of the feature "Crop all images with same ratio at once", but cause the ratios are slightly different they wont be selected together. =
75
  You can add the following filter in the functions.php of your theme to adjust the ratio of one or more specified image-sizes.
76
  CAUTION: use only when the ratios are really close.
82
  return $printRatio;
83
  }`
84
 
85
+ = I display the cropped image in the backend in an custom meta-box. It does not update after the modal-dialog closed. Is there a way to fix this =
 
 
 
 
 
 
 
 
 
 
86
  Yeah, there is a way. After the crop-thumbnails-modal closed it triggeres a javascript event on the body element. You could use jQuery to cache-break your cropped thumbnail (in backend-view).
87
  The event called "cropThumbnailModalClosed". The plugin also provides a global function that could be called (only in post-edit-view and mediathek) to do the cache-break.
88
  Example-Code:
111
  5. Choose what image-sizes should be hidden (for what post-types), for better usability.
112
  6. Quicktest on settings-page, to check if your system is correct setup.
113
 
114
+ == Changelog ==
115
+
116
+ = 1.0.0 =
117
+ * modal dialog rewritten
118
+ * crop functionality refactored
119
+ * changed the crop-library for improved touch support
120
+ * the action "crop_thumbnails_modal_window_settings" is gone, you can adjust style by override admin-css
121
+ * the filter "crop_post_thumbnail_window_css" is gone, you can adjust style by override admin-css
122
+ * adjusting dialog style - make it more responsive
123
+ * reviewed dynamic sizes: sizes with 9999 will no longer have ratio of the original image
124
+ * reviewed dynamic sizes: filenames will no longer be changed
125
+ * fix image-metadata polution
126
+ * refactoring and cleanup a lot of the code
127
+ * change from a language constant to 'cpt_lang' (as recommended by developer guide)
128
+ * secure translations
129
+
130
+ = 0.10.15 =
131
+ * bugfix: use wordpress-function to determine mime-type, as some servers do not define "mime_content_type" (Thank you Eskil Keskikangas for the submission)
132
+
133
+ = 0.10.14 =
134
+ * bugfix: add mime-type to image-metadata (the mime-type was deleted by crop-thumbnails before unintentional)
135
+
136
+ = 0.10.13 =
137
+ * bugfix: filter-settings will work again in media-dialog
138
+
139
+ = 0.10.12 =
140
+ * add italian translation (thanks to akteon18)
141
+
142
+ = 0.10.11 =
143
+ * bugfix: hide disabled image-sizes in the crop-editor again
144
+
145
+ = 0.10.10 =
146
+ * bugfix: Checks if the current page have a featured image box in the first place
147
+
148
  = 0.10.9 =
149
+ * bugfix: click on the button in the featured image box (WP 4.6 and above)
150
  * button in featured image box is no longer visible if no image is choosed
151
  * minor style improvements
152
 
213
  * fix warning: when settings are saved
214
 
215
  = 0.8.0 =
 
216
  * change Constant from CPT_VERSION to CROP_THUMBS_VERSION
217
  * bug fix: wrong calculated scale in the cpt-crop.js (selection will again always fill the maximum space)
218
  * change behavior: on landscape-ratio-images the selection will be initial in the middle of the image (portrait-ratio-images stay the same - i asume that portrait-ratio images are mostly portraits)