Robin image optimizer — save money on image compression - Version 1.4.6

Version Description

  • Added: Lazy Load option for images
Download this release

Release Info

Developer alexkovalevv
Plugin Icon 128x128 Robin image optimizer — save money on image compression
Version 1.4.6
Comparing to
See all releases

Code changes from version 1.4.2 to 1.4.6

Files changed (77) hide show
  1. admin/activation.php +3 -3
  2. admin/ajax/bulk-optimization.php +98 -88
  3. admin/assets/css/base-statistic.css +675 -676
  4. admin/assets/css/base-statistic.less +1 -1
  5. admin/assets/css/settings-premium.css +17 -0
  6. admin/assets/css/sweetalert-custom.css +155 -156
  7. admin/assets/js/Chart.min.js +3 -3
  8. admin/assets/js/bulk-optimization.js +566 -553
  9. admin/assets/js/settings-premium.js +1 -0
  10. admin/assets/js/statistic.js +23 -21
  11. admin/boot.php +9 -9
  12. admin/includes/classes/class-rio-optimize-template.php +18 -18
  13. admin/pages/class-rio-license.php +3 -3
  14. admin/pages/class-rio-log.php +2 -2
  15. admin/pages/class-rio-page.php +1 -1
  16. admin/pages/class-rio-settings.php +113 -60
  17. admin/pages/class-rio-statistic.php +261 -241
  18. assets/js/jquery.lazy.js +872 -0
  19. assets/js/jquery.lazy.min.js +2 -0
  20. assets/js/lazy-load.js +8 -0
  21. includes/class-rio-plugin.php +177 -170
  22. includes/classes/class-rio-attachment.php +16 -14
  23. includes/classes/class-rio-backup.php +1 -3
  24. includes/classes/class-rio-image-statistic.php +33 -24
  25. includes/classes/class-rio-lazy-load.php +76 -0
  26. includes/classes/class-rio-media-library.php +34 -23
  27. includes/classes/class-rio-optimization-tools.php +2 -10
  28. includes/classes/class-rio-views.php +4 -4
  29. includes/classes/processors/class-rio-server-abstract.php +81 -20
  30. includes/classes/processors/class-rio-server-premium.php +26 -11
  31. includes/classes/processors/class-rio-server-resmush.php +37 -31
  32. includes/classes/processors/class-rio-server-robin.php +184 -0
  33. includes/functions.php +17 -4
  34. languages/robin-image-optimizer-ru_RU.mo +0 -0
  35. languages/robin-image-optimizer-ru_RU.po +1234 -800
  36. libs/addons/admin/assets/js/custom-folders.js +4 -4
  37. libs/addons/admin/boot.php +1 -1
  38. libs/addons/admin/filters/settings-page.php +4 -2
  39. libs/addons/includes/classes/class.folder.php +11 -1
  40. libs/addons/includes/classes/webp/class-webp-api.php +85 -80
  41. libs/addons/includes/classes/webp/vendor/autoload.php +7 -7
  42. libs/addons/includes/classes/webp/vendor/composer/ClassLoader.php +445 -445
  43. libs/addons/includes/classes/webp/vendor/composer/InstalledVersions.php +220 -0
  44. libs/addons/includes/classes/webp/vendor/composer/LICENSE +21 -21
  45. libs/addons/includes/classes/webp/vendor/composer/autoload_classmap.php +10 -9
  46. libs/addons/includes/classes/webp/vendor/composer/autoload_namespaces.php +9 -9
  47. libs/addons/includes/classes/webp/vendor/composer/autoload_psr4.php +10 -10
  48. libs/addons/includes/classes/webp/vendor/composer/autoload_real.php +55 -52
  49. libs/addons/includes/classes/webp/vendor/composer/autoload_static.php +36 -31
  50. libs/addons/includes/classes/webp/vendor/composer/installed.json +63 -59
  51. libs/addons/includes/classes/webp/vendor/composer/installed.php +35 -0
  52. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/.php_cs.dist +19 -19
  53. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/README.md +161 -161
  54. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/composer.json +60 -60
  55. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpstan.neon +3 -3
  56. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src-vendor/simple_html_dom/simple_html_dom.inc +2930 -2930
  57. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php +230 -230
  58. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php +202 -202
  59. libs/addons/readme.txt +2 -3
  60. libs/addons/robin-image-optimizer-premium.php +1 -1
  61. libs/addons/views/modal-select-custom-folders.php +1 -1
  62. libs/addons/views/part-bulk-optimization-table-folders.php +1 -1
  63. libs/addons/views/part-settings-page-webp-options.php +15 -1
  64. libs/factory/adverts/boot.php +14 -14
  65. libs/factory/adverts/includes/class-base.php +6 -6
  66. libs/factory/adverts/includes/class-dashboard-widget.php +4 -4
  67. libs/factory/adverts/includes/class-rest-request.php +67 -47
  68. libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.mo +0 -0
  69. libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.po +83 -0
  70. libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.mo +0 -0
  71. libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.po +83 -0
  72. libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.mo +0 -0
  73. libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.po +83 -0
  74. libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css +1 -1
  75. libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css +1 -1
  76. libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css +1 -1
  77. libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css +0 -1
admin/activation.php CHANGED
@@ -5,7 +5,7 @@
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
- * @see Factory425_Activator
9
  * @version 1.0
10
  */
11
 
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- class WIO_Activation extends Wbcr_Factory425_Activator {
18
 
19
  /**
20
  * Runs activation actions.
@@ -49,7 +49,7 @@ class WIO_Activation extends Wbcr_Factory425_Activator {
49
 
50
  RIO_Process_Queue::try_create_plugin_tables();
51
 
52
- WbcrFactoryClearfy217_Helpers::flushPageCache();
53
 
54
  WRIO_Logger::info( 'Parent plugin installation complete!' );
55
  }
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
+ * @see Factory436_Activator
9
  * @version 1.0
10
  */
11
 
14
  exit;
15
  }
16
 
17
+ class WIO_Activation extends Wbcr_Factory436_Activator {
18
 
19
  /**
20
  * Runs activation actions.
49
 
50
  RIO_Process_Queue::try_create_plugin_tables();
51
 
52
+ WbcrFactoryClearfy227_Helpers::flushPageCache();
53
 
54
  WRIO_Logger::info( 'Parent plugin installation complete!' );
55
  }
admin/ajax/bulk-optimization.php CHANGED
@@ -19,23 +19,23 @@ add_action( 'wp_ajax_wrio-cron-start', function () {
19
  if ( ! current_user_can( 'manage_options' ) ) {
20
  wp_die( - 1 );
21
  }
22
-
23
  $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
24
-
25
  if ( empty( $scope ) ) {
26
  wp_die( - 1 );
27
  }
28
-
29
  // where was runned cron
30
  $cron_running_place = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
31
-
32
  if ( $scope == $cron_running_place ) {
33
  wp_send_json_success();
34
  }
35
-
36
  WRIO_Plugin::app()->updatePopulateOption( 'cron_running', $scope );
37
  WRIO_Cron::start();
38
-
39
  wp_send_json_success();
40
  } );
41
 
@@ -44,14 +44,14 @@ add_action( 'wp_ajax_wrio-cron-start', function () {
44
  */
45
  add_action( 'wp_ajax_wrio-cron-stop', function () {
46
  check_ajax_referer( 'bulk_optimization' );
47
-
48
  if ( ! current_user_can( 'manage_options' ) ) {
49
  wp_die( - 1 );
50
  }
51
-
52
  WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false );
53
  WRIO_Cron::stop();
54
-
55
  wp_send_json_success();
56
  } );
57
 
@@ -60,26 +60,26 @@ add_action( 'wp_ajax_wrio-cron-stop', function () {
60
  */
61
  add_action( 'wp_ajax_wrio-bulk-optimization-process', function () {
62
  check_admin_referer( 'bulk_optimization' );
63
-
64
  if ( ! current_user_can( 'manage_options' ) ) {
65
  wp_die( - 1 );
66
  }
67
-
68
  $reset_current_error = (bool) WRIO_Plugin::app()->request->request( 'reset_current_errors' );
69
  $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
70
-
71
  WRIO_Logger::info( sprintf( 'Start bulk optimization process! Scope: %s', $scope ) );
72
-
73
  if ( empty( $scope ) ) {
74
  wp_die( - 1 );
75
  }
76
-
77
  // Context class name. If plugin expands with add-ons
78
  $class_name = 'WRIO_' . wrio_dashes_to_camel_case( $scope, true );
79
-
80
  if ( ! class_exists( $class_name ) ) {
81
  WRIO_Logger::error( sprintf( 'Bulk optimization error: Context class (%s) not found.', $class_name ) );
82
-
83
  //todo: Temporary bug fix.
84
  if ( 'media-library' === $scope ) {
85
  $class_name = 'WRIO_Media_Library';
@@ -88,12 +88,12 @@ add_action( 'wp_ajax_wrio-bulk-optimization-process', function () {
88
  } else if ( 'nextgen-gallery' == $scope ) {
89
  $class_name = 'WRIO_Nextgen_Gallery';
90
  }
91
-
92
  if ( ! class_exists( $class_name ) ) {
93
  wp_send_json_error( [ 'error_message' => 'Context class not found.' ] );
94
  }
95
  }
96
-
97
  /**
98
  * Create an instance of the class depending on the context in which scope user
99
  * has runned optimization.
@@ -103,38 +103,38 @@ add_action( 'wp_ajax_wrio-bulk-optimization-process', function () {
103
  * @see WRIO_Nextgen_Gallery
104
  */
105
  $optimizer = new $class_name();
106
-
107
  // в ajax запросе мы не знаем, получен ли он из мультиадминки или из обычной. Поэтому проверяем параметр, полученный из frontend
108
  /*if ( isset( $_POST['multisite'] ) && (bool) $_POST['multisite'] ) {
109
  $multisite = new WIO_Multisite;
110
  $multisite->initHooks();
111
  }*/
112
-
113
  if ( $reset_current_error ) {
114
  $optimizer->resetCurrentErrors(); // сбрасываем текущие ошибки оптимизации
115
  }
116
-
117
  $result = $optimizer->processUnoptimizedImages( 1 );
118
-
119
  if ( is_wp_error( $result ) ) {
120
  $error_massage = $result->get_error_message();
121
-
122
  if ( empty( $error ) ) {
123
  $error_massage = __( "Unknown error. Enable error log on the plugin's settings page, then check the error report on the Error Log page. You can export the error report and send it to the support service of the plugin.", "robin-image-optimizer" );
124
  }
125
-
126
  WRIO_Logger::error( sprintf( 'Bulk optimization error: %s.', $result->get_error_message() ) );
127
-
128
  wp_send_json_error( [ 'error_message' => $error_massage ] );
129
  }
130
-
131
  // если изображения закончились - посылаем команду завершения
132
  if ( $result['remain'] <= 0 ) {
133
  $result['end'] = true;
134
  }
135
-
136
  WRIO_Logger::info( sprintf( 'End bulk optimization process! Scope: %s. Remain: %d', $scope, $result['remain'] ) );
137
-
138
  wp_send_json_success( $result );
139
  } );
140
 
@@ -142,32 +142,32 @@ add_action( 'wp_ajax_wrio-bulk-optimization-process', function () {
142
  * Переоптимизация аттачмента
143
  */
144
  add_action( 'wp_ajax_wio_reoptimize_image', function () {
145
-
146
  if ( ! current_user_can( 'manage_options' ) ) {
147
  wp_die( - 1 );
148
  }
149
-
150
  $default_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
151
-
152
  $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
153
  $level = WRIO_Plugin::app()->request->post( 'level', $default_level, true );
154
-
155
  $backup = WIO_Backup::get_instance();
156
  $media_library = WRIO_Media_Library::get_instance();
157
  $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
158
-
159
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
160
  echo $media_library->getMediaColumnContent( $attachment_id );
161
  die();
162
  }
163
-
164
  $optimized_data = $media_library->optimizeAttachment( $attachment_id, $level );
165
-
166
  if ( $optimized_data && isset( $optimized_data['processing'] ) ) {
167
  echo 'processing';
168
  die();
169
  }
170
-
171
  echo $media_library->getMediaColumnContent( $attachment_id );
172
  die();
173
  } );
@@ -176,20 +176,20 @@ add_action( 'wp_ajax_wio_reoptimize_image', function () {
176
  * Восстановление аттачмента из резервной копии
177
  */
178
  add_action( 'wp_ajax_wio_restore_image', function () {
179
-
180
  if ( ! current_user_can( 'manage_options' ) ) {
181
  wp_die( - 1 );
182
  }
183
-
184
  $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
185
-
186
  $media_library = WRIO_Media_Library::get_instance();
187
  $wio_attachment = $media_library->getAttachment( $attachment_id );
188
-
189
  if ( $wio_attachment->isOptimized() ) {
190
  $media_library->restoreAttachment( $attachment_id );
191
  }
192
-
193
  echo $media_library->getMediaColumnContent( $attachment_id );
194
  die();
195
  } );
@@ -201,43 +201,40 @@ add_action( 'wp_ajax_wio_restore_image', function () {
201
  * статус выбранный).
202
  */
203
  add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
204
-
205
  check_ajax_referer( 'bulk_optimization' );
206
-
207
  if ( ! current_user_can( 'manage_options' ) ) {
208
  wp_die( - 1 );
209
  }
210
-
211
  $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
212
-
213
  if ( empty( $server_name ) || ! in_array( $server_name, [
214
  'server_1',
215
  'server_2',
216
- 'server_3',
217
- 'server_4',
218
  'server_5'
219
  ] ) ) {
220
  wp_send_json_error( [ 'error' => __( 'Server name is empty!', 'robin-image-optimizer' ) ] );
221
  }
222
-
223
  // Позволяем выбрать сервер, даже если он недоступен.
224
  WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', $server_name );
225
-
226
  // Проверяем доступность сервер
227
  // --------------------------------------------------------------------
228
  $return_data = [ 'server_name' => $server_name ];
229
-
230
  $server_url = wrio_get_server_url( $server_name );
231
  $headers = [];
232
-
233
  $method = 'POST';
234
- /*if ( $server_name == 'server_4' ) {
235
- $api_url = $server_url . '/upload/' . wrio_generate_random_string( 16 ) . '/';
236
- } */
237
-
238
- if ( $server_name == 'server_3' ) {
239
- $api_url = $server_url . '/s.w.org/images/home/screen-themes.png';
240
- $method = 'GET';
241
  } else if ( $server_name == 'server_5' ) {
242
  $api_url = "https://dashboard.robinoptimizer.com/v1/license/check";
243
  $method = 'GET';
@@ -246,34 +243,26 @@ add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
246
  } else {
247
  $api_url = $server_url;
248
  }
249
-
250
  $request = wp_remote_request( $api_url, [
251
  'method' => $method,
252
  'headers' => $headers
253
  ] );
254
-
255
  if ( is_wp_error( $request ) ) {
256
  $er_msg = $request->get_error_message();
257
-
258
- if ( "server_2" == $server_name ) {
259
- // Hostgator Issue.
260
- if ( ! empty( $er_msg ) && strpos( $er_msg, 'SSL CA cert' ) !== false ) {
261
- // Update DB for using http protocol.
262
- WRIO_Plugin::app()->updatePopulateOption( 'use_http', 1 );
263
- }
264
- }
265
-
266
  $return_data['error'] = $er_msg;
267
  wp_send_json_error( $return_data );
268
  }
269
-
270
  $response_code = wp_remote_retrieve_response_code( $request );
271
-
272
  if ( $response_code != 200 ) {
273
  $return_data['error'] = 'Server response ' . $response_code;
274
  wp_send_json_error( $return_data );
275
  }
276
-
277
  wp_send_json_success( $return_data );
278
  } );
279
 
@@ -284,32 +273,53 @@ add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
284
  * статус выбранный).
285
  */
286
  add_action( 'wp_ajax_wbcr-rio-check-user-balance', function () {
287
-
288
  check_ajax_referer( 'bulk_optimization' );
289
-
290
  if ( ! current_user_can( 'manage_options' ) ) {
291
  wp_die( - 1 );
292
  }
293
-
294
- $api_url = 'https://dashboard.robinoptimizer.com/v1/license/remaining';
295
- $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
296
- $headers['PluginId'] = wrio_get_freemius_plugin_id();
297
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  $request = wp_remote_request( $api_url, [
299
  'method' => 'GET',
300
  'headers' => $headers
301
  ] );
302
-
303
  if ( is_wp_error( $request ) ) {
304
  $error_msg = $request->get_error_message();
305
-
306
  $return_data['error'] = $error_msg;
307
  wp_send_json_error( $return_data );
308
  }
309
-
310
  $response_code = wp_remote_retrieve_response_code( $request );
311
  $response_body = wp_remote_retrieve_body( $request );
312
-
313
  if ( $response_code != 200 ) {
314
  $return_data['error'] = 'Server response ' . $response_code;
315
  if ( $response_code === 401 ) {
@@ -318,22 +328,22 @@ add_action( 'wp_ajax_wbcr-rio-check-user-balance', function () {
318
  }
319
  wp_send_json_error( $return_data );
320
  }
321
-
322
  if ( empty( $response_body ) ) {
323
  $return_data['error'] = "Server responded an empty request body!";
324
  wp_send_json_error( $return_data );
325
  }
326
-
327
  $data = @json_decode( $response_body );
328
-
329
  if ( ! isset( $data->status ) || $data->status != 'ok' ) {
330
  $return_data['error'] = "Server responded an fail status";
331
  wp_send_json_error( $return_data );
332
  }
333
-
334
  $current_quota = (int) $data->response->quota;
335
  WRIO_Plugin::app()->app()->updateOption( 'current_quota', $current_quota );
336
-
337
  wp_send_json_success( [
338
  'balance' => $current_quota,
339
  ] );
19
  if ( ! current_user_can( 'manage_options' ) ) {
20
  wp_die( - 1 );
21
  }
22
+
23
  $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
24
+
25
  if ( empty( $scope ) ) {
26
  wp_die( - 1 );
27
  }
28
+
29
  // where was runned cron
30
  $cron_running_place = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
31
+
32
  if ( $scope == $cron_running_place ) {
33
  wp_send_json_success();
34
  }
35
+
36
  WRIO_Plugin::app()->updatePopulateOption( 'cron_running', $scope );
37
  WRIO_Cron::start();
38
+
39
  wp_send_json_success();
40
  } );
41
 
44
  */
45
  add_action( 'wp_ajax_wrio-cron-stop', function () {
46
  check_ajax_referer( 'bulk_optimization' );
47
+
48
  if ( ! current_user_can( 'manage_options' ) ) {
49
  wp_die( - 1 );
50
  }
51
+
52
  WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false );
53
  WRIO_Cron::stop();
54
+
55
  wp_send_json_success();
56
  } );
57
 
60
  */
61
  add_action( 'wp_ajax_wrio-bulk-optimization-process', function () {
62
  check_admin_referer( 'bulk_optimization' );
63
+
64
  if ( ! current_user_can( 'manage_options' ) ) {
65
  wp_die( - 1 );
66
  }
67
+
68
  $reset_current_error = (bool) WRIO_Plugin::app()->request->request( 'reset_current_errors' );
69
  $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
70
+
71
  WRIO_Logger::info( sprintf( 'Start bulk optimization process! Scope: %s', $scope ) );
72
+
73
  if ( empty( $scope ) ) {
74
  wp_die( - 1 );
75
  }
76
+
77
  // Context class name. If plugin expands with add-ons
78
  $class_name = 'WRIO_' . wrio_dashes_to_camel_case( $scope, true );
79
+
80
  if ( ! class_exists( $class_name ) ) {
81
  WRIO_Logger::error( sprintf( 'Bulk optimization error: Context class (%s) not found.', $class_name ) );
82
+
83
  //todo: Temporary bug fix.
84
  if ( 'media-library' === $scope ) {
85
  $class_name = 'WRIO_Media_Library';
88
  } else if ( 'nextgen-gallery' == $scope ) {
89
  $class_name = 'WRIO_Nextgen_Gallery';
90
  }
91
+
92
  if ( ! class_exists( $class_name ) ) {
93
  wp_send_json_error( [ 'error_message' => 'Context class not found.' ] );
94
  }
95
  }
96
+
97
  /**
98
  * Create an instance of the class depending on the context in which scope user
99
  * has runned optimization.
103
  * @see WRIO_Nextgen_Gallery
104
  */
105
  $optimizer = new $class_name();
106
+
107
  // в ajax запросе мы не знаем, получен ли он из мультиадминки или из обычной. Поэтому проверяем параметр, полученный из frontend
108
  /*if ( isset( $_POST['multisite'] ) && (bool) $_POST['multisite'] ) {
109
  $multisite = new WIO_Multisite;
110
  $multisite->initHooks();
111
  }*/
112
+
113
  if ( $reset_current_error ) {
114
  $optimizer->resetCurrentErrors(); // сбрасываем текущие ошибки оптимизации
115
  }
116
+
117
  $result = $optimizer->processUnoptimizedImages( 1 );
118
+
119
  if ( is_wp_error( $result ) ) {
120
  $error_massage = $result->get_error_message();
121
+
122
  if ( empty( $error ) ) {
123
  $error_massage = __( "Unknown error. Enable error log on the plugin's settings page, then check the error report on the Error Log page. You can export the error report and send it to the support service of the plugin.", "robin-image-optimizer" );
124
  }
125
+
126
  WRIO_Logger::error( sprintf( 'Bulk optimization error: %s.', $result->get_error_message() ) );
127
+
128
  wp_send_json_error( [ 'error_message' => $error_massage ] );
129
  }
130
+
131
  // если изображения закончились - посылаем команду завершения
132
  if ( $result['remain'] <= 0 ) {
133
  $result['end'] = true;
134
  }
135
+
136
  WRIO_Logger::info( sprintf( 'End bulk optimization process! Scope: %s. Remain: %d', $scope, $result['remain'] ) );
137
+
138
  wp_send_json_success( $result );
139
  } );
140
 
142
  * Переоптимизация аттачмента
143
  */
144
  add_action( 'wp_ajax_wio_reoptimize_image', function () {
145
+
146
  if ( ! current_user_can( 'manage_options' ) ) {
147
  wp_die( - 1 );
148
  }
149
+
150
  $default_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
151
+
152
  $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
153
  $level = WRIO_Plugin::app()->request->post( 'level', $default_level, true );
154
+
155
  $backup = WIO_Backup::get_instance();
156
  $media_library = WRIO_Media_Library::get_instance();
157
  $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
158
+
159
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
160
  echo $media_library->getMediaColumnContent( $attachment_id );
161
  die();
162
  }
163
+
164
  $optimized_data = $media_library->optimizeAttachment( $attachment_id, $level );
165
+
166
  if ( $optimized_data && isset( $optimized_data['processing'] ) ) {
167
  echo 'processing';
168
  die();
169
  }
170
+
171
  echo $media_library->getMediaColumnContent( $attachment_id );
172
  die();
173
  } );
176
  * Восстановление аттачмента из резервной копии
177
  */
178
  add_action( 'wp_ajax_wio_restore_image', function () {
179
+
180
  if ( ! current_user_can( 'manage_options' ) ) {
181
  wp_die( - 1 );
182
  }
183
+
184
  $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
185
+
186
  $media_library = WRIO_Media_Library::get_instance();
187
  $wio_attachment = $media_library->getAttachment( $attachment_id );
188
+
189
  if ( $wio_attachment->isOptimized() ) {
190
  $media_library->restoreAttachment( $attachment_id );
191
  }
192
+
193
  echo $media_library->getMediaColumnContent( $attachment_id );
194
  die();
195
  } );
201
  * статус выбранный).
202
  */
203
  add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
204
+
205
  check_ajax_referer( 'bulk_optimization' );
206
+
207
  if ( ! current_user_can( 'manage_options' ) ) {
208
  wp_die( - 1 );
209
  }
210
+
211
  $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
212
+
213
  if ( empty( $server_name ) || ! in_array( $server_name, [
214
  'server_1',
215
  'server_2',
 
 
216
  'server_5'
217
  ] ) ) {
218
  wp_send_json_error( [ 'error' => __( 'Server name is empty!', 'robin-image-optimizer' ) ] );
219
  }
220
+
221
  // Позволяем выбрать сервер, даже если он недоступен.
222
  WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', $server_name );
223
+
224
  // Проверяем доступность сервер
225
  // --------------------------------------------------------------------
226
  $return_data = [ 'server_name' => $server_name ];
227
+
228
  $server_url = wrio_get_server_url( $server_name );
229
  $headers = [];
230
+
231
  $method = 'POST';
232
+
233
+ if ( $server_name == 'server_2' ) {
234
+ $api_url = "https://dev.robinoptimizer.com/v1/free/license/check";
235
+ $method = 'GET';
236
+ $host = get_option( 'siteurl' );
237
+ $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
 
238
  } else if ( $server_name == 'server_5' ) {
239
  $api_url = "https://dashboard.robinoptimizer.com/v1/license/check";
240
  $method = 'GET';
243
  } else {
244
  $api_url = $server_url;
245
  }
246
+
247
  $request = wp_remote_request( $api_url, [
248
  'method' => $method,
249
  'headers' => $headers
250
  ] );
251
+
252
  if ( is_wp_error( $request ) ) {
253
  $er_msg = $request->get_error_message();
254
+
 
 
 
 
 
 
 
 
255
  $return_data['error'] = $er_msg;
256
  wp_send_json_error( $return_data );
257
  }
258
+
259
  $response_code = wp_remote_retrieve_response_code( $request );
260
+
261
  if ( $response_code != 200 ) {
262
  $return_data['error'] = 'Server response ' . $response_code;
263
  wp_send_json_error( $return_data );
264
  }
265
+
266
  wp_send_json_success( $return_data );
267
  } );
268
 
273
  * статус выбранный).
274
  */
275
  add_action( 'wp_ajax_wbcr-rio-check-user-balance', function () {
276
+
277
  check_ajax_referer( 'bulk_optimization' );
278
+
279
  if ( ! current_user_can( 'manage_options' ) ) {
280
  wp_die( - 1 );
281
  }
282
+
283
+ $optimization_server = $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
284
+ // $optimization_server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' );
285
+ if ( $optimization_server !== 'server_5' && $optimization_server !== 'server_2' ) {
286
+ $processor = WIO_OptimizationTools::getImageProcessor();
287
+
288
+ $processor->checkLimits( false );
289
+
290
+ $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
291
+ $remaining = $processor->iamokay() - $usage;
292
+ wp_send_json_success( [
293
+ 'balance' => $remaining,
294
+ ] );
295
+ }
296
+
297
+ if ( $optimization_server == 'server_2') {
298
+ $api_url = "https://dev.robinoptimizer.com/v1/free/license/remaining";
299
+ $host = get_option( 'siteurl' );
300
+ $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
301
+ } elseif ( $optimization_server == 'server_5') {
302
+ $api_url = 'https://dashboard.robinoptimizer.com/v1/license/remaining';
303
+ $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
304
+ $headers['PluginId'] = wrio_get_freemius_plugin_id();
305
+ }
306
+
307
+
308
  $request = wp_remote_request( $api_url, [
309
  'method' => 'GET',
310
  'headers' => $headers
311
  ] );
312
+
313
  if ( is_wp_error( $request ) ) {
314
  $error_msg = $request->get_error_message();
315
+
316
  $return_data['error'] = $error_msg;
317
  wp_send_json_error( $return_data );
318
  }
319
+
320
  $response_code = wp_remote_retrieve_response_code( $request );
321
  $response_body = wp_remote_retrieve_body( $request );
322
+
323
  if ( $response_code != 200 ) {
324
  $return_data['error'] = 'Server response ' . $response_code;
325
  if ( $response_code === 401 ) {
328
  }
329
  wp_send_json_error( $return_data );
330
  }
331
+
332
  if ( empty( $response_body ) ) {
333
  $return_data['error'] = "Server responded an empty request body!";
334
  wp_send_json_error( $return_data );
335
  }
336
+
337
  $data = @json_decode( $response_body );
338
+
339
  if ( ! isset( $data->status ) || $data->status != 'ok' ) {
340
  $return_data['error'] = "Server responded an fail status";
341
  wp_send_json_error( $return_data );
342
  }
343
+
344
  $current_quota = (int) $data->response->quota;
345
  WRIO_Plugin::app()->app()->updateOption( 'current_quota', $current_quota );
346
+
347
  wp_send_json_success( [
348
  'balance' => $current_quota,
349
  ] );
admin/assets/css/base-statistic.css CHANGED
@@ -1,676 +1,675 @@
1
- /**
2
- * Styles for the Widget to be displayed in the Clearfy plugin
3
-
4
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
- * @copyright Webcraftic 14.06.2019
6
- */
7
- #WBCR {
8
- /* Doughnut */
9
- /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
- .wio-overview-chart-container {
11
- float: none;
12
- margin-right: 0;
13
- }
14
- }
15
-
16
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
- .wio-overview-chart-container {
18
- float: none;
19
- margin-right: 0;
20
- }
21
-
22
- .wio-doughnut-legend {
23
- margin-top: 18px;
24
- }
25
-
26
- .wio-global-optim-phrase {
27
- padding-top: 0;
28
- width: auto;
29
- }
30
- }*/
31
- }
32
- #WBCR .wio-clear {
33
- clear: both;
34
- }
35
- #WBCR #io_folders_statistic-wbcr_clearfy-tab,
36
- #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
37
- display: none !important;
38
- }
39
- #WBCR .wrio-statistic-nav {
40
- margin: 0;
41
- background: #efefef;
42
- }
43
- #WBCR .wrio-statistic-nav ul {
44
- margin: 0;
45
- }
46
- #WBCR .wrio-statistic-nav ul li {
47
- position: relative;
48
- display: inline-block;
49
- margin: 0 0 0 0;
50
- background: #ffffff;
51
- box-shadow: 0 -2px 0 #eaeaea;
52
- }
53
- #WBCR .wrio-statistic-nav ul li:hover {
54
- background: #f7f7f7;
55
- }
56
- #WBCR .wrio-statistic-nav ul li.active {
57
- background: #f7f7f7;
58
- border-top: 1px solid #d4d4d4;
59
- border-left: 1px solid #d4d4d4;
60
- border-right: 1px solid #d4d4d4;
61
- border-bottom: 1px solid #f7f7f7;
62
- margin-bottom: -1px;
63
- }
64
- #WBCR .wrio-statistic-nav ul li.active a {
65
- color: #222;
66
- }
67
- #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
68
- border: 2px dashed #8bc34a;
69
- color: #5e8237;
70
- }
71
- #WBCR .wrio-statistic-nav ul li.active .dashicons,
72
- #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
73
- color: #ff8b66;
74
- }
75
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
76
- display: block;
77
- padding: 10px 20px 10px 20px;
78
- text-decoration: none;
79
- color: #d4d4d4;
80
- font-size: 22px;
81
- line-height: 2;
82
- }
83
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
84
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
85
- background: 0;
86
- box-shadow: none;
87
- outline: none;
88
- }
89
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
90
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
91
- display: inline-block;
92
- width: 30px;
93
- height: 30px;
94
- font-size: 30px;
95
- line-height: 1.5;
96
- margin-right: 15px;
97
- color: #d4d4d4;
98
- }
99
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
100
- display: inline-block;
101
- width: 42px;
102
- height: 42px;
103
- border-radius: 100px;
104
- border: 2px dashed #e4e4e4;
105
- padding: 5px;
106
- margin-left: 30px;
107
- font-size: 14px;
108
- font-weight: 600;
109
- text-align: center;
110
- color: #bdbdbd;
111
- }
112
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
113
- display: inline-block;
114
- position: absolute;
115
- content: 'PRO';
116
- background: #ff5722;
117
- border-radius: 4px;
118
- color: #fff;
119
- font-size: 10px;
120
- line-height: 1;
121
- font-style: normal;
122
- padding: 4px 6px;
123
- margin-left: 4px;
124
- vertical-align: top;
125
- top: 10px;
126
- left: auto;
127
- right: 10px;
128
- z-index: 11;
129
- }
130
- #WBCR .wrio-table {
131
- width: 100%;
132
- table-layout: fixed;
133
- box-sizing: border-box;
134
- border-spacing: 3px;
135
- background: #fff;
136
- border-top: 2px dashed #cac9c9;
137
- }
138
- #WBCR .wrio-table th,
139
- #WBCR .wrio-table td {
140
- padding: 16px 10px;
141
- text-align: center;
142
- }
143
- #WBCR .wrio-table th {
144
- background: #f3f3f3;
145
- color: #777777;
146
- box-shadow: 0 1px 0 #d8d8d8;
147
- }
148
- #WBCR .wrio-table th:nth-child(2n+1) {
149
- background: #f9f9f9;
150
- }
151
- #WBCR .wrio-table tr.wrio-error {
152
- background-color: #ffe9e9 !important;
153
- }
154
- #WBCR .wrio-table .wrio-table-spinner {
155
- background: url("../img/quick-start-loader.gif") center center no-repeat;
156
- }
157
- #WBCR .wrio-table .wrio-table-highlighter {
158
- display: inline-block;
159
- padding: 3px 7px;
160
- background: #f3f3f3;
161
- }
162
- #WBCR .wrio-table .wbcr-rio-server-success {
163
- color: #8CC152;
164
- }
165
- #WBCR .wrio-table .wbcr-rio-server-error {
166
- color: #fb5d49;
167
- }
168
- #WBCR .wrio-table .wbcr-rio-server-warning {
169
- color: #ffb635;
170
- }
171
- #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
172
- text-align: left;
173
- }
174
- #WBCR .wrio-servers {
175
- padding: 40px 20px;
176
- }
177
- #WBCR .wrio-servers label span {
178
- display: block;
179
- font-weight: normal;
180
- font-size: 12px;
181
- color: #b7b2b2;
182
- }
183
- #WBCR .wrio-servers #wrio-change-optimization-server {
184
- position: relative;
185
- display: inline-block;
186
- max-width: 400px;
187
- margin-right: 15px;
188
- margin-bottom: 0;
189
- border: 1px solid #d2d0d0;
190
- background: #efefef;
191
- }
192
- #WBCR .wrio-servers .wrio-servers-info {
193
- margin: 0 0 0;
194
- padding: 20px;
195
- background: #fff;
196
- }
197
- #WBCR .wrio-servers .wrio-server-status-wrap {
198
- display: inline-block;
199
- margin-top: 8px;
200
- }
201
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
202
- background: transparent;
203
- color: #fff;
204
- padding: 3px 5px;
205
- border-radius: 4px;
206
- }
207
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
208
- background: #ff5722;
209
- }
210
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
211
- background: #8bc34a;
212
- }
213
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
214
- display: inline-block;
215
- height: 10px;
216
- width: 30px;
217
- background: url("../img/quick-start-loader.gif") center no-repeat;
218
- }
219
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap {
220
- display: none;
221
- margin-top: 8px;
222
- margin-left: 10px;
223
- }
224
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance {
225
- color: #fff;
226
- padding: 3px 5px;
227
- border-radius: 4px;
228
- background: #ffc107;
229
- }
230
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance-check-proccess {
231
- display: inline-block;
232
- height: 10px;
233
- width: 30px;
234
- background: url("../img/quick-start-loader.gif") center no-repeat;
235
- }
236
- #WBCR .wio-columns {
237
- overflow: hidden;
238
- padding: 15px 0;
239
- counter-reset: cols;
240
- }
241
- #WBCR .wio-columns [class^="col-"] {
242
- float: left;
243
- -webkit-box-sizing: border-box;
244
- -moz-box-sizing: border-box;
245
- box-sizing: border-box;
246
- }
247
- #WBCR .wio-columns .col-1-3 {
248
- width: 33.333%;
249
- padding-left: 28px;
250
- }
251
- #WBCR .wio-columns .col-2-3 {
252
- width: 66.666%;
253
- padding-left: 28px;
254
- }
255
- #WBCR .wio-columns .col-1-2 {
256
- width: 50%;
257
- padding: 0 20px;
258
- }
259
- #WBCR .wio-columns .col-statistics.col-statistics {
260
- width: 60%;
261
- }
262
- #WBCR .wio-columns .col-chart.col-chart {
263
- width: 40%;
264
- position: relative;
265
- padding: 20px;
266
- font-size: 12px;
267
- text-transform: uppercase;
268
- background: #f1f1f1b3;
269
- color: #abacaf;
270
- font-weight: bold;
271
- border-radius: 5px;
272
- margin-top: 10px;
273
- text-align: left;
274
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
275
- }
276
- #WBCR .wio-col {
277
- float: left;
278
- width: 50%;
279
- box-sizing: border-box;
280
- -webkit-flex-basis: 50%;
281
- -ms-flex-preferred-size: 50%;
282
- flex-basis: 50%;
283
- }
284
- #WBCR .wio-col {
285
- padding-right: 20px;
286
- }
287
- #WBCR .wio-col + .wio-col {
288
- padding-right: 0;
289
- padding-left: 50px;
290
- }
291
- #WBCR .wio-col:target {
292
- animation: wiohello 1s 3 linear backwards;
293
- }
294
- #WBCR .wio-number-you-optimized {
295
- margin-bottom: 1.35em;
296
- overflow: hidden;
297
- }
298
- #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
299
- color: #828282;
300
- }
301
- #WBCR .wio-number-you-optimized .wio-number {
302
- display: table-cell;
303
- padding-right: 15px;
304
- font-size: 48px;
305
- font-weight: bold;
306
- line-height: 1;
307
- vertical-align: middle;
308
- white-space: nowrap;
309
- color: #828282;
310
- }
311
- #WBCR .wio-number-you-optimized .wio-text {
312
- display: table-cell;
313
- vertical-align: middle;
314
- overflow: hidden;
315
- font-size: 12px;
316
- color: #828282;
317
- }
318
- #WBCR .wio-number-you-optimized > p {
319
- display: table;
320
- }
321
- #WBCR .wio-bars {
322
- padding-right: 15px;
323
- }
324
- #WBCR .wio-bars p {
325
- font-size: 12px;
326
- margin-bottom: 5px;
327
- }
328
- #WBCR .wio-bars + .wio-number-you-optimized {
329
- border-bottom: 0;
330
- padding-top: 0.85em;
331
- }
332
- #WBCR .wio-bars + .wio-number-you-optimized p {
333
- color: #72a53b;
334
- }
335
- #WBCR .wio-bar-negative .wio-progress {
336
- background: #D2D3D6;
337
- }
338
- #WBCR .wio-bar-negative .wio-barnb {
339
- color: #9d9fa5;
340
- }
341
- #WBCR .wio-progress {
342
- height: 8px;
343
- transition: width 0.3s;
344
- /*.wio-bar-negative {
345
- width: 92% !important;
346
- }*/
347
- }
348
- #WBCR .wio-bar-positive .wio-progress {
349
- background: #8CC152;
350
- }
351
- #WBCR .wio-bar-positive .wio-barnb {
352
- color: #72a53b;
353
- }
354
- #WBCR .wio-bar-primary .wio-progress {
355
- background: #8CC152;
356
- }
357
- #WBCR .wio-bar-primary .wio-barnb {
358
- color: #72a53b;
359
- }
360
- #WBCR .wio-right-outside-number .wio-barnb {
361
- display: block;
362
- margin-right: -5.25em;
363
- text-align: right;
364
- font-weight: bold;
365
- line-height: 0.8;
366
- }
367
- #WBCR .wio-chart {
368
- position: relative;
369
- top: 1px;
370
- display: inline-block;
371
- vertical-align: middle;
372
- }
373
- #WBCR .wio-chart-container {
374
- position: relative;
375
- display: inline-block;
376
- margin-right: 5px;
377
- }
378
- #WBCR .wio-chart-container canvas {
379
- display: block;
380
- }
381
- #WBCR .wio-overview-chart-container {
382
- float: left;
383
- margin-right: 20px;
384
- }
385
- #WBCR .wio-chart-percent {
386
- position: absolute;
387
- left: 0;
388
- right: 0;
389
- top: 50%;
390
- margin-top: -0.5em;
391
- line-height: 0.8;
392
- text-align: center;
393
- font-size: 54px;
394
- font-weight: bold;
395
- color: #afafaf;
396
- }
397
- #WBCR .wio-chart-percent span {
398
- font-size: 20px;
399
- vertical-align: super;
400
- }
401
- #WBCR #wio-overview-chart-legend {
402
- overflow: hidden;
403
- }
404
- #WBCR .wio-doughnut-legend li {
405
- display: inline-block;
406
- position: relative;
407
- margin-bottom: 15px;
408
- border-radius: 5px;
409
- padding: 3px 8px 2px 31px;
410
- font-size: 9px;
411
- cursor: default;
412
- -webkit-transition: background-color 200ms ease-in-out;
413
- -moz-transition: background-color 200ms ease-in-out;
414
- -o-transition: background-color 200ms ease-in-out;
415
- transition: background-color 200ms ease-in-out;
416
- }
417
- #WBCR .wio-doughnut-legend li span {
418
- display: block;
419
- position: absolute;
420
- left: 0;
421
- top: 0;
422
- width: 25px;
423
- height: 25px;
424
- border-radius: 50%;
425
- }
426
- #WBCR .wio-optimize-button {
427
- min-width: 180px;
428
- padding: 12px 30px;
429
- background: #c9deb2;
430
- color: #586549;
431
- border: 0;
432
- box-shadow: none;
433
- font-size: 14px;
434
- text-transform: uppercase !important;
435
- font-weight: bold;
436
- border-radius: 4px;
437
- outline: none;
438
- }
439
- #WBCR .wio-optimize-button:active {
440
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
441
- }
442
- #WBCR .wio-optimize-button:disabled {
443
- background: #e2edd6;
444
- color: #a5b295;
445
- }
446
- #WBCR .wio-optimize-button.wio-running {
447
- color: #a57b3c;
448
- background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
449
- padding-left: 50px;
450
- }
451
- #WBCR .wio-global-optim-phrase {
452
- width: 180px;
453
- padding-top: 20px;
454
- font-size: 14px;
455
- text-align: center;
456
- }
457
- #WBCR .wio-total-percent {
458
- color: #587f2e;
459
- }
460
- #WBCR #wio-start-msg-top,
461
- #WBCR #wio-start-msg-right,
462
- #WBCR #wio-start-msg-complete {
463
- display: none;
464
- }
465
- #WBCR .wio-text-left {
466
- text-align: left;
467
- }
468
- #WBCR span.wio-num {
469
- display: inline !important;
470
- position: inherit !important;
471
- }
472
- #WBCR .wio-image-optimize-board {
473
- padding-bottom: 0 !important;
474
- }
475
- #WBCR .wio-page-statistic {
476
- padding-left: 40px;
477
- }
478
- #WBCR .wio-page-statistic .wio-chart-percent {
479
- margin-top: -1.1em;
480
- }
481
- #WBCR .wrio-optimization-progress {
482
- background: none;
483
- padding: 0;
484
- /*button {
485
- padding: 5px 10px;
486
- border: 0;
487
- font-size: 11px;
488
- text-transform: uppercase !important;
489
- font-weight: bold;
490
- border-radius: 4px;
491
- outline: none;
492
- background: @greyButtonBg;
493
- color: @greyButtonColor;
494
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
495
-
496
- &:active {
497
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
498
- }
499
-
500
- &.wbcr-rio-loading {
501
- width: 56px;
502
- font-size: 0;
503
- background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
504
- }
505
-
506
- &.wbcr-rio-selected {
507
- background: #f3efe2;
508
- color: #d8d8d8;
509
-
510
- &:active {
511
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
512
- }
513
- }
514
- }*/
515
- }
516
- #WBCR .wrio-optimization-progress h4 {
517
- font-size: 15px;
518
- font-weight: 700;
519
- }
520
- #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
521
- padding: 20px;
522
- background: #efefef;
523
- font-size: 15px;
524
- color: #b7b7b7;
525
- font-style: italic;
526
- }
527
- #WBCR .wio-widget {
528
- padding: 0 !important;
529
- }
530
- #WBCR .wio-widget .wio-chart-percent {
531
- font-size: 44px;
532
- line-height: 1;
533
- }
534
- #WBCR .wio-widget .wio-bars {
535
- width: 60%;
536
- margin-left: 155px;
537
- }
538
- #WBCR .wio-widget .col-chart.col-chart {
539
- width: 100%;
540
- }
541
- #WBCR .wio-widget .col-controls {
542
- width: 45%;
543
- padding-left: 5px;
544
- padding-top: 110px;
545
- }
546
- #WBCR .wio-widget .wio-doughnut-legend {
547
- /*padding-top:30px;*/
548
- text-align: left;
549
- }
550
- #WBCR .wio-widget .wio-widget-bottom {
551
- display: table;
552
- padding-top: 20px !important;
553
- width: 100%;
554
- text-align: right;
555
- }
556
- #WBCR .wio-widget .wio-widget-bottom li {
557
- display: table-cell;
558
- }
559
- #WBCR .wio-widget .wio-widget-bottom li:first-child {
560
- text-align: left;
561
- }
562
- #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
563
- display: inline-block;
564
- position: relative;
565
- content: 'PRO';
566
- background: #ff5722;
567
- border-radius: 4px;
568
- color: #fff;
569
- font-size: 10px;
570
- line-height: 1;
571
- font-style: normal;
572
- padding: 4px 6px;
573
- margin-left: 4px;
574
- vertical-align: top;
575
- top: -8px;
576
- left: -10px;
577
- right: auto;
578
- z-index: 11;
579
- }
580
- #WBCR .factory-checkbox-disabled input,
581
- #WBCR .factory-checkbox-disabled button {
582
- pointer-events: none;
583
- cursor: not-allowed;
584
- opacity: 0.65;
585
- filter: alpha(opacity=65);
586
- -webkit-box-shadow: none;
587
- box-shadow: none;
588
- }
589
- #WBCR #wrio-webp-options h3,
590
- #WBCR #wrio-error-log-options h3 {
591
- font-size: 14px;
592
- margin: 0 0 10px 0;
593
- font-weight: 600;
594
- color: #565656;
595
- }
596
- #WBCR #wrio-webp-options .wrio-webp-options-info,
597
- #WBCR #wrio-error-log-options .wrio-webp-options-info {
598
- color: #8a8787;
599
- font-size: 12px;
600
- }
601
- #WBCR #wrio-webp-options ul,
602
- #WBCR #wrio-error-log-options ul {
603
- padding-left: 0;
604
- }
605
- #WBCR #wrio-webp-options ul li:after,
606
- #WBCR #wrio-error-log-options ul li:after {
607
- content: '';
608
- display: block;
609
- clear: both;
610
- }
611
- #WBCR #wrio-webp-options ul li label,
612
- #WBCR #wrio-error-log-options ul li label {
613
- font-weight: 600;
614
- }
615
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
616
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
617
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
618
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
619
- display: block;
620
- float: left;
621
- margin-top: 2px;
622
- margin-right: 8px;
623
- }
624
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
625
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
626
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
627
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
628
- outline: none;
629
- box-shadow: none;
630
- }
631
- #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
632
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
633
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
634
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
635
- padding-left: 25px;
636
- }
637
- @media (max-width: 830px) {
638
- #WBCR .wio [class^="col-"] {
639
- float: none;
640
- margin-bottom: 1.5em;
641
- }
642
- #WBCR .wio .col-1-3,
643
- #WBCR .wio .col-1-2 {
644
- width: auto;
645
- padding: 0 28px;
646
- clear: both;
647
- padding-top: 1em;
648
- }
649
- }
650
- @keyframes wiohello {
651
- 0%,
652
- 100% {
653
- background: #FFF;
654
- }
655
- 50% {
656
- background: #F4F7F9;
657
- }
658
- }
659
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
660
- #WBCR .wio-columns .col-statistics.col-statistics,
661
- #WBCR .wio-columns .col-chart.col-chart {
662
- width: 50%;
663
- }
664
- }
665
- @media (max-width: 808px) {
666
- #WBCR .wio-columns .col-statistics.col-statistics,
667
- #WBCR .wio-columns .col-chart.col-chart {
668
- width: auto;
669
- float: none;
670
- padding: 0;
671
- }
672
- #WBCR .wio-columns .col-chart.col-chart {
673
- margin-top: 3em;
674
- }
675
- }
676
- /*# sourceMappingURL=base-statistic.css.map */
1
+ /**
2
+ * Styles for the Widget to be displayed in the Clearfy plugin
3
+
4
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 14.06.2019
6
+ */
7
+ #WBCR {
8
+ /* Doughnut */
9
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
+ .wio-overview-chart-container {
11
+ float: none;
12
+ margin-right: 0;
13
+ }
14
+ }
15
+
16
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
+ .wio-overview-chart-container {
18
+ float: none;
19
+ margin-right: 0;
20
+ }
21
+
22
+ .wio-doughnut-legend {
23
+ margin-top: 18px;
24
+ }
25
+
26
+ .wio-global-optim-phrase {
27
+ padding-top: 0;
28
+ width: auto;
29
+ }
30
+ }*/
31
+ }
32
+ #WBCR .wio-clear {
33
+ clear: both;
34
+ }
35
+ #WBCR #io_folders_statistic-wbcr_clearfy-tab,
36
+ #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
37
+ display: none !important;
38
+ }
39
+ #WBCR .wrio-statistic-nav {
40
+ margin: 0;
41
+ background: #efefef;
42
+ }
43
+ #WBCR .wrio-statistic-nav ul {
44
+ margin: 0;
45
+ }
46
+ #WBCR .wrio-statistic-nav ul li {
47
+ position: relative;
48
+ display: inline-block;
49
+ margin: 0 0 0 0;
50
+ background: #ffffff;
51
+ box-shadow: 0 -2px 0 #eaeaea;
52
+ }
53
+ #WBCR .wrio-statistic-nav ul li:hover {
54
+ background: #f7f7f7;
55
+ }
56
+ #WBCR .wrio-statistic-nav ul li.active {
57
+ background: #f7f7f7;
58
+ border-top: 1px solid #d4d4d4;
59
+ border-left: 1px solid #d4d4d4;
60
+ border-right: 1px solid #d4d4d4;
61
+ border-bottom: 1px solid #f7f7f7;
62
+ margin-bottom: -1px;
63
+ }
64
+ #WBCR .wrio-statistic-nav ul li.active a {
65
+ color: #222;
66
+ }
67
+ #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
68
+ border: 2px dashed #8bc34a;
69
+ color: #5e8237;
70
+ }
71
+ #WBCR .wrio-statistic-nav ul li.active .dashicons,
72
+ #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
73
+ color: #ff8b66;
74
+ }
75
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
76
+ display: block;
77
+ padding: 10px 20px 10px 20px;
78
+ text-decoration: none;
79
+ color: #d4d4d4;
80
+ font-size: 22px;
81
+ line-height: 2;
82
+ }
83
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
84
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
85
+ background: 0;
86
+ box-shadow: none;
87
+ outline: none;
88
+ }
89
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
90
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
91
+ display: inline-block;
92
+ width: 30px;
93
+ height: 30px;
94
+ font-size: 30px;
95
+ line-height: 1.5;
96
+ margin-right: 15px;
97
+ color: #d4d4d4;
98
+ }
99
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
100
+ display: inline-block;
101
+ width: 42px;
102
+ height: 42px;
103
+ border-radius: 100px;
104
+ border: 2px dashed #e4e4e4;
105
+ padding: 5px;
106
+ margin-left: 30px;
107
+ font-size: 14px;
108
+ font-weight: 600;
109
+ text-align: center;
110
+ color: #bdbdbd;
111
+ }
112
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
113
+ display: inline-block;
114
+ position: absolute;
115
+ content: 'PRO';
116
+ background: #ff5722;
117
+ border-radius: 4px;
118
+ color: #fff;
119
+ font-size: 10px;
120
+ line-height: 1;
121
+ font-style: normal;
122
+ padding: 4px 6px;
123
+ margin-left: 4px;
124
+ vertical-align: top;
125
+ top: 10px;
126
+ left: auto;
127
+ right: 10px;
128
+ z-index: 11;
129
+ }
130
+ #WBCR .wrio-table {
131
+ width: 100%;
132
+ table-layout: fixed;
133
+ box-sizing: border-box;
134
+ border-spacing: 3px;
135
+ background: #fff;
136
+ border-top: 2px dashed #cac9c9;
137
+ }
138
+ #WBCR .wrio-table th,
139
+ #WBCR .wrio-table td {
140
+ padding: 16px 10px;
141
+ text-align: center;
142
+ }
143
+ #WBCR .wrio-table th {
144
+ background: #f3f3f3;
145
+ color: #777777;
146
+ box-shadow: 0 1px 0 #d8d8d8;
147
+ }
148
+ #WBCR .wrio-table th:nth-child(2n+1) {
149
+ background: #f9f9f9;
150
+ }
151
+ #WBCR .wrio-table tr.wrio-error {
152
+ background-color: #ffe9e9 !important;
153
+ }
154
+ #WBCR .wrio-table .wrio-table-spinner {
155
+ background: url("../img/quick-start-loader.gif") center center no-repeat;
156
+ }
157
+ #WBCR .wrio-table .wrio-table-highlighter {
158
+ display: inline-block;
159
+ padding: 3px 7px;
160
+ background: #f3f3f3;
161
+ }
162
+ #WBCR .wrio-table .wbcr-rio-server-success {
163
+ color: #8CC152;
164
+ }
165
+ #WBCR .wrio-table .wbcr-rio-server-error {
166
+ color: #fb5d49;
167
+ }
168
+ #WBCR .wrio-table .wbcr-rio-server-warning {
169
+ color: #ffb635;
170
+ }
171
+ #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
172
+ text-align: left;
173
+ }
174
+ #WBCR .wrio-servers {
175
+ padding: 40px 20px;
176
+ }
177
+ #WBCR .wrio-servers label span {
178
+ display: block;
179
+ font-weight: normal;
180
+ font-size: 12px;
181
+ color: #b7b2b2;
182
+ }
183
+ #WBCR .wrio-servers #wrio-change-optimization-server {
184
+ position: relative;
185
+ display: inline-block;
186
+ max-width: 400px;
187
+ margin-right: 15px;
188
+ margin-bottom: 0;
189
+ border: 1px solid #d2d0d0;
190
+ background: #efefef;
191
+ }
192
+ #WBCR .wrio-servers .wrio-servers-info {
193
+ margin: 0 0 0;
194
+ padding: 20px;
195
+ background: #fff;
196
+ }
197
+ #WBCR .wrio-servers .wrio-server-status-wrap {
198
+ display: inline-block;
199
+ margin-top: 8px;
200
+ }
201
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
202
+ background: transparent;
203
+ color: #fff;
204
+ padding: 3px 5px;
205
+ border-radius: 4px;
206
+ }
207
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
208
+ background: #ff5722;
209
+ }
210
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
211
+ background: #8bc34a;
212
+ }
213
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
214
+ display: inline-block;
215
+ height: 10px;
216
+ width: 30px;
217
+ background: url("../img/quick-start-loader.gif") center no-repeat;
218
+ }
219
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap {
220
+ display: inline-block;
221
+ margin-top: 8px;
222
+ margin-left: 10px;
223
+ }
224
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance {
225
+ color: #fff;
226
+ padding: 3px 5px;
227
+ border-radius: 4px;
228
+ background: #ffc107;
229
+ }
230
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance-check-proccess {
231
+ display: inline-block;
232
+ height: 10px;
233
+ width: 30px;
234
+ background: url("../img/quick-start-loader.gif") center no-repeat;
235
+ }
236
+ #WBCR .wio-columns {
237
+ overflow: hidden;
238
+ padding: 15px 0;
239
+ counter-reset: cols;
240
+ }
241
+ #WBCR .wio-columns [class^="col-"] {
242
+ float: left;
243
+ -webkit-box-sizing: border-box;
244
+ -moz-box-sizing: border-box;
245
+ box-sizing: border-box;
246
+ }
247
+ #WBCR .wio-columns .col-1-3 {
248
+ width: 33.333%;
249
+ padding-left: 28px;
250
+ }
251
+ #WBCR .wio-columns .col-2-3 {
252
+ width: 66.666%;
253
+ padding-left: 28px;
254
+ }
255
+ #WBCR .wio-columns .col-1-2 {
256
+ width: 50%;
257
+ padding: 0 20px;
258
+ }
259
+ #WBCR .wio-columns .col-statistics.col-statistics {
260
+ width: 60%;
261
+ }
262
+ #WBCR .wio-columns .col-chart.col-chart {
263
+ width: 40%;
264
+ position: relative;
265
+ padding: 20px;
266
+ font-size: 12px;
267
+ text-transform: uppercase;
268
+ background: #f1f1f1b3;
269
+ color: #abacaf;
270
+ font-weight: bold;
271
+ border-radius: 5px;
272
+ margin-top: 10px;
273
+ text-align: left;
274
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
275
+ }
276
+ #WBCR .wio-col {
277
+ float: left;
278
+ width: 50%;
279
+ box-sizing: border-box;
280
+ -webkit-flex-basis: 50%;
281
+ -ms-flex-preferred-size: 50%;
282
+ flex-basis: 50%;
283
+ }
284
+ #WBCR .wio-col {
285
+ padding-right: 20px;
286
+ }
287
+ #WBCR .wio-col + .wio-col {
288
+ padding-right: 0;
289
+ padding-left: 50px;
290
+ }
291
+ #WBCR .wio-col:target {
292
+ animation: wiohello 1s 3 linear backwards;
293
+ }
294
+ #WBCR .wio-number-you-optimized {
295
+ margin-bottom: 1.35em;
296
+ overflow: hidden;
297
+ }
298
+ #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
299
+ color: #828282;
300
+ }
301
+ #WBCR .wio-number-you-optimized .wio-number {
302
+ display: table-cell;
303
+ padding-right: 15px;
304
+ font-size: 48px;
305
+ font-weight: bold;
306
+ line-height: 1;
307
+ vertical-align: middle;
308
+ white-space: nowrap;
309
+ color: #828282;
310
+ }
311
+ #WBCR .wio-number-you-optimized .wio-text {
312
+ display: table-cell;
313
+ vertical-align: middle;
314
+ overflow: hidden;
315
+ font-size: 12px;
316
+ color: #828282;
317
+ }
318
+ #WBCR .wio-number-you-optimized > p {
319
+ display: table;
320
+ }
321
+ #WBCR .wio-bars {
322
+ padding-right: 15px;
323
+ }
324
+ #WBCR .wio-bars p {
325
+ font-size: 12px;
326
+ margin-bottom: 5px;
327
+ }
328
+ #WBCR .wio-bars + .wio-number-you-optimized {
329
+ border-bottom: 0;
330
+ padding-top: 0.85em;
331
+ }
332
+ #WBCR .wio-bars + .wio-number-you-optimized p {
333
+ color: #72a53b;
334
+ }
335
+ #WBCR .wio-bar-negative .wio-progress {
336
+ background: #D2D3D6;
337
+ }
338
+ #WBCR .wio-bar-negative .wio-barnb {
339
+ color: #9d9fa5;
340
+ }
341
+ #WBCR .wio-progress {
342
+ height: 8px;
343
+ transition: width 0.3s;
344
+ /*.wio-bar-negative {
345
+ width: 92% !important;
346
+ }*/
347
+ }
348
+ #WBCR .wio-bar-positive .wio-progress {
349
+ background: #8CC152;
350
+ }
351
+ #WBCR .wio-bar-positive .wio-barnb {
352
+ color: #72a53b;
353
+ }
354
+ #WBCR .wio-bar-primary .wio-progress {
355
+ background: #8CC152;
356
+ }
357
+ #WBCR .wio-bar-primary .wio-barnb {
358
+ color: #72a53b;
359
+ }
360
+ #WBCR .wio-right-outside-number .wio-barnb {
361
+ display: block;
362
+ margin-right: -5.25em;
363
+ text-align: right;
364
+ font-weight: bold;
365
+ line-height: 0.8;
366
+ }
367
+ #WBCR .wio-chart {
368
+ position: relative;
369
+ top: 1px;
370
+ display: inline-block;
371
+ vertical-align: middle;
372
+ }
373
+ #WBCR .wio-chart-container {
374
+ position: relative;
375
+ display: inline-block;
376
+ margin-right: 5px;
377
+ }
378
+ #WBCR .wio-chart-container canvas {
379
+ display: block;
380
+ }
381
+ #WBCR .wio-overview-chart-container {
382
+ float: left;
383
+ margin-right: 20px;
384
+ }
385
+ #WBCR .wio-chart-percent {
386
+ position: absolute;
387
+ left: 0;
388
+ right: 0;
389
+ top: 50%;
390
+ margin-top: -0.5em;
391
+ line-height: 0.8;
392
+ text-align: center;
393
+ font-size: 54px;
394
+ font-weight: bold;
395
+ color: #afafaf;
396
+ }
397
+ #WBCR .wio-chart-percent span {
398
+ font-size: 20px;
399
+ vertical-align: super;
400
+ }
401
+ #WBCR #wio-overview-chart-legend {
402
+ overflow: hidden;
403
+ }
404
+ #WBCR .wio-doughnut-legend li {
405
+ display: inline-block;
406
+ position: relative;
407
+ margin-bottom: 15px;
408
+ border-radius: 5px;
409
+ padding: 3px 8px 2px 31px;
410
+ font-size: 9px;
411
+ cursor: default;
412
+ -webkit-transition: background-color 200ms ease-in-out;
413
+ -moz-transition: background-color 200ms ease-in-out;
414
+ -o-transition: background-color 200ms ease-in-out;
415
+ transition: background-color 200ms ease-in-out;
416
+ }
417
+ #WBCR .wio-doughnut-legend li span {
418
+ display: block;
419
+ position: absolute;
420
+ left: 0;
421
+ top: 0;
422
+ width: 25px;
423
+ height: 25px;
424
+ border-radius: 50%;
425
+ }
426
+ #WBCR .wio-optimize-button {
427
+ min-width: 180px;
428
+ padding: 12px 30px;
429
+ background: #c9deb2;
430
+ color: #586549;
431
+ border: 0;
432
+ box-shadow: none;
433
+ font-size: 14px;
434
+ text-transform: uppercase !important;
435
+ font-weight: bold;
436
+ border-radius: 4px;
437
+ outline: none;
438
+ }
439
+ #WBCR .wio-optimize-button:active {
440
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
441
+ }
442
+ #WBCR .wio-optimize-button:disabled {
443
+ background: #e2edd6;
444
+ color: #a5b295;
445
+ }
446
+ #WBCR .wio-optimize-button.wio-running {
447
+ color: #a57b3c;
448
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
449
+ padding-left: 50px;
450
+ }
451
+ #WBCR .wio-global-optim-phrase {
452
+ width: 180px;
453
+ padding-top: 20px;
454
+ font-size: 14px;
455
+ text-align: center;
456
+ }
457
+ #WBCR .wio-total-percent {
458
+ color: #587f2e;
459
+ }
460
+ #WBCR #wio-start-msg-top,
461
+ #WBCR #wio-start-msg-right,
462
+ #WBCR #wio-start-msg-complete {
463
+ display: none;
464
+ }
465
+ #WBCR .wio-text-left {
466
+ text-align: left;
467
+ }
468
+ #WBCR span.wio-num {
469
+ display: inline !important;
470
+ position: inherit !important;
471
+ }
472
+ #WBCR .wio-image-optimize-board {
473
+ padding-bottom: 0 !important;
474
+ }
475
+ #WBCR .wio-page-statistic {
476
+ padding-left: 40px;
477
+ }
478
+ #WBCR .wio-page-statistic .wio-chart-percent {
479
+ margin-top: -1.1em;
480
+ }
481
+ #WBCR .wrio-optimization-progress {
482
+ background: none;
483
+ padding: 0;
484
+ /*button {
485
+ padding: 5px 10px;
486
+ border: 0;
487
+ font-size: 11px;
488
+ text-transform: uppercase !important;
489
+ font-weight: bold;
490
+ border-radius: 4px;
491
+ outline: none;
492
+ background: @greyButtonBg;
493
+ color: @greyButtonColor;
494
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
495
+
496
+ &:active {
497
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
498
+ }
499
+
500
+ &.wbcr-rio-loading {
501
+ width: 56px;
502
+ font-size: 0;
503
+ background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
504
+ }
505
+
506
+ &.wbcr-rio-selected {
507
+ background: #f3efe2;
508
+ color: #d8d8d8;
509
+
510
+ &:active {
511
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
512
+ }
513
+ }
514
+ }*/
515
+ }
516
+ #WBCR .wrio-optimization-progress h4 {
517
+ font-size: 15px;
518
+ font-weight: 700;
519
+ }
520
+ #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
521
+ padding: 20px;
522
+ background: #efefef;
523
+ font-size: 15px;
524
+ color: #b7b7b7;
525
+ font-style: italic;
526
+ }
527
+ #WBCR .wio-widget {
528
+ padding: 0 !important;
529
+ }
530
+ #WBCR .wio-widget .wio-chart-percent {
531
+ font-size: 44px;
532
+ line-height: 1;
533
+ }
534
+ #WBCR .wio-widget .wio-bars {
535
+ width: 60%;
536
+ margin-left: 155px;
537
+ }
538
+ #WBCR .wio-widget .col-chart.col-chart {
539
+ width: 100%;
540
+ }
541
+ #WBCR .wio-widget .col-controls {
542
+ width: 45%;
543
+ padding-left: 5px;
544
+ padding-top: 110px;
545
+ }
546
+ #WBCR .wio-widget .wio-doughnut-legend {
547
+ /*padding-top:30px;*/
548
+ text-align: left;
549
+ }
550
+ #WBCR .wio-widget .wio-widget-bottom {
551
+ display: table;
552
+ padding-top: 20px !important;
553
+ width: 100%;
554
+ text-align: right;
555
+ }
556
+ #WBCR .wio-widget .wio-widget-bottom li {
557
+ display: table-cell;
558
+ }
559
+ #WBCR .wio-widget .wio-widget-bottom li:first-child {
560
+ text-align: left;
561
+ }
562
+ #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
563
+ display: inline-block;
564
+ position: relative;
565
+ content: 'PRO';
566
+ background: #ff5722;
567
+ border-radius: 4px;
568
+ color: #fff;
569
+ font-size: 10px;
570
+ line-height: 1;
571
+ font-style: normal;
572
+ padding: 4px 6px;
573
+ margin-left: 4px;
574
+ vertical-align: top;
575
+ top: -8px;
576
+ left: -10px;
577
+ right: auto;
578
+ z-index: 11;
579
+ }
580
+ #WBCR .factory-checkbox-disabled input,
581
+ #WBCR .factory-checkbox-disabled button {
582
+ pointer-events: none;
583
+ cursor: not-allowed;
584
+ opacity: 0.65;
585
+ filter: alpha(opacity=65);
586
+ -webkit-box-shadow: none;
587
+ box-shadow: none;
588
+ }
589
+ #WBCR #wrio-webp-options h3,
590
+ #WBCR #wrio-error-log-options h3 {
591
+ font-size: 14px;
592
+ margin: 0 0 10px 0;
593
+ font-weight: 600;
594
+ color: #565656;
595
+ }
596
+ #WBCR #wrio-webp-options .wrio-webp-options-info,
597
+ #WBCR #wrio-error-log-options .wrio-webp-options-info {
598
+ color: #8a8787;
599
+ font-size: 12px;
600
+ }
601
+ #WBCR #wrio-webp-options ul,
602
+ #WBCR #wrio-error-log-options ul {
603
+ padding-left: 0;
604
+ }
605
+ #WBCR #wrio-webp-options ul li:after,
606
+ #WBCR #wrio-error-log-options ul li:after {
607
+ content: '';
608
+ display: block;
609
+ clear: both;
610
+ }
611
+ #WBCR #wrio-webp-options ul li label,
612
+ #WBCR #wrio-error-log-options ul li label {
613
+ font-weight: 600;
614
+ }
615
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
616
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
617
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
618
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
619
+ display: block;
620
+ float: left;
621
+ margin-top: 2px;
622
+ margin-right: 8px;
623
+ }
624
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
625
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
626
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
627
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
628
+ outline: none;
629
+ box-shadow: none;
630
+ }
631
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
632
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
633
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
634
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
635
+ padding-left: 25px;
636
+ }
637
+ @media (max-width: 830px) {
638
+ #WBCR .wio [class^="col-"] {
639
+ float: none;
640
+ margin-bottom: 1.5em;
641
+ }
642
+ #WBCR .wio .col-1-3,
643
+ #WBCR .wio .col-1-2 {
644
+ width: auto;
645
+ padding: 0 28px;
646
+ clear: both;
647
+ padding-top: 1em;
648
+ }
649
+ }
650
+ @keyframes wiohello {
651
+ 0%,
652
+ 100% {
653
+ background: #FFF;
654
+ }
655
+ 50% {
656
+ background: #F4F7F9;
657
+ }
658
+ }
659
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
660
+ #WBCR .wio-columns .col-statistics.col-statistics,
661
+ #WBCR .wio-columns .col-chart.col-chart {
662
+ width: 50%;
663
+ }
664
+ }
665
+ @media (max-width: 808px) {
666
+ #WBCR .wio-columns .col-statistics.col-statistics,
667
+ #WBCR .wio-columns .col-chart.col-chart {
668
+ width: auto;
669
+ float: none;
670
+ padding: 0;
671
+ }
672
+ #WBCR .wio-columns .col-chart.col-chart {
673
+ margin-top: 3em;
674
+ }
675
+ }
 
admin/assets/css/base-statistic.less CHANGED
@@ -258,7 +258,7 @@
258
 
259
 
260
  .wrio-premium-user-balance-wrap {
261
- display: none;
262
  margin-top: 8px;
263
  margin-left: 10px;
264
 
258
 
259
 
260
  .wrio-premium-user-balance-wrap {
261
+ display: inline-block;
262
  margin-top: 8px;
263
  margin-left: 10px;
264
 
admin/assets/css/settings-premium.css ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ button[data-value="googlepage"]:after {
2
+ display: inline-block;
3
+ position: absolute;
4
+ content: 'PRO';
5
+ background: #ff5722;
6
+ border-radius: 4px;
7
+ color: #fff;
8
+ font-size: 10px;
9
+ line-height: 1;
10
+ font-style: normal;
11
+ padding: 4px 6px;
12
+ margin-left: 4px;
13
+ vertical-align: top;
14
+ top: -8px;
15
+ right: 0;
16
+ z-index: 11;
17
+ }
admin/assets/css/sweetalert-custom.css CHANGED
@@ -1,156 +1,155 @@
1
- /* Sub Layer */
2
- body[class*="_rio"] .swal2-container.swal2-shown {
3
- background: rgba(16, 17, 21, 0.9);
4
- z-index: 100000;
5
- }
6
- .wrio-modal {
7
- padding: 0 !important;
8
- }
9
- .wrio-modal .swal2-close {
10
- color: rgba(0, 0, 0, 0.8);
11
- }
12
- .wrio-modal .swal2-modal {
13
- border-radius: 2px;
14
- }
15
- .wrio-modal .swal2-icon {
16
- margin-bottom: 25px;
17
- }
18
- .wrio-modal .swal2-title {
19
- margin: 0;
20
- padding: 28px 32px;
21
- font-size: 24px;
22
- text-align: left;
23
- color: #fff !important;
24
- background: #3e3e3e !important;
25
- }
26
- .wrio-modal .swal2-content {
27
- font-size: 14px;
28
- padding: 28px 32px;
29
- background: #efefef;
30
- }
31
- .wrio-modal .swal2-buttonswrapper {
32
- margin-top: 0;
33
- padding: 22px;
34
- background: #F4F7F9;
35
- }
36
- .wrio-modal .swal2-buttonswrapper a.button svg {
37
- margin-right: 12px;
38
- vertical-align: -2px;
39
- }
40
- .wrio-modal .swal2-buttonswrapper button.loading {
41
- border-radius: 100% !important;
42
- height: 40px !important;
43
- padding: 0 !important;
44
- box-shadow: none !important;
45
- }
46
- .wrio-modal .swal2-buttonswrapper button.swal2-styled {
47
- height: auto;
48
- padding: 12px 32px;
49
- margin: 10px;
50
- font-size: 14px;
51
- letter-spacing: 1px;
52
- text-transform: uppercase;
53
- border-radius: 3px;
54
- font-weight: bold;
55
- outline: none;
56
- }
57
- .wrio-modal .swal2-buttonswrapper button.swal2-styled.swal2-confirm {
58
- background-color: #fdd599 !important;
59
- text-shadow: none !important;
60
- box-shadow: 0 3px 0 #ceac7a !important;
61
- color: #a57b3c !important;
62
- }
63
- .wrio-modal .swal2-buttonswrapper button.swal2-styled.swal2-cancel {
64
- background-color: #d2d2d2 !important;
65
- color: #656464 !important;
66
- text-shadow: none !important;
67
- box-shadow: 0 3px 0 #a9a9a9;
68
- /*background-color: #c9deb2 !important;
69
- color: #606956 !important;
70
- text-shadow: none !important;
71
- box-shadow: 0 3px 0 #a7b994;*/
72
- }
73
- .wrio-modal .swal2-buttonswrapper button.swal2-styled:focus,
74
- .wrio-modal .swal2-buttonswrapper button.swal2-styled:hover {
75
- outline: none;
76
- text-shadow: none;
77
- color: #FFF;
78
- }
79
- .wrio-modal-warning {
80
- background: #FF5722 !important;
81
- }
82
- .wrio-modal-warning .swal2-title {
83
- text-align: center;
84
- color: #222 !important;
85
- background: #efefef !important;
86
- }
87
- .wrio-modal-warning .swal2-content {
88
- font-size: 16px;
89
- padding: 10px 20px 32px;
90
- background: #efefef;
91
- }
92
- .wrio-modal-warning .swal2-buttonswrapper {
93
- background: #efefef;
94
- }
95
- .wrio-modal-error {
96
- background: #dec2c0 !important;
97
- }
98
- .wrio-modal-error .swal2-title {
99
- text-align: center;
100
- color: #222 !important;
101
- background: #efefef !important;
102
- }
103
- .wrio-modal-error .swal2-content {
104
- font-size: 16px;
105
- padding: 10px 20px 32px;
106
- background: #efefef;
107
- }
108
- .wrio-modal-error .swal2-buttonswrapper {
109
- background: #efefef;
110
- }
111
- .wrio-modal-optimization-way {
112
- background: #1F2332 !important;
113
- }
114
- .wrio-modal-optimization-way .wrio-swal-subtitle {
115
- padding: 0 0 28px;
116
- margin-top: 0px;
117
- font-weight: 500;
118
- font-size: 18px;
119
- text-align: left;
120
- color: #8c8888;
121
- background: #efefef;
122
- }
123
- .wrio-modal-optimization-way .wrio-list-infos {
124
- margin: 0;
125
- padding: 0;
126
- }
127
- .wrio-modal-optimization-way .wrio-list-infos li {
128
- display: flex;
129
- align-items: center;
130
- padding: 15px 5px;
131
- text-align: left;
132
- font-size: 14px;
133
- line-height: 1.5;
134
- color: #8c8888;
135
- }
136
- .wrio-modal-optimization-way .wrio-list-infos li:first-child {
137
- padding-top: 5px;
138
- }
139
- .wrio-modal-optimization-way .wrio-list-infos li:last-child {
140
- padding-bottom: 5px;
141
- }
142
- .wrio-modal-optimization-way .wrio-list-infos li + li {
143
- border-top: 1px solid #E9EFF2;
144
- }
145
- .wrio-modal-optimization-way .wrio-list-infos a:before {
146
- content: '';
147
- display: block;
148
- }
149
- .wrio-modal-optimization-way .wrio-info-icon {
150
- flex-grow: 0;
151
- flex-basis: 50px;
152
- }
153
- .wrio-modal-optimization-way .wrio-info-icon + span {
154
- padding-left: 20px;
155
- }
156
- /*# sourceMappingURL=sweetalert-custom.css.map */
1
+ /* Sub Layer */
2
+ body[class*="_rio"] .swal2-container.swal2-shown {
3
+ background: rgba(16, 17, 21, 0.9);
4
+ z-index: 100000;
5
+ }
6
+ .wrio-modal {
7
+ padding: 0 !important;
8
+ }
9
+ .wrio-modal .swal2-close {
10
+ color: rgba(0, 0, 0, 0.8);
11
+ }
12
+ .wrio-modal .swal2-modal {
13
+ border-radius: 2px;
14
+ }
15
+ .wrio-modal .swal2-icon {
16
+ margin-bottom: 25px;
17
+ }
18
+ .wrio-modal .swal2-title {
19
+ margin: 0;
20
+ padding: 28px 32px;
21
+ font-size: 24px;
22
+ text-align: left;
23
+ color: #fff !important;
24
+ background: #3e3e3e !important;
25
+ }
26
+ .wrio-modal .swal2-content {
27
+ font-size: 14px;
28
+ padding: 28px 32px;
29
+ background: #efefef;
30
+ }
31
+ .wrio-modal .swal2-buttonswrapper {
32
+ margin-top: 0;
33
+ padding: 22px;
34
+ background: #F4F7F9;
35
+ }
36
+ .wrio-modal .swal2-buttonswrapper a.button svg {
37
+ margin-right: 12px;
38
+ vertical-align: -2px;
39
+ }
40
+ .wrio-modal .swal2-buttonswrapper button.loading {
41
+ border-radius: 100% !important;
42
+ height: 40px !important;
43
+ padding: 0 !important;
44
+ box-shadow: none !important;
45
+ }
46
+ .wrio-modal .swal2-buttonswrapper button.swal2-styled {
47
+ height: auto;
48
+ padding: 12px 32px;
49
+ margin: 10px;
50
+ font-size: 14px;
51
+ letter-spacing: 1px;
52
+ text-transform: uppercase;
53
+ border-radius: 3px;
54
+ font-weight: bold;
55
+ outline: none;
56
+ }
57
+ .wrio-modal .swal2-buttonswrapper button.swal2-styled.swal2-confirm {
58
+ background-color: #fdd599 !important;
59
+ text-shadow: none !important;
60
+ box-shadow: 0 3px 0 #ceac7a !important;
61
+ color: #a57b3c !important;
62
+ }
63
+ .wrio-modal .swal2-buttonswrapper button.swal2-styled.swal2-cancel {
64
+ background-color: #d2d2d2 !important;
65
+ color: #656464 !important;
66
+ text-shadow: none !important;
67
+ box-shadow: 0 3px 0 #a9a9a9;
68
+ /*background-color: #c9deb2 !important;
69
+ color: #606956 !important;
70
+ text-shadow: none !important;
71
+ box-shadow: 0 3px 0 #a7b994;*/
72
+ }
73
+ .wrio-modal .swal2-buttonswrapper button.swal2-styled:focus,
74
+ .wrio-modal .swal2-buttonswrapper button.swal2-styled:hover {
75
+ outline: none;
76
+ text-shadow: none;
77
+ color: #FFF;
78
+ }
79
+ .wrio-modal-warning {
80
+ background: #FF5722 !important;
81
+ }
82
+ .wrio-modal-warning .swal2-title {
83
+ text-align: center;
84
+ color: #222 !important;
85
+ background: #efefef !important;
86
+ }
87
+ .wrio-modal-warning .swal2-content {
88
+ font-size: 16px;
89
+ padding: 10px 20px 32px;
90
+ background: #efefef;
91
+ }
92
+ .wrio-modal-warning .swal2-buttonswrapper {
93
+ background: #efefef;
94
+ }
95
+ .wrio-modal-error {
96
+ background: #dec2c0 !important;
97
+ }
98
+ .wrio-modal-error .swal2-title {
99
+ text-align: center;
100
+ color: #222 !important;
101
+ background: #efefef !important;
102
+ }
103
+ .wrio-modal-error .swal2-content {
104
+ font-size: 16px;
105
+ padding: 10px 20px 32px;
106
+ background: #efefef;
107
+ }
108
+ .wrio-modal-error .swal2-buttonswrapper {
109
+ background: #efefef;
110
+ }
111
+ .wrio-modal-optimization-way {
112
+ background: #1F2332 !important;
113
+ }
114
+ .wrio-modal-optimization-way .wrio-swal-subtitle {
115
+ padding: 0 0 28px;
116
+ margin-top: 0px;
117
+ font-weight: 500;
118
+ font-size: 18px;
119
+ text-align: left;
120
+ color: #8c8888;
121
+ background: #efefef;
122
+ }
123
+ .wrio-modal-optimization-way .wrio-list-infos {
124
+ margin: 0;
125
+ padding: 0;
126
+ }
127
+ .wrio-modal-optimization-way .wrio-list-infos li {
128
+ display: flex;
129
+ align-items: center;
130
+ padding: 15px 5px;
131
+ text-align: left;
132
+ font-size: 14px;
133
+ line-height: 1.5;
134
+ color: #8c8888;
135
+ }
136
+ .wrio-modal-optimization-way .wrio-list-infos li:first-child {
137
+ padding-top: 5px;
138
+ }
139
+ .wrio-modal-optimization-way .wrio-list-infos li:last-child {
140
+ padding-bottom: 5px;
141
+ }
142
+ .wrio-modal-optimization-way .wrio-list-infos li + li {
143
+ border-top: 1px solid #E9EFF2;
144
+ }
145
+ .wrio-modal-optimization-way .wrio-list-infos a:before {
146
+ content: '';
147
+ display: block;
148
+ }
149
+ .wrio-modal-optimization-way .wrio-info-icon {
150
+ flex-grow: 0;
151
+ flex-basis: 50px;
152
+ }
153
+ .wrio-modal-optimization-way .wrio-info-icon + span {
154
+ padding-left: 20px;
155
+ }
 
admin/assets/js/Chart.min.js CHANGED
@@ -1,10 +1,10 @@
1
  /*!
2
  * Chart.js
3
  * http://chartjs.org/
4
- * Version: 2.7.2
5
  *
6
- * Copyright 2018 Chart.js Contributors
7
  * Released under the MIT license
8
  * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
  */
10
- !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,i,n){function a(r,s){if(!i[r]){if(!e[r]){var l="function"==typeof require&&require;if(!s&&l)return l(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return a(i||t)},d,d.exports,t,e,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;r<n.length;r++)a(n[r]);return a}({1:[function(t,e,i){},{}],2:[function(t,e,i){var n=t(6);function a(t){if(t){var e=[0,0,0],i=1,a=t.match(/^#([a-fA-F0-9]{3})$/i);if(a){a=a[1];for(var o=0;o<e.length;o++)e[o]=parseInt(a[o]+a[o],16)}else if(a=t.match(/^#([a-fA-F0-9]{6})$/i)){a=a[1];for(o=0;o<e.length;o++)e[o]=parseInt(a.slice(2*o,2*o+2),16)}else if(a=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(o=0;o<e.length;o++)e[o]=parseInt(a[o+1]);i=parseFloat(a[4])}else if(a=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(o=0;o<e.length;o++)e[o]=Math.round(2.55*parseFloat(a[o+1]));i=parseFloat(a[4])}else if(a=t.match(/(\w+)/)){if("transparent"==a[1])return[0,0,0,0];if(!(e=n[a[1]]))return}for(o=0;o<e.length;o++)e[o]=d(e[o],0,255);return i=i||0==i?d(i,0,1):1,e[3]=i,e}}function o(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var i=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(i)?1:i,0,1)]}}}function r(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var i=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(i)?1:i,0,1)]}}}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function u(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function d(t,e,i){return Math.min(Math.max(e,t),i)}function c(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}e.exports={getRgba:a,getHsla:o,getRgb:function(t){var e=a(t);return e&&e.slice(0,3)},getHsl:function(t){var e=o(t);return e&&e.slice(0,3)},getHwb:r,getAlpha:function(t){var e=a(t);{if(e)return e[3];if(e=o(t))return e[3];if(e=r(t))return e[3]}},hexString:function(t){return"#"+c(t[0])+c(t[1])+c(t[2])},rgbString:function(t,e){if(e<1||t[3]&&t[3]<1)return s(t,e);return"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:s,percentString:function(t,e){if(e<1||t[3]&&t[3]<1)return l(t,e);var i=Math.round(t[0]/255*100),n=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+i+"%, "+n+"%, "+a+"%)"},percentaString:l,hslString:function(t,e){if(e<1||t[3]&&t[3]<1)return u(t,e);return"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:u,hwbString:function(t,e){void 0===e&&(e=void 0!==t[3]?t[3]:1);return"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in n)h[n[f]]=f},{6:6}],3:[function(t,e,i){var n=t(5),a=t(2),o=function(t){return t instanceof o?t:this instanceof o?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new o(t);var e};o.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],i=0;i<t.length;i++){var n=t[i]/255;e[i]=n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),i=t.luminosity();return e>i?(e+.05)/(i+.05):(i+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,i=(e[0]+t)%360;return e[0]=i<0?360+i:i,this.setValues("hsl",e),this},mix:function(t,e){var i=this,n=t,a=void 0===e?.5:e,o=2*a-1,r=i.alpha()-n.alpha(),s=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,l=1-s;return this.rgb(s*i.red()+l*n.red(),s*i.green()+l*n.green(),s*i.blue()+l*n.blue()).alpha(i.alpha()*a+n.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,i=new o,n=this.values,a=i.values;for(var r in n)n.hasOwnProperty(r)&&(t=n[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return i}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,i={},n=0;n<t.length;n++)i[t.charAt(n)]=e[t][n];return 1!==e.alpha&&(i.a=e.alpha),i},o.prototype.setValues=function(t,e){var i,a,o=this.values,r=this.spaces,s=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)o[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(i=0;i<t.length;i++)o[t][i]=e[t.charAt(i)];l=e.a}else if(void 0!==e[r[t][0]]){var u=r[t];for(i=0;i<t.length;i++)o[t][i]=e[u[i]];l=e.alpha}if(o.alpha=Math.max(0,Math.min(1,void 0===l?o.alpha:l)),"alpha"===t)return!1;for(i=0;i<t.length;i++)a=Math.max(0,Math.min(s[t][i],o[t][i])),o[t][i]=Math.round(a);for(var d in r)d!==t&&(o[d]=n[t][d](o[t]));return!0},o.prototype.setSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i),this)},o.prototype.setChannel=function(t,e,i){var n=this.values[t];return void 0===i?n[e]:i===n[e]?this:(n[e]=i,this.setValues(t,n),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,i){function n(t){var e,i,n=t[0]/255,a=t[1]/255,o=t[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r;return s==r?e=0:n==s?e=(a-o)/l:a==s?e=2+(o-n)/l:o==s&&(e=4+(n-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),i=(r+s)/2,[e,100*(s==r?0:i<=.5?l/(s+r):l/(2-s-r)),100*i]}function a(t){var e,i,n=t[0],a=t[1],o=t[2],r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r;return i=0==s?0:l/s*1e3/10,s==r?e=0:n==s?e=(a-o)/l:a==s?e=2+(o-n)/l:o==s&&(e=4+(n-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),[e,i,s/255*1e3/10]}function o(t){var e=t[0],i=t[1],a=t[2];return[n(t)[0],100*(1/255*Math.min(e,Math.min(i,a))),100*(a=1-1/255*Math.max(e,Math.max(i,a)))]}function s(t){var e,i=t[0]/255,n=t[1]/255,a=t[2]/255;return[100*((1-i-(e=Math.min(1-i,1-n,1-a)))/(1-e)||0),100*((1-n-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]}function l(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,i=t[1]/255,n=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)+.1805*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)),100*(.2126*e+.7152*i+.0722*n),100*(.0193*e+.1192*i+.9505*n)]}function d(t){var e=u(t),i=e[0],n=e[1],a=e[2];return n/=100,a/=108.883,i=(i/=95.047)>.008856?Math.pow(i,1/3):7.787*i+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(i-n),200*(n-(a=a>.008856?Math.pow(a,1/3):7.787*a+16/116))]}function c(t){var e,i,n,a,o,r=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return[o=255*l,o,o];e=2*l-(i=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(n=r+1/3*-(u-1))<0&&n++,n>1&&n--,o=6*n<1?e+6*(i-e)*n:2*n<1?i:3*n<2?e+(i-e)*(2/3-n)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,i=t[1]/100,n=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*n*(1-i),s=255*n*(1-i*o),l=255*n*(1-i*(1-o));n*=255;switch(a){case 0:return[n,l,r];case 1:return[s,n,r];case 2:return[r,n,l];case 3:return[r,s,n];case 4:return[l,r,n];case 5:return[n,r,s]}}function f(t){var e,i,n,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),n=6*o-(e=Math.floor(6*o)),0!=(1&e)&&(n=1-n),a=s+n*((i=1-l)-s),e){default:case 6:case 0:r=i,g=a,b=s;break;case 1:r=a,g=i,b=s;break;case 2:r=s,g=i,b=a;break;case 3:r=s,g=a,b=i;break;case 4:r=a,g=s,b=i;break;case 5:r=i,g=s,b=a}return[255*r,255*g,255*b]}function p(t){var e=t[0]/100,i=t[1]/100,n=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,i*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a))]}function m(t){var e,i,n,a=t[0]/100,o=t[1]/100,r=t[2]/100;return i=-.9689*a+1.8758*o+.0415*r,n=.0557*a+-.204*o+1.057*r,e=(e=3.2406*a+-1.5372*o+-.4986*r)>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,[255*(e=Math.min(Math.max(0,e),1)),255*(i=Math.min(Math.max(0,i),1)),255*(n=Math.min(Math.max(0,n),1))]}function v(t){var e=t[0],i=t[1],n=t[2];return i/=100,n/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(e-i),200*(i-(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116))]}function x(t){var e,i,n,a,o=t[0],r=t[1],s=t[2];return o<=8?a=(i=100*o/903.3)/100*7.787+16/116:(i=100*Math.pow((o+16)/116,3),a=Math.pow(i/100,1/3)),[e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i,n=n/108.883<=.008859?n=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3)]}function y(t){var e,i=t[0],n=t[1],a=t[2];return(e=360*Math.atan2(a,n)/2/Math.PI)<0&&(e+=360),[i,Math.sqrt(n*n+a*a),e]}function k(t){return m(x(t))}function M(t){var e,i=t[0],n=t[1];return e=t[2]/360*2*Math.PI,[i,n*Math.cos(e),n*Math.sin(e)]}function w(t){return S[t]}e.exports={rgb2hsl:n,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e=t[0],i=t[1]/100,n=t[2]/100;if(0===n)return[0,0,0];return[e,100*(2*(i*=(n*=2)<=1?n:2-n)/(n+i)),100*((n+i)/2)]},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,i,n=t[0],a=t[1]/100,o=t[2]/100;return e=a*o,[n,100*(e=(e/=(i=(2-a)*o)<=1?i:2-i)||0),100*(i/=2)]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return n(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return n(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return l(p(t))},keyword2rgb:w,keyword2hsl:function(t){return n(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:m,xyz2lab:v,xyz2lch:function(t){return y(v(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:M,lch2xyz:function(t){return x(M(t))},lch2rgb:function(t){return k(M(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,i){var n=t(4),a=function(){return new u};for(var o in n){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),n[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),s=r[1],l=r[2];(a[s]=a[s]||{})[l]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var i=n[t](e);if("string"==typeof i||void 0===i)return i;for(var a=0;a<i.length;a++)i[a]=Math.round(i[a]);return i}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var i=this.space,n=this.convs[i];e=a[i][t](n),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,i){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,i){var n=t(29)();n.helpers=t(45),t(27)(n),n.defaults=t(25),n.Element=t(26),n.elements=t(40),n.Interaction=t(28),n.layouts=t(30),n.platform=t(48),n.plugins=t(31),n.Ticks=t(34),t(22)(n),t(23)(n),t(24)(n),t(33)(n),t(32)(n),t(35)(n),t(55)(n),t(53)(n),t(54)(n),t(56)(n),t(57)(n),t(58)(n),t(15)(n),t(16)(n),t(17)(n),t(18)(n),t(19)(n),t(20)(n),t(21)(n),t(8)(n),t(9)(n),t(10)(n),t(11)(n),t(12)(n),t(13)(n),t(14)(n);var a=t(49);for(var o in a)a.hasOwnProperty(o)&&n.plugins.register(a[o]);n.platform.initialize(),e.exports=n,"undefined"!=typeof window&&(window.Chart=n),n.Legend=a.legend._element,n.Title=a.title._element,n.pluginService=n.plugins,n.PluginBase=n.Element.extend({}),n.canvasHelpers=n.helpers.canvas,n.layoutService=n.layouts},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,40:40,45:45,48:48,49:49,53:53,54:54,55:55,56:56,57:57,58:58,8:8,9:9}],8:[function(t,e,i){"use strict";e.exports=function(t){t.Bar=function(e,i){return i.type="bar",new t(e,i)}}},{}],9:[function(t,e,i){"use strict";e.exports=function(t){t.Bubble=function(e,i){return i.type="bubble",new t(e,i)}}},{}],10:[function(t,e,i){"use strict";e.exports=function(t){t.Doughnut=function(e,i){return i.type="doughnut",new t(e,i)}}},{}],11:[function(t,e,i){"use strict";e.exports=function(t){t.Line=function(e,i){return i.type="line",new t(e,i)}}},{}],12:[function(t,e,i){"use strict";e.exports=function(t){t.PolarArea=function(e,i){return i.type="polarArea",new t(e,i)}}},{}],13:[function(t,e,i){"use strict";e.exports=function(t){t.Radar=function(e,i){return i.type="radar",new t(e,i)}}},{}],14:[function(t,e,i){"use strict";e.exports=function(t){t.Scatter=function(e,i){return i.type="scatter",new t(e,i)}}},{}],15:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),n._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var i="";return t.length>0&&(t[0].yLabel?i=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e;t.DatasetController.prototype.initialize.apply(this,arguments),(e=this.getMeta()).stack=this.getDataset().stack,e.bar=!0},update:function(t){var e,i,n=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,i=n.length;e<i;++e)this.updateElement(n[e],e,t)},updateElement:function(t,e,i){var n=this,a=n.chart,r=n.getMeta(),s=n.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=n.getScaleForId(r.xAxisID),t._yScale=n.getScaleForId(r.yAxisID),t._datasetIndex=n.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:o.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:o.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:o.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},n.updateElementGeometry(t,e,i),t.pivot()},updateElementGeometry:function(t,e,i){var n=this,a=t._model,o=n.getValueScale(),r=o.getBasePixel(),s=o.isHorizontal(),l=n._ruler||n.getRuler(),u=n.calculateBarValuePixels(n.index,e),d=n.calculateBarIndexPixels(n.index,e,l);a.horizontal=s,a.base=i?r:u.base,a.x=s?i?r:u.head:d.center,a.y=s?d.center:i?r:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},_getStacks:function(t){var e,i,n=this.chart,a=this.getIndexScale().options.stacked,o=void 0===t?n.data.datasets.length:t+1,r=[];for(e=0;e<o;++e)(i=n.getDatasetMeta(e)).bar&&n.isDatasetVisible(e)&&(!1===a||!0===a&&-1===r.indexOf(i.stack)||void 0===a&&(void 0===i.stack||-1===r.indexOf(i.stack)))&&r.push(i.stack);return r},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var i=this._getStacks(t),n=void 0!==e?i.indexOf(e):-1;return-1===n?i.length-1:n},getRuler:function(){var t,e,i=this.getIndexScale(),n=this.getStackCount(),a=this.index,r=i.isHorizontal(),s=r?i.left:i.top,l=s+(r?i.width:i.height),u=[];for(t=0,e=this.getMeta().data.length;t<e;++t)u.push(i.getPixelForValue(null,t,a));return{min:o.isNullOrUndef(i.options.barThickness)?function(t,e){var i,n,a,o,r=t.isHorizontal()?t.width:t.height,s=t.getTicks();for(a=1,o=e.length;a<o;++a)r=Math.min(r,e[a]-e[a-1]);for(a=0,o=s.length;a<o;++a)n=t.getPixelForTick(a),r=a>0?Math.min(r,n-i):r,i=n;return r}(i,u):-1,pixels:u,start:s,end:l,stackCount:n,scale:i}},calculateBarValuePixels:function(t,e){var i,n,a,o,r,s,l=this.chart,u=this.getMeta(),d=this.getValueScale(),c=l.data.datasets,h=d.getRightValue(c[t].data[e]),f=d.options.stacked,g=u.stack,p=0;if(f||void 0===f&&void 0!==g)for(i=0;i<t;++i)(n=l.getDatasetMeta(i)).bar&&n.stack===g&&n.controller.getValueScaleId()===d.id&&l.isDatasetVisible(i)&&(a=d.getRightValue(c[i].data[e]),(h<0&&a<0||h>=0&&a>0)&&(p+=a));return o=d.getPixelForValue(p),{size:s=((r=d.getPixelForValue(p+h))-o)/2,base:o,head:r,center:r+s/2}},calculateBarIndexPixels:function(t,e,i){var n,a,r,s,l,u,d,c,h,f,g,p,m,v,b,x,y,k=i.scale.options,M="flex"===k.barThickness?(h=e,g=k,m=(f=i).pixels,v=m[h],b=h>0?m[h-1]:null,x=h<m.length-1?m[h+1]:null,y=g.categoryPercentage,null===b&&(b=v-(null===x?f.end-v:x-v)),null===x&&(x=v+v-b),p=v-(v-b)/2*y,{chunk:(x-b)/2*y/f.stackCount,ratio:g.barPercentage,start:p}):(n=e,a=i,u=(r=k).barThickness,d=a.stackCount,c=a.pixels[n],o.isNullOrUndef(u)?(s=a.min*r.categoryPercentage,l=r.barPercentage):(s=u*d,l=1),{chunk:s/d,ratio:l,start:c-s/2}),w=this.getStackIndex(t,this.getMeta().stack),S=M.start+M.chunk*w+M.chunk/2,C=Math.min(o.valueOrDefault(k.maxBarThickness,1/0),M.chunk*M.ratio);return{base:S-C/2,head:S+C/2,center:S,size:C}},draw:function(){var t=this.chart,e=this.getValueScale(),i=this.getMeta().data,n=this.getDataset(),a=i.length,r=0;for(o.canvas.clipArea(t.ctx,t.chartArea);r<a;++r)isNaN(e.getRightValue(n.data[r]))||i[r].draw();o.canvas.unclipArea(t.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model;a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.hoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.hoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.hoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model,r=this.chart.options.elements.rectangle;a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.backgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.borderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.borderWidth,i,r.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"",n=e.datasets[t.datasetIndex].data[t.index];return i+": ("+t.xLabel+", "+t.yLabel+", "+n.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,i=e.getMeta().data;o.each(i,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){var n=this,a=n.getMeta(),o=t.custom||{},r=n.getScaleForId(a.xAxisID),s=n.getScaleForId(a.yAxisID),l=n._resolveElementOptions(t,e),u=n.getDataset().data[e],d=n.index,c=i?r.getPixelForDecimal(.5):r.getPixelForValue("object"==typeof u?u:NaN,e,d),h=i?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=r,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,radius:i?0:l.radius,skip:o.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,i=t._options;e.backgroundColor=o.valueOrDefault(i.hoverBackgroundColor,o.getHoverColor(i.backgroundColor)),e.borderColor=o.valueOrDefault(i.hoverBorderColor,o.getHoverColor(i.borderColor)),e.borderWidth=o.valueOrDefault(i.hoverBorderWidth,i.borderWidth),e.radius=i.radius+i.hoverRadius},removeHoverStyle:function(t){var e=t._model,i=t._options;e.backgroundColor=i.backgroundColor,e.borderColor=i.borderColor,e.borderWidth=i.borderWidth,e.radius=i.radius},_resolveElementOptions:function(t,e){var i,n,a,r=this.chart,s=r.data.datasets[this.index],l=t.custom||{},u=r.options.elements.point,d=o.options.resolve,c=s.data[e],h={},f={chart:r,dataIndex:e,dataset:s,datasetIndex:this.index},g=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(i=0,n=g.length;i<n;++i)h[a=g[i]]=d([l[a],s[a],u[a]],f,e);return h.radius=d([l.radius,c?c.r:void 0,s.radius,u.radius],f,e),h}})}},{25:25,40:40,45:45}],17:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(i,n){var a=t.getDatasetMeta(0),r=e.datasets[0],s=a.data[n],l=s&&s.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:i,fillStyle:l.backgroundColor?l.backgroundColor:u(r.backgroundColor,n,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(r.borderColor,n,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(r.borderWidth,n,d.borderWidth),hidden:isNaN(r.data[n])||a.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;i<n;++i)(a=r.getDatasetMeta(i)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var i=e.labels[t.index],n=": "+e.datasets[t.datasetIndex].data[t.index];return o.isArray(i)?(i=i.slice())[0]+=n:i+=n,i}}}}),n._set("pie",o.clone(n.doughnut)),n._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,getRingIndex:function(t){for(var e=0,i=0;i<t;++i)this.chart.isDatasetVisible(i)&&++e;return e},update:function(t){var e=this,i=e.chart,n=i.chartArea,a=i.options,r=a.elements.arc,s=n.right-n.left-r.borderWidth,l=n.bottom-n.top-r.borderWidth,u=Math.min(s,l),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,m=Math.cos(g),v=Math.sin(g),b=Math.cos(p),x=Math.sin(p),y=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,k=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,M=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,w=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,S=h/100,C=M?-1:Math.min(m*(m<0?1:S),b*(b<0?1:S)),_=w?-1:Math.min(v*(v<0?1:S),x*(x<0?1:S)),D=y?1:Math.max(m*(m>0?1:S),b*(b>0?1:S)),I=k?1:Math.max(v*(v>0?1:S),x*(x>0?1:S)),P=.5*(D-C),A=.5*(I-_);u=Math.min(s/P,l/A),d={x:-.5*(D+C),y:-.5*(I+_)}}i.borderWidth=e.getMaxBorderWidth(c.data),i.outerRadius=Math.max((u-i.borderWidth)/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:0,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=d.x*i.outerRadius,i.offsetY=d.y*i.outerRadius,c.total=e.calculateTotal(),e.outerRadius=i.outerRadius-i.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-i.radiusLength,0),o.each(c.data,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){var n=this,a=n.chart,r=a.chartArea,s=a.options,l=s.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=s.rotation,h=s.rotation,f=n.getDataset(),g=i&&l.animateRotate?0:t.hidden?0:n.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),p=i&&l.animateScale?0:n.innerRadius,m=i&&l.animateScale?0:n.outerRadius,v=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:n.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:v(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),i&&l.animateRotate||(b.startAngle=0===e?s.rotation:n.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),i=this.getMeta(),n=0;return o.each(i.data,function(i,a){t=e.data[a],isNaN(t)||i.hidden||(n+=Math.abs(t))}),n},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){for(var e,i,n=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,n=(i=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0)>(n=e>n?e:n)?i:n;return n}})}},{25:25,40:40,45:45}],18:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var i,n,a,r=this,s=r.getMeta(),l=s.dataset,u=s.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(s.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=r.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),i=0,n=u.length;i<n;++i)r.updateElement(u[i],i,t);for(g&&0!==l._model.tension&&r.updateBezierControlPoints(),i=0,n=u.length;i<n;++i)u[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,n=this.getDataset(),a=t.custom||{};return a.backgroundColor?i=a.backgroundColor:n.pointBackgroundColor?i=o.valueAtIndexOrDefault(n.pointBackgroundColor,e,i):n.backgroundColor&&(i=n.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,n=this.getDataset(),a=t.custom||{};return a.borderColor?i=a.borderColor:n.pointBorderColor?i=o.valueAtIndexOrDefault(n.pointBorderColor,e,i):n.borderColor&&(i=n.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,n=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(n.pointBorderWidth)||o.isArray(n.pointBorderWidth)?i=o.valueAtIndexOrDefault(n.pointBorderWidth,e,i):isNaN(n.borderWidth)||(i=n.borderWidth):i=a.borderWidth,i},updateElement:function(t,e,i){var n,a,r=this,s=r.getMeta(),l=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(s.yAxisID),f=r.getScaleForId(s.xAxisID),g=r.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),n=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=i?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:n,y:a,skip:l.skip||isNaN(n)||isNaN(a),radius:l.radius||o.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||o.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||o.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,i){var n,a,o,r=this.chart,s=this.getMeta(),l=this.getScaleForId(s.yAxisID),u=0,d=0;if(l.options.stacked){for(n=0;n<i;n++)if(a=r.data.datasets[n],"line"===(o=r.getDatasetMeta(n)).type&&o.yAxisID===l.id&&r.isDatasetVisible(n)){var c=Number(l.getRightValue(a.data[e]));c<0?d+=c||0:u+=c||0}var h=Number(l.getRightValue(t));return h<0?l.getPixelForValue(d+h):l.getPixelForValue(u+h)}return l.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,i,n,a=this.getMeta(),r=this.chart.chartArea,s=a.data||[];function l(t,e,i){return Math.max(Math.min(t,i),e)}if(a.dataset._model.spanGaps&&(s=s.filter(function(t){return!t._model.skip})),"monotone"===a.dataset._model.cubicInterpolationMode)o.splineCurveMonotone(s);else for(t=0,e=s.length;t<e;++t)i=s[t]._model,n=o.splineCurve(o.previousItem(s,t)._model,i,o.nextItem(s,t)._model,a.dataset._model.tension),i.controlPointPreviousX=n.previous.x,i.controlPointPreviousY=n.previous.y,i.controlPointNextX=n.next.x,i.controlPointNextY=n.next.y;if(this.chart.options.elements.line.capBezierPoints)for(t=0,e=s.length;t<e;++t)(i=s[t]._model).controlPointPreviousX=l(i.controlPointPreviousX,r.left,r.right),i.controlPointPreviousY=l(i.controlPointPreviousY,r.top,r.bottom),i.controlPointNextX=l(i.controlPointNextX,r.left,r.right),i.controlPointNextY=l(i.controlPointNextY,r.top,r.bottom)},draw:function(){var t=this.chart,i=this.getMeta(),n=i.data||[],a=t.chartArea,r=n.length,s=0;for(o.canvas.clipArea(t.ctx,a),e(this.getDataset(),t.options)&&i.dataset.draw(),o.canvas.unclipArea(t.ctx);s<r;++s)n[s].draw(a)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model;a.radius=n.hoverRadius||o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor||o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor||o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth||o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),r.radius=a.radius||o.valueAtIndexOrDefault(i.pointRadius,n,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,n),r.borderColor=e.getPointBorderColor(t,n),r.borderWidth=e.getPointBorderWidth(t,n)}})}},{25:25,40:40,45:45}],19:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(i,n){var a=t.getDatasetMeta(0),r=e.datasets[0],s=a.data[n].custom||{},l=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:i,fillStyle:s.backgroundColor?s.backgroundColor:l(r.backgroundColor,n,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(r.borderColor,n,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(r.borderWidth,n,u.borderWidth),hidden:isNaN(r.data[n])||a.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;i<n;++i)(a=r.getDatasetMeta(i)).data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,update:function(t){var e=this,i=e.chart,n=i.chartArea,a=e.getMeta(),r=i.options,s=r.elements.arc,l=Math.min(n.right-n.left,n.bottom-n.top);i.outerRadius=Math.max((l-s.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),e.outerRadius=i.outerRadius-i.radiusLength*e.index,e.innerRadius=e.outerRadius-i.radiusLength,a.count=e.countVisibleElements(),o.each(a.data,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){for(var n=this,a=n.chart,r=n.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,c=n.calculateCircumference(r.data[e]),h=u.xCenter,f=u.yCenter,g=0,p=n.getMeta(),m=0;m<e;++m)isNaN(r.data[m])||p.data[m].hidden||++g;var v=s.startAngle,b=t.hidden?0:u.getDistanceFromCenterForValue(r.data[e]),x=v+c*g,y=x+(t.hidden?0:c),k=l.animateScale?0:u.getDistanceFromCenterForValue(r.data[e]);o.extend(t,{_datasetIndex:n.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:i?k:b,startAngle:i&&l.animateRotate?v:x,endAngle:i&&l.animateRotate?v:y,label:o.valueAtIndexOrDefault(d,e,d[e])}}),n.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),i=0;return o.each(e.data,function(e,n){isNaN(t.data[n])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,i=e.getMeta(),n=i.dataset,a=i.data,r=n.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),o.extend(i.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(s.lineTension,l.tension),backgroundColor:r.backgroundColor?r.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:s.borderWidth||l.borderWidth,borderColor:r.borderColor?r.borderColor:s.borderColor||l.borderColor,fill:r.fill?r.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:r.borderDash?r.borderDash:s.borderDash||l.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),i.dataset.pivot(),o.each(a,function(i,n){e.updateElement(i,n,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,i){var n=this,a=t.custom||{},r=n.getDataset(),s=n.chart.scale,l=n.chart.options.elements.point,u=s.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:n.index,_index:e,_scale:s,_model:{x:i?s.xCenter:u.x,y:i?s.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,n.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(i,n){var a=i._model,r=o.splineCurve(o.previousItem(e.data,n,!0)._model,a,o.nextItem(e.data,n,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,a=t._model;a.radius=i.hoverRadius?i.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=i.radius?i.radius:o.valueAtIndexOrDefault(e.pointRadius,n,r.radius),a.backgroundColor=i.backgroundColor?i.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,n,r.backgroundColor),a.borderColor=i.borderColor?i.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,n,r.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,n,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,i){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,i,n){var a,o,r=this.animations;for(e.chart=t,n||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=o.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=o.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),i=0;t.dropFrames>1&&(i=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+i);var n=Date.now();t.dropFrames+=(n-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,i,n=this.animations,a=0;a<n.length;)i=(e=n[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),o.callback(e.render,[i,e],i),o.callback(e.onAnimationProgress,[e],i),e.currentStep>=e.numSteps?(o.callback(e.onAnimationComplete,[e],i),i.animating=!1,n.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(28),r=t(30),s=t(48),l=t(31);e.exports=function(t){function e(t){return"top"===t||"bottom"===t}t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(e,i){var o,r,l=this;(r=(o=(o=i)||{}).data=o.data||{}).datasets=r.datasets||[],r.labels=r.labels||[],o.options=a.configMerge(n.global,n[o.type],o.options||{}),i=o;var u=s.acquireContext(e,i),d=u&&u.canvas,c=d&&d.height,h=d&&d.width;l.id=a.uid(),l.ctx=u,l.canvas=d,l.config=i,l.width=h,l.height=c,l.aspectRatio=c?h/c:null,l.options=i.options,l._bufferedRender=!1,l.chart=l,l.controller=l,t.instances[l.id]=l,Object.defineProperty(l,"data",{get:function(){return l.config.data},set:function(t){l.config.data=t}}),u&&d?(l.initialize(),l.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,i=e.options,n=e.canvas,o=i.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(n))),s=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(n)));if((e.width!==r||e.height!==s)&&(n.width=e.width=r,n.height=e.height=s,n.style.width=r+"px",n.style.height=s+"px",a.retinaScale(e,i.devicePixelRatio),!t)){var u={width:r,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},i=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildOrUpdateScales:function(){var i=this,n=i.options,o=i.scales||{},r=[],s=Object.keys(o).reduce(function(t,e){return t[e]=!1,t},{});n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,l=r.id,u=a.valueOrDefault(r.type,n.dtype);e(r.position)!==e(n.dposition)&&(r.position=n.dposition),s[l]=!0;var d=null;if(l in o&&o[l].type===u)(d=o[l]).options=r,d.ctx=i.ctx,d.chart=i;else{var c=t.scaleService.getScaleConstructor(u);if(!c)return;d=new c({id:l,type:u,options:r,ctx:i.ctx,chart:i}),o[d.id]=d}d.mergeTicksOptions(),n.isDefault&&(i.scale=d)}),a.each(s,function(t,e){t||delete o[e]}),i.scales=o,t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,i=[],n=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),s=a.type||e.config.type;if(r.type&&r.type!==s&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=s,i.push(r.type),r.controller)r.controller.updateIndex(o),r.controller.linkScales();else{var l=t.controllers[r.type];if(void 0===l)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new l(e,o),n.push(r.controller)}},e),n},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,i){t.getDatasetMeta(i).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(e){var i,n,o=this;if(e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]}),n=(i=o).options,a.each(i.scales,function(t){r.removeBox(i,t)}),n=a.configMerge(t.defaults.global,t.defaults[i.config.type],n),i.options=i.config.options=n,i.ensureScalesHaveIDs(),i.buildOrUpdateScales(),i.tooltip._options=n.tooltips,i.tooltip.initialize(),l._invalidate(o),!1!==l.notify(o,"beforeUpdate")){o.tooltip._data=o.data;var s=o.buildOrUpdateControllers();a.each(o.data.datasets,function(t,e){o.getDatasetMeta(e).controller.buildOrUpdateElements()},o),o.updateLayout(),o.options.animation&&o.options.animation.duration&&a.each(s,function(t){t.reset()}),o.updateDatasets(),o.tooltip.initialize(),o.lastActive=[],l.notify(o,"afterUpdate"),o._bufferedRender?o._bufferedRequest={duration:e.duration,easing:e.easing,lazy:e.lazy}:o.render(e)}},updateLayout:function(){!1!==l.notify(this,"beforeLayout")&&(r.update(this,this.width,this.height),l.notify(this,"afterScaleUpdate"),l.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==l.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);l.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),i={meta:e,index:t};!1!==l.notify(this,"beforeDatasetUpdate",[i])&&(e.controller.update(),l.notify(this,"afterDatasetUpdate",[i]))},render:function(e){var i=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var n=e.duration,o=e.lazy;if(!1!==l.notify(i,"beforeRender")){var r=i.options.animation,s=function(t){l.notify(i,"afterRender"),a.callback(r&&r.onComplete,[t],i)};if(r&&(void 0!==n&&0!==n||void 0===n&&0!==r.duration)){var u=new t.Animation({numSteps:(n||r.duration)/16.66,easing:e.easing||r.easing,render:function(t,e){var i=a.easing.effects[e.easing],n=e.currentStep,o=n/e.numSteps;t.draw(i(o),o,n)},onAnimationProgress:r.onProgress,onAnimationComplete:s});t.animationService.addAnimation(i,u,n,o)}else i.draw(),s(new t.Animation({numSteps:0,chart:i}));return i}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==l.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e._drawTooltip(t),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=0,i=(this.data.datasets||[]).length;e<i;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var i=(e.data.datasets||[]).length-1;i>=0;--i)e.isDatasetVisible(i)&&e.drawDataset(i,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var i=this.getDatasetMeta(t),n={meta:i,index:t,easingValue:e};!1!==l.notify(this,"beforeDatasetDraw",[n])&&(i.controller.draw(e),l.notify(this,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this.tooltip,i={tooltip:e,easingValue:t};!1!==l.notify(this,"beforeTooltipDraw",[i])&&(e.draw(),l.notify(this,"afterTooltipDraw",[i]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,i){var n=o.modes[e];return"function"==typeof n?n(this,t,i):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var i=e._meta[this.id];return i||(i=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,i=this.data.datasets.length;e<i;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,i=this.data.datasets[t],n=i._meta&&i._meta[e];n&&(n.controller.destroy(),delete i._meta[e])},destroy:function(){var e,i,n=this,o=n.canvas;for(n.stop(),e=0,i=n.data.datasets.length;e<i;++e)n.destroyDatasetMeta(e);o&&(n.unbindEvents(),a.canvas.clear(n),s.releaseContext(n.ctx),n.canvas=null,n.ctx=null),l.notify(n,"destroy"),delete t.instances[n.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},i=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(n){s.addEventListener(t,n,i),e[n]=i}),t.options.responsive&&(i=function(){t.resize()},s.addEventListener(t,"resize",i),e.resize=i)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,i){s.removeEventListener(t,i,e)}))},updateHoverStyle:function(t,e,i){var n,a,o,r=i?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(n=t[a])&&this.getDatasetMeta(n._datasetIndex).controller[r](n)},eventHandler:function(t){var e=this,i=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var n=e.handleEvent(t);i&&(n=i._start?i.handleEvent(t):n|i.handleEvent(t)),l.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):n&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,i=this,n=i.options||{},o=n.hover;return i.lastActive=i.lastActive||[],"mouseout"===t.type?i.active=[]:i.active=i.getElementsAtEventForMode(t,o.mode,o),a.callback(n.onHover||n.hover.onHover,[t.native,i.active],i),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(i,t.native,i.active),i.lastActive.length&&i.updateHoverStyle(i.lastActive,o.mode,!1),i.active.length&&o.mode&&i.updateHoverStyle(i.active,o.mode,!0),e=!a.arrayEquals(i.active,i.lastActive),i.lastActive=i.active,e}}),t.Controller=t}},{25:25,28:28,30:30,31:31,45:45,48:48}],24:[function(t,e,i){"use strict";var n=t(45);e.exports=function(t){var e=["push","pop","shift","splice","unshift"];function i(t,i){var n=t._chartjs;if(n){var a=n.listeners,o=a.indexOf(i);-1!==o&&a.splice(o,1),a.length>0||(e.forEach(function(e){delete t[e]}),delete t._chartjs)}}t.DatasetController=function(t,e){this.initialize(t,e)},n.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),i=t.getDataset();null!==e.xAxisID&&e.xAxisID in t.chart.scales||(e.xAxisID=i.xAxisID||t.chart.options.scales.xAxes[0].id),null!==e.yAxisID&&e.yAxisID in t.chart.scales||(e.yAxisID=i.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&i(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,i=this.getMeta(),n=this.getDataset().data||[],a=i.data;for(t=0,e=n.length;t<e;++t)a[t]=a[t]||this.createMetaData(t);i.dataset=i.dataset||this.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t,a,o=this,r=o.getDataset(),s=r.data||(r.data=[]);o._data!==s&&(o._data&&i(o._data,o),a=o,(t=s)._chartjs?t._chartjs.listeners.push(a):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[a]}}),e.forEach(function(e){var i="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return n.each(t._chartjs.listeners,function(t){"function"==typeof t[i]&&t[i].apply(t,e)}),o}})})),o._data=s),o.resyncElements()},update:n.noop,transition:function(t){for(var e=this.getMeta(),i=e.data||[],n=i.length,a=0;a<n;++a)i[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],i=e.length,n=0;for(t.dataset&&t.dataset.draw();n<i;++n)e[n].draw()},removeHoverStyle:function(t,e){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=n.valueAtIndexOrDefault,s=t._model;s.backgroundColor=o.backgroundColor?o.backgroundColor:r(i.backgroundColor,a,e.backgroundColor),s.borderColor=o.borderColor?o.borderColor:r(i.borderColor,a,e.borderColor),s.borderWidth=o.borderWidth?o.borderWidth:r(i.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=n.valueAtIndexOrDefault,r=n.getHoverColor,s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,i,r(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,i,r(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,i,s.borderWidth)},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,i=t.data.length,n=e.length;n<i?t.data.splice(n,i-n):n>i&&this.insertElements(i,n-i)},insertElements:function(t,e){for(var i=0;i<e;++i)this.addElementAndReset(t+i)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=n.inherits}},{45:45}],25:[function(t,e,i){"use strict";var n=t(45);e.exports={_set:function(t,e){return n.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,i){"use strict";var n=t(3),a=t(45);var o=function(t){a.extend(this,t),this.initialize.apply(this,arguments)};a.extend(o.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=a.clone(t._model)),t._start={},t},transition:function(t){var e=this,i=e._model,a=e._start,o=e._view;return i&&1!==t?(o||(o=e._view={}),a||(a=e._start={}),function(t,e,i,a){var o,r,s,l,u,d,c,h,f,g=Object.keys(i);for(o=0,r=g.length;o<r;++o)if(d=i[s=g[o]],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),(c=typeof d)==typeof(u=t[s]))if("string"===c){if((h=n(u)).valid&&(f=n(d)).valid){e[s]=f.mix(h,a).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*a;continue}e[s]=d}}(a,o,i,t),e):(e._view=i,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return a.isNumber(this._model.x)&&a.isNumber(this._model.y)}}),o.extend=a.inherits,e.exports=o},{3:3,45:45}],27:[function(t,e,i){"use strict";var n=t(3),a=t(25),o=t(45);e.exports=function(t){function e(t,e,i){var n;return"string"==typeof t?(n=parseInt(t,10),-1!==t.indexOf("%")&&(n=n/100*e.parentNode[i])):n=t,n}function i(t){return null!=t&&"none"!==t}function r(t,n,a){var o=document.defaultView,r=t.parentNode,s=o.getComputedStyle(t)[n],l=o.getComputedStyle(r)[n],u=i(s),d=i(l),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(s,t,a):c,d?e(l,r,a):c):"none"}o.configMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,i,n,a){var r=i[e]||{},s=n[e];"scales"===e?i[e]=o.scaleMerge(r,s):"scale"===e?i[e]=o.merge(r,[t.scaleService.getScaleDefaults(s.type),s]):o._merger(e,i,n,a)}})},o.scaleMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,i,n,a){if("xAxes"===e||"yAxes"===e){var r,s,l,u=n[e].length;for(i[e]||(i[e]=[]),r=0;r<u;++r)l=n[e][r],s=o.valueOrDefault(l.type,"xAxes"===e?"category":"linear"),r>=i[e].length&&i[e].push({}),!i[e][r].type||l.type&&l.type!==i[e][r].type?o.merge(i[e][r],[t.scaleService.getScaleDefaults(s),l]):o.merge(i[e][r],l)}else o._merger(e,i,n,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var i=[];return o.each(t,function(t){e(t)&&i.push(t)}),i},o.findIndex=Array.prototype.findIndex?function(t,e,i){return t.findIndex(e,i)}:function(t,e,i){i=void 0===i?t:i;for(var n=0,a=t.length;n<a;++n)if(e.call(i,t[n],n,t))return n;return-1},o.findNextWhere=function(t,e,i){o.isNullOrUndef(i)&&(i=-1);for(var n=i+1;n<t.length;n++){var a=t[n];if(e(a))return a}},o.findPreviousWhere=function(t,e,i){o.isNullOrUndef(i)&&(i=t.length);for(var n=i-1;n>=0;n--){var a=t[n];if(e(a))return a}},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,i){return Math.abs(t-e)<i},o.almostWhole=function(t,e){var i=Math.round(t);return i-e<t&&i+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0===(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){var e=Math.log(t)*Math.LOG10E,i=Math.round(e);return t===Math.pow(10,i)?i:e},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var i=e.x-t.x,n=e.y-t.y,a=Math.sqrt(i*i+n*n),o=Math.atan2(n,i);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,i,n){var a=t.skip?e:t,o=e,r=i.skip?e:i,s=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),l=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=s/(s+l),d=l/(s+l),c=n*(u=isNaN(u)?0:u),h=n*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,i,n,a,r,s,l,u,d,c=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),h=c.length;for(e=0;e<h;++e)if(!(n=c[e]).model.skip){if(i=e>0?c[e-1]:null,(a=e<h-1?c[e+1]:null)&&!a.model.skip){var f=a.model.x-n.model.x;n.deltaK=0!==f?(a.model.y-n.model.y)/f:0}!i||i.model.skip?n.mK=n.deltaK:!a||a.model.skip?n.mK=i.deltaK:this.sign(i.deltaK)!==this.sign(n.deltaK)?n.mK=0:n.mK=(i.deltaK+n.deltaK)/2}for(e=0;e<h-1;++e)n=c[e],a=c[e+1],n.model.skip||a.model.skip||(o.almostEquals(n.deltaK,0,this.EPSILON)?n.mK=a.mK=0:(r=n.mK/n.deltaK,s=a.mK/n.deltaK,(u=Math.pow(r,2)+Math.pow(s,2))<=9||(l=3/Math.sqrt(u),n.mK=r*l*n.deltaK,a.mK=s*l*n.deltaK)));for(e=0;e<h;++e)(n=c[e]).model.skip||(i=e>0?c[e-1]:null,a=e<h-1?c[e+1]:null,i&&!i.model.skip&&(d=(n.model.x-i.model.x)/3,n.model.controlPointPreviousX=n.model.x-d,n.model.controlPointPreviousY=n.model.y-d*n.mK),a&&!a.model.skip&&(d=(a.model.x-n.model.x)/3,n.model.controlPointNextX=n.model.x+d,n.model.controlPointNextY=n.model.y+d*n.mK))},o.nextItem=function(t,e,i){return i?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,i){return i?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var i=Math.floor(o.log10(t)),n=t/Math.pow(10,i);return(e?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10)*Math.pow(10,i)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var i,n,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,s=r.getBoundingClientRect(),l=a.touches;l&&l.length>0?(i=l[0].clientX,n=l[0].clientY):(i=a.clientX,n=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return{x:i=Math.round((i-s.left-u)/f*r.width/e.currentDevicePixelRatio),y:n=Math.round((n-s.top-d)/g*r.height/e.currentDevicePixelRatio)}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var i=parseInt(o.getStyle(e,"padding-left"),10),n=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-i-n,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var i=parseInt(o.getStyle(e,"padding-top"),10),n=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-i-n,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var i=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==i){var n=t.canvas,a=t.height,o=t.width;n.height=a*i,n.width=o*i,t.ctx.scale(i,i),n.style.height||n.style.width||(n.style.height=a+"px",n.style.width=o+"px")}},o.fontString=function(t,e,i){return e+" "+t+"px "+i},o.longestText=function(t,e,i,n){var a=(n=n||{}).data=n.data||{},r=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(a=n.data={},r=n.garbageCollect=[],n.font=e),t.font=e;var s=0;o.each(i,function(e){null!=e&&!0!==o.isArray(e)?s=o.measureText(t,a,r,s,e):o.isArray(e)&&o.each(e,function(e){null==e||o.isArray(e)||(s=o.measureText(t,a,r,s,e))})});var l=r.length/2;if(l>i.length){for(var u=0;u<l;u++)delete a[r[u]];r.splice(0,l)}return s},o.measureText=function(t,e,i,n,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,i.push(a)),o>n&&(n=o),n},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=n?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),n(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,i){"use strict";var n=t(45);function a(t,e){return t.native?{x:t.x,y:t.y}:n.getRelativePosition(t,e)}function o(t,e){var i,n,a,o,r;for(n=0,o=t.data.datasets.length;n<o;++n)if(t.isDatasetVisible(n))for(a=0,r=(i=t.getDatasetMeta(n)).data.length;a<r;++a){var s=i.data[a];s._view.skip||e(s)}}function r(t,e){var i=[];return o(t,function(t){t.inRange(e.x,e.y)&&i.push(t)}),i}function s(t,e,i,n){var a=Number.POSITIVE_INFINITY,r=[];return o(t,function(t){if(!i||t.inRange(e.x,e.y)){var o=t.getCenterPoint(),s=n(e,o);s<a?(r=[t],a=s):s===a&&r.push(t)}}),r}function l(t){var e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,n){var a=e?Math.abs(t.x-n.x):0,o=i?Math.abs(t.y-n.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(o,2))}}function u(t,e,i){var n=a(e,t);i.axis=i.axis||"x";var o=l(i.axis),u=i.intersect?r(t,n):s(t,n,!1,o),d=[];return u.length?(t.data.datasets.forEach(function(e,i){if(t.isDatasetVisible(i)){var n=t.getDatasetMeta(i).data[u[0]._index];n&&!n._view.skip&&d.push(n)}}),d):[]}e.exports={modes:{single:function(t,e){var i=a(e,t),n=[];return o(t,function(t){if(t.inRange(i.x,i.y))return n.push(t),n}),n.slice(0,1)},label:u,index:u,dataset:function(t,e,i){var n=a(e,t);i.axis=i.axis||"xy";var o=l(i.axis),u=i.intersect?r(t,n):s(t,n,!1,o);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return u(t,e,{intersect:!1})},point:function(t,e){return r(t,a(e,t))},nearest:function(t,e,i){var n=a(e,t);i.axis=i.axis||"xy";var o=l(i.axis),r=s(t,n,i.intersect,o);return r.length>1&&r.sort(function(t,e){var i=t.getArea()-e.getArea();return 0===i&&(i=t._datasetIndex-e._datasetIndex),i}),r.slice(0,1)},x:function(t,e,i){var n=a(e,t),r=[],s=!1;return o(t,function(t){t.inXRange(n.x)&&r.push(t),t.inRange(n.x,n.y)&&(s=!0)}),i.intersect&&!s&&(r=[]),r},y:function(t,e,i){var n=a(e,t),r=[],s=!1;return o(t,function(t){t.inYRange(n.y)&&r.push(t),t.inRange(n.x,n.y)&&(s=!0)}),i.intersect&&!s&&(r=[]),r}}}},{45:45}],29:[function(t,e,i){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,i){"use strict";var n=t(45);function a(t,e){return n.where(t,function(t){return t.position===e})}function o(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,i){var n=e?i:t,a=e?t:i;return n.weight===a.weight?n._tmpIndex_-a._tmpIndex_:n.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}e.exports={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure:function(t,e,i){for(var n,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)n=a[r],i.hasOwnProperty(n)&&(e[n]=i[n])},update:function(t,e,i){if(t){var r=t.options.layout||{},s=n.options.toPadding(r.padding),l=s.left,u=s.right,d=s.top,c=s.bottom,h=a(t.boxes,"left"),f=a(t.boxes,"right"),g=a(t.boxes,"top"),p=a(t.boxes,"bottom"),m=a(t.boxes,"chartArea");o(h,!0),o(f,!1),o(g,!0),o(p,!1);var v=e-l-u,b=i-d-c,x=b/2,y=(e-v/2)/(h.length+f.length),k=(i-x)/(g.length+p.length),M=v,w=b,S=[];n.each(h.concat(f,g,p),function(t){var e,i=t.isHorizontal();i?(e=t.update(t.fullWidth?v:M,k),w-=e.height):(e=t.update(y,w),M-=e.width),S.push({horizontal:i,minSize:e,box:t})});var C=0,_=0,D=0,I=0;n.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();C=Math.max(C,e.left),_=Math.max(_,e.right)}}),n.each(h.concat(f),function(t){if(t.getPadding){var e=t.getPadding();D=Math.max(D,e.top),I=Math.max(I,e.bottom)}});var P=l,A=u,T=d,F=c;n.each(h.concat(f),N),n.each(h,function(t){P+=t.width}),n.each(f,function(t){A+=t.width}),n.each(g.concat(p),N),n.each(g,function(t){T+=t.height}),n.each(p,function(t){F+=t.height}),n.each(h.concat(f),function(t){var e=n.findNextWhere(S,function(e){return e.box===t}),i={left:0,right:0,top:T,bottom:F};e&&t.update(e.minSize.width,w,i)}),P=l,A=u,T=d,F=c,n.each(h,function(t){P+=t.width}),n.each(f,function(t){A+=t.width}),n.each(g,function(t){T+=t.height}),n.each(p,function(t){F+=t.height});var O=Math.max(C-P,0);P+=O,A+=Math.max(_-A,0);var R=Math.max(D-T,0);T+=R,F+=Math.max(I-F,0);var L=i-T-F,z=e-P-A;z===M&&L===w||(n.each(h,function(t){t.height=L}),n.each(f,function(t){t.height=L}),n.each(g,function(t){t.fullWidth||(t.width=z)}),n.each(p,function(t){t.fullWidth||(t.width=z)}),w=L,M=z);var B=l+O,W=d+R;n.each(h.concat(g),V),B+=M,W+=w,n.each(f,V),n.each(p,V),t.chartArea={left:P,top:T,right:P+M,bottom:T+w},n.each(m,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(M,w)})}function N(t){var e=n.findNextWhere(S,function(e){return e.box===t});if(e)if(t.isHorizontal()){var i={left:Math.max(P,C),right:Math.max(A,_),top:0,bottom:0};t.update(t.fullWidth?v:M,b/2,i)}else t.update(e.minSize.width,w)}function V(t){t.isHorizontal()?(t.left=t.fullWidth?l:P,t.right=t.fullWidth?e-u:P+M,t.top=W,t.bottom=W+t.height,W=t.bottom):(t.left=B,t.right=B+t.width,t.top=T,t.bottom=T+w,B=t.right)}}}},{45:45}],31:[function(t,e,i){"use strict";var n=t(25),a=t(45);n._set("global",{plugins:{}}),e.exports={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var i=e.indexOf(t);-1!==i&&e.splice(i,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,i){var n,a,o,r,s,l=this.descriptors(t),u=l.length;for(n=0;n<u;++n)if("function"==typeof(s=(o=(a=l[n]).plugin)[e])&&((r=[t].concat(i||[])).push(a.options),!1===s.apply(o,r)))return!1;return!0},descriptors:function(t){var e=t.$plugins||(t.$plugins={});if(e.id===this._cacheId)return e.descriptors;var i=[],o=[],r=t&&t.config||{},s=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===i.indexOf(t)){var e=t.id,r=s[e];!1!==r&&(!0===r&&(r=a.clone(n.global.plugins[e])),i.push(t),o.push({plugin:t,options:r||{}}))}}),e.descriptors=o,e.id=this._cacheId,o},_invalidate:function(t){delete t.$plugins}}},{25:25,45:45}],32:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(34);function s(t){var e,i,n=[];for(e=0,i=t.length;e<i;++e)n.push(t[e].label);return n}function l(t,e,i){var n=t.getPixelForTick(e);return i&&(n-=0===e?(t.getPixelForTick(1)-n)/2:(n-t.getPixelForTick(e-1))/2),n}n._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:r.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,i){return o.isArray(e)?o.longestText(t,i,e):t.measureText(e).width}function i(t){var e=o.valueOrDefault,i=n.global,a=e(t.fontSize,i.defaultFontSize),r=e(t.fontStyle,i.defaultFontStyle),s=e(t.fontFamily,i.defaultFontFamily);return{size:a,style:r,family:s,font:o.fontString(a,r,s)}}function r(t){return o.options.toLineHeight(o.valueOrDefault(t.lineHeight,1.2),o.valueOrDefault(t.fontSize,n.global.defaultFontSize))}t.Scale=a.extend({getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;for(var e in!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1}),t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){o.callback(this.options.beforeUpdate,[this])},update:function(t,e,i){var n,a,r,s,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=o.extend({left:0,right:0,top:0,bottom:0},i),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),r=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=r,n=0,a=r.length;n<a;++n)s=r[n],(u=l[n])?u.label=s:l.push(u={label:s,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){o.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){o.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){o.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){o.callback(this.options.beforeDataLimits,[this])},determineDataLimits:o.noop,afterDataLimits:function(){o.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){o.callback(this.options.beforeBuildTicks,[this])},buildTicks:o.noop,afterBuildTicks:function(){o.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){o.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){o.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){o.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,n=t.options.ticks,a=s(t._ticks),r=i(n);e.font=r.font;var l=n.minRotation||0;if(a.length&&t.options.display&&t.isHorizontal())for(var u,d=o.longestText(e,r.font,a,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&l<n.maxRotation;){var f=o.toRadians(l);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){o.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){o.callback(this.options.beforeFit,[this])},fit:function(){var t=this,n=t.minSize={width:0,height:0},a=s(t._ticks),l=t.options,u=l.ticks,d=l.scaleLabel,c=l.gridLines,h=l.display,f=t.isHorizontal(),g=i(u),p=l.gridLines.tickMarkLength;if(n.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,n.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var m=r(d)+o.options.toPadding(d.padding).height;f?n.height+=m:n.width+=m}if(u.display&&h){var v=o.longestText(t.ctx,g.font,a,t.longestTextCache),b=o.numberOfLabelLines(a),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var k=o.toRadians(t.labelRotation),M=Math.cos(k),w=Math.sin(k)*v+g.size*b+x*(b-1)+x;n.height=Math.min(t.maxHeight,n.height+w+y),t.ctx.font=g.font;var S=e(t.ctx,a[0],g.font),C=e(t.ctx,a[a.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===l.position?M*S+3:M*x+3,t.paddingRight="bottom"===l.position?M*x+3:M*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?v=0:v+=y+x,n.width=Math.min(t.maxWidth,n.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=n.width,t.height=n.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){o.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(o.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:o.noop,getPixelForValue:o.noop,getValueForPixel:o.noop,getPixelForTick:function(t){var e=this,i=e.options.offset;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(i?0:1),1),a=n*t+e.paddingLeft;i&&(a+=n/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,n=e.left+Math.round(i);return n+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,i,n,a,r=this,s=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=o.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),s&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),i=0;i<u;i++)n=t[i],(e>1&&i%e>0||i%e==0&&i+e>=u)&&i!==u-1&&delete n.label,f.push(n);return f},draw:function(t){var e=this,a=e.options;if(a.display){var s=e.ctx,u=n.global,d=a.ticks.minor,c=a.ticks.major||d,h=a.gridLines,f=a.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),m=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=o.valueOrDefault(d.fontColor,u.defaultFontColor),b=i(d),x=o.valueOrDefault(c.fontColor,u.defaultFontColor),y=i(c),k=h.drawTicks?h.tickMarkLength:0,M=o.valueOrDefault(f.fontColor,u.defaultFontColor),w=i(f),S=o.options.toPadding(f.padding),C=o.toRadians(e.labelRotation),_=[],D=e.options.gridLines.lineWidth,I="right"===a.position?e.right:e.right-D-k,P="right"===a.position?e.right+k:e.right,A="bottom"===a.position?e.top+D:e.bottom-k-D,T="bottom"===a.position?e.top+D+k:e.bottom+D;if(o.each(m,function(i,n){if(!o.isNullOrUndef(i.label)){var r,s,c,f,v,b,x,y,M,w,S,F,O,R,L=i.label;n===e.zeroLineIndex&&a.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=o.valueAtIndexOrDefault(h.lineWidth,n),s=o.valueAtIndexOrDefault(h.color,n),c=o.valueOrDefault(h.borderDash,u.borderDash),f=o.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var z="middle",B="middle",W=d.padding;if(p){var N=k+W;"bottom"===a.position?(B=g?"middle":"top",z=g?"right":"center",R=e.top+N):(B=g?"middle":"bottom",z=g?"left":"center",R=e.bottom-N);var V=l(e,n,h.offsetGridLines&&m.length>1);V<e.left&&(s="rgba(0,0,0,0)"),V+=o.aliasPixel(r),O=e.getPixelForTick(n)+d.labelOffset,v=x=M=S=V,b=A,y=T,w=t.top,F=t.bottom+D}else{var E,H="left"===a.position;d.mirror?(z=H?"left":"right",E=W):(z=H?"right":"left",E=k+W),O=H?e.right-E:e.left+E;var j=l(e,n,h.offsetGridLines&&m.length>1);j<e.top&&(s="rgba(0,0,0,0)"),j+=o.aliasPixel(r),R=e.getPixelForTick(n)+d.labelOffset,v=I,x=P,M=t.left,S=t.right+D,b=y=w=F=j}_.push({tx1:v,ty1:b,tx2:x,ty2:y,x1:M,y1:w,x2:S,y2:F,labelX:O,labelY:R,glWidth:r,glColor:s,glBorderDash:c,glBorderDashOffset:f,rotation:-1*C,label:L,major:i.major,textBaseline:B,textAlign:z})}}),o.each(_,function(t){if(h.display&&(s.save(),s.lineWidth=t.glWidth,s.strokeStyle=t.glColor,s.setLineDash&&(s.setLineDash(t.glBorderDash),s.lineDashOffset=t.glBorderDashOffset),s.beginPath(),h.drawTicks&&(s.moveTo(t.tx1,t.ty1),s.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(s.moveTo(t.x1,t.y1),s.lineTo(t.x2,t.y2)),s.stroke(),s.restore()),d.display){s.save(),s.translate(t.labelX,t.labelY),s.rotate(t.rotation),s.font=t.major?y.font:b.font,s.fillStyle=t.major?x:v,s.textBaseline=t.textBaseline,s.textAlign=t.textAlign;var i=t.label;if(o.isArray(i))for(var n=i.length,a=1.5*b.size,r=e.isHorizontal()?0:-a*(n-1)/2,l=0;l<n;++l)s.fillText(""+i[l],0,r),r+=a;else s.fillText(i,0,0);s.restore()}}),f.display){var F,O,R=0,L=r(f)/2;if(p)F=e.left+(e.right-e.left)/2,O="bottom"===a.position?e.bottom-L-S.bottom:e.top+L+S.top;else{var z="left"===a.position;F=z?e.left+L+S.top:e.right-L-S.top,O=e.top+(e.bottom-e.top)/2,R=z?-.5*Math.PI:.5*Math.PI}s.save(),s.translate(F,O),s.rotate(R),s.textAlign="center",s.textBaseline="middle",s.fillStyle=M,s.font=w.font,s.fillText(f.labelString,0,0),s.restore()}if(h.drawBorder){s.lineWidth=o.valueAtIndexOrDefault(h.lineWidth,0),s.strokeStyle=o.valueAtIndexOrDefault(h.color,0);var B=e.left,W=e.right+D,N=e.top,V=e.bottom+D,E=o.aliasPixel(s.lineWidth);p?(N=V="top"===a.position?e.bottom:e.top,N+=E,V+=E):(B=W="left"===a.position?e.right:e.left,B+=E,W+=E),s.beginPath(),s.moveTo(B,N),s.lineTo(W,V),s.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(30);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,i){this.constructors[t]=e,this.defaults[t]=a.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[n.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=a.extend(this.defaults[t],e))},addScalesToLayout:function(t){a.each(t.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,o.addBox(t,e)})}}}},{25:25,30:30,45:45}],34:[function(t,e,i){"use strict";var n=t(45);e.exports={formatters:{values:function(t){return n.isArray(t)?t:""+t},linear:function(t,e,i){var a=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=n.log10(Math.abs(a)),r="";if(0!==t){var s=-1*Math.floor(o);s=Math.max(Math.min(s,20),0),r=t.toFixed(s)}else r="0";return r},logarithmic:function(t,e,i){var a=t/Math.pow(10,Math.floor(n.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===i.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var i="",n=e.labels,a=n?n.length:0;if(t.length>0){var o=t[0];o.xLabel?i=o.xLabel:a>0&&o.index<a&&(i=n[o.index])}return i},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i&&(i+=": "),i+=t.yLabel},labelColor:function(t,e){var i=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:i.borderColor,backgroundColor:i.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}}}),e.exports=function(t){function e(t,e){var i=o.color(t);return i.alpha(e*i.alpha()).rgbaString()}function i(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function r(t){var e=n.global,i=o.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:i(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:i(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:i(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:i(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:i(t.titleFontStyle,e.defaultFontStyle),titleFontSize:i(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:i(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:i(t.footerFontStyle,e.defaultFontStyle),footerFontSize:i(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}t.Tooltip=a.extend({initialize:function(){this._model=r(this._options),this._lastActive=[]},getTitle:function(){var t=this._options.callbacks,e=t.beforeTitle.apply(this,arguments),n=t.title.apply(this,arguments),a=t.afterTitle.apply(this,arguments),o=[];return o=i(o=i(o=i(o,e),n),a)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var n=this,a=n._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};i(o.before,a.beforeLabel.call(n,t,e)),i(o.lines,a.label.call(n,t,e)),i(o.after,a.afterLabel.call(n,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this._options.callbacks,e=t.beforeFooter.apply(this,arguments),n=t.footer.apply(this,arguments),a=t.afterFooter.apply(this,arguments),o=[];return o=i(o=i(o=i(o,e),n),a)},update:function(e){var i,n,a,s,l,u,d,c,h,f,g,p,m,v,b,x,y,k,M,w,S=this,C=S._options,_=S._model,D=S._model=r(C),I=S._active,P=S._data,A={xAlign:_.xAlign,yAlign:_.yAlign},T={x:_.x,y:_.y},F={width:_.width,height:_.height},O={x:_.caretX,y:_.caretY};if(I.length){D.opacity=1;var R=[],L=[];O=t.Tooltip.positioners[C.position].call(S,I,S._eventPosition);var z=[];for(i=0,n=I.length;i<n;++i)z.push((x=I[i],y=void 0,k=void 0,void 0,void 0,y=x._xScale,k=x._yScale||x._scale,M=x._index,w=x._datasetIndex,{xLabel:y?y.getLabelForIndex(M,w):"",yLabel:k?k.getLabelForIndex(M,w):"",index:M,datasetIndex:w,x:x._model.x,y:x._model.y}));C.filter&&(z=z.filter(function(t){return C.filter(t,P)})),C.itemSort&&(z=z.sort(function(t,e){return C.itemSort(t,e,P)})),o.each(z,function(t){R.push(C.callbacks.labelColor.call(S,t,S._chart)),L.push(C.callbacks.labelTextColor.call(S,t,S._chart))}),D.title=S.getTitle(z,P),D.beforeBody=S.getBeforeBody(z,P),D.body=S.getBody(z,P),D.afterBody=S.getAfterBody(z,P),D.footer=S.getFooter(z,P),D.x=Math.round(O.x),D.y=Math.round(O.y),D.caretPadding=C.caretPadding,D.labelColors=R,D.labelTextColors=L,D.dataPoints=z,A=function(t,e){var i,n,a,o,r,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",c="center";s.y<e.height?c="top":s.y>l.height-e.height&&(c="bottom");var h=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===c?(i=function(t){return t<=h},n=function(t){return t>h}):(i=function(t){return t<=e.width/2},n=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},o=function(t){return t-e.width-s.caretSize-s.caretPadding<0},r=function(t){return t<=f?"top":"bottom"},i(s.x)?(d="left",a(s.x)&&(d="center",c=r(s.y))):n(s.x)&&(d="right",o(s.x)&&(d="center",c=r(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:c}}(this,F=function(t,e){var i=t._chart.ctx,n=2*e.yPadding,a=0,r=e.body,s=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);s+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;n+=l*d,n+=l?(l-1)*e.titleSpacing:0,n+=l?e.titleMarginBottom:0,n+=s*c,n+=s?(s-1)*e.bodySpacing:0,n+=u?e.footerMarginTop:0,n+=u*h,n+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,i.measureText(t).width+f)};return i.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),i.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,i.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),{width:a+=2*e.xPadding,height:n}}(this,D)),a=D,s=F,l=A,u=S._chart,d=a.x,c=a.y,h=a.caretSize,f=a.caretPadding,g=a.cornerRadius,p=l.xAlign,m=l.yAlign,v=h+f,b=g+f,"right"===p?d-=s.width:"center"===p&&((d-=s.width/2)+s.width>u.width&&(d=u.width-s.width),d<0&&(d=0)),"top"===m?c+=v:c-="bottom"===m?s.height+v:s.height/2,"center"===m?"left"===p?d+=v:"right"===p&&(d-=v):"left"===p?d-=b:"right"===p&&(d+=b),T={x:d,y:c}}else D.opacity=0;return D.xAlign=A.xAlign,D.yAlign=A.yAlign,D.x=T.x,D.y=T.y,D.width=F.width,D.height=F.height,D.caretX=O.x,D.caretY=O.y,S._model=D,e&&C.custom&&C.custom.call(S,D),S},drawCaret:function(t,e){var i=this._chart.ctx,n=this._view,a=this.getCaretPosition(t,e,n);i.lineTo(a.x1,a.y1),i.lineTo(a.x2,a.y2),i.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,i){var n,a,o,r,s,l,u=i.caretSize,d=i.cornerRadius,c=i.xAlign,h=i.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===h)s=g+m/2,"left"===c?(a=(n=f)-u,o=n,r=s+u,l=s-u):(a=(n=f+p)+u,o=n,r=s-u,l=s+u);else if("left"===c?(n=(a=f+d+u)-u,o=a+u):"right"===c?(n=(a=f+p-d-u)-u,o=a+u):(n=(a=i.caretX)-u,o=a+u),"top"===h)s=(r=g)-u,l=r;else{s=(r=g+m)+u,l=r;var v=o;o=n,n=v}return{x1:n,x2:a,x3:o,y1:r,y2:s,y3:l}},drawTitle:function(t,i,n,a){var r=i.title;if(r.length){n.textAlign=i._titleAlign,n.textBaseline="top";var s,l,u=i.titleFontSize,d=i.titleSpacing;for(n.fillStyle=e(i.titleFontColor,a),n.font=o.fontString(u,i._titleFontStyle,i._titleFontFamily),s=0,l=r.length;s<l;++s)n.fillText(r[s],t.x,t.y),t.y+=u+d,s+1===r.length&&(t.y+=i.titleMarginBottom-d)}},drawBody:function(t,i,n,a){var r=i.bodyFontSize,s=i.bodySpacing,l=i.body;n.textAlign=i._bodyAlign,n.textBaseline="top",n.font=o.fontString(r,i._bodyFontStyle,i._bodyFontFamily);var u=0,d=function(e){n.fillText(e,t.x+u,t.y),t.y+=r+s};n.fillStyle=e(i.bodyFontColor,a),o.each(i.beforeBody,d);var c=i.displayColors;u=c?r+2:0,o.each(l,function(s,l){var u=e(i.labelTextColors[l],a);n.fillStyle=u,o.each(s.before,d),o.each(s.lines,function(o){c&&(n.fillStyle=e(i.legendColorBackground,a),n.fillRect(t.x,t.y,r,r),n.lineWidth=1,n.strokeStyle=e(i.labelColors[l].borderColor,a),n.strokeRect(t.x,t.y,r,r),n.fillStyle=e(i.labelColors[l].backgroundColor,a),n.fillRect(t.x+1,t.y+1,r-2,r-2),n.fillStyle=u),d(o)}),o.each(s.after,d)}),u=0,o.each(i.afterBody,d),t.y-=s},drawFooter:function(t,i,n,a){var r=i.footer;r.length&&(t.y+=i.footerMarginTop,n.textAlign=i._footerAlign,n.textBaseline="top",n.fillStyle=e(i.footerFontColor,a),n.font=o.fontString(i.footerFontSize,i._footerFontStyle,i._footerFontFamily),o.each(r,function(e){n.fillText(e,t.x,t.y),t.y+=i.footerFontSize+i.footerSpacing}))},drawBackground:function(t,i,n,a,o){n.fillStyle=e(i.backgroundColor,o),n.strokeStyle=e(i.borderColor,o),n.lineWidth=i.borderWidth;var r=i.xAlign,s=i.yAlign,l=t.x,u=t.y,d=a.width,c=a.height,h=i.cornerRadius;n.beginPath(),n.moveTo(l+h,u),"top"===s&&this.drawCaret(t,a),n.lineTo(l+d-h,u),n.quadraticCurveTo(l+d,u,l+d,u+h),"center"===s&&"right"===r&&this.drawCaret(t,a),n.lineTo(l+d,u+c-h),n.quadraticCurveTo(l+d,u+c,l+d-h,u+c),"bottom"===s&&this.drawCaret(t,a),n.lineTo(l+h,u+c),n.quadraticCurveTo(l,u+c,l,u+c-h),"center"===s&&"left"===r&&this.drawCaret(t,a),n.lineTo(l,u+h),n.quadraticCurveTo(l,u,l+h,u),n.closePath(),n.fill(),i.borderWidth>0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var i={width:e.width,height:e.height},n={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(n,e,t,i,a),n.x+=e.xPadding,n.y+=e.yPadding,this.drawTitle(n,e,t,a),this.drawBody(n,e,t,a),this.drawFooter(n,e,t,a))}},handleEvent:function(t){var e,i=this,n=i._options;return i._lastActive=i._lastActive||[],"mouseout"===t.type?i._active=[]:i._active=i._chart.getElementsAtEventForMode(t,n.mode,n),(e=!o.arrayEquals(i._active,i._lastActive))&&(i._lastActive=i._active,(n.enabled||n.custom)&&(i._eventPosition={x:t.x,y:t.y},i.update(!0),i.pivot())),e}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,i,n=0,a=0,o=0;for(e=0,i=t.length;e<i;++e){var r=t[e];if(r&&r.hasValue()){var s=r.tooltipPosition();n+=s.x,a+=s.y,++o}}return{x:Math.round(n/o),y:Math.round(a/o)}},nearest:function(t,e){var i,n,a,r=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(i=0,n=t.length;i<n;++i){var u=t[i];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<l&&(l=c,a=u)}}if(a){var h=a.tooltipPosition();r=h.x,s=h.y}return{x:r,y:s}}}}},{25:25,26:26,45:45}],36:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{elements:{arc:{backgroundColor:n.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var i=this._view;if(i){for(var n=o.getAngleFromPoint(i,{x:t,y:e}),a=n.angle,r=n.distance,s=i.startAngle,l=i.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;var u=a>=s&&a<=l,d=r>=i.innerRadius&&r<=i.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,i=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,i=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},draw:function(){var t=this._chart.ctx,e=this._view,i=e.startAngle,n=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,i,n),t.arc(e.x,e.y,e.innerRadius,n,i,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=n.global;n._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,i,n,a=this._view,s=this._chart.ctx,l=a.spanGaps,u=this._children.slice(),d=r.elements.line,c=-1;for(this._loop&&u.length&&u.push(u[0]),s.save(),s.lineCap=a.borderCapStyle||d.borderCapStyle,s.setLineDash&&s.setLineDash(a.borderDash||d.borderDash),s.lineDashOffset=a.borderDashOffset||d.borderDashOffset,s.lineJoin=a.borderJoinStyle||d.borderJoinStyle,s.lineWidth=a.borderWidth||d.borderWidth,s.strokeStyle=a.borderColor||r.defaultColor,s.beginPath(),c=-1,t=0;t<u.length;++t)e=u[t],i=o.previousItem(u,t),n=e._view,0===t?n.skip||(s.moveTo(n.x,n.y),c=t):(i=-1===c?i:u[c],n.skip||(c!==t-1&&!l||-1===c?s.moveTo(n.x,n.y):o.canvas.lineTo(s,i._view,e._view),c=t));s.stroke(),s.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=n.global.defaultColor;function s(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}n._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:r,borderColor:r,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=a.extend({inRange:function(t,e){var i=this._view;return!!i&&Math.pow(t-i.x,2)+Math.pow(e-i.y,2)<Math.pow(i.hitRadius+i.radius,2)},inLabelRange:s,inXRange:s,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,i=this._model,a=this._chart.ctx,s=e.pointStyle,l=e.radius,u=e.x,d=e.y,c=o.color,h=0;e.skip||(a.strokeStyle=e.borderColor||r,a.lineWidth=o.valueOrDefault(e.borderWidth,n.global.elements.point.borderWidth),a.fillStyle=e.backgroundColor||r,void 0!==t&&(i.x<t.left||1.01*t.right<i.x||i.y<t.top||1.01*t.bottom<i.y)&&(i.x<t.left?h=(u-i.x)/(t.left-i.x):1.01*t.right<i.x?h=(i.x-u)/(i.x-t.right):i.y<t.top?h=(d-i.y)/(t.top-i.y):1.01*t.bottom<i.y&&(h=(i.y-d)/(i.y-t.bottom)),h=Math.round(100*h)/100,a.strokeStyle=c(a.strokeStyle).alpha(h).rgbString(),a.fillStyle=c(a.fillStyle).alpha(h).rgbString()),o.canvas.drawPoint(a,s,l,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,i){"use strict";var n=t(25),a=t(26);function o(t){return void 0!==t._view.width}function r(t){var e,i,n,a,r=t._view;if(o(t)){var s=r.width/2;e=r.x-s,i=r.x+s,n=Math.min(r.y,r.base),a=Math.max(r.y,r.base)}else{var l=r.height/2;e=Math.min(r.x,r.base),i=Math.max(r.x,r.base),n=r.y-l,a=r.y+l}return{left:e,top:n,right:i,bottom:a}}n._set("global",{elements:{rectangle:{backgroundColor:n.global.defaultColor,borderColor:n.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=a.extend({draw:function(){var t,e,i,n,a,o,r,s=this._chart.ctx,l=this._view,u=l.borderWidth;if(l.horizontal?(t=l.base,e=l.x,i=l.y-l.height/2,n=l.y+l.height/2,a=e>t?1:-1,o=1,r=l.borderSkipped||"left"):(t=l.x-l.width/2,e=l.x+l.width/2,i=l.y,a=1,o=(n=l.base)>i?1:-1,r=l.borderSkipped||"bottom"),u){var d=Math.min(Math.abs(t-e),Math.abs(i-n)),c=(u=u>d?d:u)/2,h=t+("left"!==r?c*a:0),f=e+("right"!==r?-c*a:0),g=i+("top"!==r?c*o:0),p=n+("bottom"!==r?-c*o:0);h!==f&&(i=g,n=p),g!==p&&(t=h,e=f)}s.beginPath(),s.fillStyle=l.backgroundColor,s.strokeStyle=l.borderColor,s.lineWidth=u;var m=[[t,n],[t,i],[e,i],[e,n]],v=["bottom","left","top","right"].indexOf(r,0);function b(t){return m[(v+t)%4]}-1===v&&(v=0);var x=b(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=b(y),s.lineTo(x[0],x[1]);s.fill(),u&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=!1;if(this._view){var n=r(this);i=t>=n.left&&t<=n.right&&e>=n.top&&e<=n.bottom}return i},inLabelRange:function(t,e){if(!this._view)return!1;var i=r(this);return o(this)?t>=i.left&&t<=i.right:e>=i.top&&e<=i.bottom},inXRange:function(t){var e=r(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=r(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,i=this._view;return o(this)?(t=i.x,e=(i.y+i.base)/2):(t=(i.x+i.base)/2,e=i.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,i){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,i){"use strict";var n=t(42);i=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,i,n,a,o){if(o){var r=Math.min(o,n/2),s=Math.min(o,a/2);t.moveTo(e+r,i),t.lineTo(e+n-r,i),t.quadraticCurveTo(e+n,i,e+n,i+s),t.lineTo(e+n,i+a-s),t.quadraticCurveTo(e+n,i+a,e+n-r,i+a),t.lineTo(e+r,i+a),t.quadraticCurveTo(e,i+a,e,i+a-s),t.lineTo(e,i+s),t.quadraticCurveTo(e,i,e+r,i)}else t.rect(e,i,n,a)},drawPoint:function(t,e,i,n,a){var o,r,s,l,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(i)||i<=0)){switch(e){default:t.beginPath(),t.arc(n,a,i,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*i/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(n-r/2,a+u/3),t.lineTo(n+r/2,a+u/3),t.lineTo(n,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*i,t.beginPath(),t.fillRect(n-d,a-d,2*d,2*d),t.strokeRect(n-d,a-d,2*d,2*d);break;case"rectRounded":var c=i/Math.SQRT2,h=n-c,f=a-c,g=Math.SQRT2*i;t.beginPath(),this.roundedRect(t,h,f,g,g,i/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*i,t.beginPath(),t.moveTo(n-d,a),t.lineTo(n,a+d),t.lineTo(n+d,a),t.lineTo(n,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(n,a+i),t.lineTo(n,a-i),t.moveTo(n-i,a),t.lineTo(n+i,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*i,l=Math.sin(Math.PI/4)*i,t.moveTo(n-s,a-l),t.lineTo(n+s,a+l),t.moveTo(n-s,a+l),t.lineTo(n+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(n,a+i),t.lineTo(n,a-i),t.moveTo(n-i,a),t.lineTo(n+i,a),s=Math.cos(Math.PI/4)*i,l=Math.sin(Math.PI/4)*i,t.moveTo(n-s,a-l),t.lineTo(n+s,a+l),t.moveTo(n-s,a+l),t.lineTo(n+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(n-i,a),t.lineTo(n+i,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(n,a),t.lineTo(n+i,a),t.closePath()}t.stroke()}}else t.drawImage(e,n-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,i,n){if(i.steppedLine)return"after"===i.steppedLine&&!n||"after"!==i.steppedLine&&n?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y),void t.lineTo(i.x,i.y);i.tension?t.bezierCurveTo(n?e.controlPointPreviousX:e.controlPointNextX,n?e.controlPointPreviousY:e.controlPointNextY,n?i.controlPointNextX:i.controlPointPreviousX,n?i.controlPointNextY:i.controlPointPreviousY,i.x,i.y):t.lineTo(i.x,i.y)}};n.clear=i.clear,n.drawRoundedRectangle=function(t){t.beginPath(),i.roundedRect.apply(i,arguments),t.closePath()}},{42:42}],42:[function(t,e,i){"use strict";var n,a={noop:function(){},uid:(n=0,function(){return n++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,i){return a.valueOrDefault(a.isArray(t)?t[e]:t,i)},callback:function(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)},each:function(t,e,i,n){var o,r,s;if(a.isArray(t))if(r=t.length,n)for(o=r-1;o>=0;o--)e.call(i,t[o],o);else for(o=0;o<r;o++)e.call(i,t[o],o);else if(a.isObject(t))for(r=(s=Object.keys(t)).length,o=0;o<r;o++)e.call(i,t[s[o]],s[o])},arrayEquals:function(t,e){var i,n,o,r;if(!t||!e||t.length!==e.length)return!1;for(i=0,n=t.length;i<n;++i)if(o=t[i],r=e[i],o instanceof Array&&r instanceof Array){if(!a.arrayEquals(o,r))return!1}else if(o!==r)return!1;return!0},clone:function(t){if(a.isArray(t))return t.map(a.clone);if(a.isObject(t)){for(var e={},i=Object.keys(t),n=i.length,o=0;o<n;++o)e[i[o]]=a.clone(t[i[o]]);return e}return t},_merger:function(t,e,i,n){var o=e[t],r=i[t];a.isObject(o)&&a.isObject(r)?a.merge(o,r,n):e[t]=a.clone(r)},_mergerIf:function(t,e,i){var n=e[t],o=i[t];a.isObject(n)&&a.isObject(o)?a.mergeIf(n,o):e.hasOwnProperty(t)||(e[t]=a.clone(o))},merge:function(t,e,i){var n,o,r,s,l,u=a.isArray(e)?e:[e],d=u.length;if(!a.isObject(t))return t;for(n=(i=i||{}).merger||a._merger,o=0;o<d;++o)if(e=u[o],a.isObject(e))for(l=0,s=(r=Object.keys(e)).length;l<s;++l)n(r[l],t,e,i);return t},mergeIf:function(t,e){return a.merge(t,e,{merger:a._mergerIf})},extend:function(t){for(var e=function(e,i){t[i]=e},i=1,n=arguments.length;i<n;++i)a.each(arguments[i],e);return t},inherits:function(t){var e=this,i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},n=function(){this.constructor=i};return n.prototype=e.prototype,i.prototype=new n,i.extend=a.inherits,t&&a.extend(i.prototype,t),i.__super__=e.prototype,i}};e.exports=a,a.callCallback=a.callback,a.indexOf=function(t,e,i){return Array.prototype.indexOf.call(t,e,i)},a.getValueOrDefault=a.valueOrDefault,a.getValueAtIndexOrDefault=a.valueAtIndexOrDefault},{}],43:[function(t,e,i){"use strict";var n=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===t?1:(i||(i=.3),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i))},easeOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===t?1:(i||(i=.3),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/i)+1)},easeInOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:2==(t/=.5)?1:(i||(i=.45),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),t<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*.5+1)},easeInBack:function(t){return t*t*(2.70158*t-1.70158)},easeOutBack:function(t){return(t-=1)*t*(2.70158*t+1.70158)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},n.easingEffects=a},{42:42}],44:[function(t,e,i){"use strict";var n=t(42);e.exports={toLineHeight:function(t,e){var i=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,i,a,o;return n.isObject(t)?(e=+t.top||0,i=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=i=a=o=+t||0,{top:e,right:i,bottom:a,left:o,height:e+a,width:o+i}},resolve:function(t,e,i){var a,o,r;for(a=0,o=t.length;a<o;++a)if(void 0!==(r=t[a])&&(void 0!==e&&"function"==typeof r&&(r=r(e)),void 0!==i&&n.isArray(r)&&(r=r[i]),void 0!==r))return r}}},{42:42}],45:[function(t,e,i){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,i){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,i){"use strict";var n=t(45),a="$chartjs",o="chartjs-",r=o+"render-monitor",s=o+"render-animation",l=["animationstart","webkitAnimationStart"],u={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function d(t,e){var i=n.getStyle(t,e),a=i&&i.match(/^(\d+)(\.\d+)?px$/);return a?Number(a[1]):void 0}var c=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};function h(t,e,i){t.addEventListener(e,i,c)}function f(t,e,i){t.removeEventListener(e,i,c)}function g(t,e,i,n,a){return{type:t,chart:e,native:a||null,x:void 0!==i?i:null,y:void 0!==n?n:null}}function p(t,e,i){var u,d,c,f,p,m,v,b,x=t[a]||(t[a]={}),y=x.resizer=function(t){var e=document.createElement("div"),i=o+"size-monitor",n="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=n,e.className=i,e.innerHTML='<div class="'+i+'-expand" style="'+n+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+i+'-shrink" style="'+n+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var s=function(){e._reset(),t()};return h(a,"scroll",s.bind(a,"expand")),h(r,"scroll",s.bind(r,"shrink")),e}((u=function(){if(x.resizer)return e(g("resize",i))},c=!1,f=[],function(){f=Array.prototype.slice.call(arguments),d=d||this,c||(c=!0,n.requestAnimFrame.call(window,function(){c=!1,u.apply(d,f)}))}));m=function(){if(x.resizer){var e=t.parentNode;e&&e!==y.parentNode&&e.insertBefore(y,e.firstChild),y._reset()}},v=(p=t)[a]||(p[a]={}),b=v.renderProxy=function(t){t.animationName===s&&m()},n.each(l,function(t){h(p,t,b)}),v.reflow=!!p.offsetParent,p.classList.add(r)}function m(t){var e,i,o,s=t[a]||{},u=s.resizer;delete s.resizer,i=(e=t)[a]||{},(o=i.renderProxy)&&(n.each(l,function(t){f(e,t,o)}),delete i.renderProxy),e.classList.remove(r),u&&u.parentNode&&u.parentNode.removeChild(u)}e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,i,n="from{opacity:0.99}to{opacity:1}";e="@-webkit-keyframes "+s+"{"+n+"}@keyframes "+s+"{"+n+"}."+r+"{-webkit-animation:"+s+" 0.001s;animation:"+s+" 0.001s;}",i=(t=this)._style||document.createElement("style"),t._style||(t._style=i,e="/* Chart.js */\n"+e,i.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(i)),i.appendChild(document.createTextNode(e))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){var i=t.style,n=t.getAttribute("height"),o=t.getAttribute("width");if(t[a]={initial:{height:n,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",null===o||""===o){var r=d(t,"width");void 0!==r&&(t.width=r)}if(null===n||""===n)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=d(t,"height");void 0!==r&&(t.height=s)}}(t,e),i):null},releaseContext:function(t){var e=t.canvas;if(e[a]){var i=e[a].initial;["height","width"].forEach(function(t){var a=i[t];n.isNullOrUndef(a)?e.removeAttribute(t):e.setAttribute(t,a)}),n.each(i.style||{},function(t,i){e.style[i]=t}),e.width=e.width,delete e[a]}},addEventListener:function(t,e,i){var o=t.canvas;if("resize"!==e){var r=i[a]||(i[a]={});h(o,e,(r.proxies||(r.proxies={}))[t.id+"_"+e]=function(e){var a,o,r,s;i((o=t,r=u[(a=e).type]||a.type,s=n.getRelativePosition(a,o),g(r,o,s.x,s.y,a)))})}else p(o,i,t)},removeEventListener:function(t,e,i){var n=t.canvas;if("resize"!==e){var o=((i[a]||{}).proxies||{})[t.id+"_"+e];o&&f(n,e,o)}else m(n)}},n.addEvent=h,n.removeEvent=f},{45:45}],48:[function(t,e,i){"use strict";var n=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=n.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,i){"use strict";e.exports={},e.exports.filler=t(50),e.exports.legend=t(51),e.exports.title=t(52)},{50:50,51:51,52:52}],50:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("global",{plugins:{filler:{propagate:!0}}});var r={dataset:function(t){var e=t.fill,i=t.chart,n=i.getDatasetMeta(e),a=n&&i.isDatasetVisible(e)&&n.dataset._children||[],o=a.length||0;return o?function(t,e){return e<o&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,i=e?e.x:null,n=e?e.y:null;return function(t){return{x:null===i?t.x:i,y:null===n?t.y:n}}}};function s(t,e,i){var n,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(n=parseFloat(o,10),isFinite(n)&&Math.floor(n)===n)return"-"!==o[0]&&"+"!==o[0]||(n=e+n),!(n===e||n<0||n>=i)&&n;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function l(t){var e,i=t.el._model||{},n=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===i.scaleBottom?n.bottom:i.scaleBottom:"end"===a?o=void 0===i.scaleTop?n.top:i.scaleTop:void 0!==i.scaleZero?o=i.scaleZero:n.getBasePosition?o=n.getBasePosition():n.getBasePixel&&(o=n.getBasePixel()),null!=o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return{x:(e=n.isHorizontal())?o:null,y:e?null:o}}return null}function u(t,e,i){var n,a=t[e].fill,o=[e];if(!i)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(n=t[a]))return!1;if(n.visible)return a;o.push(a),a=n.fill}return!1}function d(t){return t&&!t.skip}function c(t,e,i,n,a){var r;if(n&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<n;++r)o.canvas.lineTo(t,e[r-1],e[r]);for(t.lineTo(i[a-1].x,i[a-1].y),r=a-1;r>0;--r)o.canvas.lineTo(t,i[r],i[r-1],!0)}}e.exports={id:"filler",afterDatasetsUpdate:function(t,e){var i,n,o,d,c,h,f,g=(t.data.datasets||[]).length,p=e.propagate,m=[];for(n=0;n<g;++n)d=null,(o=(i=t.getDatasetMeta(n)).dataset)&&o._model&&o instanceof a.Line&&(d={visible:t.isDatasetVisible(n),fill:s(o,n,g),chart:t,el:o}),i.$filler=d,m.push(d);for(n=0;n<g;++n)(d=m[n])&&(d.fill=u(m,n,p),d.boundary=l(d),d.mapper=(void 0,f=void 0,h=(c=d).fill,f="dataset",!1===h?null:(isFinite(h)||(f="boundary"),r[f](c))))},beforeDatasetDraw:function(t,e){var i=e.meta.$filler;if(i){var a=t.ctx,r=i.el,s=r._view,l=r._children||[],u=i.mapper,h=s.backgroundColor||n.global.defaultColor;u&&h&&l.length&&(o.canvas.clipArea(a,t.chartArea),function(t,e,i,n,a,o){var r,s,l,u,h,f,g,p=e.length,m=n.spanGaps,v=[],b=[],x=0,y=0;for(t.beginPath(),r=0,s=p+!!o;r<s;++r)h=i(u=e[l=r%p]._view,l,n),f=d(u),g=d(h),f&&g?(x=v.push(u),y=b.push(h)):x&&y&&(m?(f&&v.push(u),g&&b.push(h)):(c(t,v,b,x,y),x=y=0,v=[],b=[]));c(t,v,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}(a,l,u,s,h,r._loop),o.canvas.unclipArea(a))}}}},{25:25,40:40,45:45}],51:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(30),s=o.noop;function l(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}n._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var i=e.datasetIndex,n=this.chart,a=n.getDatasetMeta(i);a.hidden=null===a.hidden?!n.data.datasets[i].hidden:null,n.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return o.isArray(e.datasets)?e.datasets.map(function(e,i){return{text:e.label,fillStyle:o.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:i}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var i=0;i<t.data.datasets.length;i++)e.push('<li><span style="background-color:'+t.data.datasets[i].backgroundColor+'"></span>'),t.data.datasets[i].label&&e.push(t.data.datasets[i].label),e.push("</li>");return e.push("</ul>"),e.join("")}});var u=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n.margins=i,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeBuildLabels(),n.buildLabels(),n.afterBuildLabels(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},i=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(i=i.filter(function(i){return e.filter(i,t.chart.data)})),t.options.reverse&&i.reverse(),t.legendItems=i},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=t.options,i=e.labels,a=e.display,r=t.ctx,s=n.global,u=o.valueOrDefault,d=u(i.fontSize,s.defaultFontSize),c=u(i.fontStyle,s.defaultFontStyle),h=u(i.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,m=t.isHorizontal();if(m?(p.width=t.maxWidth,p.height=a?10:0):(p.width=a?10:0,p.height=t.maxHeight),a)if(r.font=f,m){var v=t.lineWidths=[0],b=t.legendItems.length?d+i.padding:0;r.textAlign="left",r.textBaseline="top",o.each(t.legendItems,function(e,n){var a=l(i,d)+d/2+r.measureText(e.text).width;v[v.length-1]+a+i.padding>=t.width&&(b+=d+i.padding,v[v.length]=t.left),g[n]={left:0,top:0,width:a,height:d},v[v.length-1]+=a+i.padding}),p.height+=b}else{var x=i.padding,y=t.columnWidths=[],k=i.padding,M=0,w=0,S=d+x;o.each(t.legendItems,function(t,e){var n=l(i,d)+d/2+r.measureText(t.text).width;w+S>p.height&&(k+=M+i.padding,y.push(M),M=0,w=0),M=Math.max(M,n),w+=S,g[e]={left:0,top:0,width:n,height:d}}),k+=M,y.push(M),p.width+=k}t.width=p.width,t.height=p.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,i=e.labels,a=n.global,r=a.elements.line,s=t.width,u=t.lineWidths;if(e.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(i.fontColor,a.defaultFontColor),g=h(i.fontSize,a.defaultFontSize),p=h(i.fontStyle,a.defaultFontStyle),m=h(i.fontFamily,a.defaultFontFamily),v=o.fontString(g,p,m);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var b=l(i,g),x=t.legendHitBoxes,y=t.isHorizontal();d=y?{x:t.left+(s-u[0])/2,y:t.top+i.padding,line:0}:{x:t.left+i.padding,y:t.top+i.padding,line:0};var k=g+i.padding;o.each(t.legendItems,function(n,l){var f,p,m,v,M,w=c.measureText(n.text).width,S=b+g/2+w,C=d.x,_=d.y;y?C+S>=s&&(_=d.y+=k,d.line++,C=d.x=t.left+(s-u[d.line])/2):_+k>t.bottom&&(C=d.x=C+t.columnWidths[d.line]+i.padding,_=d.y=t.top+i.padding,d.line++),function(t,i,n){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(n.fillStyle,a.defaultColor),c.lineCap=h(n.lineCap,r.borderCapStyle),c.lineDashOffset=h(n.lineDashOffset,r.borderDashOffset),c.lineJoin=h(n.lineJoin,r.borderJoinStyle),c.lineWidth=h(n.lineWidth,r.borderWidth),c.strokeStyle=h(n.strokeStyle,a.defaultColor);var s=0===h(n.lineWidth,r.borderWidth);if(c.setLineDash&&c.setLineDash(h(n.lineDash,r.borderDash)),e.labels&&e.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=i+u;o.canvas.drawPoint(c,n.pointStyle,l,d,f)}else s||c.strokeRect(t,i,b,g),c.fillRect(t,i,b,g);c.restore()}}(C,_,n),x[l].left=C,x[l].top=_,f=n,p=w,v=b+(m=g/2)+C,M=_+m,c.fillText(f.text,v,M),f.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(v,M),c.lineTo(v+p,M),c.stroke()),y?d.x+=S+i.padding:d.y+=k})}},handleEvent:function(t){var e=this,i=e.options,n="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===n){if(!i.onHover)return}else{if("click"!==n)return;if(!i.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===n){i.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===n){i.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}});function d(t,e){var i=new u({ctx:t.ctx,options:e,chart:t});r.configure(t,i,e),r.addBox(t,i),t.legend=i}e.exports={id:"legend",_element:u,beforeInit:function(t){var e=t.options.legend;e&&d(t,e)},beforeUpdate:function(t){var e=t.options.legend,i=t.legend;e?(o.mergeIf(e,n.global.legend),i?(r.configure(t,i,e),i.options=e):d(t,e)):i&&(r.removeBox(t,i),delete t.legend)},afterEvent:function(t,e){var i=t.legend;i&&i.handleEvent(e)}}},{25:25,26:26,30:30,45:45}],52:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(30),s=o.noop;n._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var l=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:s,update:function(t,e,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n.margins=i,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeBuildLabels(),n.buildLabels(),n.afterBuildLabels(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:s,afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=o.valueOrDefault,i=t.options,a=i.display,r=e(i.fontSize,n.global.defaultFontSize),s=t.minSize,l=o.isArray(i.text)?i.text.length:1,u=o.options.toLineHeight(i.lineHeight,r),d=a?l*u+2*i.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:s,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,i=o.valueOrDefault,a=t.options,r=n.global;if(a.display){var s,l,u,d=i(a.fontSize,r.defaultFontSize),c=i(a.fontStyle,r.defaultFontStyle),h=i(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,m=0,v=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=i(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(l=b+(y-b)/2,u=v+p,s=y-b):(l="left"===a.position?b+p:y-p,u=v+(x-v)/2,s=x-v,m=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(m),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var M=0,w=0;w<k.length;++w)e.fillText(k[w],0,M,s),M+=g;else e.fillText(k,0,0,s);e.restore()}}});function u(t,e){var i=new l({ctx:t.ctx,options:e,chart:t});r.configure(t,i,e),r.addBox(t,i),t.titleBlock=i}e.exports={id:"title",_element:l,beforeInit:function(t){var e=t.options.title;e&&u(t,e)},beforeUpdate:function(t){var e=t.options.title,i=t.titleBlock;e?(o.mergeIf(e,n.global.title),i?(r.configure(t,i,e),i.options=e):u(t,e)):i&&(r.removeBox(t,i),delete t.titleBlock)}}},{25:25,26:26,30:30,45:45}],53:[function(t,e,i){"use strict";e.exports=function(t){var e=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t,e=this,i=e.getLabels();e.minIndex=0,e.maxIndex=i.length-1,void 0!==e.options.ticks.min&&(t=i.indexOf(e.options.ticks.min),e.minIndex=-1!==t?t:e.minIndex),void 0!==e.options.ticks.max&&(t=i.indexOf(e.options.ticks.max),e.maxIndex=-1!==t?t:e.maxIndex),e.min=i[e.minIndex],e.max=i[e.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var i=this,n=i.chart.data,a=i.isHorizontal();return n.yLabels&&!a?i.getRightValue(n.datasets[e].data[t]):i.ticks[t-i.minIndex]},getPixelForValue:function(t,e){var i,n=this,a=n.options.offset,o=Math.max(n.maxIndex+1-n.minIndex-(a?0:1),1);if(null!=t&&(i=n.isHorizontal()?t.x:t.y),void 0!==i||void 0!==t&&isNaN(e)){t=i||t;var r=n.getLabels().indexOf(t);e=-1!==r?r:e}if(n.isHorizontal()){var s=n.width/o,l=s*(e-n.minIndex);return a&&(l+=s/2),n.left+Math.round(l)}var u=n.height/o,d=u*(e-n.minIndex);return a&&(d+=u/2),n.top+Math.round(d)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,i=e.options.offset,n=Math.max(e._ticks.length-(i?0:1),1),a=e.isHorizontal(),o=(a?e.width:e.height)/n;return t-=a?e.left:e.top,i&&(t-=o/2),(t<=0?0:Math.round(t/o))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",e,{position:"bottom"})}},{}],54:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},i=t.LinearScaleBase.extend({determineDataLimits:function(){var t=this,e=t.options,i=t.chart,n=i.data.datasets,o=t.isHorizontal();function r(e){return o?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null;var s=e.stacked;if(void 0===s&&a.each(n,function(t,e){if(!s){var n=i.getDatasetMeta(e);i.isDatasetVisible(e)&&r(n)&&void 0!==n.stack&&(s=!0)}}),e.stacked||s){var l={};a.each(n,function(n,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===e.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&r(s)&&a.each(n.data,function(i,n){var a=+t.getRightValue(i);isNaN(a)||s.data[n].hidden||(d[n]=d[n]||0,c[n]=c[n]||0,e.relativePoints?d[n]=100:a<0?c[n]+=a:d[n]+=a)})}),a.each(l,function(e){var i=e.positiveValues.concat(e.negativeValues),n=a.min(i),o=a.max(i);t.min=null===t.min?n:Math.min(t.min,n),t.max=null===t.max?o:Math.max(t.max,o)})}else a.each(n,function(e,n){var o=i.getDatasetMeta(n);i.isDatasetVisible(n)&&r(o)&&a.each(e.data,function(e,i){var n=+t.getRightValue(e);isNaN(n)||o.data[i].hidden||(null===t.min?t.min=n:n<t.min&&(t.min=n),null===t.max?t.max=n:n>t.max&&(t.max=n))})});t.min=isFinite(t.min)&&!isNaN(t.min)?t.min:0,t.max=isFinite(t.max)&&!isNaN(t.max)?t.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var i=a.valueOrDefault(e.fontSize,n.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*i)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this,i=e.start,n=+e.getRightValue(t),a=e.end-i;return e.isHorizontal()?e.left+e.width/a*(n-i):e.bottom-e.height/a*(n-i)},getValueForPixel:function(t){var e=this,i=e.isHorizontal(),n=i?e.width:e.height,a=(i?t-e.left:e.bottom-t)/n;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",i,e)}},{25:25,34:34,45:45}],55:[function(t,e,i){"use strict";var n=t(45);e.exports=function(t){var e=n.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var i=n.sign(t.min),a=n.sign(t.max);i<0&&a<0?t.max=0:i>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,i=t.getTickLimit(),a={maxTicks:i=Math.max(2,i),min:e.min,max:e.max,stepSize:n.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=function(t,e){var i,a=[];if(t.stepSize&&t.stepSize>0)i=t.stepSize;else{var o=n.niceNum(e.max-e.min,!1);i=n.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/i)*i,s=Math.ceil(e.max/i)*i;t.min&&t.max&&t.stepSize&&n.almostWhole((t.max-t.min)/t.stepSize,i/1e3)&&(r=t.min,s=t.max);var l=(s-r)/i;l=n.almostEquals(l,Math.round(l),i/1e3)?Math.round(l):Math.ceil(l);var u=1;i<1&&(u=Math.pow(10,i.toString().length-2),r=Math.round(r*u)/u,s=Math.round(s*u)/u),a.push(void 0!==t.min?t.min:r);for(var d=1;d<l;++d)a.push(Math.round((r+d*i)*u)/u);return a.push(void 0!==t.max?t.max:s),a}(a,t);t.handleDirectionalChanges(),t.max=n.max(o),t.min=n.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{45:45}],56:[function(t,e,i){"use strict";var n=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},i=t.Scale.extend({determineDataLimits:function(){var t=this,e=t.options,i=t.chart,a=i.data.datasets,o=t.isHorizontal();function r(e){return o?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null,t.minNotZero=null;var s=e.stacked;if(void 0===s&&n.each(a,function(t,e){if(!s){var n=i.getDatasetMeta(e);i.isDatasetVisible(e)&&r(n)&&void 0!==n.stack&&(s=!0)}}),e.stacked||s){var l={};n.each(a,function(a,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===e.stacked&&void 0===s.stack?o:"",s.stack].join(".");i.isDatasetVisible(o)&&r(s)&&(void 0===l[u]&&(l[u]=[]),n.each(a.data,function(e,i){var n=l[u],a=+t.getRightValue(e);isNaN(a)||s.data[i].hidden||a<0||(n[i]=n[i]||0,n[i]+=a)}))}),n.each(l,function(e){if(e.length>0){var i=n.min(e),a=n.max(e);t.min=null===t.min?i:Math.min(t.min,i),t.max=null===t.max?a:Math.max(t.max,a)}})}else n.each(a,function(e,a){var o=i.getDatasetMeta(a);i.isDatasetVisible(a)&&r(o)&&n.each(e.data,function(e,i){var n=+t.getRightValue(e);isNaN(n)||o.data[i].hidden||n<0||(null===t.min?t.min=n:n<t.min&&(t.min=n),null===t.max?t.max=n:n>t.max&&(t.max=n),0!==n&&(null===t.minNotZero||n<t.minNotZero)&&(t.minNotZero=n))})});this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks,i=n.valueOrDefault;t.min=i(e.min,t.min),t.max=i(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(n.log10(t.min))-1),t.max=Math.pow(10,Math.floor(n.log10(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(n.log10(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(n.log10(t.min))+1):10),null===t.minNotZero&&(t.min>0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(n.log10(t.max))):t.minNotZero=1)},buildTicks:function(){var t=this,e=t.options.ticks,i=!t.isHorizontal(),a={min:e.min,max:e.max},o=t.ticks=function(t,e){var i,a,o=[],r=n.valueOrDefault,s=r(t.min,Math.pow(10,Math.floor(n.log10(e.min)))),l=Math.floor(n.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(i=Math.floor(n.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,i)),o.push(s),s=a*Math.pow(10,i)):(i=Math.floor(n.log10(s)),a=Math.floor(s/Math.pow(10,i)));for(var d=i<0?Math.pow(10,Math.abs(i)):1;o.push(s),10==++a&&(a=1,d=++i>=0?1:d),s=Math.round(a*Math.pow(10,i)*d)/d,i<l||i===l&&a<u;);var c=r(t.max,s);return o.push(c),o}(a,t);t.max=n.max(o),t.min=n.min(o),e.reverse?(i=!i,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),i&&o.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},_getFirstTickValue:function(t){var e=Math.floor(n.log10(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},getPixelForValue:function(e){var i,a,o,r,s,l=this,u=l.options.ticks.reverse,d=n.log10,c=l._getFirstTickValue(l.minNotZero),h=0;return e=+l.getRightValue(e),u?(o=l.end,r=l.start,s=-1):(o=l.start,r=l.end,s=1),l.isHorizontal()?(i=l.width,a=u?l.right:l.left):(i=l.height,s*=-1,a=u?l.top:l.bottom),e!==o&&(0===o&&(i-=h=n.getValueOrDefault(l.options.ticks.fontSize,t.defaults.global.defaultFontSize),o=c),0!==e&&(h+=i/(d(r)-d(o))*(d(e)-d(o))),a+=s*h),a},getValueForPixel:function(e){var i,a,o,r,s=this,l=s.options.ticks.reverse,u=n.log10,d=s._getFirstTickValue(s.minNotZero);if(l?(a=s.end,o=s.start):(a=s.start,o=s.end),s.isHorizontal()?(i=s.width,r=l?s.right-e:e-s.left):(i=s.height,r=l?e-s.top:s.bottom-e),r!==a){if(0===a){var c=n.getValueOrDefault(s.options.ticks.fontSize,t.defaults.global.defaultFontSize);r-=c,i-=c,a=d}r*=u(o)-u(a),r/=i,r=Math.pow(10,u(a)+r)}return r}});t.scaleService.registerScaleType("logarithmic",i,e)}},{34:34,45:45}],57:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(34);e.exports=function(t){var e=n.global,i={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function r(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function s(t){var i=t.options.pointLabels,n=a.valueOrDefault(i.fontSize,e.defaultFontSize),o=a.valueOrDefault(i.fontStyle,e.defaultFontStyle),r=a.valueOrDefault(i.fontFamily,e.defaultFontFamily);return{size:n,style:o,family:r,font:a.fontString(n,o,r)}}function l(t,e,i,n,a){return t===n||t===a?{start:e-i/2,end:e+i/2}:t<n||t>a?{start:e-i-5,end:e}:{start:e,end:e+i+5}}function u(t,e,i,n){if(a.isArray(e))for(var o=i.y,r=1.5*n,s=0;s<e.length;++s)t.fillText(e[s],i.x,o),o+=r;else t.fillText(e,i.x,i.y)}function d(t){return a.isNumber(t)?t:0}var c=t.LinearScaleBase.extend({setDimensions:function(){var t=this,i=t.options,n=i.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var o=a.min([t.height,t.width]),r=a.valueOrDefault(n.fontSize,e.defaultFontSize);t.drawingArea=i.display?o/2-(r/2+n.backdropPaddingY):o/2},determineDataLimits:function(){var t=this,e=t.chart,i=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(o,r){if(e.isDatasetVisible(r)){var s=e.getDatasetMeta(r);a.each(o.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||s.data[a].hidden||(i=Math.min(o,i),n=Math.max(o,n))})}}),t.min=i===Number.POSITIVE_INFINITY?0:i,t.max=n===Number.NEGATIVE_INFINITY?0:n,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,i=a.valueOrDefault(t.fontSize,e.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*i)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,e;this.options.pointLabels.display?function(t){var e,i,n,o=s(t),u=Math.min(t.height/2,t.width/2),d={r:t.width,l:0,t:t.height,b:0},c={};t.ctx.font=o.font,t._pointLabelSizes=[];var h,f,g,p=r(t);for(e=0;e<p;e++){n=t.getPointPosition(e,u),h=t.ctx,f=o.size,g=t.pointLabels[e]||"",i=a.isArray(g)?{w:a.longestText(h,h.font,g),h:g.length*f+1.5*(g.length-1)*f}:{w:h.measureText(g).width,h:f},t._pointLabelSizes[e]=i;var m=t.getIndexAngle(e),v=a.toDegrees(m)%360,b=l(v,n.x,i.w,0,180),x=l(v,n.y,i.h,90,270);b.start<d.l&&(d.l=b.start,c.l=m),b.end>d.r&&(d.r=b.end,c.r=m),x.start<d.t&&(d.t=x.start,c.t=m),x.end>d.b&&(d.b=x.end,c.b=m)}t.setReductions(u,d,c)}(this):(t=this,e=Math.min(t.height/2,t.width/2),t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0))},setReductions:function(t,e,i){var n=e.l/Math.sin(i.l),a=Math.max(e.r-this.width,0)/Math.sin(i.r),o=-e.t/Math.cos(i.t),r=-Math.max(e.b-this.height,0)/Math.cos(i.b);n=d(n),a=d(a),o=d(o),r=d(r),this.drawingArea=Math.min(Math.round(t-(n+a)/2),Math.round(t-(o+r)/2)),this.setCenterPoint(n,a,o,r)},setCenterPoint:function(t,e,i,n){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,s=i+a.drawingArea,l=a.height-n-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/r(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var i=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*i:(t-e.min)*i},getPointPosition:function(t,e){var i=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+this.xCenter,y:Math.round(Math.sin(i)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0)},draw:function(){var t=this,i=t.options,n=i.gridLines,o=i.ticks,l=a.valueOrDefault;if(i.display){var d=t.ctx,c=this.getIndexAngle(0),h=l(o.fontSize,e.defaultFontSize),f=l(o.fontStyle,e.defaultFontStyle),g=l(o.fontFamily,e.defaultFontFamily),p=a.fontString(h,f,g);a.each(t.ticks,function(i,s){if(s>0||o.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[s]);if(n.display&&0!==s&&function(t,e,i,n){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(e.color,n-1),o.lineWidth=a.valueAtIndexOrDefault(e.lineWidth,n-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=r(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u<s;u++)l=t.getPointPosition(u,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}(t,n,u,s),o.display){var f=l(o.fontColor,e.defaultFontColor);if(d.font=p,d.save(),d.translate(t.xCenter,t.yCenter),d.rotate(c),o.showLabelBackdrop){var g=d.measureText(i).width;d.fillStyle=o.backdropColor,d.fillRect(-g/2-o.backdropPaddingX,-u-h/2-o.backdropPaddingY,g+2*o.backdropPaddingX,h+2*o.backdropPaddingY)}d.textAlign="center",d.textBaseline="middle",d.fillStyle=f,d.fillText(i,0,-u),d.restore()}}}),(i.angleLines.display||i.pointLabels.display)&&function(t){var i=t.ctx,n=t.options,o=n.angleLines,l=n.pointLabels;i.lineWidth=o.lineWidth,i.strokeStyle=o.color;var d,c,h,f,g=t.getDistanceFromCenterForValue(n.ticks.reverse?t.min:t.max),p=s(t);i.textBaseline="top";for(var m=r(t)-1;m>=0;m--){if(o.display){var v=t.getPointPosition(m,g);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(v.x,v.y),i.stroke(),i.closePath()}if(l.display){var b=t.getPointPosition(m,g+5),x=a.valueAtIndexOrDefault(l.fontColor,m,e.defaultFontColor);i.font=p.font,i.fillStyle=x;var y=t.getIndexAngle(m),k=a.toDegrees(y);i.textAlign=0===(f=k)||180===f?"center":f<180?"left":"right",d=k,c=t._pointLabelSizes[m],h=b,90===d||270===d?h.y-=c.h/2:(d>270||d<90)&&(h.y-=c.h),u(i,t.pointLabels[m]||"",b,p.size)}}}(t)}}});t.scaleService.registerScaleType("radialLinear",c,i)}},{25:25,34:34,45:45}],58:[function(t,e,i){"use strict";var n=t(1);n="function"==typeof n?n:window.moment;var a=t(25),o=t(45),r=Number.MIN_SAFE_INTEGER||-9007199254740991,s=Number.MAX_SAFE_INTEGER||9007199254740991,l={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},u=Object.keys(l);function d(t,e){return t-e}function c(t){var e,i,n,a={},o=[];for(e=0,i=t.length;e<i;++e)a[n=t[e]]||(a[n]=!0,o.push(n));return o}function h(t,e,i,n){var a=function(t,e,i){for(var n,a,o,r=0,s=t.length-1;r>=0&&r<=s;){if(a=t[(n=r+s>>1)-1]||null,o=t[n],!a)return{lo:null,hi:o};if(o[e]<i)r=n+1;else{if(!(a[e]>i))return{lo:a,hi:o};s=n-1}}return{lo:o,hi:null}}(t,e,i),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],r=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=r[e]-o[e],l=s?(i-o[e])/s:0,u=(r[n]-o[n])*l;return o[n]+u}function f(t,e){var i=e.parser,a=e.parser||e.format;return"function"==typeof i?i(t):"string"==typeof t&&"string"==typeof a?n(t,a):(t instanceof n||(t=n(t)),t.isValid()?t:"function"==typeof a?a(t):t)}function g(t,e){if(o.isNullOrUndef(t))return null;var i=e.options.time,n=f(e.getRightValue(t),i);return n.isValid()?(i.round&&n.startOf(i.round),n.valueOf()):null}function p(t){for(var e=u.indexOf(t)+1,i=u.length;e<i;++e)if(l[u[e]].common)return u[e]}function m(t,e,i,a){var r,d=a.time,c=d.unit||function(t,e,i,n){var a,o,r,d=u.length;for(a=u.indexOf(t);a<d-1;++a)if(r=(o=l[u[a]]).steps?o.steps[o.steps.length-1]:s,o.common&&Math.ceil((i-e)/(r*o.size))<=n)return u[a];return u[d-1]}(d.minUnit,t,e,i),h=p(c),f=o.valueOrDefault(d.stepSize,d.unitStepSize),g="week"===c&&d.isoWeekday,m=a.ticks.major.enabled,v=l[c],b=n(t),x=n(e),y=[];for(f||(f=function(t,e,i,n){var a,o,r,s=e-t,u=l[i],d=u.size,c=u.steps;if(!c)return Math.ceil(s/(n*d));for(a=0,o=c.length;a<o&&(r=c[a],!(Math.ceil(s/(d*r))<=n));++a);return r}(t,e,c,i)),g&&(b=b.isoWeekday(g),x=x.isoWeekday(g)),b=b.startOf(g?"day":c),(x=x.startOf(g?"day":c))<e&&x.add(1,c),r=n(b),m&&h&&!g&&!d.round&&(r.startOf(h),r.add(~~((b-r)/(v.size*f))*f,c));r<x;r.add(f,c))y.push(+r);return y.push(+r),y}e.exports=function(t){var e=t.Scale.extend({initialize:function(){if(!n)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this.options;return e.time&&e.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(this,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,i,a,l,u,h=this,f=h.chart,p=h.options.time,m=p.unit||"day",v=s,b=r,x=[],y=[],k=[];for(t=0,i=f.data.labels.length;t<i;++t)k.push(g(f.data.labels[t],h));for(t=0,i=(f.data.datasets||[]).length;t<i;++t)if(f.isDatasetVisible(t))if(l=f.data.datasets[t].data,o.isObject(l[0]))for(y[t]=[],e=0,a=l.length;e<a;++e)u=g(l[e],h),x.push(u),y[t][e]=u;else x.push.apply(x,k),y[t]=k.slice(0);else y[t]=[];k.length&&(k=c(k).sort(d),v=Math.min(v,k[0]),b=Math.max(b,k[k.length-1])),x.length&&(x=c(x).sort(d),v=Math.min(v,x[0]),b=Math.max(b,x[x.length-1])),v=g(p.min,h)||v,b=g(p.max,h)||b,v=v===s?+n().startOf(m):v,b=b===r?+n().endOf(m)+1:b,h.min=Math.min(v,b),h.max=Math.max(v+1,b),h._horizontal=h.isHorizontal(),h._table=[],h._timestamps={data:x,datasets:y,labels:k}},buildTicks:function(){var t,e,i,a,o,r,s,d,c,v,b,x,y=this,k=y.min,M=y.max,w=y.options,S=w.time,C=[],_=[];switch(w.ticks.source){case"data":C=y._timestamps.data;break;case"labels":C=y._timestamps.labels;break;case"auto":default:C=m(k,M,y.getLabelCapacity(k),w)}for("ticks"===w.bounds&&C.length&&(k=C[0],M=C[C.length-1]),k=g(S.min,y)||k,M=g(S.max,y)||M,t=0,e=C.length;t<e;++t)(i=C[t])>=k&&i<=M&&_.push(i);return y.min=k,y.max=M,y._unit=S.unit||function(t,e,i,a){var o,r,s=n.duration(n(a).diff(n(i)));for(o=u.length-1;o>=u.indexOf(e);o--)if(r=u[o],l[r].common&&s.as(r)>=t.length)return r;return u[e?u.indexOf(e):0]}(_,S.minUnit,y.min,y.max),y._majorUnit=p(y._unit),y._table=function(t,e,i,n){if("linear"===n||!t.length)return[{time:e,pos:0},{time:i,pos:1}];var a,o,r,s,l,u=[],d=[e];for(a=0,o=t.length;a<o;++a)(s=t[a])>e&&s<i&&d.push(s);for(d.push(i),a=0,o=d.length;a<o;++a)l=d[a+1],r=d[a-1],s=d[a],void 0!==r&&void 0!==l&&Math.round((l+r)/2)===s||u.push({time:s,pos:a/(o-1)});return u}(y._timestamps.data,k,M,w.distribution),y._offsets=(a=y._table,o=_,r=k,s=M,b=0,x=0,(d=w).offset&&o.length&&(d.time.min||(c=o.length>1?o[1]:s,v=o[0],b=(h(a,"time",c,"pos")-h(a,"time",v,"pos"))/2),d.time.max||(c=o[o.length-1],v=o.length>1?o[o.length-2]:r,x=(h(a,"time",c,"pos")-h(a,"time",v,"pos"))/2)),{left:b,right:x}),y._labelFormat=function(t,e){var i,n,a,o=t.length;for(i=0;i<o;i++){if(0!==(n=f(t[i],e)).millisecond())return"MMM D, YYYY h:mm:ss.SSS a";0===n.second()&&0===n.minute()&&0===n.hour()||(a=!0)}return a?"MMM D, YYYY h:mm:ss a":"MMM D, YYYY"}(y._timestamps.data,S),function(t,e){var i,a,o,r,s=[];for(i=0,a=t.length;i<a;++i)o=t[i],r=!!e&&o===+n(o).startOf(e),s.push({value:o,major:r});return s}(_,y._majorUnit)},getLabelForIndex:function(t,e){var i=this.chart.data,n=this.options.time,a=i.labels&&t<i.labels.length?i.labels[t]:"",r=i.datasets[e].data[t];return o.isObject(r)&&(a=this.getRightValue(r)),n.tooltipFormat?f(a,n).format(n.tooltipFormat):"string"==typeof a?a:f(a,n).format(this._labelFormat)},tickFormatFunction:function(t,e,i,n){var a=this.options,r=t.valueOf(),s=a.time.displayFormats,l=s[this._unit],u=this._majorUnit,d=s[u],c=t.clone().startOf(u).valueOf(),h=a.ticks.major,f=h.enabled&&u&&d&&r===c,g=t.format(n||(f?d:l)),p=f?h:a.ticks.minor,m=o.valueOrDefault(p.callback,p.userCallback);return m?m(g,e,i):g},convertTicksToLabels:function(t){var e,i,a=[];for(e=0,i=t.length;e<i;++e)a.push(this.tickFormatFunction(n(t[e].value),e,t));return a},getPixelForOffset:function(t){var e=this,i=e._horizontal?e.width:e.height,n=e._horizontal?e.left:e.top,a=h(e._table,"time",t,"pos");return n+i*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,i){var n=null;if(void 0!==e&&void 0!==i&&(n=this._timestamps.datasets[i][e]),null===n&&(n=g(t,this)),null!==n)return this.getPixelForOffset(n)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,i=e._horizontal?e.width:e.height,a=e._horizontal?e.left:e.top,o=(i?(t-a)/i:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,r=h(e._table,"pos",o,"time");return n(r)},getLabelWidth:function(t){var e=this.options.ticks,i=this.ctx.measureText(t).width,n=o.toRadians(e.maxRotation),r=Math.cos(n),s=Math.sin(n);return i*r+o.valueOrDefault(e.fontSize,a.global.defaultFontSize)*s},getLabelCapacity:function(t){var e=this,i=e.options.time.displayFormats.millisecond,a=e.tickFormatFunction(n(t),0,[],i),o=e.getLabelWidth(a),r=e.isHorizontal()?e.width:e.height,s=Math.floor(r/o);return s>0?s:1}});t.scaleService.registerScaleType("time",e,{position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}})}},{1:1,25:25,45:45}]},{},[7])(7)});
1
  /*!
2
  * Chart.js
3
  * http://chartjs.org/
4
+ * Version: 2.7.1
5
  *
6
+ * Copyright 2017 Nick Downie
7
  * Released under the MIT license
8
  * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
  */
10
+ window.robin=window.robin||{};!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window.robin:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)a(i[r]);return a}({1:[function(t,e,n){},{}],2:[function(t,e,n){function i(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3})$/i);if(i){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i[a]+i[a],16)}else if(i=t.match(/^#([a-fA-F0-9]{6})$/i)){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i.slice(2*a,2*a+2),16)}else if(i=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(a=0;a<e.length;a++)e[a]=parseInt(i[a+1]);n=parseFloat(i[4])}else if(i=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(a=0;a<e.length;a++)e[a]=Math.round(2.55*parseFloat(i[a+1]));n=parseFloat(i[4])}else if(i=t.match(/(\w+)/)){if("transparent"==i[1])return[0,0,0,0];if(!(e=c[i[1]]))return}for(var a=0;a<e.length;a++)e[a]=u(e[a],0,255);return n=n||0==n?u(n,0,1):1,e[3]=n,e}}function a(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function o(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function r(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(6);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?r(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:r,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:s,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{6:6}],3:[function(t,e,n){var i=t(5),a=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};o.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},o.prototype.setValues=function(t,e){var n,a=this.values,o=this.spaces,r=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(n=0;n<t.length;n++)a[t][n]=e[s[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(r[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in o)d!==t&&(a[d]=i[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},o.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.robin.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(l+s)/2,n=s==l?0:i<=.5?u/(s+l):u/(2-s-l),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],o=t[1],r=t[2],l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return n=0==s?0:u/s*1e3/10,s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=s/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function l(t){var e,n,i,a,o=t[0]/255,r=t[1]/255,l=t[2]/255;return a=Math.min(1-o,1-r,1-l),e=(1-o-a)/(1-a)||0,n=(1-r-a)/(1-a)||0,i=(1-l-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function s(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?a=(n=100*o/903.3)/100*7.787+16/116:(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return v(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:v,xyz2lab:m,xyz2lch:function(t){return y(m(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.robin.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,r=i.getMeta(),l=i.getDataset(),s=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(r.xAxisID),t._yScale=i.getScaleForId(r.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:l.label,label:a.data.labels[e],borderSkipped:s.borderSkipped?s.borderSkipped:u.borderSkipped,backgroundColor:s.backgroundColor?s.backgroundColor:o.valueAtIndexOrDefault(l.backgroundColor,e,u.backgroundColor),borderColor:s.borderColor?s.borderColor:o.valueAtIndexOrDefault(l.borderColor,e,u.borderColor),borderWidth:s.borderWidth?s.borderWidth:o.valueAtIndexOrDefault(l.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,o=i.getValueScale(),r=o.getBasePixel(),l=o.isHorizontal(),s=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,s);a.horizontal=l,a.base=n?r:u.base,a.x=l?n?r:u.head:d.center,a.y=l?d.center:n?r:u.head,a.height=l?d.size:void 0,a.width=l?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,o=i.getIndexScale().options.stacked,r=void 0===t?a.data.datasets.length:t+1,l=[];for(e=0;e<r;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===o||!0===o&&-1===l.indexOf(n.stack)||void 0===o&&(void 0===n.stack||-1===l.indexOf(n.stack)))&&l.push(n.stack);return l.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),o=n.index,r=[],l=i.isHorizontal(),s=l?i.left:i.top,u=s+(l?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)r.push(i.getPixelForValue(null,t,o));return{pixels:r,start:s,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,o,r,l,s=this,u=s.chart,d=s.getMeta(),c=s.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,p=d.stack,v=0;if(g||void 0===g&&void 0!==p)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===p&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(v+=a));return o=c.getPixelForValue(v),r=c.getPixelForValue(v+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i,a,r,l,s,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],p=f.length,v=n.start,m=n.end;return 1===p?(i=g>v?g-v:m-g,a=g<m?m-g:g-v):(e>0&&(i=(g-f[e-1])/2,e===p-1&&(a=i)),e<p-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),r=i*c.categoryPercentage,l=a*c.categoryPercentage,s=(r+l)/n.stackCount,u=s*c.barPercentage,u=Math.min(o.valueOrDefault(c.barThickness,u),o.valueOrDefault(c.maxBarThickness,1/0)),g-=r,g+=s*h,g+=(s-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),r=i.length,l=0;for(o.canvas.clipArea(e.ctx,e.chartArea);l<r;++l)isNaN(n.getRightValue(a.data[l]))||i[l].draw();o.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:o.valueAtIndexOrDefault(e.hoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:o.valueAtIndexOrDefault(e.hoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:o.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,r=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:o.valueAtIndexOrDefault(e.backgroundColor,n,r.backgroundColor),a.borderColor=i.borderColor?i.borderColor:o.valueAtIndexOrDefault(e.borderColor,n,r.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:o.valueAtIndexOrDefault(e.borderWidth,n,r.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;o.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),o=t.custom||{},r=i.getScaleForId(a.xAxisID),l=i.getScaleForId(a.yAxisID),s=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?r.getPixelForDecimal(.5):r.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?l.getBasePixel():l.getPixelForValue(u,e,d);t._xScale=r,t._yScale=l,t._options=s,t._datasetIndex=d,t._index=e,t._model={backgroundColor:s.backgroundColor,borderColor:s.borderColor,borderWidth:s.borderWidth,hitRadius:s.hitRadius,pointStyle:s.pointStyle,radius:n?0:s.radius,skip:o.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=o.valueOrDefault(n.hoverBackgroundColor,o.getHoverColor(n.backgroundColor)),e.borderColor=o.valueOrDefault(n.hoverBorderColor,o.getHoverColor(n.borderColor)),e.borderWidth=o.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,r=this,l=r.chart,s=l.data.datasets[r.index],u=t.custom||{},d=l.options.elements.point,c=o.options.resolve,h=s.data[e],f={},g={chart:l,dataIndex:e,dataset:s,datasetIndex:r.index},p=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=p.length;n<i;++n)f[a=p[n]]=c([u[a],s[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,s.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i],s=l&&l.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,i,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,i,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,i,d.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return o.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",o.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,r=a.elements.arc,l=i.right-i.left-r.borderWidth,s=i.bottom-i.top-r.borderWidth,u=Math.min(l,s),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,v={x:Math.cos(g),y:Math.sin(g)},m={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(v.x*(v.x<0?1:w),m.x*(m.x<0?1:w)),y:k?-1:Math.min(v.y*(v.y<0?1:w),m.y*(m.y<0?1:w))},S={x:b?1:Math.max(v.x*(v.x>0?1:w),m.x*(m.x>0?1:w)),y:x?1:Math.max(v.y*(v.y>0?1:w),m.y*(m.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),o.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,l=a.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=i.getDataset(),g=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(l.circumference/(2*Math.PI)),p=n&&s.animateScale?0:i.innerRadius,v=n&&s.animateScale?0:i.outerRadius,m=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:v,innerRadius:p,label:m(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),n&&s.animateRotate||(b.startAngle=0===e?l.rotation:i.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return o.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,i=(n=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),n=0,i=u.length;n<i;++n)r.updateElement(u[n],n,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=o.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=o.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||o.isArray(i.pointBorderWidth)?n=o.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,r=this,l=r.getMeta(),s=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:s.skip||isNaN(i)||isNaN(a),radius:s.radius||o.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:s.pointStyle||o.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:!!l.dataset._model&&l.dataset._model.steppedLine,hitRadius:s.hitRadius||o.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,o,r=this,l=r.chart,s=r.getMeta(),u=r.getScaleForId(s.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=l.data.datasets[i],"line"===(o=l.getDatasetMeta(i)).type&&o.yAxisID===u.id&&l.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,r=this,l=r.getMeta(),s=r.chart.chartArea,u=l.data||[];if(l.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===l.dataset._model.cubicInterpolationMode)o.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=o.splineCurve(o.previousItem(u,e)._model,i,o.nextItem(u,e)._model,l.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(r.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,s.left,s.right),i.controlPointPreviousY=t(i.controlPointPreviousY,s.top,s.bottom),i.controlPointNextX=t(i.controlPointNextX,s.left,s.right),i.controlPointNextY=t(i.controlPointNextY,s.top,s.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],r=n.chartArea,l=a.length,s=0;for(o.canvas.clipArea(n.ctx,r),e(t.getDataset(),n.options)&&i.dataset.draw(),o.canvas.unclipArea(n.ctx);s<l;++s)a[s].draw(r)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||o.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||o.valueAtIndexOrDefault(e.pointHoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||o.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),r.radius=a.radius||o.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,i),r.borderColor=e.getPointBorderColor(t,i),r.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i].custom||{},s=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,i,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,i,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,i,u.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),r=n.options,l=r.elements.arc,s=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((s-l.borderWidth/2)/2,0),n.innerRadius=Math.max(r.cutoutPercentage?n.outerRadius/100*r.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),o.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,r=i.getDataset(),l=a.options,s=l.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(r.data[e]),h=u.xCenter,f=u.yCenter,g=0,p=i.getMeta(),v=0;v<e;++v)isNaN(r.data[v])||p.data[v].hidden||++g;var m=l.startAngle,b=t.hidden?0:u.getDistanceFromCenterForValue(r.data[e]),x=m+c*g,y=x+(t.hidden?0:c),k=s.animateScale?0:u.getDistanceFromCenterForValue(r.data[e]);o.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?k:b,startAngle:n&&s.animateRotate?m:x,endAngle:n&&s.animateRotate?m:y,label:o.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return o.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,r=i.custom||{},l=e.getDataset(),s=e.chart.options.elements.line,u=e.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),o.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),n.dataset.pivot(),o.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),l=i.chart.scale,s=i.chart.options.elements.point,u=l.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{x:n?l.xCenter:u.x,y:n?l.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,s.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,s.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,s.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,s.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,s.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,s.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(n,i){var a=n._model,r=o.splineCurve(o.previousItem(e.data,i,!0)._model,a,o.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=n.radius?n.radius:o.valueAtIndexOrDefault(e.pointRadius,i,r.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,i,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=o.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=o.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),o.callback(e.render,[n,e],n),o.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(o.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(28),r=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function l(t){return"top"===t||"bottom"===t}var s=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var o=this;i=e(i);var l=r.acquireContext(n,i),s=l&&l.canvas,u=s&&s.height,d=s&&s.width;o.id=a.uid(),o.ctx=l,o.canvas=s,o.config=i,o.width=d,o.height=u,o.aspectRatio=u?d/u:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),l&&s?(o.initialize(),o.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return s.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),s.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,o=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(i))),l=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(i)));if((e.width!==r||e.height!==l)&&(i.width=e.width=r,i.height=e.height=l,i.style.width=r+"px",i.style.height=l+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:r,height:l};s.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},o=[];n.scales&&(o=o.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&o.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(o,function(n){var o=n.options,r=a.valueOrDefault(o.type,n.dtype),s=t.scaleService.getScaleConstructor(r);if(s){l(o.position)!==l(n.dposition)&&(o.position=n.dposition);var u=new s({id:o.id,options:o,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),l=a.type||e.config.type;if(r.type&&r.type!==l&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=l,n.push(r.type),r.controller)r.controller.updateIndex(o);else{var s=t.controllers[r.type];if(void 0===s)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new s(e,o),i.push(r.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==s.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),e.tooltip.initialize(),e.lastActive=[],s.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==s.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),s.notify(e,"afterScaleUpdate"),s.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==s.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);s.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==s.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),s.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,o=e.lazy;if(!1!==s.notify(n,"beforeRender")){var r=n.options.animation,l=function(t){s.notify(n,"afterRender"),a.callback(r&&r.onComplete,[t],n)};if(r&&(void 0!==i&&0!==i||void 0===i&&0!==r.duration)){var u=new t.Animation({numSteps:(i||r.duration)/16.66,easing:e.easing||r.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,o=i/e.numSteps;t.draw(n(o),o,i)},onAnimationProgress:r.onProgress,onAnimationComplete:l});t.animationService.addAnimation(n,u,i,o)}else n.draw(),l(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==s.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e._drawTooltip(t),s.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==s.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);s.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==s.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),s.notify(n,"afterDatasetDraw",[a]))},_drawTooltip:function(t){var e=this,n=e.tooltip,i={tooltip:n,easingValue:t};!1!==s.notify(e,"beforeTooltipDraw",[i])&&(n.draw(),s.notify(e,"afterTooltipDraw",[i]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=o.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,o=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);o&&(i.unbindEvents(),a.canvas.clear(i),r.releaseContext(i.ctx),i.canvas=null,i.ctx=null),s.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){r.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},r.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){r.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,o,r=n?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==s.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),s.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,o=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),o=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,o}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),o}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,o=i.indexOf(e);-1!==o&&i.splice(o,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;t<e;++t)o[t]=o[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=i.valueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=i.valueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,n,r(l.backgroundColor)),l.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,n,r(l.borderColor)),l.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,n,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var o,r,l,s,u,d,c,h,f,g=Object.keys(n);for(o=0,r=g.length;o<r;++o)if(l=g[o],d=n[l],e.hasOwnProperty(l)||(e[l]=d),(s=e[l])!==d&&"_"!==l[0]){if(t.hasOwnProperty(l)||(t[l]=s),u=t[l],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[l]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[l]=u+(d-u)*i;continue}e[l]=d}}var a=t(3),o=t(45),r=function(t){o.extend(this,t),this.initialize.apply(this,arguments)};o.extend(r.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=o.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,o=e._view;return n&&1!==t?(o||(o=e._view={}),a||(a=e._start={}),i(a,o,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return o.isNumber(this._model.x)&&o.isNumber(this._model.y)}}),r.extend=o.inherits,e.exports=r},{3:3,45:45}],27:[function(t,e,n){"use strict";var i=t(3),a=t(25),o=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function r(t,i,a){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],u=n(l),d=n(s),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(l,t,a):c,d?e(s,r,a):c):"none"}o.configMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var r=n[e]||{},l=i[e];"scales"===e?n[e]=o.scaleMerge(r,l):"scale"===e?n[e]=o.merge(r,[t.scaleService.getScaleDefaults(l.type),l]):o._merger(e,n,i,a)}})},o.scaleMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var r,l,s,u=i[e].length;for(n[e]||(n[e]=[]),r=0;r<u;++r)s=i[e][r],l=o.valueOrDefault(s.type,"xAxes"===e?"category":"linear"),r>=n[e].length&&n[e].push({}),!n[e][r].type||s.type&&s.type!==n[e][r].type?o.merge(n[e][r],[t.scaleService.getScaleDefaults(l),s]):o.merge(n[e][r],s)}else o._merger(e,n,i,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},o.findPreviousWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)<n},o.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e<l;++e)if(!(i=r[e]).model.skip){if(n=e>0?r[e-1]:null,(a=e<l-1?r[e+1]:null)&&!a.model.skip){var s=a.model.x-i.model.x;i.deltaK=0!==s?(a.model.y-i.model.y)/s:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<l-1;++e)i=r[e],a=r[e+1],i.model.skip||a.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<l;++e)(i=r[e]).model.skip||(n=e>0?r[e-1]:null,a=e<l-1?r[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},o.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,o=t.width;i.height=a*n,i.width=o*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=o+"px"}},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;u<s;u++)delete a[r[u]];r.splice(0,s)}return l},o.measureText=function(t,e,n,i,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,n.push(a)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i<o;++i)if(t.isDatasetVisible(i))for(a=0,r=(n=t.getDatasetMeta(i)).data.length;a<r;++a){var l=n.data[a];l._view.skip||e(l)}}function o(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function r(t,e,n,i){var o=Number.POSITIVE_INFINITY,r=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),l=i(e,a);l<o?(r=[t],o=l):l===o&&r.push(t)}}),r}function l(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,o=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(o,2))}}function s(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),o=[];return a(t,function(t){if(t.inRange(n.x,n.y))return o.push(t),o}),o.slice(0,1)},label:s,index:s,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return s(t,e,{intersect:!1})},point:function(t,e){return o(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var o=l(n.axis),s=r(t,a,n.intersect,o);return s.length>1&&s.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),s.slice(0,1)},x:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r},y:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)i=a[r],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,o){function r(t){var e=i.findNextWhere(_,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(T,D),right:Math.max(F,I),top:0,bottom:0};t.update(t.fullWidth?x:S,y/2,n)}else t.update(e.minSize.width,C)}function l(t){t.isHorizontal()?(t.left=t.fullWidth?d:T,t.right=t.fullWidth?a-c:T+S,t.top=V,t.bottom=V+t.height,V=t.bottom):(t.left=N,t.right=N+t.width,t.top=O,t.bottom=O+C,N=t.right)}if(t){var s=t.options.layout||{},u=i.options.toPadding(s.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),p=e(t.boxes,"right"),v=e(t.boxes,"top"),m=e(t.boxes,"bottom"),b=e(t.boxes,"chartArea");n(g,!0),n(p,!1),n(v,!0),n(m,!1);var x=a-d-c,y=o-h-f,k=y/2,w=(a-x/2)/(g.length+p.length),M=(o-k)/(v.length+m.length),S=x,C=y,_=[];i.each(g.concat(p,v,m),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?x:S,M),C-=e.height):(e=t.update(w,k),S-=e.width),_.push({horizontal:n,minSize:e,box:t})});var D=0,I=0,P=0,A=0;i.each(v.concat(m),function(t){if(t.getPadding){var e=t.getPadding();D=Math.max(D,e.left),I=Math.max(I,e.right)}}),i.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();P=Math.max(P,e.top),A=Math.max(A,e.bottom)}});var T=d,F=c,O=h,R=f;i.each(g.concat(p),r),i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(v.concat(m),r),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height}),i.each(g.concat(p),function(t){var e=i.findNextWhere(_,function(e){return e.box===t}),n={left:0,right:0,top:O,bottom:R};e&&t.update(e.minSize.width,C,n)}),T=d,F=c,O=h,R=f,i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height});var L=Math.max(D-T,0);T+=L,F+=Math.max(I-F,0);var z=Math.max(P-O,0);O+=z,R+=Math.max(A-R,0);var B=o-O-R,W=a-T-F;W===S&&B===C||(i.each(g,function(t){t.height=B}),i.each(p,function(t){t.height=B}),i.each(v,function(t){t.fullWidth||(t.width=W)}),i.each(m,function(t){t.fullWidth||(t.width=W)}),C=B,S=W);var N=d+L,V=h+z;i.each(g.concat(v),l),N+=S,V+=C,i.each(p,l),i.each(m,l),t.chartArea={left:T,top:O,right:T+S,bottom:O+C},i.each(b,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(S,C)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,o,r,l,s=this.descriptors(t),u=s.length;for(i=0;i<u;++i)if(a=s[i],o=a.plugin,"function"==typeof(l=o[e])&&((r=[t].concat(n||[])).push(a.options),!1===l.apply(o,r)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],r=t&&t.config||{},l=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,r=l[e];!1!==r&&(!0===r&&(r=o.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:r||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var o=t(25),r=t(26),l=t(45),s=t(34);o._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:s.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return l.isArray(e)?l.longestText(t,n,e):t.measureText(e).width}function n(t){var e=l.valueOrDefault,n=o.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),r=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:r,font:l.fontString(i,a,r)}}function s(t){return l.options.toLineHeight(l.valueOrDefault(t.lineHeight,1.2),l.valueOrDefault(t.fontSize,o.global.defaultFontSize))}t.Scale=r.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){l.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,o,r,s,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=l.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),s=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),o=d.convertTicksToLabels(s)||d.ticks,d.afterTickToLabelConversion(),d.ticks=o,i=0,a=o.length;i<a;++i)r=o[i],(u=s[i])?u.label=r:s.push(u={label:r,major:!1});return d._ticks=s,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){l.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){l.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){l.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){l.callback(this.options.beforeDataLimits,[this])},determineDataLimits:l.noop,afterDataLimits:function(){l.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){l.callback(this.options.beforeBuildTicks,[this])},buildTicks:l.noop,afterBuildTicks:function(){l.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){l.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){l.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){l.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,o=i(t._ticks),r=n(a);e.font=r.font;var s=a.minRotation||0;if(o.length&&t.options.display&&t.isHorizontal())for(var u,d=l.longestText(e,r.font,o,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&s<a.maxRotation;){var f=l.toRadians(s);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){s--;break}s++,c=u*d}t.labelRotation=s},afterCalculateTickRotation:function(){l.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){l.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=i(t._ticks),r=t.options,u=r.ticks,d=r.scaleLabel,c=r.gridLines,h=r.display,f=t.isHorizontal(),g=n(u),p=r.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,a.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var v=s(d)+l.options.toPadding(d.padding).height;f?a.height+=v:a.width+=v}if(u.display&&h){var m=l.longestText(t.ctx,g.font,o,t.longestTextCache),b=l.numberOfLabelLines(o),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=m;var k=l.toRadians(t.labelRotation),w=Math.cos(k),M=Math.sin(k)*m+g.size*b+x*(b-1)+x;a.height=Math.min(t.maxHeight,a.height+M+y),t.ctx.font=g.font;var S=e(t.ctx,o[0],g.font),C=e(t.ctx,o[o.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===r.position?w*S+3:w*x+3,t.paddingRight="bottom"===r.position?w*x+3:w*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?m=0:m+=y+x,a.width=Math.min(t.maxWidth,a.width+m),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){l.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(l.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:l.noop,getPixelForValue:l.noop,getValueForPixel:l.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,o=this,r=o.isHorizontal(),s=o.options.ticks.minor,u=t.length,d=l.toRadians(o.labelRotation),c=Math.cos(d),h=o.longestLabelWidth*c,f=[];for(s.maxTicksLimit&&(a=s.maxTicksLimit),r&&(e=!1,(h+s.autoSkipPadding)*u>o.width-(o.paddingLeft+o.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*u/(o.width-(o.paddingLeft+o.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var r=e.ctx,u=o.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),v=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),m=l.valueOrDefault(d.fontColor,u.defaultFontColor),b=n(d),x=l.valueOrDefault(c.fontColor,u.defaultFontColor),y=n(c),k=h.drawTicks?h.tickMarkLength:0,w=l.valueOrDefault(f.fontColor,u.defaultFontColor),M=n(f),S=l.options.toPadding(f.padding),C=l.toRadians(e.labelRotation),_=[],D="right"===i.position?e.left:e.right-k,I="right"===i.position?e.left+k:e.right,P="bottom"===i.position?e.top:e.bottom-k,A="bottom"===i.position?e.top+k:e.bottom;if(l.each(v,function(n,o){if(!l.isNullOrUndef(n.label)){var r,s,c,f,m=n.label;o===e.zeroLineIndex&&i.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=l.valueAtIndexOrDefault(h.lineWidth,o),s=l.valueAtIndexOrDefault(h.color,o),c=l.valueOrDefault(h.borderDash,u.borderDash),f=l.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var b,x,y,w,M,S,T,F,O,R,L="middle",z="middle",B=d.padding;if(p){var W=k+B;"bottom"===i.position?(z=g?"middle":"top",L=g?"right":"center",R=e.top+W):(z=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-W);var N=a(e,o,h.offsetGridLines&&v.length>1);N<e.left&&(s="rgba(0,0,0,0)"),N+=l.aliasPixel(r),O=e.getPixelForTick(o)+d.labelOffset,b=y=M=T=N,x=P,w=A,S=t.top,F=t.bottom}else{var V,E="left"===i.position;d.mirror?(L=E?"left":"right",V=B):(L=E?"right":"left",V=k+B),O=E?e.right-V:e.left+V;var H=a(e,o,h.offsetGridLines&&v.length>1);H<e.top&&(s="rgba(0,0,0,0)"),H+=l.aliasPixel(r),R=e.getPixelForTick(o)+d.labelOffset,b=D,y=I,M=t.left,T=t.right,x=w=S=F=H}_.push({tx1:b,ty1:x,tx2:y,ty2:w,x1:M,y1:S,x2:T,y2:F,labelX:O,labelY:R,glWidth:r,glColor:s,glBorderDash:c,glBorderDashOffset:f,rotation:-1*C,label:m,major:n.major,textBaseline:z,textAlign:L})}}),l.each(_,function(t){if(h.display&&(r.save(),r.lineWidth=t.glWidth,r.strokeStyle=t.glColor,r.setLineDash&&(r.setLineDash(t.glBorderDash),r.lineDashOffset=t.glBorderDashOffset),r.beginPath(),h.drawTicks&&(r.moveTo(t.tx1,t.ty1),r.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(r.moveTo(t.x1,t.y1),r.lineTo(t.x2,t.y2)),r.stroke(),r.restore()),d.display){r.save(),r.translate(t.labelX,t.labelY),r.rotate(t.rotation),r.font=t.major?y.font:b.font,r.fillStyle=t.major?x:m,r.textBaseline=t.textBaseline,r.textAlign=t.textAlign;var e=t.label;if(l.isArray(e))for(var n=0,i=0;n<e.length;++n)r.fillText(""+e[n],0,i),i+=1.5*b.size;else r.fillText(e,0,0);r.restore()}}),f.display){var T,F,O=0,R=s(f)/2;if(p)T=e.left+(e.right-e.left)/2,F="bottom"===i.position?e.bottom-R-S.bottom:e.top+R+S.top;else{var L="left"===i.position;T=L?e.left+R+S.top:e.right-R-S.top,F=e.top+(e.bottom-e.top)/2,O=L?-.5*Math.PI:.5*Math.PI}r.save(),r.translate(T,F),r.rotate(O),r.textAlign="center",r.textBaseline="middle",r.fillStyle=w,r.font=M.font,r.fillText(f.labelString,0,0),r.restore()}if(h.drawBorder){r.lineWidth=l.valueAtIndexOrDefault(h.lineWidth,0),r.strokeStyle=l.valueAtIndexOrDefault(h.color,0);var z=e.left,B=e.right,W=e.top,N=e.bottom,V=l.aliasPixel(r.lineWidth);p?(W=N="top"===i.position?e.bottom:e.top,W+=V,N+=V):(z=B="left"===i.position?e.right:e.left,z+=V,B+=V),r.beginPath(),r.moveTo(z,W),r.lineTo(B,N),r.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var o=i.niceNum(e.max-e.min,!1);n=i.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/n)*n,l=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(r=t.min,l=t.max);var s=(l-r)/n;s=i.almostEquals(s,Math.round(s),n/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u<s;++u)a.push(r+u*n);return a.push(void 0!==t.max?t.max:l),a},logarithmic:function(t,e){var n,a,o=[],r=i.valueOrDefault,l=r(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),s=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,s));0===l?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),o.push(l),l=a*Math.pow(10,n)):(n=Math.floor(i.log10(l)),a=Math.floor(l/Math.pow(10,n)));do{o.push(l),10===++a&&(a=1,++n),l=a*Math.pow(10,n)}while(n<s||n===s&&a<u);var d=r(t.max,l);return o.push(d),o}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=i.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.index<a&&(n=i[o.index])}return n},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}}}),e.exports=function(t){function e(t,e){var n=o.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function r(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function l(t){var e=i.global,n=o.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function s(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,l=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);l+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=s*d,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=l*c,i+=l?(l-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),n.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,n.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,o="center",r="center";n.y<e.height?r="top":n.y>i.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}function d(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=l(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=l(c),g=a._active,p=a._data,v={xAlign:h.xAlign,yAlign:h.yAlign},m={x:h.x,y:h.y},b={width:h.width,height:h.height},x={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var y=[],k=[];x=t.Tooltip.positioners[c.position].call(a,g,a._eventPosition);var w=[];for(n=0,i=g.length;n<i;++n)w.push(r(g[n]));c.filter&&(w=w.filter(function(t){return c.filter(t,p)})),c.itemSort&&(w=w.sort(function(t,e){return c.itemSort(t,e,p)})),o.each(w,function(t){y.push(c.callbacks.labelColor.call(a,t,a._chart)),k.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(w,p),f.beforeBody=a.getBeforeBody(w,p),f.body=a.getBody(w,p),f.afterBody=a.getAfterBody(w,p),f.footer=a.getFooter(w,p),f.x=Math.round(x.x),f.y=Math.round(x.y),f.caretPadding=c.caretPadding,f.labelColors=y,f.labelTextColors=k,f.dataPoints=w,m=d(f,b=s(this,f),v=u(this,b))}else f.opacity=0;return f.xAlign=v.xAlign,f.yAlign=v.yAlign,f.x=m.x,f.y=m.y,f.width=b.width,f.height=b.height,f.caretX=x.x,f.caretY=x.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,o,r,l,s,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,p=e.width,v=e.height;if("center"===h)l=g+v/2,"left"===c?(a=(i=f)-u,o=i,r=l+u,s=l-u):(a=(i=f+p)+u,o=i,r=l-u,s=l+u);else if("left"===c?(i=(a=f+d+u)-u,o=a+u):"right"===c?(i=(a=f+p-d-u)-u,o=a+u):(i=(a=f+p/2)-u,o=a+u),"top"===h)l=(r=g)-u,s=r;else{l=(r=g+v)+u,s=r;var m=o;o=i,i=m}return{x1:i,x2:a,x3:o,y1:r,y2:l,y3:s}},drawTitle:function(t,n,i,a){var r=n.title;if(r.length){i.textAlign=n._titleAlign,i.textBaseline="top";var l=n.titleFontSize,s=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=o.fontString(l,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=r.length;u<d;++u)i.fillText(r[u],t.x,t.y),t.y+=l+s,u+1===r.length&&(t.y+=n.titleMarginBottom-s)}},drawBody:function(t,n,i,a){var r=n.bodyFontSize,l=n.bodySpacing,s=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=o.fontString(r,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=r+l};i.fillStyle=e(n.bodyFontColor,a),o.each(n.beforeBody,d);var c=n.displayColors;u=c?r+2:0,o.each(s,function(l,s){var u=e(n.labelTextColors[s],a);i.fillStyle=u,o.each(l.before,d),o.each(l.lines,function(o){c&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,r,r),i.lineWidth=1,i.strokeStyle=e(n.labelColors[s].borderColor,a),i.strokeRect(t.x,t.y,r,r),i.fillStyle=e(n.labelColors[s].backgroundColor,a),i.fillRect(t.x+1,t.y+1,r-2,r-2),i.fillStyle=u),d(o)}),o.each(l.after,d)}),u=0,o.each(n.afterBody,d),t.y-=l},drawFooter:function(t,n,i,a){var r=n.footer;r.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=o.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),o.each(r,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,o){i.fillStyle=e(n.backgroundColor,o),i.strokeStyle=e(n.borderColor,o),i.lineWidth=n.borderWidth;var r=n.xAlign,l=n.yAlign,s=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(s+h,u),"top"===l&&this.drawCaret(t,a),i.lineTo(s+d-h,u),i.quadraticCurveTo(s+d,u,s+d,u+h),"center"===l&&"right"===r&&this.drawCaret(t,a),i.lineTo(s+d,u+c-h),i.quadraticCurveTo(s+d,u+c,s+d-h,u+c),"bottom"===l&&this.drawCaret(t,a),i.lineTo(s+h,u+c),i.quadraticCurveTo(s,u+c,s,u+c-h),"center"===l&&"left"===r&&this.drawCaret(t,a),i.lineTo(s,u+h),i.quadraticCurveTo(s,u,s+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;e<n;++e){var r=t[e];if(r&&r.hasValue()){var l=r.tooltipPosition();i+=l.x,a+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(a/o)}},nearest:function(t,e){var n,i,a,r=e.x,l=e.y,s=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<s&&(s=c,a=u)}}if(a){var h=a.tooltipPosition();r=h.x,l=h.y}return{x:r,y:l}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=o.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,r=i.distance,l=n.startAngle,s=n.endAngle;s<l;)s+=2*Math.PI;for(;a>s;)a-=2*Math.PI;for(;a<l;)a+=2*Math.PI;var u=a>=l&&a<=s,d=r>=n.innerRadius&&r<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45),r=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,l=a._view,s=a._chart.ctx,u=l.spanGaps,d=a._children.slice(),c=r.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||r.defaultColor,s.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=o.previousItem(d,t),i=e._view,0===t?i.skip||(s.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?s.moveTo(i.x,i.y):o.canvas.lineTo(s,n._view,e._view),h=t));s.stroke(),s.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),o=t(26),r=t(45),l=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:l,borderColor:l,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=o.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,o=e.pointStyle,s=e.radius,u=e.x,d=e.y,c=r.color,h=0;e.skip||(i.strokeStyle=e.borderColor||l,i.lineWidth=r.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||l,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),r.canvas.drawPoint(i,o,s,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,o,r=t._view;if(i(t)){var l=r.width/2;e=r.x-l,n=r.x+l,a=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;e=Math.min(r.x,r.base),n=Math.max(r.x,r.base),a=r.y-s,o=r.y+s}return{left:e,top:a,right:n,bottom:o}}var o=t(25),r=t(26);o._set("global",{elements:{rectangle:{backgroundColor:o.global.defaultColor,borderColor:o.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=r.extend({draw:function(){function t(t){return m[(b+t)%4]}var e,n,i,a,o,r,l,s=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,o=n>e?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,o=1,r=(a=u.base)>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),v=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=v),p!==v&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var m=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var o=a(n);return i(n)?t>=o.left&&t<=o.right:e>=o.top&&e<=o.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,o){if(o){var r=Math.min(o,i/2),l=Math.min(o,a/2);t.moveTo(e+r,n),t.lineTo(e+i-r,n),t.quadraticCurveTo(e+i,n,e+i,n+l),t.lineTo(e+i,n+a-l),t.quadraticCurveTo(e+i,n+a,e+i-r,n+a),t.lineTo(e+r,n+a),t.quadraticCurveTo(e,n+a,e,n+a-l),t.lineTo(e,n+l),t.quadraticCurveTo(e,n,e+r,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var o,r,l,s,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-r/2,a+u/3),t.lineTo(i+r/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var o,r,l;if(i.isArray(t))if(r=t.length,a)for(o=r-1;o>=0;o--)e.call(n,t[o],o);else for(o=0;o<r;o++)e.call(n,t[o],o);else if(i.isObject(t))for(r=(l=Object.keys(t)).length,o=0;o<r;o++)e.call(n,t[l[o]],l[o])},arrayEquals:function(t,e){var n,a,o,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(o=t[n],r=e[n],o instanceof Array&&r instanceof Array){if(!i.arrayEquals(o,r))return!1}else if(o!==r)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,o=0;o<a;++o)e[n[o]]=i.clone(t[n[o]]);return e}return t},_merger:function(t,e,n,a){var o=e[t],r=n[t];i.isObject(o)&&i.isObject(r)?i.merge(o,r,a):e[t]=i.clone(r)},_mergerIf:function(t,e,n){var a=e[t],o=n[t];i.isObject(a)&&i.isObject(o)?i.mergeIf(a,o):e.hasOwnProperty(t)||(e[t]=i.clone(o))},merge:function(t,e,n){var a,o,r,l,s,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,o=0;o<d;++o)if(e=u[o],i.isObject(e))for(s=0,l=(r=Object.keys(e)).length;s<l;++s)a(r[s],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})},extend:function(t){for(var e=1,n=arguments.length;e<n;++e)i.each(arguments[e],function(e,n){t[n]=e});return t},inherits:function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},a=function(){this.constructor=n};return a.prototype=e.prototype,n.prototype=new a,n.extend=i.inherits,t&&i.extend(n.prototype,t),n.__super__=e.prototype,n}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,o;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=n=a=o=+t||0,{top:e,right:n,bottom:a,left:o,height:e+a,width:o+n}},resolve:function(t,e,n){var a,o,r;for(a=0,o=t.length;a<o;++a)if(void 0!==(r=t[a])&&(void 0!==e&&"function"==typeof r&&(r=r(e)),void 0!==n&&i.isArray(r)&&(r=r[n]),void 0!==r))return r}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=v.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),o=t.getAttribute("width");if(t[m]={initial:{height:a,width:o,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===o||""===o){var r=i(t,"width");void 0!==r&&(t.width=r)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var l=i(t,"height");void 0!==r&&(t.height=l)}return t}function o(t,e,n){t.addEventListener(e,n,M)}function r(t,e,n){t.removeEventListener(e,n,M)}function l(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function s(t,e){var n=w[t.type]||t.type,i=v.getRelativePosition(t,e);return l(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,v.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=b+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var l=function(){e._reset(),t()};return o(a,"scroll",l.bind(a,"expand")),o(r,"scroll",l.bind(r,"shrink")),e}function c(t,e){var n=t[m]||(t[m]={}),i=n.renderProxy=function(t){t.animationName===y&&e()};v.each(k,function(e){o(t,e,i)}),n.reflow=!!t.offsetParent,t.classList.add(x)}function h(t){var e=t[m]||{},n=e.renderProxy;n&&(v.each(k,function(e){r(t,e,n)}),delete e.renderProxy),t.classList.remove(x)}function f(t,e,n){var i=t[m]||(t[m]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(l("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[m]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function p(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var v=t(45),m="$chartjs",b="chartjs-",x=b+"render-monitor",y=b+"render-animation",k=["animationstart","webkitAnimationStart"],w={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},M=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";p(this,"@-webkit-keyframes "+y+"{"+t+"}@keyframes "+y+"{"+t+"}."+x+"{-webkit-animation:"+y+" 0.001s;animation:"+y+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[m]){var n=e[m].initial;["height","width"].forEach(function(t){var i=n[t];v.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),v.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[m]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[m]||(n[m]={});o(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(s(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[m]||{}).proxies||{})[t.id+"_"+e];a&&r(i,e,a)}else g(i)}},v.addEvent=o,v.removeEvent=r},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function n(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function r(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function l(t){return t&&!t.skip}function s(t,e,n,i,a){var r;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<i;++r)o.canvas.lineTo(t,e[r-1],e[r]);for(t.lineTo(n[a-1].x,n[a-1].y),r=a-1;r>0;--r)o.canvas.lineTo(t,n[r],n[r-1],!0)}}function u(t,e,n,i,a,o){var r,u,d,c,h,f,g,p=e.length,v=i.spanGaps,m=[],b=[],x=0,y=0;for(t.beginPath(),r=0,u=p+!!o;r<u;++r)h=n(c=e[d=r%p]._view,d,i),f=l(c),g=l(h),f&&g?(x=m.push(c),y=b.push(h)):x&&y&&(v?(f&&m.push(c),g&&b.push(h)):(s(t,m,b,x,y),x=y=0,m=[],b=[]));s(t,m,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],o=a.length||0;return o?function(t,e){return e<o&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,o){var l,s,u,d,c=(i.data.datasets||[]).length,h=o.propagate,f=[];for(s=0;s<c;++s)d=null,(u=(l=i.getDatasetMeta(s)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(s),fill:t(u,s,c),chart:i,el:u}),l.$filler=d,f.push(d);for(s=0;s<c;++s)(d=f[s])&&(d.fill=n(f,s,h),d.boundary=e(d),d.mapper=r(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,r=n.el,l=r._view,s=r._children||[],d=n.mapper,c=l.backgroundColor||i.global.defaultColor;d&&c&&s.length&&(o.canvas.clipArea(a,t.chartArea),u(a,s,d,l,c,r._loop),o.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return o.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:o.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});r.configure(e,i,n),r.addBox(e,i),e.legend=i}var r=t.layoutService,l=o.noop;return t.Legend=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:l,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:l,beforeSetDimensions:l,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:l,beforeBuildLabels:l,buildLabels:function(){var t=this,e=t.options.labels||{},n=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:l,beforeFit:l,fit:function(){var t=this,n=t.options,a=n.labels,r=n.display,l=t.ctx,s=i.global,u=o.valueOrDefault,d=u(a.fontSize,s.defaultFontSize),c=u(a.fontStyle,s.defaultFontStyle),h=u(a.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,v=t.isHorizontal();if(v?(p.width=t.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=t.maxHeight),r)if(l.font=f,v){var m=t.lineWidths=[0],b=t.legendItems.length?d+a.padding:0;l.textAlign="left",l.textBaseline="top",o.each(t.legendItems,function(n,i){var o=e(a,d)+d/2+l.measureText(n.text).width;m[m.length-1]+o+a.padding>=t.width&&(b+=d+a.padding,m[m.length]=t.left),g[i]={left:0,top:0,width:o,height:d},m[m.length-1]+=o+a.padding}),p.height+=b}else{var x=a.padding,y=t.columnWidths=[],k=a.padding,w=0,M=0,S=d+x;o.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+a.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}t.width=p.width,t.height=p.height},afterFit:l,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,r=i.global,l=r.elements.line,s=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(a.fontColor,r.defaultFontColor),g=h(a.fontSize,r.defaultFontSize),p=h(a.fontStyle,r.defaultFontStyle),v=h(a.fontFamily,r.defaultFontFamily),m=o.fontString(g,p,v);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=m;var b=e(a,g),x=t.legendHitBoxes,y=function(t,e,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var a=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),n.labels&&n.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=t+u,f=e+u;o.canvas.drawPoint(c,i.pointStyle,s,d,f)}else a||c.strokeRect(t,e,b,g),c.fillRect(t,e,b,g);c.restore()}},k=function(t,e,n,i){var a=g/2,o=b+a+t,r=e+a;c.fillText(n.text,o,r),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(o,r),c.lineTo(o+i,r),c.stroke())},w=t.isHorizontal();d=w?{x:t.left+(s-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var M=g+a.padding;o.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,o=b+g/2+i,r=d.x,l=d.y;w?r+o>=s&&(l=d.y+=M,d.line++,r=d.x=t.left+(s-u[d.line])/2):l+M>t.bottom&&(r=d.x=r+t.columnWidths[d.line]+a.padding,l=d.y=t.top+a.padding,d.line++),y(r,l,e),x[n].left=r,x[n].top=l,k(r,l,e,i),w?d.x+=o+a.padding:d.y+=M})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s<l.length;++s){var u=l[s];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(o.mergeIf(e,i.global.legend),a?(r.configure(t,a,e),a.options=e):n(t,e)):a&&(r.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,r=o.noop;return t.Title=a.extend({initialize:function(t){var e=this;o.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=this,e=o.valueOrDefault,n=t.options,a=n.display,r=e(n.fontSize,i.global.defaultFontSize),l=t.minSize,s=o.isArray(n.text)?n.text.length:1,u=o.options.toLineHeight(n.lineHeight,r),d=a?s*u+2*n.padding:0;t.isHorizontal()?(l.width=t.maxWidth,l.height=d):(l.width=d,l.height=t.maxHeight),t.width=l.width,t.height=l.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=o.valueOrDefault,a=t.options,r=i.global;if(a.display){var l,s,u,d=n(a.fontSize,r.defaultFontSize),c=n(a.fontStyle,r.defaultFontStyle),h=n(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,v=0,m=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=n(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(s=b+(y-b)/2,u=m+p,l=y-b):(s="left"===a.position?b+p:y-p,u=m+(x-m)/2,l=x-m,v=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(s,u),e.rotate(v),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var w=0,M=0;M<k.length;++M)e.fillText(k[M],0,w,l),w+=g;else e.fillText(k,0,0,l);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var r=a.options.title,l=a.titleBlock;r?(o.mergeIf(r,i.global.title),l?(n.configure(a,l,r),l.options=r):e(a,r)):l&&(t.layoutService.removeBox(a,l),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,o=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var r=i.getLabels();t=n||t;var l=r.indexOf(t);e=-1!==l?l:e}if(i.isHorizontal()){var s=i.width/o,u=s*(e-i.minIndex);return a&&(u+=s/2),i.left+Math.round(u)}var d=i.height/o,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),o=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=o/2),(t<=0?0:Math.round(t/o))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",e,{position:"bottom"})}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return r?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,o=i.data.datasets,r=e.isHorizontal();e.min=null,e.max=null;var l=n.stacked;if(void 0===l&&a.each(o,function(e,n){if(!l){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(l=!0)}}),n.stacked||l){var s={};a.each(o,function(o,r){var l=i.getDatasetMeta(r),u=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");void 0===s[u]&&(s[u]={positiveValues:[],negativeValues:[]});var d=s[u].positiveValues,c=s[u].negativeValues;i.isDatasetVisible(r)&&t(l)&&a.each(o.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||l.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(s,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),o=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?o:Math.max(e.max,o)})}else a.each(o,function(n,o){var r=i.getDatasetMeta(o);i.isDatasetVisible(o)&&t(r)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var o=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*o)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),o={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},r=t.ticks=a.generators.linear(o,t);t.handleDirectionalChanges(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,o=e.chart,r=o.data.datasets,l=i.valueOrDefault,s=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),i.each(a.data,function(t,i){var a=d[s],o=+e.getRightValue(t);isNaN(o)||l.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=o)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(r,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=l(a.min,e.min),e.max=l(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},o=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||o.reverse(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,o=this,r=o.start,l=+o.getRightValue(t),s=o.options.ticks;return o.isHorizontal()?(a=i.log10(o.end)-i.log10(r),0===l?n=o.left:(e=o.width,n=o.left+e/a*(i.log10(l)-i.log10(r)))):(e=o.height,0!==r||s.reverse?0===o.end&&s.reverse?(a=i.log10(o.start)-i.log10(o.minNotZero),n=l===o.end?o.top:l===o.minNotZero?o.top+.02*e:o.top+.02*e+.98*e/a*(i.log10(l)-i.log10(o.minNotZero))):0===l?n=s.reverse?o.top:o.bottom:(a=i.log10(o.end)-i.log10(r),e=o.height,n=o.bottom-e/a*(i.log10(l)-i.log10(r))):(a=i.log10(o.end)-i.log10(o.minNotZero),n=l===r?o.bottom:l===o.minNotZero?o.bottom-.02*e:o.bottom-.02*e-.98*e/a*(i.log10(l)-i.log10(o.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,o=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*o/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*o/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,v.defaultFontSize),i=a.valueOrDefault(e.fontStyle,v.defaultFontStyle),o=a.valueOrDefault(e.fontFamily,v.defaultFontFamily);return{size:n,style:i,family:o,font:a.fontString(n,i,o)}}function r(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function l(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function s(t){var i,o,s,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){s=t.getPointPosition(i,d),o=r(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=o;var g=t.getIndexAngle(i),p=a.toDegrees(g)%360,v=l(p,s.x,o.w,0,180),m=l(p,s.y,o.h,90,270);v.start<c.l&&(c.l=v.start,h.l=g),v.end>c.r&&(c.r=v.end,h.r=g),m.start<c.t&&(c.t=m.start,h.t=g),m.end>c.b&&(c.b=m.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var o=n.y,r=1.5*i,l=0;l<e.length;++l)t.fillText(e[l],n.x,o),o+=r;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,o=a.valueOrDefault,r=t.options,l=r.angleLines,s=r.pointLabels;i.lineWidth=l.lineWidth,i.strokeStyle=l.color;var u=t.getDistanceFromCenterForValue(r.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(l.display){var p=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(p.x,p.y),i.stroke(),i.closePath()}if(s.display){var m=t.getPointPosition(g,u+5),b=o(s.fontColor,v.defaultFontColor);i.font=f.font,i.fillStyle=b;var x=t.getIndexAngle(g),y=a.toDegrees(x);i.textAlign=d(y),h(y,t._pointLabelSizes[g],m),c(i,t.pointLabels[g]||"",m,f.size)}}}function g(t,n,i,o){var r=t.ctx;if(r.strokeStyle=a.valueAtIndexOrDefault(n.color,o-1),r.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,o-1),t.options.gridLines.circular)r.beginPath(),r.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),r.closePath(),r.stroke();else{var l=e(t);if(0===l)return;r.beginPath();var s=t.getPointPosition(0,i);r.moveTo(s.x,s.y);for(var u=1;u<l;u++)s=t.getPointPosition(u,i),r.lineTo(s.x,s.y);r.closePath(),r.stroke()}}function p(t){return a.isNumber(t)?t:0}var v=i.global,m={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},b=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),o=a.valueOrDefault(n.fontSize,v.defaultFontSize);t.drawingArea=e.display?i/2-(o/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(o,r){if(e.isDatasetVisible(r)){var l=e.getDatasetMeta(r);a.each(o.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||l.data[a].hidden||(n=Math.min(o,n),i=Math.max(o,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,v.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?s(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),o=Math.max(e.r-i.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),l=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=p(a),o=p(o),r=p(r),l=p(l),i.drawingArea=Math.min(Math.round(t-(a+o)/2),Math.round(t-(r+l)/2)),i.setCenterPoint(a,o,r,l)},setCenterPoint:function(t,e,n,i){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,l=n+a.drawingArea,s=a.height-i-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((l+s)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,o=a.valueOrDefault;if(e.display){var r=t.ctx,l=this.getIndexAngle(0),s=o(i.fontSize,v.defaultFontSize),u=o(i.fontStyle,v.defaultFontStyle),d=o(i.fontFamily,v.defaultFontFamily),c=a.fontString(s,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=o(i.fontColor,v.defaultFontColor);if(r.font=c,r.save(),r.translate(t.xCenter,t.yCenter),r.rotate(l),i.showLabelBackdrop){var h=r.measureText(e).width;r.fillStyle=i.backdropColor,r.fillRect(-h/2-i.backdropPaddingX,-u-s/2-i.backdropPaddingY,h+2*i.backdropPaddingX,s+2*i.backdropPaddingY)}r.textAlign="center",r.textBaseline="middle",r.fillStyle=d,r.fillText(e,0,-u),r.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",b,m)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},o=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,o.push(i));return o}function o(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,o,r,l,s,u=[],d=[e];for(a=0,o=t.length;a<o;++a)(l=t[a])>e&&l<n&&d.push(l);for(d.push(n),a=0,o=d.length;a<o;++a)s=d[a+1],r=d[a-1],l=d[a],void 0!==r&&void 0!==s&&Math.round((s+r)/2)===l||u.push({time:l,pos:a/(o-1)});return u}function r(t,e,n){for(var i,a,o,r=0,l=t.length-1;r>=0&&r<=l;){if(i=r+l>>1,a=t[i-1]||null,o=t[i],!a)return{lo:null,hi:o};if(o[e]<n)r=i+1;else{if(!(a[e]>n))return{lo:a,hi:o};l=i-1}}return{lo:o,hi:null}}function l(t,e,n,i){var a=r(t,e,n),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],l=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=l[e]-o[e],u=s?(n-o[e])/s:0,d=(l[i]-o[i])*u;return o[i]+d}function s(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?m(t,i):(t instanceof m||(t=m(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(x.isNullOrUndef(t))return null;var n=e.options.time,i=s(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,o,r,l=e-t,s=w[n],u=s.size,d=s.steps;if(!d)return Math.ceil(l/((i||1)*u));for(a=0,o=d.length;a<o&&(r=d[a],!(Math.ceil(l/(u*r))<=i));++a);return r}function c(t,e,n,i){var a,o,r,l=M.length;for(a=M.indexOf(t);a<l-1;++a)if(o=w[M[a]],r=o.steps?o.steps[o.steps.length-1]:k,o.common&&Math.ceil((n-e)/(r*o.size))<=i)return M[a];return M[l-1]}function h(t,e,n,i){var a,o,r=m.duration(m(i).diff(m(n)));for(a=M.length-1;a>=M.indexOf(e);a--)if(o=M[a],w[o].common&&r.as(o)>=t.length)return o;return M[e?M.indexOf(e):0]}function f(t){for(var e=M.indexOf(t)+1,n=M.length;e<n;++e)if(w[M[e]].common)return M[e]}function g(t,e,n,i){var a,o=i.time,r=o.unit||c(o.minUnit,t,e,n),l=f(r),s=x.valueOrDefault(o.stepSize,o.unitStepSize),u="week"===r&&o.isoWeekday,h=i.ticks.major.enabled,g=w[r],p=m(t),v=m(e),b=[];for(s||(s=d(t,e,r,n)),u&&(p=p.isoWeekday(u),v=v.isoWeekday(u)),p=p.startOf(u?"day":r),(v=v.startOf(u?"day":r))<e&&v.add(1,r),a=m(p),h&&l&&!u&&!o.round&&(a.startOf(l),a.add(~~((p-a)/(g.size*s))*s,r));a<v;a.add(s,r))b.push(+a);return b.push(+a),b}function p(t,e,n,i,a){var o,r,s=0,u=0;return a.offset&&e.length&&(a.time.min||(o=e.length>1?e[1]:i,r=e[0],s=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2),a.time.max||(o=e[e.length-1],r=e.length>1?e[e.length-2]:n,u=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2)),{left:s,right:u}}function v(t,e){var n,i,a,o,r=[];for(n=0,i=t.length;n<i;++n)a=t[n],o=!!e&&a===+m(a).startOf(e),r.push({value:a,major:o});return r}var m=t(1);m="function"==typeof m?m:window.moment;var b=t(25),x=t(45),y=Number.MIN_SAFE_INTEGER||-9007199254740991,k=Number.MAX_SAFE_INTEGER||9007199254740991,w={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},M=Object.keys(w);e.exports=function(t){var e=t.Scale.extend({initialize:function(){if(!m)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,o,r,l,s=this,d=s.chart,c=s.options.time,h=k,f=y,g=[],p=[],v=[];for(t=0,n=d.data.labels.length;t<n;++t)v.push(u(d.data.labels[t],s));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(r=d.data.datasets[t].data,x.isObject(r[0]))for(p[t]=[],e=0,o=r.length;e<o;++e)l=u(r[e],s),g.push(l),p[t][e]=l;else g.push.apply(g,v),p[t]=v.slice(0);else p[t]=[];v.length&&(v=a(v).sort(i),h=Math.min(h,v[0]),f=Math.max(f,v[v.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=u(c.min,s)||h,f=u(c.max,s)||f,h=h===k?+m().startOf("day"):h,f=f===y?+m().endOf("day")+1:f,s.min=Math.min(h,f),s.max=Math.max(h+1,f),s._horizontal=s.isHorizontal(),s._table=[],s._timestamps={data:g,datasets:p,labels:v}},buildTicks:function(){var t,e,n,i=this,a=i.min,r=i.max,l=i.options,s=l.time,d=[],c=[];switch(l.ticks.source){case"data":d=i._timestamps.data;break;case"labels":d=i._timestamps.labels;break;case"auto":default:d=g(a,r,i.getLabelCapacity(a),l)}for("ticks"===l.bounds&&d.length&&(a=d[0],r=d[d.length-1]),a=u(s.min,i)||a,r=u(s.max,i)||r,t=0,e=d.length;t<e;++t)(n=d[t])>=a&&n<=r&&c.push(n);return i.min=a,i.max=r,i._unit=s.unit||h(c,s.minUnit,i.min,i.max),i._majorUnit=f(i._unit),i._table=o(i._timestamps.data,a,r,l.distribution),i._offsets=p(i._table,c,a,r,l),v(c,i._majorUnit)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,o=i.labels&&t<i.labels.length?i.labels[t]:"",r=i.datasets[e].data[t];return x.isObject(r)&&(o=n.getRightValue(r)),a.tooltipFormat&&(o=s(o,a).format(a.tooltipFormat)),o},tickFormatFunction:function(t,e,n,i){var a=this,o=a.options,r=t.valueOf(),l=o.time.displayFormats,s=l[a._unit],u=a._majorUnit,d=l[u],c=t.clone().startOf(u).valueOf(),h=o.ticks.major,f=h.enabled&&u&&d&&r===c,g=t.format(i||(f?d:s)),p=f?h:o.ticks.minor,v=x.valueOrDefault(p.callback,p.userCallback);return v?v(g,e,n):g},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(m(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=l(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,o=l(e._table,"pos",a,"time");return m(o)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=x.toRadians(n.maxRotation),o=Math.cos(a),r=Math.sin(a);return i*o+x.valueOrDefault(n.fontSize,b.global.defaultFontSize)*r},getLabelCapacity:function(t){var e=this,n=e.options.time.displayFormats.millisecond,i=e.tickFormatFunction(m(t),0,[],n),a=e.getLabelWidth(i),o=e.isHorizontal()?e.width:e.height;return Math.floor(o/a)}});t.scaleService.registerScaleType("time",e,{position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}})}},{1:1,25:25,45:45}]},{},[7])(7)});
admin/assets/js/bulk-optimization.js CHANGED
@@ -1,555 +1,568 @@
1
- jQuery(function($) {
2
- var bulkOptimization = {
3
-
4
- inprogress: false,
5
-
6
- serverDown: false,
7
-
8
- i18n: {},
9
-
10
- settings: {},
11
-
12
- init: function() {
13
- if( wrio_l18n_bulk_page === undefined || wrio_settings_bulk_page === undefined ) {
14
- console.log('[Error]: Required global variables are not declared.');
15
- return;
16
- }
17
-
18
- this.i18n = wrio_l18n_bulk_page;
19
- this.settings = wrio_settings_bulk_page;
20
- this.startOptButton = $('#wrio-start-optimization');
21
-
22
- this.registerEvents();
23
- this.checkServerStatus();
24
-
25
- if( 'server_5' === $('#wrio-change-optimization-server').val() ) {
26
- if( !this.settings.is_premium ) {
27
- $.wrio_modal.showErrorModal(this.i18n.premium_server_disabled);
28
- return;
29
- }
30
- this.checkPremiumUserBalance();
31
- }
32
- },
33
-
34
- registerEvents: function() {
35
- var self = this,
36
- selectedServer = $("#wrio-change-optimization-server option:selected");
37
-
38
- $('#wrio-change-optimization-server').on('change', function() {
39
- $(this).prop('disabled', true);
40
-
41
- if( 'server_5' === $(this).val() ) {
42
- if( !self.settings.is_premium ) {
43
- $.wrio_modal.showErrorModal(self.i18n.premium_server_disabled);
44
- selectedServer.prop('selected', true);
45
- $(this).prop('disabled', false);
46
-
47
- return;
48
- }
49
-
50
- $('.wrio-premium-user-balance-wrap').css('display', 'inline-block');
51
- self.checkPremiumUserBalance();
52
- } else {
53
- $('.wrio-premium-user-balance-wrap').css('display', 'none');
54
- }
55
-
56
- selectedServer = $(this).find('option:selected');
57
- self.checkServerStatus();
58
- });
59
-
60
- this.startOptButton.on('click', function() {
61
- self.startOptButton = $(this);
62
-
63
- if( $(this).hasClass('wio-running') ) {
64
- self.stop();
65
- return;
66
- }
67
-
68
- if( self.serverDown ) {
69
- $.wrio_modal.showErrorModal(self.i18n.server_down_warning);
70
- return;
71
- }
72
-
73
- if( "1" === self.settings.need_migration ) {
74
- $.wrio_modal.showErrorModal(self.i18n.need_migrations);
75
- return;
76
- }
77
-
78
- if( "0" === self.settings.images_backup ) {
79
- $.wrio_modal.showWarningModal(self.i18n.process_without_backup, function() {
80
- self.showModal();
81
- });
82
- return;
83
- }
84
-
85
- self.showModal();
86
-
87
- return false;
88
- });
89
- },
90
-
91
- checkPremiumUserBalance: function() {
92
- var self = this,
93
- userBalance = $('.wrio-premium-user-balance'),
94
- data = {
95
- 'action': 'wbcr-rio-check-user-balance',
96
- '_wpnonce': self.settings.nonce
97
- };
98
-
99
- userBalance.addClass('wrio-premium-user-balance-check-proccess');
100
- userBalance.text('');
101
-
102
- $.post(ajaxurl, data, function(response) {
103
- userBalance.removeClass('wrio-premium-user-balance-check-proccess');
104
-
105
- if( !response || !response.data || !response.success ) {
106
- console.log('[Error]: Response error');
107
- response.data && response.data.error && console.log(response.data.error);
108
-
109
- if( !response || !response.data ) {
110
- console.log(response);
111
- }
112
-
113
- userBalance.text('error');
114
- } else {
115
- userBalance.text(response.data.balance);
116
- }
117
- }).fail(function(xhr, status, error) {
118
- console.log(xhr);
119
- console.log(status);
120
- console.log(error);
121
-
122
- self.throwError(error);
123
- });
124
- },
125
-
126
- checkServerStatus: function() {
127
- var self = this,
128
- serverStatus = $('.wrio-server-status'),
129
- data = {
130
- 'action': 'wbcr-rio-check-servers-status',
131
- '_wpnonce': self.settings.nonce
132
- };
133
-
134
- self.serverDown = false;
135
-
136
- data['server_name'] = $('#wrio-change-optimization-server').val();
137
-
138
- serverStatus.addClass('wrio-server-check-proccess');
139
- serverStatus.text('');
140
- serverStatus.removeClass('wrio-down').removeClass('wrio-stable');
141
-
142
- self.startOptButton.prop('disabled', true);
143
-
144
- $.post(ajaxurl, data, function(response) {
145
- serverStatus.removeClass('wrio-server-check-proccess');
146
-
147
- if( !response || !response.data || !response.success ) {
148
- console.log('[Error]: Response error');
149
- response.data && response.data.error && console.log(response.data.error);
150
-
151
- if( !response || !response.data ) {
152
- console.log(response);
153
- }
154
-
155
- serverStatus.addClass('wrio-down');
156
- serverStatus.text(self.i18n.server_status_down);
157
- self.serverDown = true;
158
-
159
- return;
160
- } else {
161
- serverStatus.addClass('wrio-stable');
162
- serverStatus.text(self.i18n.server_status_stable);
163
- }
164
-
165
- $('#wrio-change-optimization-server').prop('disabled', false);
166
- self.startOptButton.prop('disabled', false);
167
-
168
- }).fail(function(xhr, status, error) {
169
- console.log(xhr);
170
- console.log(status);
171
- console.log(error);
172
-
173
- self.throwError(error);
174
- });
175
- },
176
-
177
- showModal: function() {
178
- var self = this;
179
- var infosModal = $('#wrio-tmpl-bulk-optimization');
180
-
181
- if( !infosModal.length ) {
182
- console.log('[Error]: Html template for modal not found.');
183
- return;
184
- }
185
-
186
- // Swal Information before loading the optimize process.
187
- swal({
188
- title: this.i18n.modal_optimization_title,
189
- html: infosModal.html(),
190
- type: '',
191
- customClass: 'wrio-modal wrio-modal-optimization-way',
192
- showCancelButton: true,
193
- showCloseButton: true,
194
- padding: 0,
195
- width: 654,
196
- confirmButtonText: this.i18n.modal_optimization_monual_button,
197
- cancelButtonText: this.i18n.modal_optimization_cron_button,
198
- reverseButtons: true,
199
- }).then(function(result) {
200
-
201
- self.process();
202
-
203
- window.onbeforeunload = function() {
204
- return self.i18n.leave_page_warning;
205
- }
206
-
207
- }, function(dismiss) {
208
- if( dismiss === 'cancel' ) { // you might also handle 'close' or 'timer' if you used those
209
- self.process('cron');
210
- } else {
211
- throw dismiss;
212
- }
213
- });
214
-
215
- },
216
-
217
- /**
218
- * Start optimization
219
- * @param {string} type
220
- */
221
- process: function(type) {
222
-
223
- this.inprogress = true;
224
-
225
- var sendData = {
226
- 'action': 'wrio-bulk-optimization-process',
227
- 'scope': this.settings.scope,
228
- 'multisite': 0,
229
- '_wpnonce': this.settings.nonce,
230
- };
231
-
232
- this.setButtonStyleRun(type);
233
-
234
- if( 'cron' === type ) {
235
- this.startOptButton.addClass('wrio-cron-mode');
236
-
237
- sendData['action'] = 'wrio-cron-start';
238
-
239
- $.post(ajaxurl, sendData, function(response) {
240
- if( !response || !response.success ) {
241
- console.log('[Error]: Failed ajax request (Start cron).');
242
- console.log(sendData);
243
- console.log(response);
244
-
245
- if( response.data && response.data.error_message ) {
246
- self.throwError(response.data.error_message);
247
- }
248
- }
249
- }).fail(function(xhr, status, error) {
250
- console.log(xhr);
251
- console.log(status);
252
- console.log(error);
253
-
254
- self.throwError(error);
255
- });
256
-
257
- return;
258
- }
259
-
260
- this.showMessage(this.i18n.optimization_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
261
-
262
- // show message: Optimization remined
263
- /*if( "1" === this.settings.is_network_admin ) {
264
- sendData['multisite'] = 1;
265
- }*/
266
-
267
- sendData['reset_current_errors'] = 1;
268
-
269
- this.sendRequest(sendData);
270
- },
271
-
272
- stop: function() {
273
- var self = this;
274
-
275
- this.inprogress = false;
276
-
277
- window.onbeforeunload = null;
278
- self.setButtonStyleStop();
279
- self.destroyMessages();
280
-
281
- if( this.startOptButton.hasClass('wrio-cron-mode') ) {
282
- this.startOptButton.removeClass('wrio-cron-mode');
283
-
284
- $.post(ajaxurl, {
285
- 'action': 'wrio-cron-stop',
286
- '_wpnonce': self.settings.nonce,
287
- 'type': self.settings.scope
288
- }, function(response) {
289
- if( !response || !response.success ) {
290
- console.log('[Error]: Failed ajax request (Stop cron).');
291
- console.log(response);
292
-
293
- if( response.data && response.data.error_message ) {
294
- self.throwError(response.data.error_message);
295
- }
296
- }
297
- }).fail(function(xhr, status, error) {
298
- console.log(xhr);
299
- console.log(status);
300
- console.log(error);
301
-
302
- self.throwError(error);
303
- });
304
- }
305
-
306
- },
307
-
308
- complete: function() {
309
- this.inprogress = false;
310
- window.onbeforeunload = null;
311
- this.setButtonStyleComplete();
312
- },
313
-
314
- setButtonStyleRun: function(mode) {
315
-
316
- this.startOptButton.addClass('wio-running');
317
-
318
- if( "cron" === mode ) {
319
- this.startOptButton.text(this.i18n.button_stop_cron);
320
- return;
321
- }
322
-
323
- this.startOptButton.text(this.i18n.button_stop);
324
- },
325
-
326
- setButtonStyleComplete: function() {
327
- this.showMessage(this.i18n.optimization_complete);
328
- this.startOptButton.text(this.i18n.button_completed);
329
- this.startOptButton.removeClass('wio-running');
330
- this.startOptButton.prop('disabled', true);
331
- },
332
-
333
- setButtonStyleStop: function() {
334
- this.startOptButton.removeClass('wio-running');
335
- this.startOptButton.text(this.i18n.buttom_start);
336
- },
337
-
338
- showMessage: function(text) {
339
- var contanier = $('.wio-page-statistic'),
340
- message;
341
-
342
- if( contanier.find('.wrio-statistic-message').length ) {
343
- message = contanier.find('.wrio-statistic-message');
344
- } else {
345
- message = $('<div>');
346
- message.addClass('wrio-statistic-message');
347
- contanier.append(message);
348
- }
349
-
350
- message.html(text);
351
- },
352
-
353
- throwError: function(error_message) {
354
- this.stop();
355
-
356
- var noticeId = $.wbcr_factory_clearfy_217.app.showNotice(error_message, 'danger');
357
-
358
- setTimeout(function() {
359
- $.wbcr_factory_clearfy_217.app.hideNotice(noticeId);
360
- }, 10000);
361
- },
362
-
363
- destroyMessages: function() {
364
- $('.wio-page-statistic').find('.wrio-statistic-message').remove();
365
- },
366
-
367
- sendRequest: function(data) {
368
- var self = this;
369
-
370
- if( !this.inprogress ) {
371
- return;
372
- }
373
-
374
- $.post(ajaxurl, data, function(response) {
375
- if( !self.inprogress ) {
376
- return;
377
- }
378
-
379
- if( !response || !response.success ) {
380
- console.log('[Error]: Failed ajax request (Try to optimize images).');
381
- console.log(response);
382
-
383
- if( response.data && response.data.error_message ) {
384
- self.throwError(response.data.error_message);
385
- }
386
-
387
- return;
388
- }
389
-
390
- data.reset_current_errors = 0;
391
-
392
- if( !response.data.end ) {
393
- $('#wio-total-unoptimized').text(parseInt(response.data.remain));
394
- self.showMessage(self.i18n.optimization_inprogress.replace("%s", parseInt(response.data.remain)));
395
- self.sendRequest(data);
396
- } else {
397
- $('#wio-total-unoptimized').text(response.data.remain);
398
- self.complete();
399
-
400
- // если мультисайт режим, то не скрываем кнопку запуска оптимизации
401
- /*if( $('#wbcr-rio-current-blog').length ) {
402
- $('#wio-start-optimization').toggleClass('wio-running');
403
- } else {
404
- $('#wio-start-optimization').hide();
405
- }*/
406
- }
407
-
408
- redraw_statistics(response.data.statistic);
409
-
410
- self.updateLog(response.data.last_optimized);
411
- }).fail(function(xhr, status, error) {
412
- console.log(xhr);
413
- console.log(status);
414
- console.log(error);
415
-
416
- self.throwError(error);
417
- });
418
- },
419
-
420
- updateLog: function(new_item_data) {
421
- var self = this;
422
-
423
- var limit = 100,
424
- tableEl = $('.wrio-optimization-progress .wrio-table');
425
-
426
- if( !tableEl.length || !new_item_data ) {
427
- return;
428
- }
429
-
430
- // если таблица была пустая
431
- if( $('.wrio-table-container-empty').length ) {
432
- $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
433
- if( tableEl.find('tbody').length ) {
434
- tableEl.find('tbody').empty();
435
- }
436
- }
437
-
438
- $.each(new_item_data, function(index, value) {
439
- var trEl = $('<tr>'),
440
- tdEl = $('<td>'),
441
- webpSize = value.webp_size ? value.webp_size : '-';
442
-
443
- if( tableEl.find('.wrio-row-id-' + value.id).length ) {
444
- tableEl.find('.wrio-row-id-' + value.id).remove();
445
- }
446
-
447
- trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
448
-
449
- if( 'error' === value.type ) {
450
- trEl.addClass('wrio-error');
451
- }
452
-
453
- var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
454
- previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
455
-
456
- tableEl.prepend(trEl);
457
-
458
- trEl.append(tdEl.clone().append(preview));
459
- trEl.append(tdEl.clone().append(previewUrl));
460
-
461
- if( 'error' === value.type ) {
462
- var colspan = value.scope !== 'custom-folders' ? '6' : '5';
463
- trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
464
- } else {
465
- trEl.append(tdEl.clone().text(value.original_size));
466
- trEl.append(tdEl.clone().text(value.optimized_size));
467
- trEl.append(tdEl.clone().text(webpSize));
468
- trEl.append(tdEl.clone().text(value.original_saving));
469
-
470
- if( "custom-folders" !== self.settings.scope ) {
471
- trEl.append(tdEl.clone().text(value.thumbnails_count));
472
- }
473
-
474
- trEl.append(tdEl.clone().text(value.total_saving));
475
- }
476
- });
477
-
478
- if( tableEl.find('tr').length > limit ) {
479
- var diff = tableEl.find('tr').length - limit;
480
-
481
- for( var i = 0; i < diff; i++ ) {
482
- tableEl.find('tr:last').remove();
483
- }
484
- }
485
- }
486
-
487
- };
488
-
489
- $(document).ready(function() {
490
- bulkOptimization.init();
491
- });
492
-
493
- var ajaxUrl = ajaxurl;
494
- var ai_data;
495
-
496
- function redraw_statistics(statistic) {
497
- $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized)
498
- .attr('data-optimized', statistic.optimized)
499
- .attr('data-errors', statistic.error);
500
- $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
501
- $('#wio-original-size').text(bytesToSize(statistic.original_size));
502
- $('#wio-optimized-size').text(bytesToSize(statistic.optimized_size));
503
- $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
504
- $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
505
- $('.wio-total-percent').text(statistic.optimized_percent + '%');
506
- $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
507
-
508
- $('#wio-unoptimized-num').text(statistic.unoptimized);
509
- $('#wio-optimized-num').text(statistic.optimized);
510
- $('#wio-error-num').text(statistic.error);
511
-
512
- if( $('.wrio-statistic-nav li.active').length ) {
513
- $('.wrio-statistic-nav li.active').find('span.wio-statistic-tab-percent').text(statistic.optimized_percent + '%');
514
- }
515
-
516
- window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
517
- window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
518
- window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
519
- window.wio_chart.update();
520
- if( $('#wio-overview-chart-percent').text() == '100%' ) {
521
- window.onbeforeunload = null;
522
- }
523
- }
524
-
525
- function bytesToSize(bytes) {
526
- var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
527
- if( bytes == 0 ) {
528
- return '0 Byte';
529
- }
530
- var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
531
- if( i == 0 ) {
532
- return bytes + ' ' + sizes[i];
533
- }
534
- return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
535
- }
536
-
537
- /*$('#wbcr-rio-current-blog').on('change', function() {
538
- var self = $(this);
539
- $('#wio-start-msg-complete').hide();
540
- $(this).attr('disabled', true);
541
- $('#wio-start-optimization').attr('disabled', true);
542
- var ai_data = {
543
- 'action': 'wbcr_rio_update_current_blog',
544
- 'wpnonce': $(this).data('nonce'),
545
- 'current_blog_id': $(this).find('option:selected').val(),
546
- 'context': $(this).attr('data-context')
547
- };
548
- $.post(ajaxUrl, ai_data, function(response) {
549
- self.removeAttr('disabled');
550
- $('#wio-start-optimization').removeAttr('disabled');
551
- redraw_statistics(response.data.statistic);
552
- });
553
- });*/
 
 
 
 
 
 
 
 
 
 
 
 
 
554
 
555
  });
1
+ jQuery(function ($) {
2
+ var bulkOptimization = {
3
+
4
+ inprogress: false,
5
+
6
+ serverDown: false,
7
+
8
+ i18n: {},
9
+
10
+ settings: {},
11
+
12
+ init: function () {
13
+ if (wrio_l18n_bulk_page === undefined || wrio_settings_bulk_page === undefined) {
14
+ console.log('[Error]: Required global variables are not declared.');
15
+ return;
16
+ }
17
+ if ('server_1' === $('#wrio-change-optimization-server').val()) {
18
+ $(".wrio-premium-user-balance-wrap").hide();
19
+ }
20
+ if ('server_5' === $('#wrio-change-optimization-server').val()) {
21
+ if (!this.settings.is_premium) {
22
+ $.wrio_modal.showErrorModal(this.i18n.premium_server_disabled);
23
+ }
24
+ }
25
+
26
+ this.i18n = wrio_l18n_bulk_page;
27
+ this.settings = wrio_settings_bulk_page;
28
+ this.startOptButton = $('#wrio-start-optimization');
29
+
30
+ this.registerEvents();
31
+ this.checkServerStatus();
32
+ this.checkPremiumUserBalance();
33
+
34
+ },
35
+
36
+ registerEvents: function () {
37
+ var self = this,
38
+ selectedServer = $("#wrio-change-optimization-server option:selected");
39
+
40
+ $('#wrio-change-optimization-server').on('change', function () {
41
+ $(this).prop('disabled', true);
42
+ $('.wrio-premium-user-balance').attr('data-server', $(this).val());
43
+ $(".wrio-premium-user-balance-wrap").show();
44
+
45
+ if ('server_1' === $(this).val()) {
46
+ $(".wrio-premium-user-balance-wrap").hide();
47
+ }
48
+ if ('server_5' === $(this).val()) {
49
+ if (!self.settings.is_premium) {
50
+ $.wrio_modal.showErrorModal(self.i18n.premium_server_disabled);
51
+ selectedServer.prop('selected', true);
52
+ $(this).prop('disabled', false);
53
+
54
+ return;
55
+ }
56
+ }
57
+
58
+ self.checkPremiumUserBalance();
59
+
60
+ selectedServer = $(this).find('option:selected');
61
+ self.checkServerStatus();
62
+ });
63
+
64
+ this.startOptButton.on('click', function () {
65
+ self.startOptButton = $(this);
66
+
67
+ if ($(this).hasClass('wio-running')) {
68
+ self.stop();
69
+ return;
70
+ }
71
+
72
+ if (self.serverDown) {
73
+ $.wrio_modal.showErrorModal(self.i18n.server_down_warning);
74
+ return;
75
+ }
76
+
77
+ if ("1" === self.settings.need_migration) {
78
+ $.wrio_modal.showErrorModal(self.i18n.need_migrations);
79
+ return;
80
+ }
81
+
82
+ if ("0" === self.settings.images_backup) {
83
+ $.wrio_modal.showWarningModal(self.i18n.process_without_backup, function () {
84
+ self.showModal();
85
+ });
86
+ return;
87
+ }
88
+
89
+ self.showModal();
90
+
91
+ return false;
92
+ });
93
+ },
94
+
95
+ checkPremiumUserBalance: function () {
96
+ var self = this,
97
+ userBalance = $('.wrio-premium-user-balance'),
98
+ data = {
99
+ 'action': 'wbcr-rio-check-user-balance',
100
+ '_wpnonce': self.settings.nonce
101
+ };
102
+
103
+ data['server_name'] = $('#wrio-change-optimization-server').val();
104
+
105
+ userBalance.addClass('wrio-premium-user-balance-check-proccess');
106
+ userBalance.text('');
107
+
108
+ $.post(ajaxurl, data, function (response) {
109
+ userBalance.removeClass('wrio-premium-user-balance-check-proccess');
110
+
111
+ if (!response || !response.data || !response.success) {
112
+ console.log('[Error]: Response error');
113
+ response.data && response.data.error && console.log(response.data.error);
114
+
115
+ if (!response || !response.data) {
116
+ console.log(response);
117
+ }
118
+
119
+ userBalance.text('error');
120
+ } else {
121
+ userBalance.text(response.data.balance);
122
+ }
123
+ }).fail(function (xhr, status, error) {
124
+ console.log(xhr);
125
+ console.log(status);
126
+ console.log(error);
127
+
128
+ self.throwError(error);
129
+ });
130
+ },
131
+
132
+ checkServerStatus: function () {
133
+ var self = this,
134
+ serverStatus = $('.wrio-server-status'),
135
+ data = {
136
+ 'action': 'wbcr-rio-check-servers-status',
137
+ '_wpnonce': self.settings.nonce
138
+ };
139
+
140
+ self.serverDown = false;
141
+
142
+ data['server_name'] = $('#wrio-change-optimization-server').val();
143
+
144
+ serverStatus.addClass('wrio-server-check-proccess');
145
+ serverStatus.text('');
146
+ serverStatus.removeClass('wrio-down').removeClass('wrio-stable');
147
+
148
+ self.startOptButton.prop('disabled', true);
149
+
150
+ $.post(ajaxurl, data, function (response) {
151
+ serverStatus.removeClass('wrio-server-check-proccess');
152
+ $('#wrio-change-optimization-server').prop('disabled', false);
153
+
154
+ if (!response || !response.data || !response.success) {
155
+ console.log('[Error]: Response error');
156
+ response.data && response.data.error && console.log(response.data.error);
157
+
158
+ if (!response || !response.data) {
159
+ console.log(response);
160
+ }
161
+
162
+ $('option[name="' + data['server_name'] + '"]').prop('disabled', true);
163
+ serverStatus.addClass('wrio-down');
164
+ serverStatus.text(self.i18n.server_status_down);
165
+ self.serverDown = true;
166
+
167
+ return;
168
+ } else {
169
+ serverStatus.addClass('wrio-stable');
170
+ serverStatus.text(self.i18n.server_status_stable);
171
+ }
172
+
173
+ self.startOptButton.prop('disabled', false);
174
+
175
+ }).fail(function (xhr, status, error) {
176
+ console.log(xhr);
177
+ console.log(status);
178
+ console.log(error);
179
+
180
+ self.throwError(error);
181
+ });
182
+ },
183
+
184
+ showModal: function () {
185
+ var self = this;
186
+ var infosModal = $('#wrio-tmpl-bulk-optimization');
187
+
188
+ if (!infosModal.length) {
189
+ console.log('[Error]: Html template for modal not found.');
190
+ return;
191
+ }
192
+
193
+ // Swal Information before loading the optimize process.
194
+ swal({
195
+ title: this.i18n.modal_optimization_title,
196
+ html: infosModal.html(),
197
+ type: '',
198
+ customClass: 'wrio-modal wrio-modal-optimization-way',
199
+ showCancelButton: true,
200
+ showCloseButton: true,
201
+ padding: 0,
202
+ width: 654,
203
+ confirmButtonText: this.i18n.modal_optimization_monual_button,
204
+ cancelButtonText: this.i18n.modal_optimization_cron_button,
205
+ reverseButtons: true,
206
+ }).then(function (result) {
207
+
208
+ self.process();
209
+
210
+ window.onbeforeunload = function () {
211
+ return self.i18n.leave_page_warning;
212
+ }
213
+
214
+ }, function (dismiss) {
215
+ if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
216
+ self.process('cron');
217
+ } else {
218
+ throw dismiss;
219
+ }
220
+ });
221
+
222
+ },
223
+
224
+ /**
225
+ * Start optimization
226
+ * @param {string} type
227
+ */
228
+ process: function (type) {
229
+
230
+ this.inprogress = true;
231
+
232
+ var sendData = {
233
+ 'action': 'wrio-bulk-optimization-process',
234
+ 'scope': this.settings.scope,
235
+ 'multisite': 0,
236
+ '_wpnonce': this.settings.nonce,
237
+ };
238
+
239
+ this.setButtonStyleRun(type);
240
+
241
+ if ('cron' === type) {
242
+ this.startOptButton.addClass('wrio-cron-mode');
243
+
244
+ sendData['action'] = 'wrio-cron-start';
245
+
246
+ $.post(ajaxurl, sendData, function (response) {
247
+ if (!response || !response.success) {
248
+ console.log('[Error]: Failed ajax request (Start cron).');
249
+ console.log(sendData);
250
+ console.log(response);
251
+
252
+ if (response.data && response.data.error_message) {
253
+ self.throwError(response.data.error_message);
254
+ }
255
+ }
256
+ }).fail(function (xhr, status, error) {
257
+ console.log(xhr);
258
+ console.log(status);
259
+ console.log(error);
260
+
261
+ self.throwError(error);
262
+ });
263
+
264
+ return;
265
+ }
266
+
267
+ this.showMessage(this.i18n.optimization_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
268
+
269
+ // show message: Optimization remined
270
+ /*if( "1" === this.settings.is_network_admin ) {
271
+ sendData['multisite'] = 1;
272
+ }*/
273
+
274
+ sendData['reset_current_errors'] = 1;
275
+
276
+ this.sendRequest(sendData);
277
+ },
278
+
279
+ stop: function () {
280
+ var self = this;
281
+
282
+ this.inprogress = false;
283
+
284
+ window.onbeforeunload = null;
285
+ self.setButtonStyleStop();
286
+ self.destroyMessages();
287
+
288
+ if (this.startOptButton.hasClass('wrio-cron-mode')) {
289
+ this.startOptButton.removeClass('wrio-cron-mode');
290
+
291
+ $.post(ajaxurl, {
292
+ 'action': 'wrio-cron-stop',
293
+ '_wpnonce': self.settings.nonce,
294
+ 'type': self.settings.scope
295
+ }, function (response) {
296
+ if (!response || !response.success) {
297
+ console.log('[Error]: Failed ajax request (Stop cron).');
298
+ console.log(response);
299
+
300
+ if (response.data && response.data.error_message) {
301
+ self.throwError(response.data.error_message);
302
+ }
303
+ }
304
+ }).fail(function (xhr, status, error) {
305
+ console.log(xhr);
306
+ console.log(status);
307
+ console.log(error);
308
+
309
+ self.throwError(error);
310
+ });
311
+ }
312
+
313
+ },
314
+
315
+ complete: function () {
316
+ this.inprogress = false;
317
+ window.onbeforeunload = null;
318
+ this.setButtonStyleComplete();
319
+ },
320
+
321
+ setButtonStyleRun: function (mode) {
322
+
323
+ this.startOptButton.addClass('wio-running');
324
+
325
+ if ("cron" === mode) {
326
+ this.startOptButton.text(this.i18n.button_stop_cron);
327
+ return;
328
+ }
329
+
330
+ this.startOptButton.text(this.i18n.button_stop);
331
+ },
332
+
333
+ setButtonStyleComplete: function () {
334
+ this.showMessage(this.i18n.optimization_complete);
335
+ this.startOptButton.text(this.i18n.button_completed);
336
+ this.startOptButton.removeClass('wio-running');
337
+ this.startOptButton.prop('disabled', true);
338
+ },
339
+
340
+ setButtonStyleStop: function () {
341
+ this.startOptButton.removeClass('wio-running');
342
+ this.startOptButton.text(this.i18n.buttom_start);
343
+ },
344
+
345
+ showMessage: function (text) {
346
+ var contanier = $('.wio-page-statistic'),
347
+ message;
348
+
349
+ if (contanier.find('.wrio-statistic-message').length) {
350
+ message = contanier.find('.wrio-statistic-message');
351
+ } else {
352
+ message = $('<div>');
353
+ message.addClass('wrio-statistic-message');
354
+ contanier.append(message);
355
+ }
356
+
357
+ message.html(text);
358
+ },
359
+
360
+ throwError: function (error_message) {
361
+ this.stop();
362
+
363
+ var noticeId = $.wbcr_factory_clearfy_227.app.showNotice(error_message, 'danger');
364
+
365
+ setTimeout(function () {
366
+ $.wbcr_factory_clearfy_227.app.hideNotice(noticeId);
367
+ }, 10000);
368
+ },
369
+
370
+ destroyMessages: function () {
371
+ $('.wio-page-statistic').find('.wrio-statistic-message').remove();
372
+ },
373
+
374
+ sendRequest: function (data) {
375
+ var self = this;
376
+
377
+ if (!this.inprogress) {
378
+ return;
379
+ }
380
+
381
+ $.post(ajaxurl, data, function (response) {
382
+ if (!self.inprogress) {
383
+ return;
384
+ }
385
+
386
+ if (!response || !response.success) {
387
+ console.log('[Error]: Failed ajax request (Try to optimize images).');
388
+ console.log(response);
389
+
390
+ if (response.data && response.data.error_message) {
391
+ self.throwError(response.data.error_message);
392
+ }
393
+
394
+ return;
395
+ }
396
+
397
+ data.reset_current_errors = 0;
398
+
399
+ if (!response.data.end) {
400
+ $('#wio-total-unoptimized').text(parseInt(response.data.remain));
401
+ self.showMessage(self.i18n.optimization_inprogress.replace("%s", parseInt(response.data.remain)));
402
+ self.sendRequest(data);
403
+ } else {
404
+ $('#wio-total-unoptimized').text(response.data.remain);
405
+ self.complete();
406
+
407
+ // если мультисайт режим, то не скрываем кнопку запуска оптимизации
408
+ /*if( $('#wbcr-rio-current-blog').length ) {
409
+ $('#wio-start-optimization').toggleClass('wio-running');
410
+ } else {
411
+ $('#wio-start-optimization').hide();
412
+ }*/
413
+ }
414
+
415
+ redraw_statistics(response.data.statistic);
416
+
417
+ self.updateLog(response.data.last_optimized);
418
+ }).fail(function (xhr, status, error) {
419
+ console.log(xhr);
420
+ console.log(status);
421
+ console.log(error);
422
+
423
+ self.throwError(error);
424
+ });
425
+ },
426
+
427
+ updateLog: function (new_item_data) {
428
+ var self = this;
429
+
430
+ var limit = 100,
431
+ tableEl = $('.wrio-optimization-progress .wrio-table');
432
+
433
+ if (!tableEl.length || !new_item_data) {
434
+ return;
435
+ }
436
+
437
+ // если таблица была пустая
438
+ if ($('.wrio-table-container-empty').length) {
439
+ $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
440
+ if (tableEl.find('tbody').length) {
441
+ tableEl.find('tbody').empty();
442
+ }
443
+ }
444
+
445
+ $.each(new_item_data, function (index, value) {
446
+ var trEl = $('<tr>'),
447
+ tdEl = $('<td>'),
448
+ webpSize = value.webp_size ? value.webp_size : '-';
449
+
450
+ if (tableEl.find('.wrio-row-id-' + value.id).length) {
451
+ tableEl.find('.wrio-row-id-' + value.id).remove();
452
+ }
453
+
454
+ trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
455
+
456
+ if ('error' === value.type) {
457
+ trEl.addClass('wrio-error');
458
+ }
459
+
460
+ var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
461
+ previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
462
+
463
+ tableEl.prepend(trEl);
464
+
465
+ trEl.append(tdEl.clone().append(preview));
466
+ trEl.append(tdEl.clone().append(previewUrl));
467
+
468
+ if ('error' === value.type) {
469
+ var colspan = value.scope !== 'custom-folders' ? '6' : '5';
470
+ trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
471
+ } else {
472
+ trEl.append(tdEl.clone().text(value.original_size));
473
+ trEl.append(tdEl.clone().text(value.optimized_size));
474
+ trEl.append(tdEl.clone().text(webpSize));
475
+ trEl.append(tdEl.clone().text(value.original_saving));
476
+
477
+ if ("custom-folders" !== self.settings.scope) {
478
+ trEl.append(tdEl.clone().text(value.thumbnails_count));
479
+ }
480
+
481
+ trEl.append(tdEl.clone().text(value.total_saving));
482
+ }
483
+ });
484
+
485
+ if (tableEl.find('tr').length > limit) {
486
+ var diff = tableEl.find('tr').length - limit;
487
+
488
+ for (var i = 0; i < diff; i++) {
489
+ tableEl.find('tr:last').remove();
490
+ }
491
+ }
492
+ }
493
+
494
+ };
495
+
496
+ $(document).ready(function () {
497
+ bulkOptimization.init();
498
+ $('[data-toggle="tooltip"]').tooltip();
499
+ });
500
+
501
+ var ajaxUrl = ajaxurl;
502
+ var ai_data;
503
+
504
+ function redraw_statistics(statistic) {
505
+ $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized)
506
+ .attr('data-optimized', statistic.optimized)
507
+ .attr('data-errors', statistic.error);
508
+ $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
509
+ $('#wio-original-size').text(bytesToSize(statistic.original_size));
510
+ $('#wio-optimized-size').text(bytesToSize(statistic.optimized_size));
511
+ $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
512
+ $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
513
+ $('.wio-total-percent').text(statistic.optimized_percent + '%');
514
+ $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
515
+
516
+ $('#wio-unoptimized-num').text(statistic.unoptimized);
517
+ $('#wio-optimized-num').text(statistic.optimized);
518
+ $('#wio-error-num').text(statistic.error);
519
+
520
+ var credits = $('.wrio-premium-user-balance');
521
+ if(credits.attr('data-server') !== "server_5") {
522
+ credits.text(statistic.credits);
523
+ }
524
+
525
+ if ($('.wrio-statistic-nav li.active').length) {
526
+ $('.wrio-statistic-nav li.active').find('span.wio-statistic-tab-percent').text(statistic.optimized_percent + '%');
527
+ }
528
+
529
+ window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
530
+ window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
531
+ window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
532
+ window.wio_chart.update();
533
+ if ($('#wio-overview-chart-percent').text() == '100%') {
534
+ window.onbeforeunload = null;
535
+ }
536
+ }
537
+
538
+ function bytesToSize(bytes) {
539
+ var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
540
+ if (bytes == 0) {
541
+ return '0 Byte';
542
+ }
543
+ var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
544
+ if (i == 0) {
545
+ return bytes + ' ' + sizes[i];
546
+ }
547
+ return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
548
+ }
549
+
550
+ /*$('#wbcr-rio-current-blog').on('change', function() {
551
+ var self = $(this);
552
+ $('#wio-start-msg-complete').hide();
553
+ $(this).attr('disabled', true);
554
+ $('#wio-start-optimization').attr('disabled', true);
555
+ var ai_data = {
556
+ 'action': 'wbcr_rio_update_current_blog',
557
+ 'wpnonce': $(this).data('nonce'),
558
+ 'current_blog_id': $(this).find('option:selected').val(),
559
+ 'context': $(this).attr('data-context')
560
+ };
561
+ $.post(ajaxUrl, ai_data, function(response) {
562
+ self.removeAttr('disabled');
563
+ $('#wio-start-optimization').removeAttr('disabled');
564
+ redraw_statistics(response.data.statistic);
565
+ });
566
+ });*/
567
 
568
  });
admin/assets/js/settings-premium.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery('button[data-value="googlepage"]').attr('disabled', 'disabled');
admin/assets/js/statistic.js CHANGED
@@ -1,36 +1,38 @@
1
  jQuery(function($) {
2
-
3
  var chat_html_id = 'wio-main-chart';
4
- var ctx = document.getElementById( chat_html_id );
5
 
6
- window.wio_chart = new Chart( ctx, {
7
- type: 'doughnut',
8
  data: {
9
- datasets: [{
10
- data: [
11
- $( '#' + chat_html_id ).attr( 'data-unoptimized' ),
12
- $( '#' + chat_html_id ).attr( 'data-optimized' ),
13
- $( '#' + chat_html_id ).attr( 'data-errors' ),
14
- ],
15
- backgroundColor: [
16
- '#d6d6d6',
17
- '#8bc34a',
18
- '#f1b1b6',
19
- ],
20
- borderWidth: 0,
21
- label: 'Dataset 1'
22
- }]
 
 
23
  },
24
  options: {
25
  legend: {
26
  display: false
27
  },
28
- events: [],
29
  animation: {
30
  easing: 'easeOutBounce'
31
  },
32
- responsive: false,
33
  cutoutPercentage: 80
34
  }
35
- } );
36
  });
1
  jQuery(function($) {
2
+
3
  var chat_html_id = 'wio-main-chart';
4
+ var ctx = document.getElementById(chat_html_id);
5
 
6
+ window.wio_chart = new window.robin.Chart(ctx, {
7
+ type: 'doughnut',
8
  data: {
9
+ datasets: [
10
+ {
11
+ data: [
12
+ $('#' + chat_html_id).attr('data-unoptimized'),
13
+ $('#' + chat_html_id).attr('data-optimized'),
14
+ $('#' + chat_html_id).attr('data-errors'),
15
+ ],
16
+ backgroundColor: [
17
+ '#d6d6d6',
18
+ '#8bc34a',
19
+ '#f1b1b6',
20
+ ],
21
+ borderWidth: 0,
22
+ label: 'Dataset 1'
23
+ }
24
+ ]
25
  },
26
  options: {
27
  legend: {
28
  display: false
29
  },
30
+ events: [],
31
  animation: {
32
  easing: 'easeOutBounce'
33
  },
34
+ responsive: false,
35
  cutoutPercentage: 80
36
  }
37
+ });
38
  });
admin/boot.php CHANGED
@@ -73,7 +73,7 @@
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
- 'wbcr-factory-clearfy-217-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
@@ -123,8 +123,8 @@
123
  *
124
  * Once all post meta migrated, notice would not be shown anymore.
125
  *
126
- * @param Wbcr_Factory425_Plugin $plugin
127
- * @param Wbcr_FactoryPages425_ImpressiveThemplate $obj
128
  *
129
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
130
  * @since 1.3.0
@@ -146,11 +146,11 @@
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WRIO_Plugin $plugin
149
- * @param Wbcr_FactoryPages425_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
- /*add_action('wbcr_factory_425_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
@@ -174,14 +174,14 @@
174
  return $page_url;
175
  }
176
 
177
- add_filter( 'wbcr_factory_pages_425_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
- * @param Wbcr_Factory425_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
@@ -320,8 +320,8 @@
320
  * Отправка уведомлений и скором окончании квоты в Impressive
321
  * Уведомления создаются только если квота <= 100
322
  *
323
- * @param Wbcr_Factory425_Plugin $plugin Экземпляр плагина, который передается в функцию обратного вызова
324
- * @param Wbcr_FactoryPages425_ImpressiveThemplate $obj Экземпляр страницы, который передается в функцию обратного вызова
325
  *
326
  * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
327
  * @since 1.4.2
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
+ 'wbcr-factory-clearfy-227-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
123
  *
124
  * Once all post meta migrated, notice would not be shown anymore.
125
  *
126
+ * @param Wbcr_Factory436_Plugin $plugin
127
+ * @param Wbcr_FactoryPages435_ImpressiveThemplate $obj
128
  *
129
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
130
  * @since 1.3.0
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WRIO_Plugin $plugin
149
+ * @param Wbcr_FactoryPages435_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
+ /*add_action('wbcr_factory_436_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
174
  return $page_url;
175
  }
176
 
177
+ add_filter( 'wbcr_factory_pages_435_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
+ * @param Wbcr_Factory436_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
320
  * Отправка уведомлений и скором окончании квоты в Impressive
321
  * Уведомления создаются только если квота <= 100
322
  *
323
+ * @param Wbcr_Factory436_Plugin $plugin Экземпляр плагина, который передается в функцию обратного вызова
324
+ * @param Wbcr_FactoryPages435_ImpressiveThemplate $obj Экземпляр страницы, который передается в функцию обратного вызова
325
  *
326
  * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
327
  * @since 1.4.2
admin/includes/classes/class-rio-optimize-template.php CHANGED
@@ -26,12 +26,12 @@ class WIO_OptimizePageTemplate {
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
- * @param Wbcr_FactoryClearfy217_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
- /*public function showPageContent( Wbcr_FactoryClearfy217_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
@@ -69,24 +69,24 @@ class WIO_OptimizePageTemplate {
69
  /**
70
  * Возвращает html код блока ручной оптимизации
71
  *
72
- * @param array $params {
73
  * Параметры
74
  *
75
- * @type int $attachment_id Attachment post ID
76
- * @type bool $is_optimized Оптимизировано ли изображение
77
- * @type string $attach_dimensions Размеры изображения. Например 200x150
78
- * @type int $attachment_file_size Размер оригинального основного файла в байтах
79
- * @type bool $is_skipped Пропущено ли изображение. Изображения с таким флагом больше не участвуют в
80
  * оптимизации
81
- * @type int $optimized_size Оптимизированный размер основного файла + превьюшек в байтах
82
- * @type int $original_size Оригинальный размер основного файла + превьюшек в байтах
83
- * @type int $original_main_size Оригинальный размер основного файла в байтах
84
- * @type int $thumbnails_optimized Кол-во оптимизированных превьюшек
85
- * @type string $optimization_level Уровень оптимизации
86
- * @type string $error_msg Текст ошибки
87
- * @type bool $backuped Сделана ли резервная копия
88
- * @type float $diff_percent Разница между оригиналом и оптимизацией в процентах
89
- * @type float $diff_percent_all Общая оптимизация в процентах
90
  * }
91
  *
92
  * @return string
@@ -209,7 +209,7 @@ class WIO_OptimizePageTemplate {
209
  </div>
210
  <!-- .wio-datas-actions-links -->
211
  <?php
212
- } else {
213
  ?>
214
  <button type="button" data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
215
  data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level=""
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
+ * @param Wbcr_FactoryClearfy227_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
+ /*public function showPageContent( Wbcr_FactoryClearfy227_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
69
  /**
70
  * Возвращает html код блока ручной оптимизации
71
  *
72
+ * @param array $params {
73
  * Параметры
74
  *
75
+ * @type int $attachment_id Attachment post ID
76
+ * @type bool $is_optimized Оптимизировано ли изображение
77
+ * @type string $attach_dimensions Размеры изображения. Например 200x150
78
+ * @type int $attachment_file_size Размер оригинального основного файла в байтах
79
+ * @type bool $is_skipped Пропущено ли изображение. Изображения с таким флагом больше не участвуют в
80
  * оптимизации
81
+ * @type int $optimized_size Оптимизированный размер основного файла + превьюшек в байтах
82
+ * @type int $original_size Оригинальный размер основного файла + превьюшек в байтах
83
+ * @type int $original_main_size Оригинальный размер основного файла в байтах
84
+ * @type int $thumbnails_optimized Кол-во оптимизированных превьюшек
85
+ * @type string $optimization_level Уровень оптимизации
86
+ * @type string $error_msg Текст ошибки
87
+ * @type bool $backuped Сделана ли резервная копия
88
+ * @type float $diff_percent Разница между оригиналом и оптимизацией в процентах
89
+ * @type float $diff_percent_all Общая оптимизация в процентах
90
  * }
91
  *
92
  * @return string
209
  </div>
210
  <!-- .wio-datas-actions-links -->
211
  <?php
212
+ } elseif ( $attach_dimensions !== '0 x 0' ) {
213
  ?>
214
  <button type="button" data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
215
  data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level=""
admin/pages/class-rio-license.php CHANGED
@@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
- class WRIO_License_Page extends Wbcr_FactoryClearfy217_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
@@ -43,9 +43,9 @@ class WRIO_License_Page extends Wbcr_FactoryClearfy217_LicensePage {
43
 
44
  /**
45
  * {@inheritdoc}
46
- * @param Wbcr_Factory425_Plugin $plugin
47
  */
48
- public function __construct( Wbcr_Factory425_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
+ class WRIO_License_Page extends Wbcr_FactoryClearfy227_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
43
 
44
  /**
45
  * {@inheritdoc}
46
+ * @param Wbcr_Factory436_Plugin $plugin
47
  */
48
+ public function __construct( Wbcr_Factory436_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
admin/pages/class-rio-log.php CHANGED
@@ -106,10 +106,10 @@ class WRIO_LogPage extends WRIO_Page {
106
 
107
  jQuery('#wbcr-log-viewer').html('');
108
  jQuery('#wbcr-log-size').text('0B');
109
- jQuery.wbcr_factory_clearfy_217.app.showNotice(data.message, data.type);
110
  },
111
  error: function(jqXHR, textStatus, errorThrown) {
112
- jQuery.wbcr_factory_clearfy_217.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
113
  btn.html(currentBtnText);
114
  }
115
  });
106
 
107
  jQuery('#wbcr-log-viewer').html('');
108
  jQuery('#wbcr-log-size').text('0B');
109
+ jQuery.wbcr_factory_clearfy_227.app.showNotice(data.message, data.type);
110
  },
111
  error: function(jqXHR, textStatus, errorThrown) {
112
+ jQuery.wbcr_factory_clearfy_227.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
113
  btn.html(currentBtnText);
114
  }
115
  });
admin/pages/class-rio-page.php CHANGED
@@ -18,7 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) {
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
- class WRIO_Page extends Wbcr_FactoryClearfy217_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
+ class WRIO_Page extends Wbcr_FactoryClearfy227_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
admin/pages/class-rio-settings.php CHANGED
@@ -12,76 +12,81 @@ if ( ! defined( 'ABSPATH' ) ) {
12
  * @version 1.0
13
  */
14
  class WRIO_SettingsPage extends WRIO_Page {
15
-
16
  /**
17
  * {@inheritdoc}
18
  */
19
  public $id = 'rio_settings';
20
-
21
  /**
22
  * {@inheritdoc}
23
  */
24
  public $page_menu_dashicon = 'dashicons-admin-generic';
25
-
26
  /**
27
  * {@inheritdoc}
28
  */
29
  public $show_right_sidebar_in_options = true;
30
-
31
  /**
32
  * @param WRIO_Plugin $plugin
33
  */
34
  public function __construct( WRIO_Plugin $plugin ) {
35
-
36
  $this->menu_title = __( 'Settings', 'robin-image-optimizer' );
37
  $this->page_menu_short_description = __( 'Plugin configuration', 'robin-image-optimizer' );
38
-
39
  parent::__construct( $plugin );
40
  }
41
-
42
  /**
43
  * Подключаем скрипты и стили для страницы
44
  *
45
  * @return void
46
  * @since 1.0.0
47
- * @see Wbcr_FactoryPages425_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
51
  parent::assets( $scripts, $styles );
52
-
53
  $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
54
  $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
55
-
 
 
 
 
 
56
  // Add Clearfy styles for HMWP pages
57
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
58
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
59
  }
60
  }
61
-
62
-
63
  /**
64
  * Выводим предупреждения
65
  *
66
  */
67
  protected function warningNotice() {
68
  $upload_dir = wp_upload_dir();
69
-
70
  if ( ! wp_is_writable( $upload_dir['basedir'] ) ) {
71
  $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
72
  }
73
-
74
  $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
75
  if ( file_exists( $wio_backup ) && ! wp_is_writable( $wio_backup ) ) {
76
  $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
77
  }
78
-
79
  if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true ) {
80
  $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
81
  }
82
  }
83
-
84
-
85
  /**
86
  * Метод должен передать массив опций для создания формы с полями.
87
  * Созданием страницы и формы занимается фреймворк
@@ -91,12 +96,12 @@ class WRIO_SettingsPage extends WRIO_Page {
91
  */
92
  public function getPageOptions() {
93
  $options = [];
94
-
95
  $options[] = [
96
  'type' => 'html',
97
  'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Main Settings', 'robin-image-optimizer' ) . '</strong><p>' . __( 'This section you can set main images optimization settings.', 'robin-image-optimizer' ) . '</p></div>'
98
  ];
99
-
100
  $options[] = [
101
  'type' => 'dropdown',
102
  'name' => 'image_optimization_server',
@@ -104,28 +109,24 @@ class WRIO_SettingsPage extends WRIO_Page {
104
  'data' => [
105
  [
106
  'server_1',
107
- __( 'Server 1 (✰✰✰✰) - image size limit up to 5 MB', 'robin-image-optimizer' ),
108
-
109
  ],
110
  [
111
  'server_2',
112
- __( 'Server 2 (✰✰) - poor compression, image size limit up to 1 MB', 'robin-image-optimizer' )
113
-
114
- ],
115
- [
116
- 'server_3',
117
- __( "Server 3 (✰✰) - poor compression, you can't use it on a localhost", 'robin-image-optimizer' )
118
  ],
119
  [
120
  'server_5',
121
- __( 'Premium (✰✰✰✰✰) no limits', 'robin-image-optimizer' )
122
  ],
123
  ],
124
  'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
125
  'hint' => __( 'We use several free servers for image optimization and can’t fully guarantee their stable performance. The server can be not available in some countries due to the political reasons. There is a solution: if one of the servers is not available or can’t optimize the image, you can try to switch to the alternative server. Each server has individual limitations for image weight and optimization level. By default, you have the best server with minimum limitations.', 'robin-image-optimizer' ),
126
  'default' => 'server_1',
127
  ];
128
-
129
  // Радио переключатель
130
  $options[] = [
131
  'type' => 'dropdown',
@@ -148,6 +149,11 @@ class WRIO_SettingsPage extends WRIO_Page {
148
  __( 'High', 'robin-image-optimizer' ),
149
  __( 'This mode will use all available optimization methods for maximum image compression. The file size will be reduced approximately 7 times. The quality of some images may deteriorate slightly. Use this mode if you need the maximum weight reduction, and you are ready to accept the loss of image quality.', 'robin-image-optimizer' )
150
  ],
 
 
 
 
 
151
  [
152
  'custom',
153
  __( 'Custom', 'robin-image-optimizer' ),
@@ -172,7 +178,7 @@ class WRIO_SettingsPage extends WRIO_Page {
172
  ],
173
  ]
174
  ];
175
-
176
  // Текстовое поле
177
  $options[] = [
178
  'type' => 'textbox',
@@ -182,7 +188,7 @@ class WRIO_SettingsPage extends WRIO_Page {
182
  'hint' => __( 'custom quality 1-100', 'robin-image-optimizer' ),
183
  'default' => '70'
184
  ];
185
-
186
  // Переключатель
187
  $options[] = [
188
  'type' => 'checkbox',
@@ -193,7 +199,7 @@ class WRIO_SettingsPage extends WRIO_Page {
193
  'hint' => __( 'Automatically compress all images that you upload directly to the WordPress media library, when editing pages and posts or using themes and plugins.', 'robin-image-optimizer' ),
194
  'default' => false
195
  ];
196
-
197
  // Переключатель
198
  $options[] = [
199
  'type' => 'checkbox',
@@ -204,7 +210,7 @@ class WRIO_SettingsPage extends WRIO_Page {
204
  'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
205
  'default' => true
206
  ];
207
-
208
  // Переключатель
209
  $options[] = [
210
  'type' => 'checkbox',
@@ -221,12 +227,12 @@ class WRIO_SettingsPage extends WRIO_Page {
221
  'hide' => '#wrio-error-log-options'
222
  ]
223
  ];
224
-
225
  $options[] = [
226
  'type' => 'html',
227
  'html' => [ $this, 'error_log_options' ]
228
  ];
229
-
230
  $options[] = [
231
  'type' => 'checkbox',
232
  'way' => 'buttons',
@@ -243,18 +249,18 @@ class WRIO_SettingsPage extends WRIO_Page {
243
  'hide' => '#wrio-webp-options'
244
  ]
245
  ];
246
-
247
  $options[] = [
248
  'type' => 'html',
249
  'html' => [ $this, 'conver_webp_options' ]
250
  ];
251
-
252
  // восстановление
253
  $options[] = [
254
  'type' => 'html',
255
  'html' => [ $this, 'rollbackButton' ],
256
  ];
257
-
258
  // Переключатель
259
  $options[] = [
260
  'type' => 'checkbox',
@@ -265,12 +271,44 @@ class WRIO_SettingsPage extends WRIO_Page {
265
  'hint' => __( 'EXIF is information stored in photos: camera model, shutter speed, exposure compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended data. If your project is dedicated to photography and you need to display this data, then enable this option.', 'robin-image-optimizer' ),
266
  'default' => true
267
  ];
268
-
 
 
 
 
 
 
 
 
 
 
269
  $options[] = [
270
  'type' => 'html',
271
  'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Here you can specify additional image optimization options.', 'robin-image-optimizer' ) . '</p></div>'
272
  ];
273
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  // Переключатель
275
  $options[] = [
276
  'type' => 'checkbox',
@@ -289,7 +327,7 @@ class WRIO_SettingsPage extends WRIO_Page {
289
  'hide' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
290
  ]
291
  ];
292
-
293
  // Текстовое поле
294
  $options[] = [
295
  'type' => 'textbox',
@@ -299,7 +337,7 @@ class WRIO_SettingsPage extends WRIO_Page {
299
  'hint' => __( 'Set the maximum images resolution on the long side. For horizontal images, this will be the width, and for vertical images - the height. The resolution of the images will be changed proportionally according to the set value.', 'robin-image-optimizer' ),
300
  'default' => '1600'
301
  ];
302
-
303
  // Текстовое поле
304
  $options[] = [
305
  'type' => 'textbox',
@@ -309,7 +347,22 @@ class WRIO_SettingsPage extends WRIO_Page {
309
  'hint' => __( 'Set the maximum images resolution on the long side. For horizontal images, this will be the width, and for vertical images - the height. The resolution of the images will be changed proportionally according to the set value.', 'robin-image-optimizer' ),
310
  'default' => '1600'
311
  ];
312
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  // получаем зарегистрированные размеры изображений
314
  $wp_image_sizes = wrio_get_image_sizes();
315
  $wio_image_sizes = [];
@@ -319,7 +372,7 @@ class WRIO_SettingsPage extends WRIO_Page {
319
  $key . ' - ' . $value['width'] . 'x' . $value['height'],
320
  ];
321
  }
322
-
323
  $options[] = [
324
  'type' => 'list',
325
  'way' => 'checklist',
@@ -330,20 +383,20 @@ class WRIO_SettingsPage extends WRIO_Page {
330
  'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
331
  'default' => 'thumbnail,medium'
332
  ];
333
-
334
  $options = apply_filters( 'wbcr/rio/settings_page/options', $options );
335
-
336
  $formOptions = [];
337
-
338
  $formOptions[] = [
339
  'type' => 'form-group',
340
  'items' => $options,
341
  //'cssClass' => 'postbox'
342
  ];
343
-
344
  return $formOptions;
345
  }
346
-
347
  /**
348
  * Save advanced options in database
349
  *
@@ -351,7 +404,7 @@ class WRIO_SettingsPage extends WRIO_Page {
351
  * @since 1.3.6
352
  */
353
  public function beforeFormSave() {
354
-
355
  /**
356
  * Used to save webp options. It can also be used to intercept
357
  * other unregistered fields.
@@ -359,18 +412,18 @@ class WRIO_SettingsPage extends WRIO_Page {
359
  * @since 1.3.6
360
  */
361
  do_action( "wrio/settings_page/berfore_form_save" );
362
-
363
  $error_log = (int) WRIO_Plugin::app()->request->post( WRIO_Plugin::app()->getPrefix() . 'error_log', 0 );
364
-
365
  if ( ! $error_log ) {
366
  return;
367
  }
368
-
369
  $keep_error_log_on_frontend = (int) WRIO_Plugin::app()->request->post( 'wrio_keep_error_log_on_frontend', 0 );
370
-
371
  WRIO_Plugin::app()->updatePopulateOption( 'keep_error_log_on_frontend', $keep_error_log_on_frontend );
372
  }
373
-
374
  /**
375
  * This method adds advanced options for the "Convert Images to WebP" checkbox.
376
  *
@@ -378,7 +431,7 @@ class WRIO_SettingsPage extends WRIO_Page {
378
  * @since 1.3.6
379
  */
380
  public function conver_webp_options() {
381
-
382
  /**
383
  * This hook prints options for delivering webp images.
384
  *
@@ -386,7 +439,7 @@ class WRIO_SettingsPage extends WRIO_Page {
386
  */
387
  do_action( "wrio/settings_page/conver_webp_options" );
388
  }
389
-
390
  /**
391
  * This method adds advanced options for the "Error log" checkbox.
392
  *
@@ -398,14 +451,14 @@ class WRIO_SettingsPage extends WRIO_Page {
398
  'keep_error_log_on_frontend' => (int) WRIO_Plugin::app()->getPopulateOption( 'keep_error_log_on_frontend', 0 )
399
  ] );
400
  }
401
-
402
  /**
403
  * Кнопка восстановления изображений
404
  */
405
  public function rollbackButton() {
406
  ?>
407
  <div class="form-group form-group-checkbox factory-control-rollback-button">
408
- <label for="wio-clear-backup-btn" class="col-sm-6 control-label">
409
  <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
410
  <span class="factory-hint-icon factory-hint-icon-red" data-toggle="factory-tooltip"
411
  data-placement="right" title=""
@@ -415,7 +468,7 @@ class WRIO_SettingsPage extends WRIO_Page {
415
  </span>
416
  </label>
417
  <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
418
- <div class="control-group col-sm-6">
419
  <div class="factory-buttons-way btn-group">
420
  <a class="btn btn-default" id="wio-restore-backup-btn"
421
  data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>"
12
  * @version 1.0
13
  */
14
  class WRIO_SettingsPage extends WRIO_Page {
15
+
16
  /**
17
  * {@inheritdoc}
18
  */
19
  public $id = 'rio_settings';
20
+
21
  /**
22
  * {@inheritdoc}
23
  */
24
  public $page_menu_dashicon = 'dashicons-admin-generic';
25
+
26
  /**
27
  * {@inheritdoc}
28
  */
29
  public $show_right_sidebar_in_options = true;
30
+
31
  /**
32
  * @param WRIO_Plugin $plugin
33
  */
34
  public function __construct( WRIO_Plugin $plugin ) {
35
+
36
  $this->menu_title = __( 'Settings', 'robin-image-optimizer' );
37
  $this->page_menu_short_description = __( 'Plugin configuration', 'robin-image-optimizer' );
38
+
39
  parent::__construct( $plugin );
40
  }
41
+
42
  /**
43
  * Подключаем скрипты и стили для страницы
44
  *
45
  * @return void
46
  * @since 1.0.0
47
+ * @see Wbcr_FactoryPages435_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
51
  parent::assets( $scripts, $styles );
52
+
53
  $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
54
  $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
55
+
56
+ if( ! wrio_is_license_activate() ) {
57
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/settings-premium.css' );
58
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/settings-premium.js');
59
+ }
60
+
61
  // Add Clearfy styles for HMWP pages
62
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
63
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
64
  }
65
  }
66
+
67
+
68
  /**
69
  * Выводим предупреждения
70
  *
71
  */
72
  protected function warningNotice() {
73
  $upload_dir = wp_upload_dir();
74
+
75
  if ( ! wp_is_writable( $upload_dir['basedir'] ) ) {
76
  $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
77
  }
78
+
79
  $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
80
  if ( file_exists( $wio_backup ) && ! wp_is_writable( $wio_backup ) ) {
81
  $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
82
  }
83
+
84
  if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true ) {
85
  $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
86
  }
87
  }
88
+
89
+
90
  /**
91
  * Метод должен передать массив опций для создания формы с полями.
92
  * Созданием страницы и формы занимается фреймворк
96
  */
97
  public function getPageOptions() {
98
  $options = [];
99
+
100
  $options[] = [
101
  'type' => 'html',
102
  'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Main Settings', 'robin-image-optimizer' ) . '</strong><p>' . __( 'This section you can set main images optimization settings.', 'robin-image-optimizer' ) . '</p></div>'
103
  ];
104
+
105
  $options[] = [
106
  'type' => 'dropdown',
107
  'name' => 'image_optimization_server',
109
  'data' => [
110
  [
111
  'server_1',
112
+ __( 'Server 1 - image size limit up to 5 MB', 'robin-image-optimizer' ),
113
+
114
  ],
115
  [
116
  'server_2',
117
+ __( 'Server 2 - beta', 'robin-image-optimizer' )
118
+
 
 
 
 
119
  ],
120
  [
121
  'server_5',
122
+ __( 'Premium - no limits', 'robin-image-optimizer' )
123
  ],
124
  ],
125
  'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
126
  'hint' => __( 'We use several free servers for image optimization and can’t fully guarantee their stable performance. The server can be not available in some countries due to the political reasons. There is a solution: if one of the servers is not available or can’t optimize the image, you can try to switch to the alternative server. Each server has individual limitations for image weight and optimization level. By default, you have the best server with minimum limitations.', 'robin-image-optimizer' ),
127
  'default' => 'server_1',
128
  ];
129
+
130
  // Радио переключатель
131
  $options[] = [
132
  'type' => 'dropdown',
149
  __( 'High', 'robin-image-optimizer' ),
150
  __( 'This mode will use all available optimization methods for maximum image compression. The file size will be reduced approximately 7 times. The quality of some images may deteriorate slightly. Use this mode if you need the maximum weight reduction, and you are ready to accept the loss of image quality.', 'robin-image-optimizer' )
151
  ],
152
+ [
153
+ 'googlepage',
154
+ __('G PageSpeed', 'robin-image-optimizer'),
155
+ __('This mode uses the optimal settings for Google Page Speed', 'robin-image-optimizer'),
156
+ ],
157
  [
158
  'custom',
159
  __( 'Custom', 'robin-image-optimizer' ),
178
  ],
179
  ]
180
  ];
181
+
182
  // Текстовое поле
183
  $options[] = [
184
  'type' => 'textbox',
188
  'hint' => __( 'custom quality 1-100', 'robin-image-optimizer' ),
189
  'default' => '70'
190
  ];
191
+
192
  // Переключатель
193
  $options[] = [
194
  'type' => 'checkbox',
199
  'hint' => __( 'Automatically compress all images that you upload directly to the WordPress media library, when editing pages and posts or using themes and plugins.', 'robin-image-optimizer' ),
200
  'default' => false
201
  ];
202
+
203
  // Переключатель
204
  $options[] = [
205
  'type' => 'checkbox',
210
  'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
211
  'default' => true
212
  ];
213
+
214
  // Переключатель
215
  $options[] = [
216
  'type' => 'checkbox',
227
  'hide' => '#wrio-error-log-options'
228
  ]
229
  ];
230
+
231
  $options[] = [
232
  'type' => 'html',
233
  'html' => [ $this, 'error_log_options' ]
234
  ];
235
+
236
  $options[] = [
237
  'type' => 'checkbox',
238
  'way' => 'buttons',
249
  'hide' => '#wrio-webp-options'
250
  ]
251
  ];
252
+
253
  $options[] = [
254
  'type' => 'html',
255
  'html' => [ $this, 'conver_webp_options' ]
256
  ];
257
+
258
  // восстановление
259
  $options[] = [
260
  'type' => 'html',
261
  'html' => [ $this, 'rollbackButton' ],
262
  ];
263
+
264
  // Переключатель
265
  $options[] = [
266
  'type' => 'checkbox',
271
  'hint' => __( 'EXIF is information stored in photos: camera model, shutter speed, exposure compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended data. If your project is dedicated to photography and you need to display this data, then enable this option.', 'robin-image-optimizer' ),
272
  'default' => true
273
  ];
274
+
275
+ $options[] = [
276
+ 'type' => 'checkbox',
277
+ 'way' => 'buttons',
278
+ 'name' => 'use_lazy_load',
279
+ 'title' => __( 'Use lazy loading for images', 'robin-image-optimizer' ),
280
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
281
+ 'hint' => __( 'Images will only load when the user has scrolled to them.', 'robin-image-optimizer' ),
282
+ 'default' => false
283
+ ];
284
+
285
  $options[] = [
286
  'type' => 'html',
287
  'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Here you can specify additional image optimization options.', 'robin-image-optimizer' ) . '</p></div>'
288
  ];
289
+
290
+ $options[] = [
291
+ 'type' => 'dropdown',
292
+ 'name' => 'image_optimization_order',
293
+ 'way' => 'buttons',
294
+ 'title' => __( 'Optimization order', 'robin-image-optimizer' ),
295
+ 'data' => [
296
+ [
297
+ 'asc',
298
+ __( 'Ascending', 'robin-image-optimizer' ),
299
+ __( 'Optimization will start with old images in the media library', 'robin-image-optimizer' )
300
+ ],
301
+ [
302
+ 'desc',
303
+ __( 'Descending', 'robin-image-optimizer' ),
304
+ __( 'Optimization will start with new images in the media library', 'robin-image-optimizer' )
305
+ ],
306
+ ],
307
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
308
+ 'hint' => __( "Select the optimization order from the media library.", 'robin-image-optimizer' ),
309
+ 'default' => 'asc',
310
+ ];
311
+
312
  // Переключатель
313
  $options[] = [
314
  'type' => 'checkbox',
327
  'hide' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
328
  ]
329
  ];
330
+
331
  // Текстовое поле
332
  $options[] = [
333
  'type' => 'textbox',
337
  'hint' => __( 'Set the maximum images resolution on the long side. For horizontal images, this will be the width, and for vertical images - the height. The resolution of the images will be changed proportionally according to the set value.', 'robin-image-optimizer' ),
338
  'default' => '1600'
339
  ];
340
+
341
  // Текстовое поле
342
  $options[] = [
343
  'type' => 'textbox',
347
  'hint' => __( 'Set the maximum images resolution on the long side. For horizontal images, this will be the width, and for vertical images - the height. The resolution of the images will be changed proportionally according to the set value.', 'robin-image-optimizer' ),
348
  'default' => '1600'
349
  ];
350
+
351
+ $options[] = [
352
+ 'type' => 'list',
353
+ 'way' => 'checklist',
354
+ 'name' => 'allowed_formats',
355
+ 'title' => __( 'Optimize formats', 'robin-image-optimizer' ),
356
+ 'data' => [
357
+ [ 'image/jpeg', 'JPG' ],
358
+ [ 'image/png', 'PNG' ],
359
+ [ 'image/gif', 'GIF' ],
360
+ ],
361
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
362
+ 'hint' => __( 'Choose which formats of images should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
363
+ 'default' => 'image/jpeg,image/png,image/gif'
364
+ ];
365
+
366
  // получаем зарегистрированные размеры изображений
367
  $wp_image_sizes = wrio_get_image_sizes();
368
  $wio_image_sizes = [];
372
  $key . ' - ' . $value['width'] . 'x' . $value['height'],
373
  ];
374
  }
375
+
376
  $options[] = [
377
  'type' => 'list',
378
  'way' => 'checklist',
383
  'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
384
  'default' => 'thumbnail,medium'
385
  ];
386
+
387
  $options = apply_filters( 'wbcr/rio/settings_page/options', $options );
388
+
389
  $formOptions = [];
390
+
391
  $formOptions[] = [
392
  'type' => 'form-group',
393
  'items' => $options,
394
  //'cssClass' => 'postbox'
395
  ];
396
+
397
  return $formOptions;
398
  }
399
+
400
  /**
401
  * Save advanced options in database
402
  *
404
  * @since 1.3.6
405
  */
406
  public function beforeFormSave() {
407
+
408
  /**
409
  * Used to save webp options. It can also be used to intercept
410
  * other unregistered fields.
412
  * @since 1.3.6
413
  */
414
  do_action( "wrio/settings_page/berfore_form_save" );
415
+
416
  $error_log = (int) WRIO_Plugin::app()->request->post( WRIO_Plugin::app()->getPrefix() . 'error_log', 0 );
417
+
418
  if ( ! $error_log ) {
419
  return;
420
  }
421
+
422
  $keep_error_log_on_frontend = (int) WRIO_Plugin::app()->request->post( 'wrio_keep_error_log_on_frontend', 0 );
423
+
424
  WRIO_Plugin::app()->updatePopulateOption( 'keep_error_log_on_frontend', $keep_error_log_on_frontend );
425
  }
426
+
427
  /**
428
  * This method adds advanced options for the "Convert Images to WebP" checkbox.
429
  *
431
  * @since 1.3.6
432
  */
433
  public function conver_webp_options() {
434
+
435
  /**
436
  * This hook prints options for delivering webp images.
437
  *
439
  */
440
  do_action( "wrio/settings_page/conver_webp_options" );
441
  }
442
+
443
  /**
444
  * This method adds advanced options for the "Error log" checkbox.
445
  *
451
  'keep_error_log_on_frontend' => (int) WRIO_Plugin::app()->getPopulateOption( 'keep_error_log_on_frontend', 0 )
452
  ] );
453
  }
454
+
455
  /**
456
  * Кнопка восстановления изображений
457
  */
458
  public function rollbackButton() {
459
  ?>
460
  <div class="form-group form-group-checkbox factory-control-rollback-button">
461
+ <label for="wio-clear-backup-btn" class="col-sm-4 control-label">
462
  <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
463
  <span class="factory-hint-icon factory-hint-icon-red" data-toggle="factory-tooltip"
464
  data-placement="right" title=""
468
  </span>
469
  </label>
470
  <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
471
+ <div class="control-group col-sm-8">
472
  <div class="factory-buttons-way btn-group">
473
  <a class="btn btn-default" id="wio-restore-backup-btn"
474
  data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>"
admin/pages/class-rio-statistic.php CHANGED
@@ -1,252 +1,272 @@
1
  <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  }
6
-
7
  /**
8
- * Class WRIO_StatisticPage
9
- * Класс отвечает за работу страницы статистики
10
  *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- */
14
- class WRIO_StatisticPage extends WRIO_Page {
15
-
16
- /**
17
- * {@inheritdoc}
18
- */
19
- public $id = 'rio_general';
20
-
21
- /**
22
- * {@inheritdoc}
23
- */
24
- public $type = 'page';
25
-
26
- /**
27
- * {@inheritdoc}
28
- */
29
- public $plugin;
30
-
31
- /**
32
- * {@inheritdoc}
33
- */
34
- public $page_menu_position = 20;
35
-
36
- /**
37
- * {@inheritdoc}
38
- */
39
- public $page_menu_dashicon = 'dashicons-chart-line';
40
-
41
- /**
42
- * @var string
43
- */
44
- public $menu_target = 'options-general.php';
45
-
46
- /**
47
- * @var bool
48
- */
49
- public $internal = false;
50
-
51
- /**
52
- * @var bool
53
- */
54
- public $add_link_to_plugin_actions = true;
55
-
56
- /**
57
- * Page type
58
- *
59
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
60
- * @since 1.3.0
61
- * @var string
62
- */
63
- protected $scope = 'media-library';
64
-
65
-
66
- /**
67
- * @param WRIO_Plugin $plugin
68
- */
69
- public function __construct( WRIO_Plugin $plugin ) {
70
- $this->menu_title = __( 'Robin image optimizer', 'robin-image-optimizer' );
71
- $this->page_menu_short_description = __( 'Compress bulk of images', 'robin-image-optimizer' );
72
- $this->plugin = $plugin;
73
-
74
- parent::__construct( $plugin );
75
-
76
- add_action( 'admin_enqueue_scripts', [ $this, 'print_i18n' ] );
77
- }
78
-
79
- /**
80
- * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
81
- * Меню текущего плагина будет добавлено в общее меню Clearfy
82
- *
83
- * @return string
84
- */
85
- public function getMenuScope() {
86
- if ( $this->clearfy_collaboration ) {
87
- //$this->internal = true;
88
-
89
- return 'wbcr_clearfy';
90
- }
91
-
92
- return $this->plugin->getPluginName();
93
  }
94
-
95
- /**
96
- * {@inheritdoc}
97
- */
98
- public function getMenuTitle() {
99
- return $this->clearfy_collaboration ? __( 'Robin Image Optimizer', 'robin-image-optimizer' ) : __( 'Robin image optimizer', 'robin-image-optimizer' );
100
  }
101
-
102
- /**
103
- * {@inheritdoc}
104
- */
105
- public function getPageTitle() {
106
- return $this->clearfy_collaboration ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Bulk optimization', 'robin-image-optimizer' );
 
 
 
 
 
 
 
107
  }
108
-
109
- /**
110
- * {@inheritdoc}
111
- */
112
- public function assets( $scripts, $styles ) {
113
- parent::assets( $scripts, $styles );
114
-
115
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
116
-
117
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/sweetalert2.js' );
118
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert2.css' );
119
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert-custom.css' );
120
-
121
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js' );
122
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js' );
123
-
124
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/modals.js', [ 'jquery' ], 'wrio-modals' );
125
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/bulk-optimization.js', [
126
- 'jquery',
127
- 'wrio-modals'
128
- ] );
129
-
130
- // Add Clearfy styles for HMWP pages
131
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
132
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
133
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
-
136
- /**
137
- * Print localization only current page
138
- *
139
- * @throws \Exception
140
- * @since 1.3.0
141
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
142
- */
143
- public function print_i18n() {
144
- $page = $this->plugin->request->get( 'page', null );
145
-
146
- if ( $page != $this->getResultId() ) {
147
- return;
148
- }
149
-
150
- $backup = new WIO_Backup();
151
-
152
- wp_localize_script( 'jquery', 'wrio_l18n_bulk_page', $this->get_i18n() );
153
-
154
- wp_localize_script( 'jquery', 'wrio_settings_bulk_page', [
155
- 'is_premium' => wrio_is_license_activate(),
156
- 'is_network_admin' => WRIO_Plugin::app()->isNetworkAdmin() ? 1 : 0,
157
- 'is_writable_backup_dir' => $backup->isBackupWritable() ? 1 : 0,
158
- 'images_backup' => WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false ) ? 1 : 0,
159
- 'need_migration' => wbcr_rio_has_meta_to_migrate() ? 1 : 0,
160
- 'scope' => $this->scope,
161
- 'nonce' => wp_create_nonce( 'bulk_optimization' )
162
- ] );
163
  }
164
-
165
- /**
166
- * {@inheritdoc}
167
- */
168
- public function showPageContent() {
169
- $is_premium = wrio_is_license_activate();
170
- $statistics = $this->get_statisctic_data();
171
-
172
- $template_data = [
173
- 'is_premium' => $is_premium,
174
- 'scope' => $this->scope
175
- ];
176
-
177
- //do_action( 'wbcr/rio/multisite_current_blog' );
178
-
179
- // Page header
180
- $this->view->print_template( 'part-page-header', [
181
- 'title' => __( 'Image optimization dashboard', 'robin-image-optimizer' ),
182
- 'description' => __( 'Monitor image optimization statistics and run on demand or scheduled optimization.', 'robin-image-optimizer' )
183
- ], $this );
184
-
185
- // Page tabs
186
- $this->view->print_template( 'part-bulk-optimization-tabs', $template_data, $this );
187
-
188
- ?>
189
- <div class="wbcr-factory-page-group-body" style="padding:0; border-top: 1px solid #d4d4d4;">
190
- <?php
191
- // Servers
192
- $this->view->print_template( 'part-bulk-optimization-servers', $template_data, $this );
193
-
194
- // Statistic
195
- $this->view->print_template( 'part-bulk-optimization-statistic', array_merge( $template_data, [
196
- 'stats' => $statistics->get()
197
- ] ), $this );
198
-
199
- // Optimization log
200
- $this->view->print_template( 'part-bulk-optimization-log', array_merge( $template_data, [
201
- 'process_log' => $statistics->get_last_optimized_images()
202
- ] ), $this );
203
- ?>
204
- </div>
205
- <script type="text/html" id="wrio-tmpl-bulk-optimization">
206
- <?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
207
- </script>
208
  <?php
209
- //do_action( 'wbcr/rio/multisite_restore_blog' );
210
- }
211
-
212
- /**
213
- * @return object|\WRIO_Image_Statistic
214
- * @since 1.3.0
215
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
216
- */
217
- protected function get_statisctic_data() {
218
- return WRIO_Image_Statistic::get_instance();
219
- }
220
-
221
- /**
222
- * @return array
223
- * @since 1.3.0
224
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
225
- */
226
- protected function get_i18n() {
227
- return [
228
- 'premium_server_disabled' => __( 'You cannot use the premium server on a free plan. You must activate the license to use all the features of the premium version.', 'robin-image-optimizer' ),
229
- 'server_down_warning' => __( 'Your selected optimization server is down. This means that you cannot optimize images through this server. Try selecting another optimization server.', 'robin-image-optimizer' ),
230
- 'server_status_down' => __( 'down', 'robin-image-optimizer' ),
231
- 'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
232
- 'modal_error' => __( 'Error', 'robin-image-optimizer' ),
233
- 'modal_cancel' => __( 'Cancel', 'robin-image-optimizer' ),
234
- 'modal_confirm' => __( 'Confirm', 'robin-image-optimizer' ),
235
- 'modal_optimization_title' => __( 'Select optimization way', 'robin-image-optimizer' ),
236
- 'modal_optimization_monual_button' => __( 'Optimize now', 'robin-image-optimizer' ),
237
- 'modal_optimization_cron_button' => __( 'Scheduled optimization', 'robin-image-optimizer' ),
238
- 'need_migrations' => __( 'To start optimizing, you must complete migration from old plugin version.', 'robin-image-optimizer' ),
239
- 'optimization_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
240
- 'optimization_inprogress' => __( 'Optimization in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
241
- 'leave_page_warning' => __( 'Are you sure that you want to leave the page? The optimization process is not over yet, stay on the page until the end of the optimization process.', 'robin-image-optimizer' ),
242
- 'process_without_backup' => __( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ),
243
- 'button_resume' => __( 'Resume', 'robin-image-optimizer' ),
244
- 'button_completed' => __( 'Completed', 'robin-image-optimizer' ),
245
- 'buttom_start' => __( 'Run', 'robin-image-optimizer' ),
246
- 'button_stop' => __( 'Stop', 'robin-image-optimizer' ),
247
- 'button_stop_cron' => __( 'Stop shedule optimization', 'robin-image-optimizer' )
248
- //Don't Need a Parachute?
249
- //If you keep this option deactivated, you won't be able to re-optimize your images to another compression level and restore your original images in case of need.
250
- ];
251
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  }
 
1
  <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Class WRIO_StatisticPage
9
+ * Класс отвечает за работу страницы статистики
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ */
14
+ class WRIO_StatisticPage extends WRIO_Page {
15
+
16
+ /**
17
+ * {@inheritdoc}
18
+ */
19
+ public $id = 'rio_general';
20
+
21
+ /**
22
+ * {@inheritdoc}
23
+ */
24
+ public $type = 'page';
25
+
26
+ /**
27
+ * {@inheritdoc}
28
+ */
29
+ public $plugin;
30
+
31
+ /**
32
+ * {@inheritdoc}
33
+ */
34
+ public $page_menu_position = 20;
35
+
36
+ /**
37
+ * {@inheritdoc}
38
+ */
39
+ public $page_menu_dashicon = 'dashicons-chart-line';
40
+
41
+ /**
42
+ * @var string
43
+ */
44
+ public $menu_target = 'options-general.php';
45
+
46
+ /**
47
+ * @var bool
48
+ */
49
+ public $internal = false;
50
+
51
+ /**
52
+ * @var bool
53
+ */
54
+ public $add_link_to_plugin_actions = true;
55
+
56
+ /**
57
+ * Page type
58
+ *
59
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
60
+ * @since 1.3.0
61
+ * @var string
62
+ */
63
+ protected $scope = 'media-library';
64
+
65
+
66
+ /**
67
+ * @param WRIO_Plugin $plugin
68
+ */
69
+ public function __construct( WRIO_Plugin $plugin ) {
70
+ $this->menu_title = __( 'Robin image optimizer', 'robin-image-optimizer' );
71
+ $this->page_menu_short_description = __( 'Compress bulk of images', 'robin-image-optimizer' );
72
+ $this->plugin = $plugin;
73
+
74
+ parent::__construct( $plugin );
75
+
76
+ add_action( 'admin_enqueue_scripts', [ $this, 'print_i18n' ] );
77
+
78
+ add_filter( 'wbcr/factory/pages/impressive/print_all_notices', [ $this, 'register_limit_notice' ], 10, 2 );
79
  }
80
+
81
  /**
82
+ * @param $plugin
83
+ * @param $obj
84
  *
85
+ * @return void|bool
86
+ */
87
+ public function register_limit_notice( $plugin, $obj ) {
88
+ if ( ( $this->plugin->getPluginName() != $plugin->getPluginName() ) || ( $obj->id != 'rio_general' ) ) {
89
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
+
92
+ if ( ! wrio_is_license_activate() && ! wrio_is_license_active() ) {
93
+ $notice = sprintf( __( "We are forced to introduce limits on free servers. Read more on <a href='%s'>our website</a>", 'robin-image-optimizer' ), 'https://robinoptimizer.com/we-are-forced-to-introduce-limits/' );
94
+ $obj->printWarningNotice( $notice );
 
 
95
  }
96
+ }
97
+
98
+ /**
99
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
100
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
101
+ *
102
+ * @return string
103
+ */
104
+ public function getMenuScope() {
105
+ if ( $this->clearfy_collaboration ) {
106
+ //$this->internal = true;
107
+
108
+ return 'wbcr_clearfy';
109
  }
110
+
111
+ return $this->plugin->getPluginName();
112
+ }
113
+
114
+ /**
115
+ * {@inheritdoc}
116
+ */
117
+ public function getMenuTitle() {
118
+ return $this->clearfy_collaboration ? __( 'Robin Image Optimizer', 'robin-image-optimizer' ) : __( 'Robin image optimizer', 'robin-image-optimizer' );
119
+ }
120
+
121
+ /**
122
+ * {@inheritdoc}
123
+ */
124
+ public function getPageTitle() {
125
+ return $this->clearfy_collaboration ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Bulk optimization', 'robin-image-optimizer' );
126
+ }
127
+
128
+ /**
129
+ * {@inheritdoc}
130
+ */
131
+ public function assets( $scripts, $styles ) {
132
+ parent::assets( $scripts, $styles );
133
+
134
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
135
+
136
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/sweetalert2.js' );
137
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert2.css' );
138
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert-custom.css' );
139
+
140
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js' );
141
+ //$this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js' );
142
+
143
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/modals.js', [ 'jquery' ], 'wrio-modals' );
144
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/bulk-optimization.js', [
145
+ 'jquery',
146
+ 'wrio-modals'
147
+ ] );
148
+
149
+ // Add Clearfy styles for HMWP pages
150
+ if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
151
+ $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
152
  }
153
+ }
154
+
155
+ /**
156
+ * Print localization only current page
157
+ *
158
+ * @throws \Exception
159
+ * @since 1.3.0
160
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
161
+ */
162
+ public function print_i18n() {
163
+ $page = $this->plugin->request->get( 'page', null );
164
+
165
+ if ( $page != $this->getResultId() ) {
166
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
+
169
+ $backup = new WIO_Backup();
170
+
171
+ wp_enqueue_script( 'wio-statistic-page', WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
172
+ wp_localize_script( 'wio-statistic-page', 'wrio_l18n_bulk_page', $this->get_i18n() );
173
+
174
+ wp_localize_script( 'wio-statistic-page', 'wrio_settings_bulk_page', [
175
+ 'is_premium' => wrio_is_license_activate(),
176
+ 'is_network_admin' => WRIO_Plugin::app()->isNetworkAdmin() ? 1 : 0,
177
+ 'is_writable_backup_dir' => $backup->isBackupWritable() ? 1 : 0,
178
+ 'images_backup' => WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false ) ? 1 : 0,
179
+ 'need_migration' => wbcr_rio_has_meta_to_migrate() ? 1 : 0,
180
+ 'scope' => $this->scope,
181
+ 'nonce' => wp_create_nonce( 'bulk_optimization' )
182
+ ] );
183
+ }
184
+
185
+ /**
186
+ * {@inheritdoc}
187
+ */
188
+ public function showPageContent() {
189
+ $is_premium = wrio_is_license_activate();
190
+ $statistics = $this->get_statisctic_data();
191
+
192
+ $template_data = [
193
+ 'is_premium' => $is_premium,
194
+ 'scope' => $this->scope
195
+ ];
196
+
197
+ //do_action( 'wbcr/rio/multisite_current_blog' );
198
+
199
+ // Page header
200
+ $this->view->print_template( 'part-page-header', [
201
+ 'title' => __( 'Image optimization dashboard', 'robin-image-optimizer' ),
202
+ 'description' => __( 'Monitor image optimization statistics and run on demand or scheduled optimization.', 'robin-image-optimizer' )
203
+ ], $this );
204
+
205
+ // Page tabs
206
+ $this->view->print_template( 'part-bulk-optimization-tabs', $template_data, $this );
207
+
208
+ ?>
209
+ <div class="wbcr-factory-page-group-body" style="padding:0; border-top: 1px solid #d4d4d4;">
 
 
210
  <?php
211
+ // Servers
212
+ $this->view->print_template( 'part-bulk-optimization-servers', $template_data, $this );
213
+
214
+ // Statistic
215
+ $this->view->print_template( 'part-bulk-optimization-statistic', array_merge( $template_data, [
216
+ 'stats' => $statistics->get()
217
+ ] ), $this );
218
+
219
+ // Optimization log
220
+ $this->view->print_template( 'part-bulk-optimization-log', array_merge( $template_data, [
221
+ 'process_log' => $statistics->get_last_optimized_images()
222
+ ] ), $this );
223
+ ?>
224
+ </div>
225
+ <script type="text/html" id="wrio-tmpl-bulk-optimization">
226
+ <?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
227
+ </script>
228
+ <?php
229
+ //do_action( 'wbcr/rio/multisite_restore_blog' );
230
+ }
231
+
232
+ /**
233
+ * @return object|\WRIO_Image_Statistic
234
+ * @since 1.3.0
235
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
236
+ */
237
+ protected function get_statisctic_data() {
238
+ return WRIO_Image_Statistic::get_instance();
239
+ }
240
+
241
+ /**
242
+ * @return array
243
+ * @since 1.3.0
244
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
245
+ */
246
+ protected function get_i18n() {
247
+ return [
248
+ 'premium_server_disabled' => __( 'You cannot use the premium server on a free plan. You must activate the license to use all the features of the premium version.', 'robin-image-optimizer' ),
249
+ 'server_down_warning' => __( 'Your selected optimization server is down. This means that you cannot optimize images through this server. Try selecting another optimization server.', 'robin-image-optimizer' ),
250
+ 'server_status_down' => __( 'down', 'robin-image-optimizer' ),
251
+ 'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
252
+ 'modal_error' => __( 'Error', 'robin-image-optimizer' ),
253
+ 'modal_cancel' => __( 'Cancel', 'robin-image-optimizer' ),
254
+ 'modal_confirm' => __( 'Confirm', 'robin-image-optimizer' ),
255
+ 'modal_optimization_title' => __( 'Select optimization way', 'robin-image-optimizer' ),
256
+ 'modal_optimization_monual_button' => __( 'Optimize now', 'robin-image-optimizer' ),
257
+ 'modal_optimization_cron_button' => __( 'Scheduled optimization', 'robin-image-optimizer' ),
258
+ 'need_migrations' => __( 'To start optimizing, you must complete migration from old plugin version.', 'robin-image-optimizer' ),
259
+ 'optimization_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
260
+ 'optimization_inprogress' => __( 'Optimization in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
261
+ 'leave_page_warning' => __( 'Are you sure that you want to leave the page? The optimization process is not over yet, stay on the page until the end of the optimization process.', 'robin-image-optimizer' ),
262
+ 'process_without_backup' => __( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ),
263
+ 'button_resume' => __( 'Resume', 'robin-image-optimizer' ),
264
+ 'button_completed' => __( 'Completed', 'robin-image-optimizer' ),
265
+ 'buttom_start' => __( 'Run', 'robin-image-optimizer' ),
266
+ 'button_stop' => __( 'Stop', 'robin-image-optimizer' ),
267
+ 'button_stop_cron' => __( 'Stop shedule optimization', 'robin-image-optimizer' )
268
+ //Don't Need a Parachute?
269
+ //If you keep this option deactivated, you won't be able to re-optimize your images to another compression level and restore your original images in case of need.
270
+ ];
271
  }
272
+ }
assets/js/jquery.lazy.js ADDED
@@ -0,0 +1,872 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery & Zepto Lazy - v1.7.10
3
+ * http://jquery.eisbehr.de/lazy/
4
+ *
5
+ * Copyright 2012 - 2018, Daniel 'Eisbehr' Kern
6
+ *
7
+ * Dual licensed under the MIT and GPL-2.0 licenses:
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ * http://www.gnu.org/licenses/gpl-2.0.html
10
+ *
11
+ * $("img.lazy").lazy();
12
+ */
13
+
14
+ ;(function(window, undefined) {
15
+ "use strict";
16
+
17
+ // noinspection JSUnresolvedVariable
18
+ /**
19
+ * library instance - here and not in construct to be shorter in minimization
20
+ * @return void
21
+ */
22
+ var $ = window.jQuery || window.Zepto,
23
+
24
+ /**
25
+ * unique plugin instance id counter
26
+ * @type {number}
27
+ */
28
+ lazyInstanceId = 0,
29
+
30
+ /**
31
+ * helper to register window load for jQuery 3
32
+ * @type {boolean}
33
+ */
34
+ windowLoaded = false;
35
+
36
+ /**
37
+ * make lazy available to jquery - and make it a bit more case-insensitive :)
38
+ * @access public
39
+ * @type {function}
40
+ * @param {object} settings
41
+ * @return {LazyPlugin}
42
+ */
43
+ $.fn.Lazy = $.fn.lazy = function(settings) {
44
+ return new LazyPlugin(this, settings);
45
+ };
46
+
47
+ /**
48
+ * helper to add plugins to lazy prototype configuration
49
+ * @access public
50
+ * @type {function}
51
+ * @param {string|Array} names
52
+ * @param {string|Array|function} [elements]
53
+ * @param {function} loader
54
+ * @return void
55
+ */
56
+ $.Lazy = $.lazy = function(names, elements, loader) {
57
+ // make second parameter optional
58
+ if ($.isFunction(elements)) {
59
+ loader = elements;
60
+ elements = [];
61
+ }
62
+
63
+ // exit here if parameter is not a callable function
64
+ if (!$.isFunction(loader)) {
65
+ return;
66
+ }
67
+
68
+ // make parameters an array of names to be sure
69
+ names = $.isArray(names) ? names : [names];
70
+ elements = $.isArray(elements) ? elements : [elements];
71
+
72
+ var config = LazyPlugin.prototype.config,
73
+ forced = config._f || (config._f = {});
74
+
75
+ // add the loader plugin for every name
76
+ for (var i = 0, l = names.length; i < l; i++) {
77
+ if (config[names[i]] === undefined || $.isFunction(config[names[i]])) {
78
+ config[names[i]] = loader;
79
+ }
80
+ }
81
+
82
+ // add forced elements loader
83
+ for (var c = 0, a = elements.length; c < a; c++) {
84
+ forced[elements[c]] = names[0];
85
+ }
86
+ };
87
+
88
+ /**
89
+ * contains all logic and the whole element handling
90
+ * is packed in a private function outside class to reduce memory usage, because it will not be created on every plugin instance
91
+ * @access private
92
+ * @type {function}
93
+ * @param {LazyPlugin} instance
94
+ * @param {object} config
95
+ * @param {object|Array} items
96
+ * @param {object} events
97
+ * @param {string} namespace
98
+ * @return void
99
+ */
100
+ function _executeLazy(instance, config, items, events, namespace) {
101
+ /**
102
+ * a helper to trigger the 'onFinishedAll' callback after all other events
103
+ * @access private
104
+ * @type {number}
105
+ */
106
+ var _awaitingAfterLoad = 0,
107
+
108
+ /**
109
+ * visible content width
110
+ * @access private
111
+ * @type {number}
112
+ */
113
+ _actualWidth = -1,
114
+
115
+ /**
116
+ * visible content height
117
+ * @access private
118
+ * @type {number}
119
+ */
120
+ _actualHeight = -1,
121
+
122
+ /**
123
+ * determine possibly detected high pixel density
124
+ * @access private
125
+ * @type {boolean}
126
+ */
127
+ _isRetinaDisplay = false,
128
+
129
+ /**
130
+ * dictionary entry for better minimization
131
+ * @access private
132
+ * @type {string}
133
+ */
134
+ _afterLoad = 'afterLoad',
135
+
136
+ /**
137
+ * dictionary entry for better minimization
138
+ * @access private
139
+ * @type {string}
140
+ */
141
+ _load = 'load',
142
+
143
+ /**
144
+ * dictionary entry for better minimization
145
+ * @access private
146
+ * @type {string}
147
+ */
148
+ _error = 'error',
149
+
150
+ /**
151
+ * dictionary entry for better minimization
152
+ * @access private
153
+ * @type {string}
154
+ */
155
+ _img = 'img',
156
+
157
+ /**
158
+ * dictionary entry for better minimization
159
+ * @access private
160
+ * @type {string}
161
+ */
162
+ _src = 'src',
163
+
164
+ /**
165
+ * dictionary entry for better minimization
166
+ * @access private
167
+ * @type {string}
168
+ */
169
+ _srcset = 'srcset',
170
+
171
+ /**
172
+ * dictionary entry for better minimization
173
+ * @access private
174
+ * @type {string}
175
+ */
176
+ _sizes = 'sizes',
177
+
178
+ /**
179
+ * dictionary entry for better minimization
180
+ * @access private
181
+ * @type {string}
182
+ */
183
+ _backgroundImage = 'background-image';
184
+
185
+ /**
186
+ * initialize plugin
187
+ * bind loading to events or set delay time to load all items at once
188
+ * @access private
189
+ * @return void
190
+ */
191
+ function _initialize() {
192
+ // detect actual device pixel ratio
193
+ // noinspection JSUnresolvedVariable
194
+ _isRetinaDisplay = window.devicePixelRatio > 1;
195
+
196
+ // prepare all initial items
197
+ items = _prepareItems(items);
198
+
199
+ // if delay time is set load all items at once after delay time
200
+ if (config.delay >= 0) {
201
+ setTimeout(function() {
202
+ _lazyLoadItems(true);
203
+ }, config.delay);
204
+ }
205
+
206
+ // if no delay is set or combine usage is active bind events
207
+ if (config.delay < 0 || config.combined) {
208
+ // create unique event function
209
+ events.e = _throttle(config.throttle, function(event) {
210
+ // reset detected window size on resize event
211
+ if (event.type === 'resize') {
212
+ _actualWidth = _actualHeight = -1;
213
+ }
214
+
215
+ // execute 'lazy magic'
216
+ _lazyLoadItems(event.all);
217
+ });
218
+
219
+ // create function to add new items to instance
220
+ events.a = function(additionalItems) {
221
+ additionalItems = _prepareItems(additionalItems);
222
+ items.push.apply(items, additionalItems);
223
+ };
224
+
225
+ // create function to get all instance items left
226
+ events.g = function() {
227
+ // filter loaded items before return in case internal filter was not running until now
228
+ return (items = $(items).filter(function() {
229
+ return !$(this).data(config.loadedName);
230
+ }));
231
+ };
232
+
233
+ // create function to force loading elements
234
+ events.f = function(forcedItems) {
235
+ for (var i = 0; i < forcedItems.length; i++) {
236
+ // only handle item if available in current instance
237
+ // use a compare function, because Zepto can't handle object parameter for filter
238
+ // var item = items.filter(forcedItems[i]);
239
+ /* jshint loopfunc: true */
240
+ var item = items.filter(function() {
241
+ return this === forcedItems[i];
242
+ });
243
+
244
+ if (item.length) {
245
+ _lazyLoadItems(false, item);
246
+ }
247
+ }
248
+ };
249
+
250
+ // load initial items
251
+ _lazyLoadItems();
252
+
253
+ // bind lazy load functions to scroll and resize event
254
+ // noinspection JSUnresolvedVariable
255
+ $(config.appendScroll).on('scroll.' + namespace + ' resize.' + namespace, events.e);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * prepare items before handle them
261
+ * @access private
262
+ * @param {Array|object|jQuery} items
263
+ * @return {Array|object|jQuery}
264
+ */
265
+ function _prepareItems(items) {
266
+ // fetch used configurations before loops
267
+ var defaultImage = config.defaultImage,
268
+ placeholder = config.placeholder,
269
+ imageBase = config.imageBase,
270
+ srcsetAttribute = config.srcsetAttribute,
271
+ loaderAttribute = config.loaderAttribute,
272
+ forcedTags = config._f || {};
273
+
274
+ // filter items and only add those who not handled yet and got needed attributes available
275
+ items = $(items).filter(function() {
276
+ var element = $(this),
277
+ tag = _getElementTagName(this);
278
+
279
+ return !element.data(config.handledName) &&
280
+ (element.attr(config.attribute) || element.attr(srcsetAttribute) || element.attr(loaderAttribute) || forcedTags[tag] !== undefined);
281
+ })
282
+
283
+ // append plugin instance to all elements
284
+ .data('plugin_' + config.name, instance);
285
+
286
+ for (var i = 0, l = items.length; i < l; i++) {
287
+ var element = $(items[i]),
288
+ tag = _getElementTagName(items[i]),
289
+ elementImageBase = element.attr(config.imageBaseAttribute) || imageBase;
290
+
291
+ // generate and update source set if an image base is set
292
+ if (tag === _img && elementImageBase && element.attr(srcsetAttribute)) {
293
+ element.attr(srcsetAttribute, _getCorrectedSrcSet(element.attr(srcsetAttribute), elementImageBase));
294
+ }
295
+
296
+ // add loader to forced element types
297
+ if (forcedTags[tag] !== undefined && !element.attr(loaderAttribute)) {
298
+ element.attr(loaderAttribute, forcedTags[tag]);
299
+ }
300
+
301
+ // set default image on every element without source
302
+ if (tag === _img && defaultImage && !element.attr(_src)) {
303
+ element.attr(_src, defaultImage);
304
+ }
305
+
306
+ // set placeholder on every element without background image
307
+ else if (tag !== _img && placeholder && (!element.css(_backgroundImage) || element.css(_backgroundImage) === 'none')) {
308
+ element.css(_backgroundImage, "url('" + placeholder + "')");
309
+ }
310
+ }
311
+
312
+ return items;
313
+ }
314
+
315
+ /**
316
+ * the 'lazy magic' - check all items
317
+ * @access private
318
+ * @param {boolean} [allItems]
319
+ * @param {object} [forced]
320
+ * @return void
321
+ */
322
+ function _lazyLoadItems(allItems, forced) {
323
+ // skip if no items where left
324
+ if (!items.length) {
325
+ // destroy instance if option is enabled
326
+ if (config.autoDestroy) {
327
+ // noinspection JSUnresolvedFunction
328
+ instance.destroy();
329
+ }
330
+
331
+ return;
332
+ }
333
+
334
+ var elements = forced || items,
335
+ loadTriggered = false,
336
+ imageBase = config.imageBase || '',
337
+ srcsetAttribute = config.srcsetAttribute,
338
+ handledName = config.handledName;
339
+
340
+ // loop all available items
341
+ for (var i = 0; i < elements.length; i++) {
342
+ // item is at least in loadable area
343
+ if (allItems || forced || _isInLoadableArea(elements[i])) {
344
+ var element = $(elements[i]),
345
+ tag = _getElementTagName(elements[i]),
346
+ attribute = element.attr(config.attribute),
347
+ elementImageBase = element.attr(config.imageBaseAttribute) || imageBase,
348
+ customLoader = element.attr(config.loaderAttribute);
349
+
350
+ // is not already handled
351
+ if (!element.data(handledName) &&
352
+ // and is visible or visibility doesn't matter
353
+ (!config.visibleOnly || element.is(':visible')) && (
354
+ // and image source or source set attribute is available
355
+ (attribute || element.attr(srcsetAttribute)) && (
356
+ // and is image tag where attribute is not equal source or source set
357
+ (tag === _img && (elementImageBase + attribute !== element.attr(_src) || element.attr(srcsetAttribute) !== element.attr(_srcset))) ||
358
+ // or is non image tag where attribute is not equal background
359
+ (tag !== _img && elementImageBase + attribute !== element.css(_backgroundImage))
360
+ ) ||
361
+ // or custom loader is available
362
+ customLoader))
363
+ {
364
+ // mark element always as handled as this point to prevent double handling
365
+ loadTriggered = true;
366
+ element.data(handledName, true);
367
+
368
+ // load item
369
+ _handleItem(element, tag, elementImageBase, customLoader);
370
+ }
371
+ }
372
+ }
373
+
374
+ // when something was loaded remove them from remaining items
375
+ if (loadTriggered) {
376
+ items = $(items).filter(function() {
377
+ return !$(this).data(handledName);
378
+ });
379
+ }
380
+ }
381
+
382
+ /**
383
+ * load the given element the lazy way
384
+ * @access private
385
+ * @param {object} element
386
+ * @param {string} tag
387
+ * @param {string} imageBase
388
+ * @param {function} [customLoader]
389
+ * @return void
390
+ */
391
+ function _handleItem(element, tag, imageBase, customLoader) {
392
+ // increment count of items waiting for after load
393
+ ++_awaitingAfterLoad;
394
+
395
+ // extended error callback for correct 'onFinishedAll' handling
396
+ var errorCallback = function() {
397
+ _triggerCallback('onError', element);
398
+ _reduceAwaiting();
399
+
400
+ // prevent further callback calls
401
+ errorCallback = $.noop;
402
+ };
403
+
404
+ // trigger function before loading image
405
+ _triggerCallback('beforeLoad', element);
406
+
407
+ // fetch all double used data here for better code minimization
408
+ var srcAttribute = config.attribute,
409
+ srcsetAttribute = config.srcsetAttribute,
410
+ sizesAttribute = config.sizesAttribute,
411
+ retinaAttribute = config.retinaAttribute,
412
+ removeAttribute = config.removeAttribute,
413
+ loadedName = config.loadedName,
414
+ elementRetina = element.attr(retinaAttribute);
415
+
416
+ // handle custom loader
417
+ if (customLoader) {
418
+ // on load callback
419
+ var loadCallback = function() {
420
+ // remove attribute from element
421
+ if (removeAttribute) {
422
+ element.removeAttr(config.loaderAttribute);
423
+ }
424
+
425
+ // mark element as loaded
426
+ element.data(loadedName, true);
427
+
428
+ // call after load event
429
+ _triggerCallback(_afterLoad, element);
430
+
431
+ // remove item from waiting queue and possibly trigger finished event
432
+ // it's needed to be asynchronous to run after filter was in _lazyLoadItems
433
+ setTimeout(_reduceAwaiting, 1);
434
+
435
+ // prevent further callback calls
436
+ loadCallback = $.noop;
437
+ };
438
+
439
+ // bind error event to trigger callback and reduce waiting amount
440
+ element.off(_error).one(_error, errorCallback)
441
+
442
+ // bind after load callback to element
443
+ .one(_load, loadCallback);
444
+
445
+ // trigger custom loader and handle response
446
+ if (!_triggerCallback(customLoader, element, function(response) {
447
+ if(response) {
448
+ element.off(_load);
449
+ loadCallback();
450
+ }
451
+ else {
452
+ element.off(_error);
453
+ errorCallback();
454
+ }
455
+ })) {
456
+ element.trigger(_error);
457
+ }
458
+ }
459
+
460
+ // handle images
461
+ else {
462
+ // create image object
463
+ var imageObj = $(new Image());
464
+
465
+ // bind error event to trigger callback and reduce waiting amount
466
+ imageObj.one(_error, errorCallback)
467
+
468
+ // bind after load callback to image
469
+ .one(_load, function() {
470
+ // remove element from view
471
+ element.hide();
472
+
473
+ // set image back to element
474
+ // do it as single 'attr' calls, to be sure 'src' is set after 'srcset'
475
+ if (tag === _img) {
476
+ element.attr(_sizes, imageObj.attr(_sizes))
477
+ .attr(_srcset, imageObj.attr(_srcset))
478
+ .attr(_src, imageObj.attr(_src));
479
+ }
480
+ else {
481
+ element.css(_backgroundImage, "url('" + imageObj.attr(_src) + "')");
482
+ }
483
+
484
+ // bring it back with some effect!
485
+ element[config.effect](config.effectTime);
486
+
487
+ // remove attribute from element
488
+ if (removeAttribute) {
489
+ element.removeAttr(srcAttribute + ' ' + srcsetAttribute + ' ' + retinaAttribute + ' ' + config.imageBaseAttribute);
490
+
491
+ // only remove 'sizes' attribute, if it was a custom one
492
+ if (sizesAttribute !== _sizes) {
493
+ element.removeAttr(sizesAttribute);
494
+ }
495
+ }
496
+
497
+ // mark element as loaded
498
+ element.data(loadedName, true);
499
+
500
+ // call after load event
501
+ _triggerCallback(_afterLoad, element);
502
+
503
+ // cleanup image object
504
+ imageObj.remove();
505
+
506
+ // remove item from waiting queue and possibly trigger finished event
507
+ _reduceAwaiting();
508
+ });
509
+
510
+ // set sources
511
+ // do it as single 'attr' calls, to be sure 'src' is set after 'srcset'
512
+ var imageSrc = (_isRetinaDisplay && elementRetina ? elementRetina : element.attr(srcAttribute)) || '';
513
+ imageObj.attr(_sizes, element.attr(sizesAttribute))
514
+ .attr(_srcset, element.attr(srcsetAttribute))
515
+ .attr(_src, imageSrc ? imageBase + imageSrc : null);
516
+
517
+ // call after load even on cached image
518
+ imageObj.complete && imageObj.trigger(_load); // jshint ignore : line
519
+ }
520
+ }
521
+
522
+ /**
523
+ * check if the given element is inside the current viewport or threshold
524
+ * @access private
525
+ * @param {object} element
526
+ * @return {boolean}
527
+ */
528
+ function _isInLoadableArea(element) {
529
+ var elementBound = element.getBoundingClientRect(),
530
+ direction = config.scrollDirection,
531
+ threshold = config.threshold,
532
+ vertical = // check if element is in loadable area from top
533
+ ((_getActualHeight() + threshold) > elementBound.top) &&
534
+ // check if element is even in loadable are from bottom
535
+ (-threshold < elementBound.bottom),
536
+ horizontal = // check if element is in loadable area from left
537
+ ((_getActualWidth() + threshold) > elementBound.left) &&
538
+ // check if element is even in loadable area from right
539
+ (-threshold < elementBound.right);
540
+
541
+ if (direction === 'vertical') {
542
+ return vertical;
543
+ }
544
+ else if (direction === 'horizontal') {
545
+ return horizontal;
546
+ }
547
+
548
+ return vertical && horizontal;
549
+ }
550
+
551
+ /**
552
+ * receive the current viewed width of the browser
553
+ * @access private
554
+ * @return {number}
555
+ */
556
+ function _getActualWidth() {
557
+ return _actualWidth >= 0 ? _actualWidth : (_actualWidth = $(window).width());
558
+ }
559
+
560
+ /**
561
+ * receive the current viewed height of the browser
562
+ * @access private
563
+ * @return {number}
564
+ */
565
+ function _getActualHeight() {
566
+ return _actualHeight >= 0 ? _actualHeight : (_actualHeight = $(window).height());
567
+ }
568
+
569
+ /**
570
+ * get lowercase tag name of an element
571
+ * @access private
572
+ * @param {object} element
573
+ * @returns {string}
574
+ */
575
+ function _getElementTagName(element) {
576
+ return element.tagName.toLowerCase();
577
+ }
578
+
579
+ /**
580
+ * prepend image base to all srcset entries
581
+ * @access private
582
+ * @param {string} srcset
583
+ * @param {string} imageBase
584
+ * @returns {string}
585
+ */
586
+ function _getCorrectedSrcSet(srcset, imageBase) {
587
+ if (imageBase) {
588
+ // trim, remove unnecessary spaces and split entries
589
+ var entries = srcset.split(',');
590
+ srcset = '';
591
+
592
+ for (var i = 0, l = entries.length; i < l; i++) {
593
+ srcset += imageBase + entries[i].trim() + (i !== l - 1 ? ',' : '');
594
+ }
595
+ }
596
+
597
+ return srcset;
598
+ }
599
+
600
+ /**
601
+ * helper function to throttle down event triggering
602
+ * @access private
603
+ * @param {number} delay
604
+ * @param {function} callback
605
+ * @return {function}
606
+ */
607
+ function _throttle(delay, callback) {
608
+ var timeout,
609
+ lastExecute = 0;
610
+
611
+ return function(event, ignoreThrottle) {
612
+ var elapsed = +new Date() - lastExecute;
613
+
614
+ function run() {
615
+ lastExecute = +new Date();
616
+ // noinspection JSUnresolvedFunction
617
+ callback.call(instance, event);
618
+ }
619
+
620
+ timeout && clearTimeout(timeout); // jshint ignore : line
621
+
622
+ if (elapsed > delay || !config.enableThrottle || ignoreThrottle) {
623
+ run();
624
+ }
625
+ else {
626
+ timeout = setTimeout(run, delay - elapsed);
627
+ }
628
+ };
629
+ }
630
+
631
+ /**
632
+ * reduce count of awaiting elements to 'afterLoad' event and fire 'onFinishedAll' if reached zero
633
+ * @access private
634
+ * @return void
635
+ */
636
+ function _reduceAwaiting() {
637
+ --_awaitingAfterLoad;
638
+
639
+ // if no items were left trigger finished event
640
+ if (!items.length && !_awaitingAfterLoad) {
641
+ _triggerCallback('onFinishedAll');
642
+ }
643
+ }
644
+
645
+ /**
646
+ * single implementation to handle callbacks, pass element and set 'this' to current instance
647
+ * @access private
648
+ * @param {string|function} callback
649
+ * @param {object} [element]
650
+ * @param {*} [args]
651
+ * @return {boolean}
652
+ */
653
+ function _triggerCallback(callback, element, args) {
654
+ if ((callback = config[callback])) {
655
+ // jQuery's internal '$(arguments).slice(1)' are causing problems at least on old iPads
656
+ // below is shorthand of 'Array.prototype.slice.call(arguments, 1)'
657
+ callback.apply(instance, [].slice.call(arguments, 1));
658
+ return true;
659
+ }
660
+
661
+ return false;
662
+ }
663
+
664
+ // if event driven or window is already loaded don't wait for page loading
665
+ if (config.bind === 'event' || windowLoaded) {
666
+ _initialize();
667
+ }
668
+
669
+ // otherwise load initial items and start lazy after page load
670
+ else {
671
+ // noinspection JSUnresolvedVariable
672
+ $(window).on(_load + '.' + namespace, _initialize);
673
+ }
674
+ }
675
+
676
+ /**
677
+ * lazy plugin class constructor
678
+ * @constructor
679
+ * @access private
680
+ * @param {object} elements
681
+ * @param {object} settings
682
+ * @return {object|LazyPlugin}
683
+ */
684
+ function LazyPlugin(elements, settings) {
685
+ /**
686
+ * this lazy plugin instance
687
+ * @access private
688
+ * @type {object|LazyPlugin|LazyPlugin.prototype}
689
+ */
690
+ var _instance = this,
691
+
692
+ /**
693
+ * this lazy plugin instance configuration
694
+ * @access private
695
+ * @type {object}
696
+ */
697
+ _config = $.extend({}, _instance.config, settings),
698
+
699
+ /**
700
+ * instance generated event executed on container scroll or resize
701
+ * packed in an object to be referenceable and short named because properties will not be minified
702
+ * @access private
703
+ * @type {object}
704
+ */
705
+ _events = {},
706
+
707
+ /**
708
+ * unique namespace for instance related events
709
+ * @access private
710
+ * @type {string}
711
+ */
712
+ _namespace = _config.name + '-' + (++lazyInstanceId);
713
+
714
+ // noinspection JSUndefinedPropertyAssignment
715
+ /**
716
+ * wrapper to get or set an entry from plugin instance configuration
717
+ * much smaller on minify as direct access
718
+ * @access public
719
+ * @type {function}
720
+ * @param {string} entryName
721
+ * @param {*} [value]
722
+ * @return {LazyPlugin|*}
723
+ */
724
+ _instance.config = function(entryName, value) {
725
+ if (value === undefined) {
726
+ return _config[entryName];
727
+ }
728
+
729
+ _config[entryName] = value;
730
+ return _instance;
731
+ };
732
+
733
+ // noinspection JSUndefinedPropertyAssignment
734
+ /**
735
+ * add additional items to current instance
736
+ * @access public
737
+ * @param {Array|object|string} items
738
+ * @return {LazyPlugin}
739
+ */
740
+ _instance.addItems = function(items) {
741
+ _events.a && _events.a($.type(items) === 'string' ? $(items) : items); // jshint ignore : line
742
+ return _instance;
743
+ };
744
+
745
+ // noinspection JSUndefinedPropertyAssignment
746
+ /**
747
+ * get all left items of this instance
748
+ * @access public
749
+ * @returns {object}
750
+ */
751
+ _instance.getItems = function() {
752
+ return _events.g ? _events.g() : {};
753
+ };
754
+
755
+ // noinspection JSUndefinedPropertyAssignment
756
+ /**
757
+ * force lazy to load all items in loadable area right now
758
+ * by default without throttle
759
+ * @access public
760
+ * @type {function}
761
+ * @param {boolean} [useThrottle]
762
+ * @return {LazyPlugin}
763
+ */
764
+ _instance.update = function(useThrottle) {
765
+ _events.e && _events.e({}, !useThrottle); // jshint ignore : line
766
+ return _instance;
767
+ };
768
+
769
+ // noinspection JSUndefinedPropertyAssignment
770
+ /**
771
+ * force element(s) to load directly, ignoring the viewport
772
+ * @access public
773
+ * @param {Array|object|string} items
774
+ * @return {LazyPlugin}
775
+ */
776
+ _instance.force = function(items) {
777
+ _events.f && _events.f($.type(items) === 'string' ? $(items) : items); // jshint ignore : line
778
+ return _instance;
779
+ };
780
+
781
+ // noinspection JSUndefinedPropertyAssignment
782
+ /**
783
+ * force lazy to load all available items right now
784
+ * this call ignores throttling
785
+ * @access public
786
+ * @type {function}
787
+ * @return {LazyPlugin}
788
+ */
789
+ _instance.loadAll = function() {
790
+ _events.e && _events.e({all: true}, true); // jshint ignore : line
791
+ return _instance;
792
+ };
793
+
794
+ // noinspection JSUndefinedPropertyAssignment
795
+ /**
796
+ * destroy this plugin instance
797
+ * @access public
798
+ * @type {function}
799
+ * @return undefined
800
+ */
801
+ _instance.destroy = function() {
802
+ // unbind instance generated events
803
+ // noinspection JSUnresolvedFunction, JSUnresolvedVariable
804
+ $(_config.appendScroll).off('.' + _namespace, _events.e);
805
+ // noinspection JSUnresolvedVariable
806
+ $(window).off('.' + _namespace);
807
+
808
+ // clear events
809
+ _events = {};
810
+
811
+ return undefined;
812
+ };
813
+
814
+ // start using lazy and return all elements to be chainable or instance for further use
815
+ // noinspection JSUnresolvedVariable
816
+ _executeLazy(_instance, _config, elements, _events, _namespace);
817
+ return _config.chainable ? elements : _instance;
818
+ }
819
+
820
+ /**
821
+ * settings and configuration data
822
+ * @access public
823
+ * @type {object|*}
824
+ */
825
+ LazyPlugin.prototype.config = {
826
+ // general
827
+ name : 'lazy',
828
+ chainable : true,
829
+ autoDestroy : true,
830
+ bind : 'load',
831
+ threshold : 500,
832
+ visibleOnly : false,
833
+ appendScroll : window,
834
+ scrollDirection : 'both',
835
+ imageBase : null,
836
+ defaultImage : 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
837
+ placeholder : null,
838
+ delay : -1,
839
+ combined : false,
840
+
841
+ // attributes
842
+ attribute : 'data-src',
843
+ srcsetAttribute : 'data-srcset',
844
+ sizesAttribute : 'data-sizes',
845
+ retinaAttribute : 'data-retina',
846
+ loaderAttribute : 'data-loader',
847
+ imageBaseAttribute : 'data-imagebase',
848
+ removeAttribute : true,
849
+ handledName : 'handled',
850
+ loadedName : 'loaded',
851
+
852
+ // effect
853
+ effect : 'show',
854
+ effectTime : 0,
855
+
856
+ // throttle
857
+ enableThrottle : true,
858
+ throttle : 250,
859
+
860
+ // callbacks
861
+ beforeLoad : undefined,
862
+ afterLoad : undefined,
863
+ onError : undefined,
864
+ onFinishedAll : undefined
865
+ };
866
+
867
+ // register window load event globally to prevent not loading elements
868
+ // since jQuery 3.X ready state is fully async and may be executed after 'load'
869
+ $(window).on('load', function() {
870
+ windowLoaded = true;
871
+ });
872
+ })(window);
assets/js/jquery.lazy.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! jQuery & Zepto Lazy v1.7.10 - http://jquery.eisbehr.de/lazy - MIT&GPL-2.0 license - Copyright 2012-2018 Daniel 'Eisbehr' Kern */
2
+ !function(t,e){"use strict";function r(r,a,i,u,l){function f(){L=t.devicePixelRatio>1,i=c(i),a.delay>=0&&setTimeout(function(){s(!0)},a.delay),(a.delay<0||a.combined)&&(u.e=v(a.throttle,function(t){"resize"===t.type&&(w=B=-1),s(t.all)}),u.a=function(t){t=c(t),i.push.apply(i,t)},u.g=function(){return i=n(i).filter(function(){return!n(this).data(a.loadedName)})},u.f=function(t){for(var e=0;e<t.length;e++){var r=i.filter(function(){return this===t[e]});r.length&&s(!1,r)}},s(),n(a.appendScroll).on("scroll."+l+" resize."+l,u.e))}function c(t){var i=a.defaultImage,o=a.placeholder,u=a.imageBase,l=a.srcsetAttribute,f=a.loaderAttribute,c=a._f||{};t=n(t).filter(function(){var t=n(this),r=m(this);return!t.data(a.handledName)&&(t.attr(a.attribute)||t.attr(l)||t.attr(f)||c[r]!==e)}).data("plugin_"+a.name,r);for(var s=0,d=t.length;s<d;s++){var A=n(t[s]),g=m(t[s]),h=A.attr(a.imageBaseAttribute)||u;g===N&&h&&A.attr(l)&&A.attr(l,b(A.attr(l),h)),c[g]===e||A.attr(f)||A.attr(f,c[g]),g===N&&i&&!A.attr(E)?A.attr(E,i):g===N||!o||A.css(O)&&"none"!==A.css(O)||A.css(O,"url('"+o+"')")}return t}function s(t,e){if(!i.length)return void(a.autoDestroy&&r.destroy());for(var o=e||i,u=!1,l=a.imageBase||"",f=a.srcsetAttribute,c=a.handledName,s=0;s<o.length;s++)if(t||e||A(o[s])){var g=n(o[s]),h=m(o[s]),b=g.attr(a.attribute),v=g.attr(a.imageBaseAttribute)||l,p=g.attr(a.loaderAttribute);g.data(c)||a.visibleOnly&&!g.is(":visible")||!((b||g.attr(f))&&(h===N&&(v+b!==g.attr(E)||g.attr(f)!==g.attr(F))||h!==N&&v+b!==g.css(O))||p)||(u=!0,g.data(c,!0),d(g,h,v,p))}u&&(i=n(i).filter(function(){return!n(this).data(c)}))}function d(t,e,r,i){++z;var o=function(){y("onError",t),p(),o=n.noop};y("beforeLoad",t);var u=a.attribute,l=a.srcsetAttribute,f=a.sizesAttribute,c=a.retinaAttribute,s=a.removeAttribute,d=a.loadedName,A=t.attr(c);if(i){var g=function(){s&&t.removeAttr(a.loaderAttribute),t.data(d,!0),y(T,t),setTimeout(p,1),g=n.noop};t.off(I).one(I,o).one(D,g),y(i,t,function(e){e?(t.off(D),g()):(t.off(I),o())})||t.trigger(I)}else{var h=n(new Image);h.one(I,o).one(D,function(){t.hide(),e===N?t.attr(C,h.attr(C)).attr(F,h.attr(F)).attr(E,h.attr(E)):t.css(O,"url('"+h.attr(E)+"')"),t[a.effect](a.effectTime),s&&(t.removeAttr(u+" "+l+" "+c+" "+a.imageBaseAttribute),f!==C&&t.removeAttr(f)),t.data(d,!0),y(T,t),h.remove(),p()});var m=(L&&A?A:t.attr(u))||"";h.attr(C,t.attr(f)).attr(F,t.attr(l)).attr(E,m?r+m:null),h.complete&&h.trigger(D)}}function A(t){var e=t.getBoundingClientRect(),r=a.scrollDirection,n=a.threshold,i=h()+n>e.top&&-n<e.bottom,o=g()+n>e.left&&-n<e.right;return"vertical"===r?i:"horizontal"===r?o:i&&o}function g(){return w>=0?w:w=n(t).width()}function h(){return B>=0?B:B=n(t).height()}function m(t){return t.tagName.toLowerCase()}function b(t,e){if(e){var r=t.split(",");t="";for(var a=0,n=r.length;a<n;a++)t+=e+r[a].trim()+(a!==n-1?",":"")}return t}function v(t,e){var n,i=0;return function(o,u){function l(){i=+new Date,e.call(r,o)}var f=+new Date-i;n&&clearTimeout(n),f>t||!a.enableThrottle||u?l():n=setTimeout(l,t-f)}}function p(){--z,i.length||z||y("onFinishedAll")}function y(t,e,n){return!!(t=a[t])&&(t.apply(r,[].slice.call(arguments,1)),!0)}var z=0,w=-1,B=-1,L=!1,T="afterLoad",D="load",I="error",N="img",E="src",F="srcset",C="sizes",O="background-image";"event"===a.bind||o?f():n(t).on(D+"."+l,f)}function a(a,o){var u=this,l=n.extend({},u.config,o),f={},c=l.name+"-"+ ++i;return u.config=function(t,r){return r===e?l[t]:(l[t]=r,u)},u.addItems=function(t){return f.a&&f.a("string"===n.type(t)?n(t):t),u},u.getItems=function(){return f.g?f.g():{}},u.update=function(t){return f.e&&f.e({},!t),u},u.force=function(t){return f.f&&f.f("string"===n.type(t)?n(t):t),u},u.loadAll=function(){return f.e&&f.e({all:!0},!0),u},u.destroy=function(){return n(l.appendScroll).off("."+c,f.e),n(t).off("."+c),f={},e},r(u,l,a,f,c),l.chainable?a:u}var n=t.jQuery||t.Zepto,i=0,o=!1;n.fn.Lazy=n.fn.lazy=function(t){return new a(this,t)},n.Lazy=n.lazy=function(t,r,i){if(n.isFunction(r)&&(i=r,r=[]),n.isFunction(i)){t=n.isArray(t)?t:[t],r=n.isArray(r)?r:[r];for(var o=a.prototype.config,u=o._f||(o._f={}),l=0,f=t.length;l<f;l++)(o[t[l]]===e||n.isFunction(o[t[l]]))&&(o[t[l]]=i);for(var c=0,s=r.length;c<s;c++)u[r[c]]=t[0]}},a.prototype.config={name:"lazy",chainable:!0,autoDestroy:!0,bind:"load",threshold:500,visibleOnly:!1,appendScroll:t,scrollDirection:"both",imageBase:null,defaultImage:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",placeholder:null,delay:-1,combined:!1,attribute:"data-src",srcsetAttribute:"data-srcset",sizesAttribute:"data-sizes",retinaAttribute:"data-retina",loaderAttribute:"data-loader",imageBaseAttribute:"data-imagebase",removeAttribute:!0,handledName:"handled",loadedName:"loaded",effect:"show",effectTime:0,enableThrottle:!0,throttle:250,beforeLoad:e,afterLoad:e,onError:e,onFinishedAll:e},n(t).on("load",function(){o=!0})}(window);
assets/js/lazy-load.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ jQuery( function () {
2
+ if('loading' in HTMLImageElement.prototype && wbcr_robin.wpCompatibleLazy === 'yes'){
3
+ //loading="lazy" in WP >= 5.5
4
+ } else {
5
+ var $tags = jQuery("img");
6
+ $tags.Lazy();
7
+ }
8
+ });
includes/class-rio-plugin.php CHANGED
@@ -1,184 +1,191 @@
1
  <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /**
8
- * Основной класс плагина
9
  *
10
- * @author Webcraftic <wordpress.webraftic@gmail.com>
11
- * @copyright (c) 19.02.2018, Webcraftic
12
- * @version 1.0
 
 
 
 
13
  */
14
- class WRIO_Plugin extends Wbcr_Factory425_Plugin {
15
-
16
- /**
17
- * @see self::app()
18
- * @var Wbcr_Factory425_Plugin
19
- */
20
- private static $app;
21
-
22
- /**
23
- * @since 3.1.0
24
- * @var array
25
- */
26
- private $plugin_data;
27
-
28
- /**
29
- * Конструктор
30
- *
31
- * Применяет конструктор родительского класса и записывает экземпляр текущего класса в свойство $app.
32
- * Подробнее о свойстве $app см. self::app()
33
- *
34
- * @param string $plugin_path
35
- * @param array $data
36
- *
37
- * @throws \Exception
38
- */
39
- public function __construct( $plugin_path, $data ) {
40
- parent::__construct( $plugin_path, $data );
41
-
42
- self::$app = $this;
43
- $this->plugin_data = $data;
44
-
45
- $this->includes();
46
-
47
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
48
- // Ajax files
49
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/backup.php' );
50
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/bulk-optimization.php' );
51
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/logs.php' );
52
- // Not under AJAX logical operator above on purpose to have helpers available to find out whether
53
- // metas were migrated or not
54
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/meta-migrations.php' );
55
- }
56
-
57
- if ( is_admin() ) {
58
- $this->initActivation();
59
-
60
- if ( wrio_is_license_activate() ) {
61
- if ( ! defined( 'FACTORY_ADVERTS_BLOCK' ) ) {
62
- define( 'FACTORY_ADVERTS_BLOCK', true );
63
- }
64
  }
65
  }
66
-
67
- add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
68
  }
69
-
70
- /**
71
- * Статический метод для быстрого доступа к интерфейсу плагина.
72
- *
73
- * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
74
- * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
75
- *
76
- * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
77
- * классам.
78
- *
79
- * @return \Wbcr_Factory425_Plugin|\WRIO_Plugin
80
- */
81
- public static function app() {
82
- return self::$app;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
84
-
85
- /**
86
- * Подключаем функции бекенда
87
- *
88
- * @throws Exception
89
- */
90
- public function pluginsLoaded() {
91
- if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
92
- $media_library = WRIO_Media_Library::get_instance();
93
- $media_library->initHooks();
94
- }
95
-
96
- if ( is_admin() ) {
97
- require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
98
- //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
99
-
100
- $this->registerPages();
101
- }
102
-
103
- if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
104
- $media_library = WRIO_Media_Library::get_instance();
105
- $media_library->initHooks();
106
- }
107
-
108
- if ( wrio_is_license_activate() ) {
109
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
110
- wrio_premium_load();
111
- }
112
  }
113
-
114
- /**
115
- * Подключаем модули классы и функции
116
- */
117
- protected function includes() {
118
-
119
- require_once( WRIO_PLUGIN_DIR . '/includes/functions.php' );
120
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-views.php' );
121
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-attachment.php' );
122
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-media-library.php' );
123
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-abstract.php' );
124
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-image-statistic.php' );
125
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-backup.php' );
126
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-optimization-tools.php' );
127
-
128
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-helper.php' );
129
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-object.php' ); // Base object
130
-
131
- // Database related models
132
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-active-record.php' );
133
- // Base class
134
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-extra-data.php' );
135
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-attachment-extra-data.php' );
136
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-server-smushit-extra-data.php' );
137
-
138
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-process-queue-table.php' ); // Processing queue model
139
-
140
- // Cron
141
- // ----------------
142
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-cron.php' );
143
- new WRIO_Cron();
144
-
145
- // Logger
146
- // ----------------
147
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-logger.php' );
148
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-export.php' );
149
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-reader.php' );
150
- new WRIO_Logger();
151
  }
152
-
153
- /**
154
- * Инициализируем активацию плагина
155
- */
156
- protected function initActivation() {
157
- include_once( WRIO_PLUGIN_DIR . '/admin/activation.php' );
158
- self::app()->registerActivation( 'WIO_Activation' );
159
  }
160
-
161
- /**
162
- * Регистрируем страницы плагина
163
- *
164
- * @throws Exception
165
- */
166
- private function registerPages() {
167
- $admin_path = WRIO_PLUGIN_DIR . '/admin/pages/';
168
-
169
- // Parent page class
170
- require_once( $admin_path . '/class-rio-page.php' );
171
-
172
- if ( ! wrio_is_clearfy_license_activate() ) {
173
- self::app()->registerPage( 'WRIO_License_Page', $admin_path . '/class-rio-license.php' );
174
- }
175
-
176
- self::app()->registerPage( 'WRIO_SettingsPage', $admin_path . '/class-rio-settings.php' );
177
- self::app()->registerPage( 'WRIO_StatisticPage', $admin_path . '/class-rio-statistic.php' );
178
-
179
- if ( self::app()->getPopulateOption( 'error_log', false ) ) {
180
- self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
181
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
  }
 
184
 
1
  <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Основной класс плагина
9
+ *
10
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
11
+ * @copyright (c) 19.02.2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WRIO_Plugin extends Wbcr_Factory436_Plugin {
15
+
16
+ /**
17
+ * @see self::app()
18
+ * @var Wbcr_Factory436_Plugin
19
+ */
20
+ private static $app;
21
+
22
+ /**
23
+ * @since 3.1.0
24
+ * @var array
25
+ */
26
+ private $plugin_data;
27
+
28
  /**
29
+ * Конструктор
30
  *
31
+ * Применяет конструктор родительского класса и записывает экземпляр текущего класса в свойство $app.
32
+ * Подробнее о свойстве $app см. self::app()
33
+ *
34
+ * @param string $plugin_path
35
+ * @param array $data
36
+ *
37
+ * @throws \Exception
38
  */
39
+ public function __construct( $plugin_path, $data ) {
40
+ parent::__construct( $plugin_path, $data );
41
+
42
+ self::$app = $this;
43
+ $this->plugin_data = $data;
44
+
45
+ $this->includes();
46
+
47
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
48
+ // Ajax files
49
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/backup.php' );
50
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/bulk-optimization.php' );
51
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/logs.php' );
52
+ // Not under AJAX logical operator above on purpose to have helpers available to find out whether
53
+ // metas were migrated or not
54
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/meta-migrations.php' );
55
+ }
56
+
57
+ if ( is_admin() ) {
58
+ $this->initActivation();
59
+
60
+ // completely disable image size threshold
61
+ add_filter( 'big_image_size_threshold', '__return_false' );
62
+
63
+ if ( wrio_is_license_activate() ) {
64
+ if ( ! defined( 'FACTORY_ADVERTS_BLOCK' ) ) {
65
+ define( 'FACTORY_ADVERTS_BLOCK', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
  }
 
 
68
  }
69
+
70
+ add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
71
+ }
72
+
73
+ /**
74
+ * Статический метод для быстрого доступа к интерфейсу плагина.
75
+ *
76
+ * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
77
+ * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
78
+ *
79
+ * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
80
+ * классам.
81
+ *
82
+ * @return \Wbcr_Factory436_Plugin|\WRIO_Plugin
83
+ */
84
+ public static function app() {
85
+ return self::$app;
86
+ }
87
+
88
+ /**
89
+ * Подключаем функции бекенда
90
+ *
91
+ * @throws Exception
92
+ */
93
+ public function pluginsLoaded() {
94
+ if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
95
+ $media_library = WRIO_Media_Library::get_instance();
96
+ $media_library->initHooks();
97
  }
98
+
99
+ if ( is_admin() ) {
100
+ require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
101
+ //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
102
+
103
+ $this->registerPages();
104
+ } else {
105
+ $lazy_load = WRIO_Lazy_Load::get_instance();
106
+ $lazy_load->init();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
+
109
+ if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
110
+ $media_library = WRIO_Media_Library::get_instance();
111
+ $media_library->initHooks();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
+
114
+ if ( wrio_is_license_activate() ) {
115
+ require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
116
+ wrio_premium_load();
 
 
 
117
  }
118
+ }
119
+
120
+ /**
121
+ * Подключаем модули классы и функции
122
+ */
123
+ protected function includes() {
124
+
125
+ require_once( WRIO_PLUGIN_DIR . '/includes/functions.php' );
126
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-views.php' );
127
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-attachment.php' );
128
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-media-library.php' );
129
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-lazy-load.php' );
130
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-abstract.php' );
131
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-image-statistic.php' );
132
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-backup.php' );
133
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-optimization-tools.php' );
134
+
135
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-helper.php' );
136
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-object.php' ); // Base object
137
+
138
+ // Database related models
139
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-active-record.php' );
140
+ // Base class
141
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-extra-data.php' );
142
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-attachment-extra-data.php' );
143
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-server-smushit-extra-data.php' );
144
+
145
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-process-queue-table.php' ); // Processing queue model
146
+
147
+ // Cron
148
+ // ----------------
149
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-cron.php' );
150
+ new WRIO_Cron();
151
+
152
+ // Logger
153
+ // ----------------
154
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-logger.php' );
155
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-export.php' );
156
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-reader.php' );
157
+ new WRIO_Logger();
158
+ }
159
+
160
+ /**
161
+ * Инициализируем активацию плагина
162
+ */
163
+ protected function initActivation() {
164
+ include_once( WRIO_PLUGIN_DIR . '/admin/activation.php' );
165
+ self::app()->registerActivation( 'WIO_Activation' );
166
+ }
167
+
168
+ /**
169
+ * Регистрируем страницы плагина
170
+ *
171
+ * @throws Exception
172
+ */
173
+ private function registerPages() {
174
+ $admin_path = WRIO_PLUGIN_DIR . '/admin/pages/';
175
+
176
+ // Parent page class
177
+ require_once( $admin_path . '/class-rio-page.php' );
178
+
179
+ if ( ! wrio_is_clearfy_license_activate() ) {
180
+ self::app()->registerPage( 'WRIO_License_Page', $admin_path . '/class-rio-license.php' );
181
+ }
182
+
183
+ self::app()->registerPage( 'WRIO_SettingsPage', $admin_path . '/class-rio-settings.php' );
184
+ self::app()->registerPage( 'WRIO_StatisticPage', $admin_path . '/class-rio-statistic.php' );
185
+
186
+ if ( self::app()->getPopulateOption( 'error_log', false ) ) {
187
+ self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
188
  }
189
  }
190
+ }
191
 
includes/classes/class-rio-attachment.php CHANGED
@@ -48,8 +48,8 @@ class WIO_Attachment {
48
  /**
49
  * Инициализация аттачмента
50
  *
51
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
52
- * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
53
  */
54
  public function __construct( $attachment_id, $attachment_meta = false ) {
55
  $this->id = $attachment_id;
@@ -65,9 +65,9 @@ class WIO_Attachment {
65
  }
66
 
67
  /**
68
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
69
- * @since 1.3.9
70
  * @return bool
 
 
71
  */
72
  public function isset_attachment_meta() {
73
  return $this->attachment_meta && isset( $this->attachment_meta['file'] );
@@ -107,9 +107,9 @@ class WIO_Attachment {
107
  * Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
108
  * of method was produced too soon.
109
  *
110
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
111
- * @since 1.3.9
112
  * @return bool
 
 
113
  */
114
  public function regenerate_metadata() {
115
  if ( $this->isset_attachment_meta() ) {
@@ -164,7 +164,7 @@ class WIO_Attachment {
164
  /**
165
  * Добавляем сообщение в лог файл.
166
  *
167
- * @param string $message Текст сообщения об ошибке.
168
  */
169
  public function writeLog( $message ) {
170
 
@@ -209,7 +209,7 @@ class WIO_Attachment {
209
  /**
210
  * Оптимизация аттачмента.
211
  *
212
- * @param string $optimization_level Уровень оптимизации изображения.
213
  *
214
  * @return array
215
  */
@@ -309,6 +309,7 @@ class WIO_Attachment {
309
  'image_path' => $this->get( 'path' ),
310
  'quality' => $image_processor->quality( $optimization_level ),
311
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
 
312
  ] );
313
 
314
  // проверяем на ошибку
@@ -640,6 +641,7 @@ class WIO_Attachment {
640
  'image_path' => $path,
641
  'quality' => $image_processor->quality( $quality ),
642
  'save_exif' => $exif,
 
643
  ] );
644
  // проверяем на ошибку
645
  if ( is_wp_error( $optimized_img_data ) ) {
@@ -682,7 +684,7 @@ class WIO_Attachment {
682
  /**
683
  * Возвращает путь.
684
  *
685
- * @param string $image_size Размер(thumbnail, medium ... )
686
  *
687
  * @return string
688
  */
@@ -700,8 +702,8 @@ class WIO_Attachment {
700
  /**
701
  * Заменяет оригинальный файл на оптимизированный.
702
  *
703
- * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
704
- * @param string $image_size Размер (thumbnail, medium ... )
705
  *
706
  * @return bool
707
  */
@@ -788,7 +790,7 @@ class WIO_Attachment {
788
  /**
789
  * Возвращает свойство аттачмента
790
  *
791
- * @param string $property имя свойства
792
  *
793
  * @return mixed
794
  */
@@ -803,7 +805,7 @@ class WIO_Attachment {
803
  /**
804
  * Возвращает URL изображения по указанному размеру
805
  *
806
- * @param string $size - размер изображения(thumbnail,medium,large...)
807
  *
808
  * @return string|null
809
  */
@@ -821,7 +823,7 @@ class WIO_Attachment {
821
  /**
822
  * Возвращает путь к изображению по указанному размеру.
823
  *
824
- * @param string $size Размер изображения (thumbnail, medium, large ...)
825
  *
826
  * @return string Путь до изображения.
827
  */
48
  /**
49
  * Инициализация аттачмента
50
  *
51
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
52
+ * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
53
  */
54
  public function __construct( $attachment_id, $attachment_meta = false ) {
55
  $this->id = $attachment_id;
65
  }
66
 
67
  /**
 
 
68
  * @return bool
69
+ * @since 1.3.9
70
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
71
  */
72
  public function isset_attachment_meta() {
73
  return $this->attachment_meta && isset( $this->attachment_meta['file'] );
107
  * Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
108
  * of method was produced too soon.
109
  *
 
 
110
  * @return bool
111
+ * @since 1.3.9
112
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
113
  */
114
  public function regenerate_metadata() {
115
  if ( $this->isset_attachment_meta() ) {
164
  /**
165
  * Добавляем сообщение в лог файл.
166
  *
167
+ * @param string $message Текст сообщения об ошибке.
168
  */
169
  public function writeLog( $message ) {
170
 
209
  /**
210
  * Оптимизация аттачмента.
211
  *
212
+ * @param string $optimization_level Уровень оптимизации изображения.
213
  *
214
  * @return array
215
  */
309
  'image_path' => $this->get( 'path' ),
310
  'quality' => $image_processor->quality( $optimization_level ),
311
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
312
+ 'is_thumb' => false,
313
  ] );
314
 
315
  // проверяем на ошибку
641
  'image_path' => $path,
642
  'quality' => $image_processor->quality( $quality ),
643
  'save_exif' => $exif,
644
+ 'is_thumb' => true,
645
  ] );
646
  // проверяем на ошибку
647
  if ( is_wp_error( $optimized_img_data ) ) {
684
  /**
685
  * Возвращает путь.
686
  *
687
+ * @param string $image_size Размер(thumbnail, medium ... )
688
  *
689
  * @return string
690
  */
702
  /**
703
  * Заменяет оригинальный файл на оптимизированный.
704
  *
705
+ * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
706
+ * @param string $image_size Размер (thumbnail, medium ... )
707
  *
708
  * @return bool
709
  */
790
  /**
791
  * Возвращает свойство аттачмента
792
  *
793
+ * @param string $property имя свойства
794
  *
795
  * @return mixed
796
  */
805
  /**
806
  * Возвращает URL изображения по указанному размеру
807
  *
808
+ * @param string $size - размер изображения(thumbnail,medium,large...)
809
  *
810
  * @return string|null
811
  */
823
  /**
824
  * Возвращает путь к изображению по указанному размеру.
825
  *
826
+ * @param string $size Размер изображения (thumbnail, medium, large ...)
827
  *
828
  * @return string Путь до изображения.
829
  */
includes/classes/class-rio-backup.php CHANGED
@@ -115,7 +115,7 @@ class WIO_Backup {
115
  }
116
  }
117
 
118
- $this->backup_dir = trailingslashit( $backup_dir );
119
 
120
  return $this->backup_dir;
121
  }
@@ -476,8 +476,6 @@ class WIO_Backup {
476
  * @return array
477
  */
478
  public static function alternateStorage( $servers ) {
479
- $servers['server_4'] = 'https://' . str_rot13( 'vzntrpbzcerffbe.pbz' );
480
- $servers['server_3'] = 'https://' . str_rot13( 'v0.jc.pbz' );
481
 
482
  return $servers;
483
  }
115
  }
116
  }
117
 
118
+ $this->backup_dir = apply_filters( 'wbcr/rio/backup/backup_dir', trailingslashit( $backup_dir ) );
119
 
120
  return $this->backup_dir;
121
  }
476
  * @return array
477
  */
478
  public static function alternateStorage( $servers ) {
 
 
479
 
480
  return $servers;
481
  }
includes/classes/class-rio-image-statistic.php CHANGED
@@ -39,10 +39,10 @@ class WRIO_Image_Statistic {
39
  }
40
 
41
  /**
42
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
43
  * @since 1.3.0
44
  *
45
- * @return object|\static object Main instance.
46
  */
47
  public static function get_instance() {
48
  if ( ! isset( static::$_instance ) ) {
@@ -65,8 +65,8 @@ class WRIO_Image_Statistic {
65
  * Добавляет новые данные к текущей статистике
66
  * К текущим числам добавляются новые
67
  *
68
- * @param string $field Поле, к которому добавляем значение
69
- * @param int $value добавляемое значение
70
  */
71
  public function addToField( $field, $value ) {
72
  if ( isset( $this->statistic[ $field ] ) ) {
@@ -78,8 +78,8 @@ class WRIO_Image_Statistic {
78
  * Вычитает данные из текущей статистики
79
  * Из текущего числа вычитается
80
  *
81
- * @param string $field Поле, из которого вычитается значение
82
- * @param int $value вычитаемое значение
83
  */
84
  public function deductFromField( $field, $value ) {
85
  $value = (int) $value;
@@ -152,6 +152,11 @@ class WRIO_Image_Statistic {
152
  $optimized_images_percent = 0;
153
  }
154
 
 
 
 
 
 
155
  return [
156
  'original' => $total_images,
157
  'optimized' => $optimized_count,
@@ -161,6 +166,7 @@ class WRIO_Image_Statistic {
161
  'optimized_size' => $optimized_size,
162
  'original_size' => $original_size,
163
  'save_size_percent' => $percent_diff,
 
164
  'error' => $error_count,
165
  ];
166
  }
@@ -168,9 +174,9 @@ class WRIO_Image_Statistic {
168
  /**
169
  * Count of non-optimized images
170
  *
171
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
172
- * @since 1.3.6
173
  * @return int
 
 
174
  */
175
  public static function get_unoptimized_count() {
176
  global $wpdb;
@@ -191,20 +197,20 @@ class WRIO_Image_Statistic {
191
  /**
192
  * Возвращает результат последних оптимизаций изображений
193
  *
194
- * @param int $limit лимит
195
  *
196
  * @return array {
197
  * Параметры
198
- * @type string $id id
199
- * @type string $file_name Имя файла
200
- * @type string $url URL
201
- * @type string $thumbnail_url URL превьюшки
202
- * @type string $original_size Размер до оптимизации
203
- * @type string $optimized_size Размер после оптимизации
204
- * @type string $webp_size webP размер
205
- * @type string $original_saving На сколько процентов изменился главный файл
206
  * @type string $thumbnails_count Сколько превьюшек оптимизировано
207
- * @type string $total_saving Процент оптимизации главного файла и превьюшек
208
  * }
209
  */
210
  public function get_last_optimized_images( $limit = 100 ) {
@@ -229,10 +235,11 @@ class WRIO_Image_Statistic {
229
  }
230
 
231
  /**
232
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
 
233
  * @since 1.3.9
234
  *
235
- * @param int $object_id
236
  */
237
  public function get_last_optimized_image( $object_id ) {
238
  global $wpdb;
@@ -254,13 +261,13 @@ class WRIO_Image_Statistic {
254
  }
255
 
256
  /**
257
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
258
- * @since 1.3.9
259
- *
260
  * @param RIO_Process_Queue $queue_model
261
  *
262
  * @return array
263
  * @throws \Exception
 
 
 
264
  */
265
  protected function format_for_log( $queue_model ) {
266
  if ( ! $queue_model instanceof RIO_Process_Queue ) {
@@ -289,6 +296,8 @@ class WRIO_Image_Statistic {
289
  $upload_dir = wp_upload_dir();
290
 
291
  $attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
 
 
292
 
293
  if ( ! empty( $attachment_meta ) ) {
294
  $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
@@ -379,7 +388,7 @@ class WRIO_Image_Statistic {
379
  * Пример: вводим 67894 байт, получаем 67.8 KB
380
  * Пример: вводим 6789477 байт, получаем 6.7 MB
381
  *
382
- * @param int $size размер файла в байтах
383
  *
384
  * @return string
385
  */
39
  }
40
 
41
  /**
42
+ * @return object|\static object Main instance.
43
  * @since 1.3.0
44
  *
45
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
46
  */
47
  public static function get_instance() {
48
  if ( ! isset( static::$_instance ) ) {
65
  * Добавляет новые данные к текущей статистике
66
  * К текущим числам добавляются новые
67
  *
68
+ * @param string $field Поле, к которому добавляем значение
69
+ * @param int $value добавляемое значение
70
  */
71
  public function addToField( $field, $value ) {
72
  if ( isset( $this->statistic[ $field ] ) ) {
78
  * Вычитает данные из текущей статистики
79
  * Из текущего числа вычитается
80
  *
81
+ * @param string $field Поле, из которого вычитается значение
82
+ * @param int $value вычитаемое значение
83
  */
84
  public function deductFromField( $field, $value ) {
85
  $value = (int) $value;
152
  $optimized_images_percent = 0;
153
  }
154
 
155
+ $processor = WIO_OptimizationTools::getImageProcessor();
156
+ $processor->checkLimits( false );
157
+ $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
158
+ $remaining = $processor->iamokay() - $usage;
159
+
160
  return [
161
  'original' => $total_images,
162
  'optimized' => $optimized_count,
166
  'optimized_size' => $optimized_size,
167
  'original_size' => $original_size,
168
  'save_size_percent' => $percent_diff,
169
+ 'credits' => $remaining,
170
  'error' => $error_count,
171
  ];
172
  }
174
  /**
175
  * Count of non-optimized images
176
  *
 
 
177
  * @return int
178
+ * @since 1.3.6
179
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
180
  */
181
  public static function get_unoptimized_count() {
182
  global $wpdb;
197
  /**
198
  * Возвращает результат последних оптимизаций изображений
199
  *
200
+ * @param int $limit лимит
201
  *
202
  * @return array {
203
  * Параметры
204
+ * @type string $id id
205
+ * @type string $file_name Имя файла
206
+ * @type string $url URL
207
+ * @type string $thumbnail_url URL превьюшки
208
+ * @type string $original_size Размер до оптимизации
209
+ * @type string $optimized_size Размер после оптимизации
210
+ * @type string $webp_size webP размер
211
+ * @type string $original_saving На сколько процентов изменился главный файл
212
  * @type string $thumbnails_count Сколько превьюшек оптимизировано
213
+ * @type string $total_saving Процент оптимизации главного файла и превьюшек
214
  * }
215
  */
216
  public function get_last_optimized_images( $limit = 100 ) {
235
  }
236
 
237
  /**
238
+ * @param int $object_id
239
+ *
240
  * @since 1.3.9
241
  *
242
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
243
  */
244
  public function get_last_optimized_image( $object_id ) {
245
  global $wpdb;
261
  }
262
 
263
  /**
 
 
 
264
  * @param RIO_Process_Queue $queue_model
265
  *
266
  * @return array
267
  * @throws \Exception
268
+ * @since 1.3.9
269
+ *
270
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
271
  */
272
  protected function format_for_log( $queue_model ) {
273
  if ( ! $queue_model instanceof RIO_Process_Queue ) {
296
  $upload_dir = wp_upload_dir();
297
 
298
  $attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
299
+ $formated_data = [];
300
+
301
 
302
  if ( ! empty( $attachment_meta ) ) {
303
  $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
388
  * Пример: вводим 67894 байт, получаем 67.8 KB
389
  * Пример: вводим 6789477 байт, получаем 6.7 MB
390
  *
391
+ * @param int $size размер файла в байтах
392
  *
393
  * @return string
394
  */
includes/classes/class-rio-lazy-load.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для ленивой загрузки изображений.
10
+ *
11
+ * @author Artem Prihodko <webtemyk@yandex.ru>
12
+ * @copyright (c) 2020, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WRIO_Lazy_Load {
16
+
17
+ /**
18
+ * The single instance of the class.
19
+ *
20
+ * @since 1.0.0
21
+ * @access protected
22
+ * @var object
23
+ */
24
+ protected static $_instance;
25
+
26
+ /**
27
+ * @return object|\WRIO_Lazy_Load object Main instance.
28
+ *
29
+ * @since 1.0.0
30
+ */
31
+ public static function get_instance() {
32
+ if ( ! isset( static::$_instance ) ) {
33
+ static::$_instance = new static();
34
+ }
35
+
36
+ return static::$_instance;
37
+ }
38
+
39
+ /**
40
+ * Установка хуков
41
+ */
42
+ public function init() {
43
+ if ( WRIO_Plugin::app()->getOption( 'use_lazy_load', false ) ) {
44
+ add_action( 'wp_enqueue_scripts', [ $this, 'front_scripts' ] );
45
+ add_filter( 'wp_get_attachment_image_attributes', [ $this, 'image_attributes' ], 10, 3 );
46
+ }
47
+ }
48
+
49
+ public function image_attributes( $attr, $attachment, $size ) {
50
+ if ( ! isset( $attr['loading'] ) ) {
51
+ $attr['loading'] = "lazy";
52
+ }
53
+
54
+ if ( isset( $attr['src'] ) ) {
55
+ $attr['data-src'] = $attr['src'];
56
+ unset( $attr['src'] );
57
+
58
+ if ( isset( $attr['srcset'] ) ) {
59
+ unset( $attr['srcset'] );
60
+ }
61
+ }
62
+
63
+ return $attr;
64
+ }
65
+
66
+ public function front_scripts() {
67
+ global $wp_version;
68
+ //do lazy
69
+ wp_enqueue_script( 'wbcr-jquery-lazy-load', WRIO_PLUGIN_URL . '/assets/js/jquery.lazy.min.js', [ 'jquery' ], false, true );
70
+ wp_enqueue_script( 'wbcr-robin-lazy-load', WRIO_PLUGIN_URL . '/assets/js/lazy-load.js', [ 'jquery' ], false, true );
71
+ wp_localize_script( 'wbcr-robin-lazy-load', 'wbcr_robin', [
72
+ 'wpCompatibleLazy' => (version_compare( $wp_version, '5.5.0' ) >= 0) ? 'yes' : 'no',
73
+ ] );
74
+ }
75
+
76
+ }
includes/classes/class-rio-media-library.php CHANGED
@@ -29,10 +29,10 @@ class WRIO_Media_Library {
29
  private $attachments = [];
30
 
31
  /**
32
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
33
  * @since 1.3.0
34
  *
35
- * @return object|\WRIO_Media_Library object Main instance.
36
  */
37
  public static function get_instance() {
38
  if ( ! isset( static::$_instance ) ) {
@@ -65,8 +65,8 @@ class WRIO_Media_Library {
65
  /**
66
  * Оптимизация при загрузке в медиабиблилтеку
67
  *
68
- * @param array $metadata метаданные аттачмента
69
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
70
  *
71
  * @return array $metadata Метаданные аттачмента
72
  */
@@ -89,11 +89,12 @@ class WRIO_Media_Library {
89
  $metadata = $attachment->getMetaData();
90
  $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
91
 
92
- // если отложенная оптимизация
93
  if ( in_array( $server, [ 'server_4' ] ) ) {
94
  sleep( 2 );
95
  $media_library->processDeferredOptimization();
96
  }
 
97
 
98
  return $metadata;
99
  }
@@ -101,7 +102,7 @@ class WRIO_Media_Library {
101
  /**
102
  * Возвращает объект аттачмента
103
  *
104
- * @param int $attachment_id
105
  * @param mixed $attachment_meta
106
  *
107
  * @return WIO_Attachment
@@ -117,8 +118,8 @@ class WRIO_Media_Library {
117
  /**
118
  * Оптимизирует аттачмент и сохраняет статистику
119
  *
120
- * @param int $attachment_id
121
- * @param string $level уровень оптимизации
122
  *
123
  * @return array
124
  */
@@ -215,10 +216,10 @@ class WRIO_Media_Library {
215
  /**
216
  * Хук срабатывает после восстановления аттачмента
217
  *
218
- * @since 1.2.0
219
- *
220
  * @param RIO_Process_Queue $optimization_data
221
  *
 
 
222
  */
223
  do_action( 'wbcr/rio/attachment_restored', $optimization_data );
224
 
@@ -228,7 +229,7 @@ class WRIO_Media_Library {
228
  /**
229
  * Обработка неоптимизированных изображений
230
  *
231
- * @param int $max_process_per_request кол-во аттачментов за 1 запуск
232
  *
233
  * @return array|\WP_Error
234
  */
@@ -249,6 +250,14 @@ class WRIO_Media_Library {
249
 
250
  $db_table = RIO_Process_Queue::table_name();
251
  $max_process_per_request = intval( $max_process_per_request );
 
 
 
 
 
 
 
 
252
 
253
  $sql = "SELECT DISTINCT posts.ID
254
  FROM {$wpdb->posts} AS posts
@@ -256,7 +265,8 @@ class WRIO_Media_Library {
256
  WHERE rio.object_id IS NULL
257
  AND posts.post_type = 'attachment'
258
  AND posts.post_status = 'inherit'
259
- AND posts.post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' )
 
260
  LIMIT {$max_process_per_request}";
261
 
262
  //выборка неоптимизированных изображений
@@ -276,6 +286,7 @@ class WRIO_Media_Library {
276
 
277
  foreach ( $unoptimized_attachments_ids as $attachment_id ) {
278
  $wio_attachment = $this->getAttachment( $attachment_id );
 
279
  if ( $wio_attachment->isOptimized() ) {
280
  $this->restoreAttachment( $attachment_id );
281
  $wio_attachment->reload();
@@ -359,7 +370,7 @@ class WRIO_Media_Library {
359
  /**
360
  * Восстановление из резервной копии.
361
  *
362
- * @param int $max_process_per_request кол-во аттачментов за 1 запуск
363
  *
364
  * @return array
365
  */
@@ -429,8 +440,8 @@ class WRIO_Media_Library {
429
  /**
430
  * Add "Image Optimizer" column in the Media Uploader
431
  *
432
- * @param array $form_fields An array of attachment form fields.
433
- * @param object $post The WP_Post attachment object.
434
  *
435
  * @return array
436
  */
@@ -455,7 +466,7 @@ class WRIO_Media_Library {
455
  /**
456
  * Add "wio" column in upload.php.
457
  *
458
- * @param array $columns An array of columns displayed in the Media list table.
459
  *
460
  * @return array
461
  */
@@ -468,8 +479,8 @@ class WRIO_Media_Library {
468
  /**
469
  * Add content to the "wio" columns in upload.php.
470
  *
471
- * @param string $column_name Name of the custom column.
472
- * @param int $attachment_id Attachment ID.
473
  */
474
  public function manageMediaColumn( $column_name, $attachment_id ) {
475
  if ( 'wio_optimized_file' !== $column_name ) {
@@ -481,8 +492,8 @@ class WRIO_Media_Library {
481
  /**
482
  * Возвращает шаблон для вывода блока кнопок на странице ручной оптимизации
483
  *
484
- * @param array $params @see calculateMediaLibraryParams()
485
- * @param string $type Тип страницы
486
  *
487
  * @return string
488
  */
@@ -496,7 +507,7 @@ class WRIO_Media_Library {
496
  /**
497
  * Выводит блок статистики для аттачмента в медиабиблиотеке
498
  *
499
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
500
  *
501
  * @return string
502
  */
@@ -611,8 +622,8 @@ class WRIO_Media_Library {
611
  * Возвращает процент оптимизации
612
  * Фильтр wbcr/rio/optimize_template/optimized_percent
613
  *
614
- * @param int $percent процент оптимизации
615
- * @param string $type тип страницы
616
  *
617
  * @return int процент оптимизации
618
  */
29
  private $attachments = [];
30
 
31
  /**
32
+ * @return object|\WRIO_Media_Library object Main instance.
33
  * @since 1.3.0
34
  *
35
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
36
  */
37
  public static function get_instance() {
38
  if ( ! isset( static::$_instance ) ) {
65
  /**
66
  * Оптимизация при загрузке в медиабиблилтеку
67
  *
68
+ * @param array $metadata метаданные аттачмента
69
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
70
  *
71
  * @return array $metadata Метаданные аттачмента
72
  */
89
  $metadata = $attachment->getMetaData();
90
  $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
91
 
92
+ /*// если отложенная оптимизация
93
  if ( in_array( $server, [ 'server_4' ] ) ) {
94
  sleep( 2 );
95
  $media_library->processDeferredOptimization();
96
  }
97
+ */
98
 
99
  return $metadata;
100
  }
102
  /**
103
  * Возвращает объект аттачмента
104
  *
105
+ * @param int $attachment_id
106
  * @param mixed $attachment_meta
107
  *
108
  * @return WIO_Attachment
118
  /**
119
  * Оптимизирует аттачмент и сохраняет статистику
120
  *
121
+ * @param int $attachment_id
122
+ * @param string $level уровень оптимизации
123
  *
124
  * @return array
125
  */
216
  /**
217
  * Хук срабатывает после восстановления аттачмента
218
  *
 
 
219
  * @param RIO_Process_Queue $optimization_data
220
  *
221
+ * @since 1.2.0
222
+ *
223
  */
224
  do_action( 'wbcr/rio/attachment_restored', $optimization_data );
225
 
229
  /**
230
  * Обработка неоптимизированных изображений
231
  *
232
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
233
  *
234
  * @return array|\WP_Error
235
  */
250
 
251
  $db_table = RIO_Process_Queue::table_name();
252
  $max_process_per_request = intval( $max_process_per_request );
253
+ $allowed_formats = explode( ',', WRIO_Plugin::app()->getOption( 'allowed_formats', "image/jpeg,image/png,image/gif" ) );
254
+ $allowed_formats_sql = [];
255
+ foreach ( $allowed_formats as $k => $format ) {
256
+ $allowed_formats_sql[ $k ] = "'{$format}'";
257
+ }
258
+ $allowed_formats_sql = implode( ',', $allowed_formats_sql );
259
+
260
+ $optimize_order = WRIO_Plugin::app()->getOption( 'image_optimization_order', "asc" );
261
 
262
  $sql = "SELECT DISTINCT posts.ID
263
  FROM {$wpdb->posts} AS posts
265
  WHERE rio.object_id IS NULL
266
  AND posts.post_type = 'attachment'
267
  AND posts.post_status = 'inherit'
268
+ AND posts.post_mime_type IN ( {$allowed_formats_sql} )
269
+ ORDER BY posts.ID {$optimize_order}
270
  LIMIT {$max_process_per_request}";
271
 
272
  //выборка неоптимизированных изображений
286
 
287
  foreach ( $unoptimized_attachments_ids as $attachment_id ) {
288
  $wio_attachment = $this->getAttachment( $attachment_id );
289
+
290
  if ( $wio_attachment->isOptimized() ) {
291
  $this->restoreAttachment( $attachment_id );
292
  $wio_attachment->reload();
370
  /**
371
  * Восстановление из резервной копии.
372
  *
373
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
374
  *
375
  * @return array
376
  */
440
  /**
441
  * Add "Image Optimizer" column in the Media Uploader
442
  *
443
+ * @param array $form_fields An array of attachment form fields.
444
+ * @param object $post The WP_Post attachment object.
445
  *
446
  * @return array
447
  */
466
  /**
467
  * Add "wio" column in upload.php.
468
  *
469
+ * @param array $columns An array of columns displayed in the Media list table.
470
  *
471
  * @return array
472
  */
479
  /**
480
  * Add content to the "wio" columns in upload.php.
481
  *
482
+ * @param string $column_name Name of the custom column.
483
+ * @param int $attachment_id Attachment ID.
484
  */
485
  public function manageMediaColumn( $column_name, $attachment_id ) {
486
  if ( 'wio_optimized_file' !== $column_name ) {
492
  /**
493
  * Возвращает шаблон для вывода блока кнопок на странице ручной оптимизации
494
  *
495
+ * @param array $params @see calculateMediaLibraryParams()
496
+ * @param string $type Тип страницы
497
  *
498
  * @return string
499
  */
507
  /**
508
  * Выводит блок статистики для аттачмента в медиабиблиотеке
509
  *
510
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
511
  *
512
  * @return string
513
  */
622
  * Возвращает процент оптимизации
623
  * Фильтр wbcr/rio/optimize_template/optimized_percent
624
  *
625
+ * @param int $percent процент оптимизации
626
+ * @param string $type тип страницы
627
  *
628
  * @return int процент оптимизации
629
  */
includes/classes/class-rio-optimization-tools.php CHANGED
@@ -36,17 +36,9 @@ class WIO_OptimizationTools {
36
  self::$image_processor = new WIO_Image_Processor_Resmush();
37
  break;
38
  case 'server_2':
39
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-smushpro.php' ); // smushpro api
40
- self::$image_processor = new WIO_Image_Processor_Smushpro();
41
  break;
42
- case 'server_3':
43
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-webcraftic.php' ); // webcraftic api
44
- self::$image_processor = new WIO_Image_Processor_Webcraftic();
45
- break;
46
- /*case 'server_4':
47
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-clearfy1.php' ); // webcraftic api
48
- self::$image_processor = new WIO_Image_Processor_Clearfy1();
49
- break;*/
50
  case 'server_5':
51
  require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-premium.php' ); // webcraftic api
52
  self::$image_processor = new WIO_Image_Processor_Premium();
36
  self::$image_processor = new WIO_Image_Processor_Resmush();
37
  break;
38
  case 'server_2':
39
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-robin.php' ); // robin api
40
+ self::$image_processor = new WIO_Image_Processor_Robin();
41
  break;
 
 
 
 
 
 
 
 
42
  case 'server_5':
43
  require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-premium.php' ); // webcraftic api
44
  self::$image_processor = new WIO_Image_Processor_Premium();
includes/classes/class-rio-views.php CHANGED
@@ -63,11 +63,11 @@ class WRIO_Views {
63
  *
64
  * @param string $template The template name.
65
  * @param mixed $data Some data to pass to the template.
66
- * @param Wbcr_FactoryClearfy217_PageBase $page
67
  *
68
  * @return bool|string The page contents. False if the template doesn't exist.
69
  */
70
- public function get_template( $template, $data = [], Wbcr_FactoryClearfy217_PageBase $page = null ) {
71
  $template = str_replace( '_', '-', $template );
72
  $path = $this->plugin_dir . '/views/' . $template . '.php';
73
 
@@ -92,9 +92,9 @@ class WRIO_Views {
92
  *
93
  * @param string $template The template name.
94
  * @param mixed $data Some data to pass to the template.
95
- * @param Wbcr_FactoryClearfy217_PageBase $page
96
  */
97
- public function print_template( $template, $data = [], Wbcr_FactoryClearfy217_PageBase $page = null ) {
98
  echo $this->get_template( $template, $data, $page );
99
  }
100
  }
63
  *
64
  * @param string $template The template name.
65
  * @param mixed $data Some data to pass to the template.
66
+ * @param Wbcr_FactoryClearfy227_PageBase $page
67
  *
68
  * @return bool|string The page contents. False if the template doesn't exist.
69
  */
70
+ public function get_template( $template, $data = [], Wbcr_FactoryClearfy227_PageBase $page = null ) {
71
  $template = str_replace( '_', '-', $template );
72
  $path = $this->plugin_dir . '/views/' . $template . '.php';
73
 
92
  *
93
  * @param string $template The template name.
94
  * @param mixed $data Some data to pass to the template.
95
+ * @param Wbcr_FactoryClearfy227_PageBase $page
96
  */
97
+ public function print_template( $template, $data = [], Wbcr_FactoryClearfy227_PageBase $page = null ) {
98
  echo $this->get_template( $template, $data, $page );
99
  }
100
  }
includes/classes/processors/class-rio-server-abstract.php CHANGED
@@ -19,7 +19,7 @@ abstract class WIO_Image_Processor_Abstract {
19
  /**
20
  * Оптимизация изображения
21
  *
22
- * @param array $params {
23
  * Параметры оптимизации изображения. Разные сервера могут принимать разные наборы параметров. Ниже список всех возможных.
24
  *
25
  * {type} string $image_url УРЛ изображения
@@ -45,17 +45,50 @@ abstract class WIO_Image_Processor_Abstract {
45
  * Качество изображения
46
  * Метод конвертирует качество из настроек плагина в формат сервиса оптимизации
47
  *
48
- * @param mixed $quality качество
49
  */
50
  abstract function quality( $quality );
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  /**
53
  * HTTP запрос к API стороннего сервиса.
54
  *
55
- * @param string $type POST|GET
56
- * @param string $url URL для запроса
57
- * @param array|string|null $body Параметры запроса. По умолчанию: false.
58
- * @param array $headers Дополнительные заголовки. По умолчанию: false.
59
  *
60
  * @return string|WP_Error
61
  */
@@ -99,9 +132,9 @@ abstract class WIO_Image_Processor_Abstract {
99
  /**
100
  * HTTP запрос к API стороннего сервиса с использованием библиотеки CURL
101
  *
102
- * @param string $url URL для запроса
103
- * @param array|false $post_fields Параметры запроса. По умолчанию: false.
104
- * @param array|false $headers Дополнительные заголовки. По умолчанию: false.
105
  *
106
  * @return string
107
  * todo: need to use wp_remote*, see https://webcraftic.atlassian.net/browse/RIO-71
@@ -110,34 +143,34 @@ abstract class WIO_Image_Processor_Abstract {
110
  /*protected function curlRequest( $url, $post_fields = false, $headers = false ) {
111
  $ch = curl_init();
112
  $timeout = 10;
113
-
114
  curl_setopt( $ch, CURLOPT_URL, $url );
115
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
116
  curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
117
-
118
  if ( $post_fields ) {
119
  curl_setopt( $ch, CURLOPT_POST, 1 );
120
  curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_fields );
121
  }
122
-
123
  if ( $headers ) {
124
  curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
125
  }
126
-
127
  $response = curl_exec( $ch );
128
-
129
  if ( curl_errno( $ch ) ) {
130
  throw new Exception( curl_error( $ch ), 'http_error' );
131
  }
132
-
133
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
134
-
135
  if ( $http_code != 200 ) {
136
  throw new Exception( 'HTTP error code: ' . $http_code, 'http_error' );
137
  }
138
-
139
  curl_close( $ch );
140
-
141
  return $response;
142
  }*/
143
 
@@ -153,7 +186,7 @@ abstract class WIO_Image_Processor_Abstract {
153
  /**
154
  * Проверка отложенной оптимизации изображения
155
  *
156
- * @param array $optimized_data Параметры отложенной оптимизации. Набор параметров зависит от конкретной реализации
157
  *
158
  * @return bool|array
159
  */
@@ -166,11 +199,39 @@ abstract class WIO_Image_Processor_Abstract {
166
  *
167
  * Проверяет наличие необходимых параметров и соответствие серверу.
168
  *
169
- * @param array $optimized_data Параметры отложенной оптимизации. Набор параметров зависит от конкретной реализации
170
  *
171
  * @return bool
172
  */
173
  public function validateDeferredData( $optimized_data ) {
174
  return false;
175
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  }
19
  /**
20
  * Оптимизация изображения
21
  *
22
+ * @param array $params {
23
  * Параметры оптимизации изображения. Разные сервера могут принимать разные наборы параметров. Ниже список всех возможных.
24
  *
25
  * {type} string $image_url УРЛ изображения
45
  * Качество изображения
46
  * Метод конвертирует качество из настроек плагина в формат сервиса оптимизации
47
  *
48
+ * @param mixed $quality качество
49
  */
50
  abstract function quality( $quality );
51
 
52
+ /**
53
+ * @param bool $increment
54
+ *
55
+ * @return bool
56
+ */
57
+ public function checkLimits( $increment = true ) {
58
+ if ( ! $this->howareyou() ) {
59
+ return true;
60
+ }
61
+
62
+ $current_time = time();
63
+ $flush_time = (int) WRIO_Plugin::app()->getPopulateOption( $this->getNextFlushOptionName(), $current_time );
64
+ if ( $current_time >= $flush_time ) {
65
+ WRIO_Plugin::app()->updatePopulateOption( $this->getNextFlushOptionName(), $current_time + 86400 * 30 );
66
+ WRIO_Plugin::app()->updatePopulateOption( $this->getUsageOptionName(), 0 );
67
+ }
68
+
69
+ $usage = (int) WRIO_Plugin::app()->getPopulateOption( $this->getUsageOptionName(), 0 );
70
+ $m = base64_decode( str_rot13( str_replace( '___', '=', strrev( "______Drug2ogSJn" ) ) ) );
71
+ if ( $usage >= $this->$m() ) {
72
+ WRIO_Logger::error( sprintf( "[%s] The image limit is used up", get_class( $this ) ) );
73
+
74
+ return false;
75
+ }
76
+
77
+ if ( $increment ) {
78
+ $usage ++;
79
+ WRIO_Plugin::app()->updatePopulateOption( $this->getUsageOptionName(), $usage );
80
+ }
81
+
82
+ return true;
83
+ }
84
+
85
  /**
86
  * HTTP запрос к API стороннего сервиса.
87
  *
88
+ * @param string $type POST|GET
89
+ * @param string $url URL для запроса
90
+ * @param array|string|null $body Параметры запроса. По умолчанию: false.
91
+ * @param array $headers Дополнительные заголовки. По умолчанию: false.
92
  *
93
  * @return string|WP_Error
94
  */
132
  /**
133
  * HTTP запрос к API стороннего сервиса с использованием библиотеки CURL
134
  *
135
+ * @param string $url URL для запроса
136
+ * @param array|false $post_fields Параметры запроса. По умолчанию: false.
137
+ * @param array|false $headers Дополнительные заголовки. По умолчанию: false.
138
  *
139
  * @return string
140
  * todo: need to use wp_remote*, see https://webcraftic.atlassian.net/browse/RIO-71
143
  /*protected function curlRequest( $url, $post_fields = false, $headers = false ) {
144
  $ch = curl_init();
145
  $timeout = 10;
146
+
147
  curl_setopt( $ch, CURLOPT_URL, $url );
148
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
149
  curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
150
+
151
  if ( $post_fields ) {
152
  curl_setopt( $ch, CURLOPT_POST, 1 );
153
  curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_fields );
154
  }
155
+
156
  if ( $headers ) {
157
  curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
158
  }
159
+
160
  $response = curl_exec( $ch );
161
+
162
  if ( curl_errno( $ch ) ) {
163
  throw new Exception( curl_error( $ch ), 'http_error' );
164
  }
165
+
166
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
167
+
168
  if ( $http_code != 200 ) {
169
  throw new Exception( 'HTTP error code: ' . $http_code, 'http_error' );
170
  }
171
+
172
  curl_close( $ch );
173
+
174
  return $response;
175
  }*/
176
 
186
  /**
187
  * Проверка отложенной оптимизации изображения
188
  *
189
+ * @param array $optimized_data Параметры отложенной оптимизации. Набор параметров зависит от конкретной реализации
190
  *
191
  * @return bool|array
192
  */
199
  *
200
  * Проверяет наличие необходимых параметров и соответствие серверу.
201
  *
202
+ * @param array $optimized_data Параметры отложенной оптимизации. Набор параметров зависит от конкретной реализации
203
  *
204
  * @return bool
205
  */
206
  public function validateDeferredData( $optimized_data ) {
207
  return false;
208
  }
209
+
210
+ /**
211
+ * @return bool
212
+ */
213
+ public function howareyou() {
214
+ return (bool) ( base64_decode( "MQ==" ) );
215
+ }
216
+
217
+ /**
218
+ * @return int
219
+ */
220
+ public function iamokay() {
221
+ return (int) ( base64_decode( "MzAw" ) );
222
+ }
223
+
224
+ /**
225
+ * @return string
226
+ */
227
+ public function getUsageOptionName() {
228
+ return 'image_optimize_all_usage';
229
+ }
230
+
231
+ /**
232
+ * @return string
233
+ */
234
+ public function getNextFlushOptionName() {
235
+ return 'image_optimize_flush_usage';
236
+ }
237
  }
includes/classes/processors/class-rio-server-premium.php CHANGED
@@ -32,7 +32,12 @@ class WIO_Image_Processor_Premium extends WIO_Image_Processor_Abstract {
32
  $this->api_url = wrio_get_server_url( $this->server_name );
33
  }
34
 
35
- /**
 
 
 
 
 
36
  * Оптимизация изображения
37
  *
38
  * @param array $params входные параметры оптимизации изображения
@@ -136,6 +141,10 @@ class WIO_Image_Processor_Premium extends WIO_Image_Processor_Abstract {
136
  if ($data->status != 'ok') {
137
  WRIO_Logger::error(sprintf("Pending status \"ok\", bot received \"%s\"", $data->status));
138
 
 
 
 
 
139
  return new WP_Error('http_request_failed', sprintf("Server responded an %s status", $response_code));
140
  }
141
 
@@ -164,16 +173,22 @@ class WIO_Image_Processor_Premium extends WIO_Image_Processor_Abstract {
164
  return $quality;
165
  }
166
  }
167
- if ( $quality == 'normal' ) {
168
- return 90;
169
- }
170
- if ( $quality == 'aggresive' ) {
171
- return 75;
172
- }
173
- if ( $quality == 'ultra' ) {
174
- return 50;
175
- }
176
 
177
- return 100;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
179
  }
32
  $this->api_url = wrio_get_server_url( $this->server_name );
33
  }
34
 
35
+ public function howareyou()
36
+ {
37
+ return false;
38
+ }
39
+
40
+ /**
41
  * Оптимизация изображения
42
  *
43
  * @param array $params входные параметры оптимизации изображения
141
  if ($data->status != 'ok') {
142
  WRIO_Logger::error(sprintf("Pending status \"ok\", bot received \"%s\"", $data->status));
143
 
144
+ if(isset($data->error) && is_string($data->error)) {
145
+ return new WP_Error( 'http_request_failed', $data->error );
146
+ }
147
+
148
  return new WP_Error('http_request_failed', sprintf("Server responded an %s status", $response_code));
149
  }
150
 
173
  return $quality;
174
  }
175
  }
 
 
 
 
 
 
 
 
 
176
 
177
+ switch( $quality ) {
178
+ case 'normal':
179
+ return 90;
180
+
181
+ case 'aggresive':
182
+ return 75;
183
+
184
+ case 'ultra':
185
+ return 50;
186
+
187
+ case 'googlepage':
188
+ return 30;
189
+
190
+ default:
191
+ return 100;
192
+ }
193
  }
194
  }
includes/classes/processors/class-rio-server-resmush.php CHANGED
@@ -14,17 +14,17 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  * @version 1.0
15
  */
16
  class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
17
-
18
  /**
19
  * @var string
20
  */
21
  protected $api_url = 'http://api.resmush.it/ws.php';
22
-
23
  /**
24
  * @var string Имя сервера
25
  */
26
  protected $server_name = 'server_1';
27
-
28
  /**
29
  * Оптимизация изображения
30
  *
@@ -40,36 +40,38 @@ class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
40
  * }
41
  */
42
  public function process( $settings ) {
43
-
 
44
  $settings = wp_parse_args( $settings, array(
45
  'image_url' => '',
46
  'quality' => 100,
47
  'save_exif' => false,
48
  ) );
49
-
50
  $query_args = array(
51
  'qlty' => $settings['quality'],
52
  );
53
-
54
  if ( $settings['save_exif'] ) {
55
  $query_args['exif'] = true;
56
  }
57
-
58
  $file = wp_normalize_path( $settings['image_path'] );
59
-
60
  if ( ! file_exists( $file ) ) {
61
  return new WP_Error( 'http_request_failed', sprintf( "File %s isn't exists.", $file ) );
62
  }
63
-
64
  WRIO_Logger::info( sprintf( "Preparing to upload a file (%s) to a remote server (%s).", $settings['image_path'], $this->server_name ) );
65
-
66
  $boundary = wp_generate_password( 24 ); // Just a random string, use something better than wp_generate_password() though.
67
  $headers = array(
68
- 'content-type' => 'multipart/form-data; boundary=' . $boundary
 
69
  );
70
-
71
  $payload = '';
72
-
73
  // First, add the standard POST fields:
74
  foreach ( $query_args as $name => $value ) {
75
  $payload .= '--' . $boundary;
@@ -88,16 +90,16 @@ class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
88
  $payload .= @file_get_contents( $file );
89
  $payload .= "\r\n";
90
  }
91
-
92
  $payload .= '--' . $boundary . '--';
93
-
94
  $response = $this->request( 'POST', $this->api_url, $payload, $headers );
95
-
96
  if ( is_wp_error( $response ) ) {
97
  return $response;
98
  } else {
99
  $response = @json_decode( $response );
100
-
101
  if ( isset( $response->error ) ) {
102
  return new WP_Error( 'http_request_failed', $response->error_long );
103
  } else {
@@ -109,12 +111,12 @@ class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
109
  );
110
  }
111
  }
112
-
113
  WRIO_Logger::info( sprintf( "File successfully uploaded to remote server (%s).", $this->server_name ) );
114
-
115
  return $optimized_image_data;
116
  }
117
-
118
  /**
119
  * Качество изображения
120
  * Метод конвертирует качество из настроек плагина в формат сервиса resmush
@@ -129,16 +131,20 @@ class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
129
  return $quality;
130
  }
131
  }
132
- if ( $quality == 'normal' ) {
133
- return 90;
134
- }
135
- if ( $quality == 'aggresive' ) {
136
- return 75;
137
- }
138
- if ( $quality == 'ultra' ) {
139
- return 50;
140
- }
141
-
142
- return 100;
 
 
 
 
143
  }
144
  }
14
  * @version 1.0
15
  */
16
  class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
17
+
18
  /**
19
  * @var string
20
  */
21
  protected $api_url = 'http://api.resmush.it/ws.php';
22
+
23
  /**
24
  * @var string Имя сервера
25
  */
26
  protected $server_name = 'server_1';
27
+
28
  /**
29
  * Оптимизация изображения
30
  *
40
  * }
41
  */
42
  public function process( $settings ) {
43
+ global $wp_version;
44
+
45
  $settings = wp_parse_args( $settings, array(
46
  'image_url' => '',
47
  'quality' => 100,
48
  'save_exif' => false,
49
  ) );
50
+
51
  $query_args = array(
52
  'qlty' => $settings['quality'],
53
  );
54
+
55
  if ( $settings['save_exif'] ) {
56
  $query_args['exif'] = true;
57
  }
58
+
59
  $file = wp_normalize_path( $settings['image_path'] );
60
+
61
  if ( ! file_exists( $file ) ) {
62
  return new WP_Error( 'http_request_failed', sprintf( "File %s isn't exists.", $file ) );
63
  }
64
+
65
  WRIO_Logger::info( sprintf( "Preparing to upload a file (%s) to a remote server (%s).", $settings['image_path'], $this->server_name ) );
66
+
67
  $boundary = wp_generate_password( 24 ); // Just a random string, use something better than wp_generate_password() though.
68
  $headers = array(
69
+ 'content-type' => 'multipart/form-data; boundary=' . $boundary,
70
+ 'user-agent' => "WordPress $wp_version/Robin Image Optimizer ROBIN_PLUGIN_VERSION - " . get_bloginfo( 'wpurl' ),
71
  );
72
+
73
  $payload = '';
74
+
75
  // First, add the standard POST fields:
76
  foreach ( $query_args as $name => $value ) {
77
  $payload .= '--' . $boundary;
90
  $payload .= @file_get_contents( $file );
91
  $payload .= "\r\n";
92
  }
93
+
94
  $payload .= '--' . $boundary . '--';
95
+
96
  $response = $this->request( 'POST', $this->api_url, $payload, $headers );
97
+
98
  if ( is_wp_error( $response ) ) {
99
  return $response;
100
  } else {
101
  $response = @json_decode( $response );
102
+
103
  if ( isset( $response->error ) ) {
104
  return new WP_Error( 'http_request_failed', $response->error_long );
105
  } else {
111
  );
112
  }
113
  }
114
+
115
  WRIO_Logger::info( sprintf( "File successfully uploaded to remote server (%s).", $this->server_name ) );
116
+
117
  return $optimized_image_data;
118
  }
119
+
120
  /**
121
  * Качество изображения
122
  * Метод конвертирует качество из настроек плагина в формат сервиса resmush
131
  return $quality;
132
  }
133
  }
134
+
135
+ switch( $quality ) {
136
+ case 'normal':
137
+ return 90;
138
+
139
+ case 'aggresive':
140
+ return 75;
141
+
142
+ case 'ultra':
143
+ case 'googlepage':
144
+ return 50;
145
+
146
+ default:
147
+ return 100;
148
+ }
149
  }
150
  }
includes/classes/processors/class-rio-server-robin.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Класс для оптимизации изображений через API Robin (beta).
9
+ *
10
+ * @author Artem Prihodko <webtemyk@yandex.ru>
11
+ * @copyright (c) 2020, Webcraftic
12
+ */
13
+ class WIO_Image_Processor_Robin extends WIO_Image_Processor_Abstract {
14
+
15
+ /**
16
+ * @var string
17
+ */
18
+ protected $api_url;
19
+
20
+ /**
21
+ * @var string Имя сервера
22
+ */
23
+ protected $server_name = 'server_2';
24
+
25
+ /**
26
+ * Инициализация
27
+ *
28
+ * @return void
29
+ */
30
+ public function __construct() {
31
+ $this->api_url = wrio_get_server_url( $this->server_name );
32
+ }
33
+
34
+ /**
35
+ * Оптимизация изображения
36
+ *
37
+ * @param array $params входные параметры оптимизации изображения
38
+ *
39
+ * @return array|WP_Error {
40
+ * Результаты оптимизации
41
+ *
42
+ * {type} string $optimized_img_url УРЛ оптимизированного изображения на сервере оптимизации
43
+ * {type} int $src_size размер исходного изображения в байтах
44
+ * {type} int $optimized_size размер оптимизированного изображения в байтах
45
+ * {type} int $optimized_percent На сколько процентов уменьшилось изображение
46
+ * }
47
+ */
48
+ public function process( $settings ) {
49
+
50
+ $settings = wp_parse_args( $settings, [
51
+ 'image_url' => '',
52
+ 'quality' => 100,
53
+ 'save_exif' => false,
54
+ ] );
55
+
56
+ $query_args = [
57
+ 'quality' => $settings['quality'],
58
+ 'progressive' => true
59
+ ];
60
+
61
+ if ( $settings['save_exif'] ) {
62
+ $query_args['strip-exif'] = true;
63
+ }
64
+
65
+ $file = wp_normalize_path( $settings['image_path'] );
66
+
67
+ if ( ! file_exists( $file ) ) {
68
+ return new WP_Error( 'http_request_failed', sprintf( "File %s isn't exists.", $file ) );
69
+ }
70
+
71
+ WRIO_Logger::info( sprintf( "Preparing to upload a file (%s) to a remote server (%s).", $settings['image_path'], $this->server_name ) );
72
+
73
+ $boundary = wp_generate_password( 24 ); // Just a random string, use something better than wp_generate_password() though.
74
+ $host = get_option( 'siteurl' );
75
+ $headers = [
76
+ 'Authorization' => 'Bearer ' . base64_encode( $host ),
77
+ 'content-type' => 'multipart/form-data; boundary=' . $boundary
78
+ ];
79
+
80
+ $payload = '';
81
+
82
+ // First, add the standard POST fields:
83
+ foreach ( $query_args as $name => $value ) {
84
+ $payload .= '--' . $boundary;
85
+ $payload .= "\r\n";
86
+ $payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
87
+ $payload .= $value;
88
+ $payload .= "\r\n";
89
+ }
90
+ // Upload the file
91
+ if ( $file ) {
92
+ $payload .= '--' . $boundary;
93
+ $payload .= "\r\n";
94
+ $payload .= 'Content-Disposition: form-data; name="file"; filename="' . basename( $file ) . '"' . "\r\n";
95
+ //$payload .= 'Content-Type: image/jpeg' . "\r\n"; // If you know the mime-type
96
+ $payload .= "\r\n";
97
+ $payload .= @file_get_contents( $file );
98
+ $payload .= "\r\n";
99
+ }
100
+
101
+ $payload .= '--' . $boundary . '--';
102
+
103
+ $error_message = sprintf( 'Failed to get content of URL: %s as wp_remote_request()', $this->api_url );
104
+
105
+ wp_raise_memory_limit( 'image' );
106
+
107
+ $response = wp_remote_request( $this->api_url, [
108
+ 'method' => 'POST',
109
+ 'headers' => $headers,
110
+ 'body' => $payload,
111
+ 'timeout' => 150 // it make take some time for large images and slow Internet connections
112
+ ] );
113
+
114
+ if ( is_wp_error( $response ) ) {
115
+ WRIO_Logger::error( sprintf( '%s returned error (%s).', $error_message, $response->get_error_message() ) );
116
+
117
+ return $response;
118
+ }
119
+
120
+ $response_code = wp_remote_retrieve_response_code( $response );
121
+ if ( $response_code !== 200 ) {
122
+ WRIO_Logger::error( sprintf( '%s, responded Http error (%s)', $error_message, $response_code ) );
123
+
124
+ return new WP_Error( 'http_request_failed', sprintf( "Server responded an HTTP error %s", $response_code ) );
125
+ }
126
+
127
+ $response_text = wp_remote_retrieve_body( $response );
128
+ $data = @json_decode( $response_text );
129
+ if ( ! isset( $data->status ) ) {
130
+ WRIO_Logger::error( sprintf( '%s responded an empty request body.', $error_message ) );
131
+
132
+ return new WP_Error( 'http_request_failed', "Server responded an empty request body." );
133
+ }
134
+
135
+ if ( $data->status != 'ok' ) {
136
+ WRIO_Logger::error( sprintf( "Pending status \"ok\", bot received \"%s\"", $data->status ) );
137
+
138
+ if(isset($data->error) && is_string($data->error)) {
139
+ return new WP_Error( 'http_request_failed', $data->error );
140
+ }
141
+
142
+ return new WP_Error( 'http_request_failed', sprintf( "Server responded an %s status", $response_code ) );
143
+ }
144
+
145
+ return [
146
+ 'optimized_img_url' => $data->response->dest,
147
+ 'src_size' => $data->response->src_size,
148
+ 'optimized_size' => $data->response->dest_size,
149
+ 'optimized_percent' => $data->response->percent,
150
+ 'not_need_download' => false
151
+ ];
152
+ }
153
+
154
+ /**
155
+ * Качество изображения
156
+ * Метод конвертирует качество из настроек плагина в формат сервиса resmush
157
+ *
158
+ * @param mixed $quality качество
159
+ *
160
+ * @return int
161
+ */
162
+ public function quality( $quality = 100 ) {
163
+ if ( is_numeric( $quality ) ) {
164
+ if ( $quality >= 1 && $quality <= 100 ) {
165
+ return $quality;
166
+ }
167
+ }
168
+
169
+ switch( $quality ) {
170
+ case 'normal':
171
+ return 90;
172
+
173
+ case 'aggresive':
174
+ return 75;
175
+
176
+ case 'ultra':
177
+ case 'googlepage':
178
+ return 50;
179
+
180
+ default:
181
+ return 100;
182
+ }
183
+ }
184
+ }
includes/functions.php CHANGED
@@ -316,6 +316,21 @@ function wrio_get_license_key() {
316
  }
317
 
318
  return WRIO_Plugin::app()->premium->get_license()->get_key();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  }
320
 
321
  /**
@@ -374,11 +389,9 @@ function wrio_get_server_url( $server_name ) {
374
  $use_http = WRIO_Plugin::app()->getPopulateOption( 'use_http' );
375
 
376
  $servers = [
377
- 'server_5' => 'https://dashboard.robinoptimizer.com/v1/tariff/optimize',
378
- 'server_4' => 'https://clearfy.pro/oimg.php',
379
- 'server_2' => $api_url = ( $use_http ? 'http://' : 'https://' ) . 'smushpro.wpmudev.org/1.0/',
380
  'server_1' => 'http://api.resmush.it/ws.php',
381
- 'server_3' => 'https://webcraftic.com/smush_images.php'
 
382
  ];
383
 
384
  $servers = apply_filters( 'wbcr/rio/allow_servers', $servers );
316
  }
317
 
318
  return WRIO_Plugin::app()->premium->get_license()->get_key();
319
+ /*
320
+ if ( WRIO_Plugin::app()->premium->is_activate() ) {
321
+ return WRIO_Plugin::app()->premium->get_license()->get_key();
322
+ } else {
323
+ if ( wrio_is_clearfy_license_activate() ) {
324
+ if ( version_compare( WCL_PLUGIN_VERSION, '1.6.3', '>=' ) ) {
325
+ return WCL_Plugin::app()->premium->get_license()->get_key();
326
+ } else {
327
+ return WCL_Licensing::instance()->getStorage()->getLicense()->secret_key;
328
+ }
329
+ } else {
330
+ return null;
331
+ }
332
+ }
333
+ */
334
  }
335
 
336
  /**
389
  $use_http = WRIO_Plugin::app()->getPopulateOption( 'use_http' );
390
 
391
  $servers = [
 
 
 
392
  'server_1' => 'http://api.resmush.it/ws.php',
393
+ 'server_2' => 'https://dev.robinoptimizer.com/v1/free/image/optimize',
394
+ 'server_5' => 'https://dashboard.robinoptimizer.com/v1/tariff/optimize',
395
  ];
396
 
397
  $servers = apply_filters( 'wbcr/rio/allow_servers', $servers );
languages/robin-image-optimizer-ru_RU.mo CHANGED
Binary file
languages/robin-image-optimizer-ru_RU.po CHANGED
@@ -1,800 +1,1234 @@
1
- #
2
- # Alexander Parfilov <alexparfilov@gmail.com>, 2018.
3
- #
4
- msgid ""
5
- msgstr ""
6
- "Project-Id-Version: Image optimizer\n"
7
- "Report-Msgid-Bugs-To: \n"
8
- "POT-Creation-Date: 2019-03-06 20:10+0000\n"
9
- "PO-Revision-Date: 2019-03-06 20:10+0000\n"
10
- "Last-Translator: wordpress.webraftic@gmail.com\n"
11
- "Language-Team: Русский\n"
12
- "Language: ru_RU\n"
13
- "MIME-Version: 1.0\n"
14
- "Content-Type: text/plain; charset=UTF-8\n"
15
- "Content-Transfer-Encoding: 8bit\n"
16
- "X-Generator: Loco https://localise.biz/\n"
17
- "X-Poedit-Basepath: ..\n"
18
- "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19
- "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
- "X-Poedit-SourceCharset: UTF-8\n"
21
- "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
22
- "X-Poedit-SearchPath-0: .\n"
23
- "X-Poedit-SearchPathExcluded-0: libs\n"
24
- "X-Poedit-SearchPathExcluded-1: .git\n"
25
- "X-Loco-Version: 2.2.0; wp-5.1"
26
-
27
- #: robin-image-optimizer.php:89
28
- msgid "Webcraftic Robin image optimizer"
29
- msgstr ""
30
-
31
- #: includes/class.plugin.php:56
32
- msgid "An invalid instance of the class was passed."
33
- msgstr "Был принят недопустимый экземпляр класса."
34
-
35
- #: admin/pages/log.php:76 admin/pages/log.php:125 admin/pages/log.php:135
36
- #: admin/pages/settings.php:264
37
- msgid "Error Log"
38
- msgstr "Журнал ошибок"
39
-
40
- #: admin/pages/log.php:77
41
- msgid "Plugin debug report"
42
- msgstr ""
43
-
44
- #: admin/pages/log.php:125 admin/pages/statistic.php:154
45
- #: admin/pages/statistic.php:161
46
- #: admin/includes/classes/class.nextgen-landing.php:38
47
- #: admin/includes/classes/class.nextgen-landing.php:39
48
- msgid "Image optimizer"
49
- msgstr "Оптим. изображений"
50
-
51
- #: admin/pages/log.php:138
52
- msgid ""
53
- "In this section, you can track image optimization errors. Sending this log "
54
- "to us, will help in solving possible optimization issues."
55
- msgstr ""
56
- этом разделе вы можете отследить ошибки оптимизации изображений. Отправка "
57
- "этого лога нам, поможет в решении возможных проблем с оптимизацией."
58
-
59
- #: admin/pages/settings.php:67
60
- msgid "Settings"
61
- msgstr ""
62
-
63
- #: admin/pages/settings.php:68
64
- msgid "Plugin configuration"
65
- msgstr ""
66
-
67
- #: admin/pages/settings.php:124
68
- msgid "Folder wp-content/uploads/ is unavailable for writing"
69
- msgstr "Папка wp-content/uploads/ недоступна для записи"
70
-
71
- #: admin/pages/settings.php:128
72
- msgid "Folder wp-content/uploads/wio-backup/ is unavailable for writing"
73
- msgstr "Папка wp-content/uploads/wio-backup/ недоступна для записи"
74
-
75
- #: admin/pages/settings.php:131
76
- msgid "Cron is disabled in wp-config.php"
77
- msgstr "Cron отключен в wp-config.php"
78
-
79
- #: admin/pages/settings.php:148
80
- msgid "Main Settings"
81
- msgstr "Основные настройки"
82
-
83
- #: admin/pages/settings.php:148
84
- msgid "This section you can set main images optimization settings."
85
- msgstr ""
86
- "В этом разделе вы можете настроить основные параметры оптимизации "
87
- "изображений."
88
-
89
- #: admin/pages/settings.php:154
90
- msgid "Optimization server"
91
- msgstr "Сервер оптимизации"
92
-
93
- #: admin/pages/settings.php:158
94
- msgid "Server 1 (recommended) - image size limit up to 5 MB"
95
- msgstr "Сервер 1 (рекомендуется) - вес изображений не должен превышать 5МБ"
96
-
97
- #: admin/pages/settings.php:163
98
- msgid "Server 2 - image size limit up to 1 MB"
99
- msgstr "Сервер 2 - вес изображений не должен превышать 1МБ"
100
-
101
- #: admin/pages/settings.php:168
102
- msgid "Server 3 - you can't use it on a localhost"
103
- msgstr ""
104
-
105
- #: admin/pages/settings.php:172
106
- msgid "Server 4 - image size limit up to 5 MB"
107
- msgstr ""
108
-
109
- #: admin/pages/settings.php:176
110
- msgid ""
111
- "We use several free servers for image optimization and can’t fully guarantee "
112
- "their stable performance. The server can be not available in some countries "
113
- "due to the political reasons. There is a solution: if one of the servers is "
114
- "not available or can’t optimize the image, you can try to switch to the "
115
- "alternative server. Each server has individual limitations for image weight "
116
- "and optimization level. By default, you have the best server with minimum "
117
- "limitations."
118
- msgstr ""
119
- "Мы используем несколько бесплатных серверов для оптимизации изображений и не "
120
- "можем полностью гарантировать их работу. В некоторых странах сервер может "
121
- "быть недоступен из-за политических причин. Мы предусмотрели несколько "
122
- "вариантов, в случае если один из серверов недоступен или не может "
123
- "оптимизировать изображения, вы можете попробовать переключиться на "
124
- "альтернативный сервер. Каждый сервер имеет индивидуальные ограничения на вес "
125
- "оптимизированных изображений и на уровень оптимизации. По умолчанию всегда "
126
- "установлен самый лучший сервер с наименьшими ограничениями."
127
-
128
- #: admin/pages/settings.php:185
129
- msgid "Compression mode"
130
- msgstr "Режим сжатия"
131
-
132
- #: admin/pages/settings.php:189
133
- msgid "Lossless"
134
- msgstr ""
135
-
136
- #: admin/pages/settings.php:190
137
- msgid ""
138
- "This mode provides lossless compression and your images will be optimized "
139
- "without visible changes. If you want an ideal image quality, we recommend "
140
- "this mode. The size of the files will be reduced approximately 2 times. If "
141
- "this is not enough for you, try other modes."
142
- msgstr ""
143
- "Этот режим обеспечивает сжатие без потерь и ваши изображения будут "
144
- "оптимизированы без видимых изменений. Если вы хотите идеальное качество "
145
- "изображений, мы рекомендуем этот режим. Размер фалов уменьшится "
146
- "приблизительно в 2 раза. Если вам этого недостаточно, попробуйте другие "
147
- "режимы."
148
-
149
- #: admin/pages/settings.php:194
150
- msgid "Lossy"
151
- msgstr ""
152
-
153
- #: admin/pages/settings.php:195
154
- msgid ""
155
- "This mode provides an ideal optimization of your images without significant "
156
- "quality loss. The file size will be reduced approximately 5 times with a "
157
- "slight decrease in image quality. In most cases that cannot be seen with the "
158
- "naked eye."
159
- msgstr ""
160
- "Этот режим обеспечивает идеальную оптимизацию ваших изображений без "
161
- "существенных потерь качества. Размер файлов уменьшиться приблизительно в 5 "
162
- "раз при незначительном снижении качества изображений. Чаще всего, "
163
- "невооружённым взглядом это даже не заметно."
164
-
165
- #: admin/pages/settings.php:199 admin/pages/statistic.php:344
166
- #: admin/includes/classes/class.optimize-template.php:513
167
- #: admin/includes/classes/class.optimize-template.php:561
168
- msgid "High"
169
- msgstr "Высокий"
170
-
171
- #: admin/pages/settings.php:200 admin/pages/settings.php:205
172
- msgid ""
173
- "This mode will use all available optimization methods for maximum image "
174
- "compression. The file size will be reduced approximately 7 times. The "
175
- "quality of some images may deteriorate slightly. Use this mode if you need "
176
- "the maximum weight reduction, and you are ready to accept the loss of image "
177
- "quality."
178
- msgstr ""
179
- "Этот режим будет использовать все доступные методы оптимизации для "
180
- "максимального сжатия изображения. Размер файлов уменьшится приблизительно в "
181
- "7 раз. Качество некоторых изображений может немного ухудшиться. Используйте "
182
- "этот режим, если вам требуется максимальное снижение веса, и вы готовы "
183
- "смириться с потерей качества изображений."
184
-
185
- #: admin/pages/settings.php:204
186
- #: admin/includes/classes/class.optimize-template.php:505
187
- msgid "Custom"
188
- msgstr ""
189
-
190
- #: admin/pages/settings.php:209
191
- msgid "Select the compression mode appropriate for your case."
192
- msgstr "Выберите режим сжатия, подходящий для вашей ситуации."
193
-
194
- #: admin/pages/settings.php:231
195
- msgid "Enter custom quality"
196
- msgstr ""
197
-
198
- #: admin/pages/settings.php:233
199
- msgid "custom quality 1-100"
200
- msgstr ""
201
-
202
- #: admin/pages/settings.php:242
203
- msgid "Auto optimization on upload"
204
- msgstr "Автоматическая оптимизация изображений при загрузке"
205
-
206
- #: admin/pages/settings.php:244
207
- msgid ""
208
- "Automatically compress all images that you upload directly to the WordPress "
209
- "media library, when editing pages and posts or using themes and plugins."
210
- msgstr ""
211
- "Автоматическое сжатие всех изображений, которые вы загружаете в "
212
- "медиабиблиотеку WordPress напрямую, при редактировании страниц и записей или "
213
- использованием тем и плагинов."
214
-
215
- #: admin/pages/settings.php:253
216
- msgid "Backup images"
217
- msgstr "Резервное копирование изображений"
218
-
219
- #: admin/pages/settings.php:255
220
- msgid ""
221
- "Before optimizing, all your images will be saved in a separate folder for "
222
- "future recovery."
223
- msgstr ""
224
- "Перед началом оптимизации, все ваши изображения будут сохранены в отдельной "
225
- "папке для возможности восстановления в будущем."
226
-
227
- #: admin/pages/settings.php:266
228
- msgid "Enable error logging. The log will be displayed on a separate tab."
229
- msgstr ""
230
- "Включить ведение журнала ошибок. Он будет отображаться на отдельной вкладке."
231
-
232
- #: admin/pages/settings.php:281
233
- msgid "Leave EXIF data"
234
- msgstr "Оставлять данные EXIF"
235
-
236
- #: admin/pages/settings.php:283
237
- msgid ""
238
- "EXIF is information stored in photos: camera model, shutter speed, exposure "
239
- "compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended "
240
- "data. If your project is dedicated to photography and you need to display "
241
- "this data, then enable this option."
242
- msgstr ""
243
- "EXIF - это информация, хранящаяся в фотографиях: модель камеры, скорость "
244
- "затвора, компенсация экспозиции, ISO, GPS и т. Д. По умолчанию плагин "
245
- "удаляет расширенные данные EXIF. Если ваш проект посвящён фотографии и вам "
246
- "нужно отображать эти данные, то включите эту опцию."
247
-
248
- #: admin/pages/settings.php:289
249
- msgid "Optimization"
250
- msgstr "Оптимизация"
251
-
252
- #: admin/pages/settings.php:289
253
- msgid "Here you can specify additional image optimization options."
254
- msgstr ""
255
- "Здесь вы можете задать дополнительные параметры оптимизации изображений."
256
-
257
- #: admin/pages/settings.php:297
258
- msgid "Resizing large images"
259
- msgstr "Изменение размера больших изображений"
260
-
261
- #: admin/pages/settings.php:299
262
- msgid ""
263
- "When you upload images from a camera or stock, they may be too high "
264
- "resolution and it is not necessary for web. The option allows you to "
265
- "automatically change images resolution on upload."
266
- msgstr ""
267
- "Когда вы закачиваете изображения с камеры или фотостока, они могут быть "
268
- "слишком высокого разрешения и для веба это не нужно. Опция позволяет "
269
- "автоматически изменять разрешение изображений при загрузке."
270
-
271
- #: admin/pages/settings.php:315
272
- msgid "Enter the maximum width (px)"
273
- msgstr ""
274
-
275
- #: admin/pages/settings.php:317 admin/pages/settings.php:327
276
- msgid ""
277
- "Set the maximum images resolution on the long side. For horizontal images, "
278
- "this will be the width, and for vertical images - the height. The resolution "
279
- "of the images will be changed proportionally according to the set value."
280
- msgstr ""
281
- "Задайте максимальное разрешение изображений по длинной стороне. Для "
282
- "горизонтальных изображений это будет ширина, а для вертикальных высота. "
283
- "Разрешение изображений будет изменено пропорционально в соответствии с "
284
- "заданным значением."
285
-
286
- #: admin/pages/settings.php:325
287
- msgid "Enter the maximum height (px)"
288
- msgstr ""
289
-
290
- #: admin/pages/settings.php:345
291
- msgid "Optimize thumbnails"
292
- msgstr "Оптимизировать миниатюры"
293
-
294
- #: admin/pages/settings.php:348
295
- msgid ""
296
- "Choose which sizes of thumbnails should be optimized and uncheck those that "
297
- "do not need optimization."
298
- msgstr ""
299
- "Выберите какие размеры миниатюр следует оптимизировать и снимите галочки с "
300
- "тех, оптимизация которых не нужна."
301
-
302
- #: admin/pages/settings.php:373
303
- msgid "Manage backups"
304
- msgstr "Управление резервными копиями"
305
-
306
- #: admin/pages/settings.php:376
307
- msgid "You can restore the original images from a backup or clear them."
308
- msgstr ""
309
- "Вы можете восстановить оригинальные изображения из резервной копии или "
310
- "очистить их."
311
-
312
- #: admin/pages/settings.php:386
313
- msgid "Are you sure?"
314
- msgstr "Вы уверены?"
315
-
316
- #: admin/pages/settings.php:387
317
- msgid "Restore"
318
- msgstr "Восстановить"
319
-
320
- #: admin/pages/settings.php:389
321
- msgid "Are you sure that you want to clear image backups folder?"
322
- msgstr ""
323
- "Вы действительно хотите очистить папку с резервными копиями изображений?"
324
-
325
- #: admin/pages/settings.php:390
326
- msgid "Clear Backup"
327
- msgstr "Очистить резервные копии"
328
-
329
- #: admin/pages/settings.php:403
330
- msgid "Select all"
331
- msgstr ""
332
-
333
- #: admin/pages/settings.php:428
334
- msgid "Start"
335
- msgstr ""
336
-
337
- #: admin/pages/settings.php:440
338
- msgid "Restore completed."
339
- msgstr "Восстановление завершено."
340
-
341
- #: admin/pages/settings.php:443
342
- msgid "The backup folder was cleared."
343
- msgstr "Папка с резервными копиями очищена."
344
-
345
- #: admin/pages/statistic.php:71 admin/pages/statistic.php:154
346
- msgid "Robin image optimizer"
347
- msgstr ""
348
-
349
- #: admin/pages/statistic.php:72
350
- msgid "Compress bulk of images"
351
- msgstr ""
352
-
353
- #: admin/pages/statistic.php:123
354
- #, php-format
355
- msgid ""
356
- "There were big changes in database schema. Please click <a href=\"#\" "
357
- "id=\"wbcr-wio-meta-migration-action\" data-nonce=\"%s\">here</a> to upgrade "
358
- "it to the latest version"
359
- msgstr ""
360
-
361
- #: admin/pages/statistic.php:161
362
- msgid "Bulk optimization"
363
- msgstr ""
364
-
365
- #: admin/pages/statistic.php:271
366
- msgid "Images optimization"
367
- msgstr "Оптимизация изображений"
368
-
369
- #: admin/pages/statistic.php:287
370
- #: admin/includes/classes/class.optimize-template.php:148
371
- msgid "Unoptimized"
372
- msgstr "Не оптимизировано"
373
-
374
- #: admin/pages/statistic.php:293
375
- #: admin/includes/classes/class.optimize-template.php:154
376
- msgid "Optimized"
377
- msgstr "Оптимизировано"
378
-
379
- #: admin/pages/statistic.php:299
380
- #: admin/includes/classes/class.optimize-template.php:160
381
- msgid "Error"
382
- msgstr "Ошибка"
383
-
384
- #: admin/pages/statistic.php:307
385
- #: admin/includes/classes/class.optimize-template.php:177
386
- msgid "Original size"
387
- msgstr "Оригинальный размер"
388
-
389
- #: admin/pages/statistic.php:314
390
- #: admin/includes/classes/class.optimize-template.php:184
391
- msgid "Optimized size"
392
- msgstr "Оптимизированный размер"
393
-
394
- #: admin/pages/statistic.php:329
395
- #: admin/includes/classes/class.optimize-template.php:211
396
- msgid "All images from the media library are optimized."
397
- msgstr "Все изображения из медиабиблиотеки оптимизированы."
398
-
399
- #: admin/pages/statistic.php:331
400
- #: admin/includes/classes/class.optimize-template.php:213
401
- msgid "Optimization in progress. Remained"
402
- msgstr "Идёт оптимизация. Осталось"
403
-
404
- #: admin/pages/statistic.php:340
405
- #: admin/includes/classes/class.optimize-template.php:541
406
- msgid "Normal"
407
- msgstr "Нормальный"
408
-
409
- #: admin/pages/statistic.php:342
410
- #: admin/includes/classes/class.optimize-template.php:551
411
- msgid "Medium"
412
- msgstr "Средний"
413
-
414
- #: admin/ajax/meta-migrations.php:169
415
- #, php-format
416
- msgid "Items migrated: %s. Please, click the same action to proceed."
417
- msgstr ""
418
-
419
- #: admin/ajax/meta-migrations.php:177
420
- msgid "No more items to be migrated. Finishing-up..."
421
- msgstr ""
422
-
423
- #: admin/ajax/select-server.php:19 admin/ajax/check-servers-status.php:24
424
- msgid "Server name is empty!"
425
- msgstr ""
426
-
427
- #: includes/classes/class.backup.php:78 includes/classes/class.backup.php:97
428
- msgid "Unable to create backup folder."
429
- msgstr "Невозможно создать папку для резервного копирования."
430
-
431
- #: includes/classes/class.backup.php:168
432
- msgid "Unable to create backup subfolder."
433
- msgstr "Невозможно создать подпапку для резервного копирования."
434
-
435
- #: includes/classes/class.backup.php:266
436
- msgid "Unable to create temp folder."
437
- msgstr ""
438
-
439
- #: includes/classes/class.backup.php:280
440
- msgid "Could not copy the file to the temporary directory"
441
- msgstr ""
442
-
443
- #: includes/classes/class.backup.php:291
444
- msgid ""
445
- "It is not possible to create a temporary file, the backup folder is not "
446
- "writable."
447
- msgstr ""
448
-
449
- #: includes/classes/class.backup.php:359
450
- msgid "Unable to restore from a backup. There is no file."
451
- msgstr "Не удалось восстановить из резервной копии. Нет файла."
452
-
453
- #: includes/classes/class.attachment.php:289
454
- msgid "Failed to get optimized image from remote server"
455
- msgstr "Не удалось получить оптимизированное изображение с удаленного сервера"
456
-
457
- #: includes/classes/class.media-library.php:206
458
- msgid "No access for writing backups."
459
- msgstr "Нет доступа для записи резервных копий."
460
-
461
- #: includes/classes/class.media-library.php:214
462
- msgid "The uploads folder is not writable."
463
- msgstr "Папка uploads недоступна для записи."
464
-
465
- #: includes/classes/class.cron.php:54
466
- msgid "Scheduled optimization"
467
- msgstr ""
468
-
469
- #: includes/classes/class.cron.php:54
470
- msgid "Schedule your images optimization."
471
- msgstr ""
472
-
473
- #: includes/classes/class.cron.php:61
474
- msgid "1 min"
475
- msgstr ""
476
-
477
- #: includes/classes/class.cron.php:62
478
- msgid "2 min"
479
- msgstr ""
480
-
481
- #: includes/classes/class.cron.php:63
482
- msgid "5 min"
483
- msgstr ""
484
-
485
- #: includes/classes/class.cron.php:64
486
- msgid "10 min"
487
- msgstr ""
488
-
489
- #: includes/classes/class.cron.php:65
490
- msgid "30 min"
491
- msgstr ""
492
-
493
- #: includes/classes/class.cron.php:66
494
- msgid "Hour"
495
- msgstr ""
496
-
497
- #: includes/classes/class.cron.php:67
498
- msgid "Day"
499
- msgstr ""
500
-
501
- #: includes/classes/class.cron.php:70
502
- msgid "Run every"
503
- msgstr ""
504
-
505
- #: includes/classes/class.cron.php:71
506
- msgid "Select time at which the task will be repeated."
507
- msgstr ""
508
-
509
- #: includes/classes/class.cron.php:78
510
- msgid "Images per iteration"
511
- msgstr ""
512
-
513
- #: includes/classes/class.cron.php:80
514
- msgid ""
515
- "Specify the number of images that will be optimized during the job. For "
516
- "example, if you enter 5 and select 5 min, the plugin will optimize 5 images "
517
- "every 5 minutes."
518
- msgstr ""
519
-
520
- #: admin/includes/classes/class.optimize-template.php:53
521
- msgid "Image optimization dashboard"
522
- msgstr "Панель управления оптимизацией изображений"
523
-
524
- #: admin/includes/classes/class.optimize-template.php:55
525
- msgid ""
526
- "Monitor image optimization statistics and run on demand or scheduled "
527
- "optimization."
528
- msgstr ""
529
- "Отслеживайте статистику оптимизации изображений и запускайте оптимизацию по "
530
- "требованию или по расписанию."
531
-
532
- #: admin/includes/classes/class.optimize-template.php:102
533
- msgid "Select optimization server:"
534
- msgstr ""
535
-
536
- #: admin/includes/classes/class.optimize-template.php:103
537
- msgid ""
538
- "Please, find the list of available servers for image optimization below. If "
539
- "the server has a state “Down”, it means that the server is not available, "
540
- "and you should choose another one. “Stable” means that the server is "
541
- "available and you can use it."
542
- msgstr ""
543
-
544
- #: admin/includes/classes/class.optimize-template.php:110
545
- #: admin/includes/classes/class.optimize-template.php:113
546
- #: admin/includes/classes/class.optimize-template.php:116
547
- #: admin/includes/classes/class.optimize-template.php:119
548
- msgid "Server"
549
- msgstr ""
550
-
551
- #: admin/includes/classes/class.optimize-template.php:110
552
- msgid "recommended"
553
- msgstr ""
554
-
555
- #: admin/includes/classes/class.optimize-template.php:110
556
- msgid "image size limit up to 5 MB"
557
- msgstr ""
558
-
559
- #: admin/includes/classes/class.optimize-template.php:113
560
- msgid "image size limit up to 1 MB"
561
- msgstr ""
562
-
563
- #: admin/includes/classes/class.optimize-template.php:116
564
- msgid "you can't use it on a localhost"
565
- msgstr ""
566
-
567
- #: admin/includes/classes/class.optimize-template.php:119
568
- msgid "image compressor test"
569
- msgstr ""
570
-
571
- #: admin/includes/classes/class.optimize-template.php:123
572
- msgid "Status:"
573
- msgstr ""
574
-
575
- #: admin/includes/classes/class.optimize-template.php:123
576
- msgid "Stable"
577
- msgstr ""
578
-
579
- #: admin/includes/classes/class.optimize-template.php:123
580
- msgid "Down"
581
- msgstr ""
582
-
583
- #: admin/includes/classes/class.optimize-template.php:139
584
- msgid "You optimized"
585
- msgstr "Вы оптимизировали"
586
-
587
- #: admin/includes/classes/class.optimize-template.php:141
588
- msgid "of your website's images"
589
- msgstr "изображений сайта"
590
-
591
- #: admin/includes/classes/class.optimize-template.php:167
592
- msgid "Statistics"
593
- msgstr "Статистика"
594
-
595
- #: admin/includes/classes/class.optimize-template.php:172
596
- msgid ""
597
- "that's the number of original images<br> you optimized with Image Optimizer"
598
- msgstr ""
599
- "количество исходных изображений<br> которые вы оптимизировали с Image "
600
- "Optimizer"
601
-
602
- #: admin/includes/classes/class.optimize-template.php:199
603
- msgid "that's the size you saved <br>by using Image Optimizer"
604
- msgstr ""
605
- "вы сохранили благодаря<br>\n"
606
- "Image Optimizer"
607
-
608
- #: admin/includes/classes/class.optimize-template.php:214
609
- msgid "images."
610
- msgstr "изображений."
611
-
612
- #: admin/includes/classes/class.optimize-template.php:295
613
- msgid "Optimization log"
614
- msgstr ""
615
-
616
- #: admin/includes/classes/class.optimize-template.php:296
617
- msgid ""
618
- "Optimization log shows the last 100 optimized images. You can check the "
619
- "quality of the image by clicking on the file name."
620
- msgstr ""
621
-
622
- #: admin/includes/classes/class.optimize-template.php:303
623
- msgid "File name"
624
- msgstr ""
625
-
626
- #: admin/includes/classes/class.optimize-template.php:304
627
- msgid "Inital size"
628
- msgstr ""
629
-
630
- #: admin/includes/classes/class.optimize-template.php:305
631
- msgid "Current size"
632
- msgstr ""
633
-
634
- #: admin/includes/classes/class.optimize-template.php:307
635
- msgid "WebP size"
636
- msgstr ""
637
-
638
- #: admin/includes/classes/class.optimize-template.php:309
639
- msgid "Original Saving"
640
- msgstr ""
641
-
642
- #: admin/includes/classes/class.optimize-template.php:310
643
- msgid "Compressed thumbnails"
644
- msgstr ""
645
-
646
- #: admin/includes/classes/class.optimize-template.php:311
647
- msgid "Overall Saving"
648
- msgstr ""
649
-
650
- #: admin/includes/classes/class.optimize-template.php:317
651
- msgid "You don't have optimized images."
652
- msgstr ""
653
-
654
- #: admin/includes/classes/class.optimize-template.php:379
655
- #: admin/includes/classes/class.optimize-template.php:386
656
- msgid "Run"
657
- msgstr "Запустить"
658
-
659
- #: admin/includes/classes/class.optimize-template.php:384
660
- #: admin/includes/classes/class.optimize-template.php:399
661
- msgid "Stop"
662
- msgstr "Остановить"
663
-
664
- #: admin/includes/classes/class.optimize-template.php:390
665
- msgid "Information"
666
- msgstr ""
667
-
668
- #: admin/includes/classes/class.optimize-template.php:390
669
- msgid "Optimize now"
670
- msgstr ""
671
-
672
- #: admin/includes/classes/class.optimize-template.php:390
673
- msgid "Scheduled"
674
- msgstr ""
675
-
676
- #: admin/includes/classes/class.optimize-template.php:394
677
- msgid ""
678
- "Are you sure that you want to leave the page? The optimization process is "
679
- "not over yet, stay on the page until the end of the optimization process."
680
- msgstr ""
681
-
682
- #: admin/includes/classes/class.optimize-template.php:397
683
- msgid "Do you want to start optimization without backup?"
684
- msgstr "Вы хотите начать оптимизацию без возможности восстановления?"
685
-
686
- #: admin/includes/classes/class.optimize-template.php:398
687
- msgid "Resume"
688
- msgstr "Возобновить"
689
-
690
- #: admin/includes/classes/class.optimize-template.php:487
691
- msgid "New Filesize:"
692
- msgstr "Новый размер:"
693
-
694
- #: admin/includes/classes/class.optimize-template.php:490
695
- msgid "Original Saving:"
696
- msgstr "Сжатие:"
697
-
698
- #: admin/includes/classes/class.optimize-template.php:496
699
- msgid "Original Filesize:"
700
- msgstr "Размер оригинала:"
701
-
702
- #: admin/includes/classes/class.optimize-template.php:499
703
- msgid "Level:"
704
- msgstr "Уровень:"
705
-
706
- #: admin/includes/classes/class.optimize-template.php:509
707
- msgid "lossless"
708
- msgstr ""
709
-
710
- #: admin/includes/classes/class.optimize-template.php:511
711
- msgid "lossy"
712
- msgstr ""
713
-
714
- #: admin/includes/classes/class.optimize-template.php:521
715
- msgid "Thumbnails Optimized:"
716
- msgstr "Оптимизированные миниатюры:"
717
-
718
- #: admin/includes/classes/class.optimize-template.php:525
719
- msgid "Overall Saving:"
720
- msgstr "Общее сохранение:"
721
-
722
- #: admin/includes/classes/class.optimize-template.php:530
723
- msgid "Error Message:"
724
- msgstr "Сообщение об ошибке:"
725
-
726
- #: admin/includes/classes/class.optimize-template.php:539
727
- #: admin/includes/classes/class.optimize-template.php:549
728
- #: admin/includes/classes/class.optimize-template.php:559
729
- #: admin/includes/classes/class.optimize-template.php:581
730
- msgid "Optimization in progress"
731
- msgstr "Выполняется оптимизация"
732
-
733
- #: admin/includes/classes/class.optimize-template.php:541
734
- #: admin/includes/classes/class.optimize-template.php:551
735
- #: admin/includes/classes/class.optimize-template.php:561
736
- msgid "Re-Optimize to"
737
- msgstr "Пережать в"
738
-
739
- #: admin/includes/classes/class.optimize-template.php:569
740
- msgid "Recovery in progress"
741
- msgstr "Восстанавливается"
742
-
743
- #: admin/includes/classes/class.optimize-template.php:570
744
- msgid "Restore original"
745
- msgstr "Восстановить оригинал"
746
-
747
- #: admin/includes/classes/class.optimize-template.php:583
748
- msgid "Optimize"
749
- msgstr "Оптимизировать"
750
-
751
- #: admin/pages/parts/optimize-popup.php:1
752
- msgid "What you need to know before starting optimization."
753
- msgstr ""
754
-
755
- #: admin/pages/parts/optimize-popup.php:13
756
- msgid ""
757
- "Remember that the optimization of a large number of images may take some "
758
- "time depending on your server and network speed."
759
- msgstr ""
760
-
761
- #: admin/pages/parts/optimize-popup.php:25
762
- msgid ""
763
- "If you choose to optimize now, you should keep this page open until a bulk "
764
- "optimization is performed. If you leave, the optimization process will stop "
765
- "and you will need to run it again.."
766
- msgstr ""
767
-
768
- #: admin/pages/parts/optimize-popup.php:36
769
- msgid "Have questions? See the documentation."
770
- msgstr ""
771
-
772
- #: admin/pages/parts/optimize-popup.php:36
773
- msgid "Open documentation."
774
- msgstr ""
775
-
776
- #: includes/classes/processors/class.image-processor-smushpro.php:51
777
- msgid "file not found"
778
- msgstr "файл не найден"
779
-
780
- #: includes/classes/processors/class.image-processor-smushpro.php:56
781
- msgid "curl not work"
782
- msgstr "curl не работает"
783
-
784
- #. Description of the plugin
785
- msgid ""
786
- "Optimize images without losing quality, speed up your website load, improve "
787
- "SEO and save money on server and CDN bandwidth."
788
- msgstr ""
789
-
790
- #. URI of the plugin
791
- msgid "https://wordpress.org/plugins/robin-image-optimizer/"
792
- msgstr ""
793
-
794
- #. Author of the plugin
795
- msgid "Webcraftic <wordpress.webraftic@gmail.com>"
796
- msgstr ""
797
-
798
- #. Author URI of the plugin
799
- msgid "https://clearfy.pro"
800
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Alexander Parfilov <alexparfilov@gmail.com>, 2018.
3
+ #
4
+ msgid ""
5
+ msgstr ""
6
+ "Project-Id-Version: Image optimizer\n"
7
+ "Report-Msgid-Bugs-To: \n"
8
+ "POT-Creation-Date: 2020-07-14 09:20+0000\n"
9
+ "PO-Revision-Date: 2020-07-14 09:21+0000\n"
10
+ "Last-Translator: \n"
11
+ "Language-Team: Русский\n"
12
+ "Language: ru_RU\n"
13
+ "MIME-Version: 1.0\n"
14
+ "Content-Type: text/plain; charset=UTF-8\n"
15
+ "Content-Transfer-Encoding: 8bit\n"
16
+ "X-Generator: Loco https://localise.biz/\n"
17
+ "X-Poedit-Basepath: ..\n"
18
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19
+ "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
+ "X-Poedit-SourceCharset: UTF-8\n"
21
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
22
+ "X-Poedit-SearchPath-0: .\n"
23
+ "X-Poedit-SearchPathExcluded-0: libs\n"
24
+ "X-Poedit-SearchPathExcluded-1: .git\n"
25
+ "X-Loco-Version: 2.4.0; wp-5.4.2"
26
+
27
+ #. Name of the plugin
28
+ #: robin-image-optimizer.php:33
29
+ msgid "Webcraftic Robin image optimizer"
30
+ msgstr ""
31
+
32
+ #: admin/boot.php:229
33
+ msgid "ROBIN IMAGE OPTIMIZER PRO"
34
+ msgstr ""
35
+
36
+ #: admin/boot.php:245
37
+ msgid "Automatic convertation in Webp"
38
+ msgstr ""
39
+
40
+ #: admin/boot.php:246
41
+ msgid "You can optimize custom folders"
42
+ msgstr ""
43
+
44
+ #: admin/boot.php:247
45
+ msgid "Support Nextgen gallery"
46
+ msgstr ""
47
+
48
+ #: admin/boot.php:248
49
+ msgid "Multisite support"
50
+ msgstr ""
51
+
52
+ #: admin/boot.php:249
53
+ msgid "Fast optimization servers"
54
+ msgstr ""
55
+
56
+ #: admin/boot.php:250
57
+ msgid "No ads"
58
+ msgstr ""
59
+
60
+ #: admin/boot.php:251
61
+ msgid "Best support"
62
+ msgstr ""
63
+
64
+ #: admin/boot.php:274
65
+ #, php-format
66
+ msgid ""
67
+ "<a href=\"%s\">License activation</a> required. A license is required to get "
68
+ "premium plugin updates, as well as to get additional services."
69
+ msgstr ""
70
+
71
+ #: admin/boot.php:276
72
+ #, php-format
73
+ msgid ""
74
+ "Your <a href=\"%s\">license</a> has expired. You can no longer get premium "
75
+ "plugin updates, premium support and your access to Webcraftic services has "
76
+ "been suspended."
77
+ msgstr ""
78
+
79
+ #: includes/functions.php:475
80
+ #, php-format
81
+ msgid ""
82
+ "There were big changes in database schema. Please <a href=\"#\" id=\"wbcr-"
83
+ "wio-meta-migration-action\" class=\"button button-default\" data-"
84
+ "nonce=\"%s\">click here</a> to upgrade it to the latest version"
85
+ msgstr ""
86
+
87
+ #: views/clearfy-component-card.php:37 admin/pages/class-rio-license.php:49
88
+ msgid "License"
89
+ msgstr ""
90
+
91
+ #: views/modal-bulk-optimization.php:2
92
+ msgid "What you need to know before starting optimization."
93
+ msgstr ""
94
+
95
+ #: views/modal-bulk-optimization.php:15
96
+ msgid ""
97
+ "If you choose to optimize now, you should keep this page open until a bulk "
98
+ "optimization is performed. If you leave, the optimization process will stop "
99
+ "and you will need to run it again.."
100
+ msgstr ""
101
+
102
+ #: views/modal-bulk-optimization.php:26
103
+ msgid ""
104
+ "If you choose to a scheduled optimization, you can leave this page or close "
105
+ "the browser. A plugin without your participation will optimize images via "
106
+ "cron until it optimizes them all. This optimization method is slower than "
107
+ "its alternative, but you don’t have to waste your time on manual "
108
+ "optimization."
109
+ msgstr ""
110
+
111
+ #: views/modal-bulk-optimization.php:37
112
+ msgid ""
113
+ "Remember that the optimization of a large number of images may take some "
114
+ "time depending on your server and network speed."
115
+ msgstr ""
116
+
117
+ #: views/part-bulk-optimization-button.php:20
118
+ #: views/part-bulk-optimization-button.php:27
119
+ #: admin/pages/class-rio-statistic.php:264
120
+ msgid "Run"
121
+ msgstr "Запустить"
122
+
123
+ #: views/part-bulk-optimization-button.php:25
124
+ #: admin/pages/class-rio-statistic.php:266
125
+ msgid "Stop shedule optimization"
126
+ msgstr ""
127
+
128
+ #: views/part-bulk-optimization-log.php:104
129
+ msgid "Optimization log"
130
+ msgstr ""
131
+
132
+ #: views/part-bulk-optimization-log.php:105
133
+ msgid ""
134
+ "Optimization log shows the last 100 optimized images. You can check the "
135
+ "quality of the image by clicking on the file name."
136
+ msgstr ""
137
+
138
+ #: views/part-bulk-optimization-log.php:112
139
+ msgid "File name"
140
+ msgstr ""
141
+
142
+ #: views/part-bulk-optimization-log.php:113
143
+ msgid "Inital size"
144
+ msgstr ""
145
+
146
+ #: views/part-bulk-optimization-log.php:114
147
+ msgid "Current size"
148
+ msgstr ""
149
+
150
+ #: views/part-bulk-optimization-log.php:115
151
+ msgid "WebP size"
152
+ msgstr ""
153
+
154
+ #: views/part-bulk-optimization-log.php:116
155
+ msgid "Original Saving"
156
+ msgstr ""
157
+
158
+ #: views/part-bulk-optimization-log.php:118
159
+ msgid "Compressed thumbnails"
160
+ msgstr ""
161
+
162
+ #: views/part-bulk-optimization-log.php:120
163
+ msgid "Overall Saving"
164
+ msgstr ""
165
+
166
+ #: views/part-bulk-optimization-log.php:126
167
+ msgid "You don't have optimized images."
168
+ msgstr ""
169
+
170
+ #: views/part-bulk-optimization-log.php:139
171
+ #: views/part-bulk-optimization-statistic.php:50
172
+ #: admin/pages/class-rio-statistic.php:251
173
+ #: libs/addons/includes/classes/class.folders-list-table.php:236
174
+ msgid "Error"
175
+ msgstr "Ошибка"
176
+
177
+ #: views/part-bulk-optimization-log.php:143
178
+ msgid "Unknown error."
179
+ msgstr ""
180
+
181
+ #: views/part-bulk-optimization-servers.php:13
182
+ msgid "Select optimization server:"
183
+ msgstr ""
184
+
185
+ #: views/part-bulk-optimization-servers.php:14
186
+ msgid ""
187
+ "Please, find the list of available servers for image optimization below. If "
188
+ "the server has a state “Down”, it means that the server is not available, "
189
+ "and you should choose another one. “Stable” means that the server is "
190
+ "available and you can use it."
191
+ msgstr ""
192
+
193
+ #: views/part-bulk-optimization-servers.php:21
194
+ #: admin/pages/class-rio-settings.php:107
195
+ msgid "Server 1 - image size limit up to 5 MB"
196
+ msgstr ""
197
+
198
+ #: views/part-bulk-optimization-servers.php:24
199
+ #: admin/pages/class-rio-settings.php:112
200
+ msgid "Server 2 - beta"
201
+ msgstr ""
202
+
203
+ #: views/part-bulk-optimization-servers.php:27
204
+ #: admin/pages/class-rio-settings.php:117
205
+ msgid "Premium - no limits"
206
+ msgstr ""
207
+
208
+ #: views/part-bulk-optimization-servers.php:31
209
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:24
210
+ msgid "Status"
211
+ msgstr ""
212
+
213
+ #: views/part-bulk-optimization-servers.php:35
214
+ msgid "Credits"
215
+ msgstr ""
216
+
217
+ #: views/part-bulk-optimization-servers.php:36
218
+ msgid "Only original images are limited. Thumbnails are not limited"
219
+ msgstr ""
220
+
221
+ #: views/part-bulk-optimization-statistic.php:24
222
+ msgid "You optimized"
223
+ msgstr "Вы оптимизировали"
224
+
225
+ #: views/part-bulk-optimization-statistic.php:28
226
+ msgid "of your website's images"
227
+ msgstr "изображений сайта"
228
+
229
+ #: views/part-bulk-optimization-statistic.php:36
230
+ #: libs/addons/includes/classes/class.folders-list-table.php:135
231
+ #: libs/addons/includes/classes/class.folders-list-table.php:238
232
+ msgid "Unoptimized"
233
+ msgstr "Не оптимизировано"
234
+
235
+ #: views/part-bulk-optimization-statistic.php:43
236
+ #: libs/addons/includes/classes/class.folders-list-table.php:132
237
+ msgid "Optimized"
238
+ msgstr "Оптимизировано"
239
+
240
+ #: views/part-bulk-optimization-statistic.php:57
241
+ msgid "Statistics"
242
+ msgstr "Статистика"
243
+
244
+ #: views/part-bulk-optimization-statistic.php:59
245
+ msgid "Original size"
246
+ msgstr "Оригинальный размер"
247
+
248
+ #: views/part-bulk-optimization-statistic.php:67
249
+ msgid "Optimized size"
250
+ msgstr "Оптимизированный размер"
251
+
252
+ #: views/part-bulk-optimization-statistic.php:83
253
+ msgid "that's the size you saved <br>by using Image Optimizer"
254
+ msgstr ""
255
+ "вы сохранили благодаря<br>\n"
256
+ "Image Optimizer"
257
+
258
+ #: views/part-bulk-optimization-tabs.php:23
259
+ msgid "Media library"
260
+ msgstr ""
261
+
262
+ #: views/part-bulk-optimization-tabs.php:32
263
+ msgid "Custom folders"
264
+ msgstr ""
265
+
266
+ #: views/part-bulk-optimization-tabs.php:42
267
+ msgid "Nextgen gallery"
268
+ msgstr ""
269
+
270
+ #: views/part-settings-page-error-log-options.php:13
271
+ msgid ""
272
+ "Additional logging levels. Enable these options only when the plugin support "
273
+ "service asks for it. If you use logging always, it can slow down your site."
274
+ msgstr ""
275
+
276
+ #: views/part-settings-page-error-log-options.php:18
277
+ msgid "Keep an error log on frontend"
278
+ msgstr ""
279
+
280
+ #: views/part-settings-page-error-log-options.php:21
281
+ msgid ""
282
+ "Option enables error logging on frontend. If for some reason webp images are "
283
+ "not displayed on the front-end, you can use this option to catch errors and "
284
+ "send this report to the plugin support service."
285
+ msgstr ""
286
+
287
+ #: admin/ajax/bulk-optimization.php:123
288
+ msgid ""
289
+ "Unknown error. Enable error log on the plugin's settings page, then check "
290
+ "the error report on the Error Log page. You can export the error report and "
291
+ "send it to the support service of the plugin."
292
+ msgstr ""
293
+
294
+ #: admin/ajax/bulk-optimization.php:218
295
+ msgid "Server name is empty!"
296
+ msgstr ""
297
+
298
+ #: admin/ajax/logs.php:15
299
+ msgid "Failed to clean-up logs. Please try again later."
300
+ msgstr ""
301
+
302
+ #: admin/ajax/logs.php:21
303
+ msgid "Logs clean-up successfully"
304
+ msgstr ""
305
+
306
+ #: admin/ajax/meta-migrations.php:152
307
+ #, php-format
308
+ msgid "left to migrate: %s items"
309
+ msgstr ""
310
+
311
+ #: admin/ajax/meta-migrations.php:163
312
+ msgid "Finishing-up..."
313
+ msgstr ""
314
+
315
+ #: admin/includes/sidebar-widgets.php:24
316
+ msgid "Activate Robin image optimizer pro"
317
+ msgstr ""
318
+
319
+ #: admin/includes/sidebar-widgets.php:28
320
+ msgid ""
321
+ "Paid license guarantees that you can download and update existing and future "
322
+ "paid components of the plugin."
323
+ msgstr ""
324
+
325
+ #: admin/includes/sidebar-widgets.php:31
326
+ #, php-format
327
+ msgid "Upgrade to Clearfy Business for $%s"
328
+ msgstr ""
329
+
330
+ #: admin/includes/sidebar-widgets.php:60
331
+ msgid "Having Issues?"
332
+ msgstr ""
333
+
334
+ #: admin/includes/sidebar-widgets.php:63
335
+ msgid ""
336
+ "We provide free support for this plugin. If you are pushed with a problem, "
337
+ "just create a new ticket. We will definitely help you!"
338
+ msgstr ""
339
+
340
+ #: admin/includes/sidebar-widgets.php:67
341
+ msgid "Get starting free support"
342
+ msgstr ""
343
+
344
+ #: admin/pages/class-rio-license.php:50
345
+ msgid "Product activation"
346
+ msgstr ""
347
+
348
+ #: admin/pages/class-rio-license.php:52
349
+ msgid "Robin image optimizer Premium"
350
+ msgstr ""
351
+
352
+ #: admin/pages/class-rio-log.php:37 admin/pages/class-rio-log.php:64
353
+ #: admin/pages/class-rio-log.php:73 admin/pages/class-rio-settings.php:209
354
+ msgid "Error Log"
355
+ msgstr "Журнал ошибок"
356
+
357
+ #: admin/pages/class-rio-log.php:38
358
+ msgid "Plugin debug report"
359
+ msgstr ""
360
+
361
+ #: admin/pages/class-rio-log.php:64 admin/pages/class-rio-statistic.php:125
362
+ #: admin/includes/classes/class-rio-nextgen-landing.php:38
363
+ #: admin/includes/classes/class-rio-nextgen-landing.php:39
364
+ msgid "Image optimizer"
365
+ msgstr "Оптим. изображений"
366
+
367
+ #: admin/pages/class-rio-log.php:75
368
+ msgid ""
369
+ "In this section, you can track image optimization errors. Sending this log "
370
+ "to us, will help in solving possible optimization issues."
371
+ msgstr ""
372
+ "В этом разделе вы можете отследить ошибки оптимизации изображений. Отправка "
373
+ "этого лога нам, поможет в решении возможных проблем с оптимизацией."
374
+
375
+ #: admin/pages/class-rio-log.php:81
376
+ msgid "Export Debug Information"
377
+ msgstr ""
378
+
379
+ #: admin/pages/class-rio-log.php:84
380
+ msgid "Working..."
381
+ msgstr ""
382
+
383
+ #: admin/pages/class-rio-log.php:85
384
+ #, php-format
385
+ msgid "Clean-up Logs (<span id=\"wbcr-log-size\">%s</span>)"
386
+ msgstr ""
387
+
388
+ #: admin/pages/class-rio-settings.php:36
389
+ msgid "Settings"
390
+ msgstr ""
391
+
392
+ #: admin/pages/class-rio-settings.php:37
393
+ msgid "Plugin configuration"
394
+ msgstr ""
395
+
396
+ #: admin/pages/class-rio-settings.php:71
397
+ msgid "Folder wp-content/uploads/ is unavailable for writing"
398
+ msgstr "Папка wp-content/uploads/ недоступна для записи"
399
+
400
+ #: admin/pages/class-rio-settings.php:76
401
+ msgid "Folder wp-content/uploads/wio-backup/ is unavailable for writing"
402
+ msgstr "Папка wp-content/uploads/wio-backup/ недоступна для записи"
403
+
404
+ #: admin/pages/class-rio-settings.php:80
405
+ msgid "Cron is disabled in wp-config.php"
406
+ msgstr "Cron отключен в wp-config.php"
407
+
408
+ #: admin/pages/class-rio-settings.php:97
409
+ msgid "Main Settings"
410
+ msgstr "Основные настройки"
411
+
412
+ #: admin/pages/class-rio-settings.php:97
413
+ msgid "This section you can set main images optimization settings."
414
+ msgstr ""
415
+ этом разделе вы можете настроить основные параметры оптимизации "
416
+ "изображений."
417
+
418
+ #: admin/pages/class-rio-settings.php:103
419
+ msgid "Optimization server"
420
+ msgstr "Сервер оптимизации"
421
+
422
+ #: admin/pages/class-rio-settings.php:121
423
+ msgid ""
424
+ "We use several free servers for image optimization and can’t fully guarantee "
425
+ "their stable performance. The server can be not available in some countries "
426
+ "due to the political reasons. There is a solution: if one of the servers is "
427
+ "not available or can’t optimize the image, you can try to switch to the "
428
+ "alternative server. Each server has individual limitations for image weight "
429
+ "and optimization level. By default, you have the best server with minimum "
430
+ "limitations."
431
+ msgstr ""
432
+ "Мы используем несколько бесплатных серверов для оптимизации изображений и не "
433
+ "можем полностью гарантировать их работу. В некоторых странах сервер может "
434
+ "быть недоступен из-за политических причин. Мы предусмотрели несколько "
435
+ "вариантов, в случае если один из серверов недоступен или не может "
436
+ "оптимизировать изображения, вы можете попробовать переключиться на "
437
+ "альтернативный сервер. Каждый сервер имеет индивидуальные ограничения на вес "
438
+ "оптимизированных изображений и на уровень оптимизации. По умолчанию всегда "
439
+ "установлен самый лучший сервер с наименьшими ограничениями."
440
+
441
+ #: admin/pages/class-rio-settings.php:130
442
+ msgid "Compression mode"
443
+ msgstr "Режим сжатия"
444
+
445
+ #: admin/pages/class-rio-settings.php:134
446
+ msgid "Lossless"
447
+ msgstr ""
448
+
449
+ #: admin/pages/class-rio-settings.php:135
450
+ msgid ""
451
+ "This mode provides lossless compression and your images will be optimized "
452
+ "without visible changes. If you want an ideal image quality, we recommend "
453
+ "this mode. The size of the files will be reduced approximately 2 times. If "
454
+ "this is not enough for you, try other modes."
455
+ msgstr ""
456
+ "Этот режим обеспечивает сжатие без потерь и ваши изображения будут "
457
+ "оптимизированы без видимых изменений. Если вы хотите идеальное качество "
458
+ "изображений, мы рекомендуем этот режим. Размер фалов уменьшится "
459
+ "приблизительно в 2 раза. Если вам этого недостаточно, попробуйте другие "
460
+ "режимы."
461
+
462
+ #: admin/pages/class-rio-settings.php:139
463
+ msgid "Lossy"
464
+ msgstr ""
465
+
466
+ #: admin/pages/class-rio-settings.php:140
467
+ msgid ""
468
+ "This mode provides an ideal optimization of your images without significant "
469
+ "quality loss. The file size will be reduced approximately 5 times with a "
470
+ "slight decrease in image quality. In most cases that cannot be seen with the "
471
+ "naked eye."
472
+ msgstr ""
473
+ "Этот режим обеспечивает идеальную оптимизацию ваших изображений без "
474
+ "существенных потерь качества. Размер файлов уменьшиться приблизительно в 5 "
475
+ "раз при незначительном снижении качества изображений. Чаще всего, "
476
+ "невооружённым взглядом это даже не заметно."
477
+
478
+ #: admin/pages/class-rio-settings.php:144
479
+ #: admin/includes/classes/class-rio-optimize-template.php:149
480
+ #: admin/includes/classes/class-rio-optimize-template.php:197
481
+ msgid "High"
482
+ msgstr "Высокий"
483
+
484
+ #: admin/pages/class-rio-settings.php:145
485
+ #: admin/pages/class-rio-settings.php:150
486
+ msgid ""
487
+ "This mode will use all available optimization methods for maximum image "
488
+ "compression. The file size will be reduced approximately 7 times. The "
489
+ "quality of some images may deteriorate slightly. Use this mode if you need "
490
+ "the maximum weight reduction, and you are ready to accept the loss of image "
491
+ "quality."
492
+ msgstr ""
493
+ "Этот режим будет использовать все доступные методы оптимизации для "
494
+ "максимального сжатия изображения. Размер файлов уменьшится приблизительно в "
495
+ "7 раз. Качество некоторых изображений может немного ухудшиться. Используйте "
496
+ "этот режим, если вам требуется максимальное снижение веса, и вы готовы "
497
+ "смириться с потерей качества изображений."
498
+
499
+ #: admin/pages/class-rio-settings.php:149
500
+ #: admin/includes/classes/class-rio-optimize-template.php:141
501
+ msgid "Custom"
502
+ msgstr ""
503
+
504
+ #: admin/pages/class-rio-settings.php:154
505
+ msgid "Select the compression mode appropriate for your case."
506
+ msgstr "Выберите режим сжатия, подходящий для вашей ситуации."
507
+
508
+ #: admin/pages/class-rio-settings.php:176
509
+ msgid "Enter custom quality"
510
+ msgstr ""
511
+
512
+ #: admin/pages/class-rio-settings.php:178
513
+ msgid "custom quality 1-100"
514
+ msgstr ""
515
+
516
+ #: admin/pages/class-rio-settings.php:187
517
+ msgid "Auto optimization on upload"
518
+ msgstr "Автоматическая оптимизация изображений при загрузке"
519
+
520
+ #: admin/pages/class-rio-settings.php:189
521
+ msgid ""
522
+ "Automatically compress all images that you upload directly to the WordPress "
523
+ "media library, when editing pages and posts or using themes and plugins."
524
+ msgstr ""
525
+ "Автоматическое сжатие всех изображений, которые вы загружаете в "
526
+ "медиабиблиотеку WordPress напрямую, при редактировании страниц и записей или "
527
+ "с использованием тем и плагинов."
528
+
529
+ #: admin/pages/class-rio-settings.php:198
530
+ msgid "Backup images"
531
+ msgstr "Резервное копирование изображений"
532
+
533
+ #: admin/pages/class-rio-settings.php:200
534
+ msgid ""
535
+ "Before optimizing, all your images will be saved in a separate folder for "
536
+ "future recovery."
537
+ msgstr ""
538
+ "Перед началом оптимизации, все ваши изображения будут сохранены в отдельной "
539
+ "папке для возможности восстановления в будущем."
540
+
541
+ #: admin/pages/class-rio-settings.php:211
542
+ msgid "Enable error logging. The log will be displayed on a separate tab."
543
+ msgstr ""
544
+ "Включить ведение журнала ошибок. Он будет отображаться на отдельной вкладке."
545
+
546
+ #: admin/pages/class-rio-settings.php:230
547
+ msgid "Convert Images to WebP"
548
+ msgstr ""
549
+
550
+ #: admin/pages/class-rio-settings.php:232
551
+ msgid ""
552
+ "Convert JPEG & PNG images into WebP format and replace them for browsers "
553
+ "which support it. Unsupported browsers would be skipped."
554
+ msgstr ""
555
+
556
+ #: admin/pages/class-rio-settings.php:259
557
+ msgid "Leave EXIF data"
558
+ msgstr "Оставлять данные EXIF"
559
+
560
+ #: admin/pages/class-rio-settings.php:261
561
+ msgid ""
562
+ "EXIF is information stored in photos: camera model, shutter speed, exposure "
563
+ "compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended "
564
+ "data. If your project is dedicated to photography and you need to display "
565
+ "this data, then enable this option."
566
+ msgstr ""
567
+ "EXIF - это информация, хранящаяся в фотографиях: модель камеры, скорость "
568
+ "затвора, компенсация экспозиции, ISO, GPS и т. Д. По умолчанию плагин "
569
+ "удаляет расширенные данные EXIF. Если ваш проект посвящён фотографии и вам "
570
+ "нужно отображать эти данные, то включите эту опцию."
571
+
572
+ #: admin/pages/class-rio-settings.php:267
573
+ msgid "Optimization"
574
+ msgstr "Оптимизация"
575
+
576
+ #: admin/pages/class-rio-settings.php:267
577
+ msgid "Here you can specify additional image optimization options."
578
+ msgstr ""
579
+ "Здесь вы можете задать дополнительные параметры оптимизации изображений."
580
+
581
+ #: admin/pages/class-rio-settings.php:274
582
+ msgid "Optimization order"
583
+ msgstr ""
584
+
585
+ #: admin/pages/class-rio-settings.php:278
586
+ msgid "Ascending"
587
+ msgstr ""
588
+
589
+ #: admin/pages/class-rio-settings.php:279
590
+ msgid "Optimization will start with old images in the media library"
591
+ msgstr ""
592
+
593
+ #: admin/pages/class-rio-settings.php:283
594
+ msgid "Descending"
595
+ msgstr ""
596
+
597
+ #: admin/pages/class-rio-settings.php:284
598
+ msgid "Optimization will start with new images in the media library"
599
+ msgstr ""
600
+
601
+ #: admin/pages/class-rio-settings.php:288
602
+ msgid "Select the optimization order from the media library."
603
+ msgstr ""
604
+
605
+ #: admin/pages/class-rio-settings.php:297
606
+ msgid "Resizing large images"
607
+ msgstr "Изменение размера больших изображений"
608
+
609
+ #: admin/pages/class-rio-settings.php:299
610
+ msgid ""
611
+ "When you upload images from a camera or stock, they may be too high "
612
+ "resolution and it is not necessary for web. The option allows you to "
613
+ "automatically change images resolution on upload."
614
+ msgstr ""
615
+ "Когда вы закачиваете изображения с камеры или фотостока, они могут быть "
616
+ "слишком высокого разрешения и для веба это не нужно. Опция позволяет "
617
+ "автоматически изменять разрешение изображений при загрузке."
618
+
619
+ #: admin/pages/class-rio-settings.php:315
620
+ msgid "Enter the maximum width (px)"
621
+ msgstr ""
622
+
623
+ #: admin/pages/class-rio-settings.php:317
624
+ #: admin/pages/class-rio-settings.php:327
625
+ msgid ""
626
+ "Set the maximum images resolution on the long side. For horizontal images, "
627
+ "this will be the width, and for vertical images - the height. The resolution "
628
+ "of the images will be changed proportionally according to the set value."
629
+ msgstr ""
630
+ "Задайте максимальное разрешение изображений по длинной стороне. Для "
631
+ "горизонтальных изображений это будет ширина, а для вертикальных — высота. "
632
+ "Разрешение изображений будет изменено пропорционально в соответствии с "
633
+ "заданным значением."
634
+
635
+ #: admin/pages/class-rio-settings.php:325
636
+ msgid "Enter the maximum height (px)"
637
+ msgstr ""
638
+
639
+ #: admin/pages/class-rio-settings.php:335
640
+ msgid "Optimize formats"
641
+ msgstr ""
642
+
643
+ #: admin/pages/class-rio-settings.php:342
644
+ msgid ""
645
+ "Choose which formats of images should be optimized and uncheck those that do "
646
+ "not need optimization."
647
+ msgstr ""
648
+
649
+ #: admin/pages/class-rio-settings.php:360
650
+ msgid "Optimize thumbnails"
651
+ msgstr "Оптимизировать миниатюры"
652
+
653
+ #: admin/pages/class-rio-settings.php:363
654
+ msgid ""
655
+ "Choose which sizes of thumbnails should be optimized and uncheck those that "
656
+ "do not need optimization."
657
+ msgstr ""
658
+ "Выберите какие размеры миниатюр следует оптимизировать и снимите галочки с "
659
+ "тех, оптимизация которых не нужна."
660
+
661
+ #: admin/pages/class-rio-settings.php:442
662
+ msgid "Manage backups"
663
+ msgstr "Управление резервными копиями"
664
+
665
+ #: admin/pages/class-rio-settings.php:445
666
+ msgid "You can restore the original images from a backup or clear them."
667
+ msgstr ""
668
+ "Вы можете восстановить оригинальные изображения из резервной копии или "
669
+ "очистить их."
670
+
671
+ #: admin/pages/class-rio-settings.php:454
672
+ msgid "Are you sure?"
673
+ msgstr "Вы уверены?"
674
+
675
+ #: admin/pages/class-rio-settings.php:455
676
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:43
677
+ msgid "Restore"
678
+ msgstr "Восстановить"
679
+
680
+ #: admin/pages/class-rio-settings.php:457
681
+ msgid "Are you sure that you want to clear image backups folder?"
682
+ msgstr ""
683
+ "Вы действительно хотите очистить папку с резервными копиями изображений?"
684
+
685
+ #: admin/pages/class-rio-settings.php:458
686
+ msgid "Clear Backup"
687
+ msgstr "Очистить резервные копии"
688
+
689
+ #: admin/pages/class-rio-settings.php:511
690
+ msgid "Restore completed."
691
+ msgstr "Восстановление завершено."
692
+
693
+ #: admin/pages/class-rio-settings.php:513
694
+ msgid "The backup folder was cleared."
695
+ msgstr "Папка с резервными копиями очищена."
696
+
697
+ #: admin/pages/class-rio-statistic.php:70
698
+ #: admin/pages/class-rio-statistic.php:118
699
+ msgid "Robin image optimizer"
700
+ msgstr ""
701
+
702
+ #: admin/pages/class-rio-statistic.php:71
703
+ msgid "Compress bulk of images"
704
+ msgstr ""
705
+
706
+ #: admin/pages/class-rio-statistic.php:93
707
+ #, php-format
708
+ msgid ""
709
+ "We are forced to introduce limits on free servers. Read more on <a href='%s'>"
710
+ "our website</a>"
711
+ msgstr ""
712
+
713
+ #: admin/pages/class-rio-statistic.php:118
714
+ msgid "Robin Image Optimizer"
715
+ msgstr ""
716
+
717
+ #: admin/pages/class-rio-statistic.php:125
718
+ msgid "Bulk optimization"
719
+ msgstr ""
720
+
721
+ #: admin/pages/class-rio-statistic.php:200
722
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:123
723
+ msgid "Image optimization dashboard"
724
+ msgstr "Панель управления оптимизацией изображений"
725
+
726
+ #: admin/pages/class-rio-statistic.php:201
727
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:124
728
+ msgid ""
729
+ "Monitor image optimization statistics and run on demand or scheduled "
730
+ "optimization."
731
+ msgstr ""
732
+ "Отслеживайте статистику оптимизации изображений и запускайте оптимизацию по "
733
+ "требованию или по расписанию."
734
+
735
+ #: admin/pages/class-rio-statistic.php:247
736
+ msgid ""
737
+ "You cannot use the premium server on a free plan. You must activate the "
738
+ "license to use all the features of the premium version."
739
+ msgstr ""
740
+
741
+ #: admin/pages/class-rio-statistic.php:248
742
+ msgid ""
743
+ "Your selected optimization server is down. This means that you cannot "
744
+ "optimize images through this server. Try selecting another optimization "
745
+ "server."
746
+ msgstr ""
747
+
748
+ #: admin/pages/class-rio-statistic.php:249
749
+ msgid "down"
750
+ msgstr ""
751
+
752
+ #: admin/pages/class-rio-statistic.php:250
753
+ msgid "stable"
754
+ msgstr ""
755
+
756
+ #: admin/pages/class-rio-statistic.php:252
757
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:26
758
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:166
759
+ msgid "Cancel"
760
+ msgstr ""
761
+
762
+ #: admin/pages/class-rio-statistic.php:253
763
+ msgid "Confirm"
764
+ msgstr ""
765
+
766
+ #: admin/pages/class-rio-statistic.php:254
767
+ msgid "Select optimization way"
768
+ msgstr ""
769
+
770
+ #: admin/pages/class-rio-statistic.php:255
771
+ msgid "Optimize now"
772
+ msgstr ""
773
+
774
+ #: admin/pages/class-rio-statistic.php:256
775
+ #: includes/classes/class-rio-cron.php:46
776
+ msgid "Scheduled optimization"
777
+ msgstr ""
778
+
779
+ #: admin/pages/class-rio-statistic.php:257
780
+ msgid ""
781
+ "To start optimizing, you must complete migration from old plugin version."
782
+ msgstr ""
783
+
784
+ #: admin/pages/class-rio-statistic.php:258
785
+ msgid "All images from the media library are optimized."
786
+ msgstr "Все изображения из медиабиблиотеки оптимизированы."
787
+
788
+ #: admin/pages/class-rio-statistic.php:259
789
+ #, php-format
790
+ msgid ""
791
+ "Optimization in progress. Remained <span id=\"wio-total-unoptimized\">"
792
+ "%s</span> images."
793
+ msgstr ""
794
+
795
+ #: admin/pages/class-rio-statistic.php:260
796
+ msgid ""
797
+ "Are you sure that you want to leave the page? The optimization process is "
798
+ "not over yet, stay on the page until the end of the optimization process."
799
+ msgstr ""
800
+
801
+ #: admin/pages/class-rio-statistic.php:261
802
+ msgid "Do you want to start optimization without backup?"
803
+ msgstr "Вы хотите начать оптимизацию без возможности восстановления?"
804
+
805
+ #: admin/pages/class-rio-statistic.php:262
806
+ msgid "Resume"
807
+ msgstr "Возобновить"
808
+
809
+ #: admin/pages/class-rio-statistic.php:263
810
+ msgid "Completed"
811
+ msgstr ""
812
+
813
+ #: admin/pages/class-rio-statistic.php:265
814
+ msgid "Stop"
815
+ msgstr "Остановить"
816
+
817
+ #: includes/classes/class-rio-attachment.php:251
818
+ msgid "Attachment cannot be optimized."
819
+ msgstr ""
820
+
821
+ #: includes/classes/class-rio-attachment.php:254
822
+ #, php-format
823
+ msgid "Attachment #%d doesn't have metadata, the image may be damaged."
824
+ msgstr ""
825
+
826
+ #: includes/classes/class-rio-attachment.php:256
827
+ #, php-format
828
+ msgid "File \"(%s)\" doesn't exist"
829
+ msgstr ""
830
+
831
+ #: includes/classes/class-rio-backup.php:321
832
+ msgid "Could not copy the file to the temporary directory"
833
+ msgstr ""
834
+
835
+ #: includes/classes/class-rio-backup.php:334
836
+ msgid ""
837
+ "It is not possible to create a temporary file, the backup folder is not "
838
+ "writable."
839
+ msgstr ""
840
+
841
+ #: includes/classes/class-rio-cron.php:46
842
+ msgid "Schedule your images optimization."
843
+ msgstr ""
844
+
845
+ #: includes/classes/class-rio-cron.php:53
846
+ #: includes/classes/class-rio-cron.php:94
847
+ msgid "1 min"
848
+ msgstr ""
849
+
850
+ #: includes/classes/class-rio-cron.php:54
851
+ #: includes/classes/class-rio-cron.php:98
852
+ msgid "2 min"
853
+ msgstr ""
854
+
855
+ #: includes/classes/class-rio-cron.php:55
856
+ #: includes/classes/class-rio-cron.php:102
857
+ msgid "5 min"
858
+ msgstr ""
859
+
860
+ #: includes/classes/class-rio-cron.php:56
861
+ #: includes/classes/class-rio-cron.php:106
862
+ msgid "10 min"
863
+ msgstr ""
864
+
865
+ #: includes/classes/class-rio-cron.php:57
866
+ #: includes/classes/class-rio-cron.php:110
867
+ msgid "30 min"
868
+ msgstr ""
869
+
870
+ #: includes/classes/class-rio-cron.php:58
871
+ msgid "Hour"
872
+ msgstr ""
873
+
874
+ #: includes/classes/class-rio-cron.php:59
875
+ msgid "Day"
876
+ msgstr ""
877
+
878
+ #: includes/classes/class-rio-cron.php:62
879
+ msgid "Run every"
880
+ msgstr ""
881
+
882
+ #: includes/classes/class-rio-cron.php:63
883
+ msgid "Select time at which the task will be repeated."
884
+ msgstr ""
885
+
886
+ #: includes/classes/class-rio-cron.php:69
887
+ msgid "Images per iteration"
888
+ msgstr ""
889
+
890
+ #: includes/classes/class-rio-cron.php:71
891
+ msgid ""
892
+ "Specify the number of images that will be optimized during the job. For "
893
+ "example, if you enter 5 and select 5 min, the plugin will optimize 5 images "
894
+ "every 5 minutes."
895
+ msgstr ""
896
+
897
+ #: includes/classes/class-rio-cron.php:114
898
+ msgid "60 min"
899
+ msgstr ""
900
+
901
+ #: includes/classes/class-rio-cron.php:118
902
+ msgid "daily"
903
+ msgstr ""
904
+
905
+ #: includes/classes/class-rio-image-statistic.php:362
906
+ #: libs/addons/includes/classes/class.image-statistic-folders.php:325
907
+ #: libs/addons/includes/classes/class.image-statistic-nextgen.php:199
908
+ msgid "Unknown error"
909
+ msgstr ""
910
+
911
+ #: includes/classes/class-rio-media-library.php:244
912
+ #: includes/classes/class-rio-media-library.php:248
913
+ #: libs/addons/includes/classes/class.custom-folders.php:311
914
+ #: libs/addons/includes/classes/class.custom-folders.php:315
915
+ #: libs/addons/includes/classes/class.gallery-nextgen.php:339
916
+ #: libs/addons/includes/classes/class.gallery-nextgen.php:342
917
+ msgid "No access for writing backups."
918
+ msgstr "Нет доступа для записи резервных копий."
919
+
920
+ #: admin/includes/classes/class-rio-optimize-template.php:123
921
+ msgid "New Filesize:"
922
+ msgstr "Новый размер:"
923
+
924
+ #: admin/includes/classes/class-rio-optimize-template.php:126
925
+ msgid "Original Saving:"
926
+ msgstr "Сжатие:"
927
+
928
+ #: admin/includes/classes/class-rio-optimize-template.php:132
929
+ msgid "Original Filesize:"
930
+ msgstr "Размер оригинала:"
931
+
932
+ #: admin/includes/classes/class-rio-optimize-template.php:135
933
+ msgid "Level:"
934
+ msgstr "Уровень:"
935
+
936
+ #: admin/includes/classes/class-rio-optimize-template.php:145
937
+ #: admin/includes/classes/class-rio-optimize-template.php:177
938
+ msgid "lossless"
939
+ msgstr ""
940
+
941
+ #: admin/includes/classes/class-rio-optimize-template.php:147
942
+ #: admin/includes/classes/class-rio-optimize-template.php:187
943
+ msgid "lossy"
944
+ msgstr ""
945
+
946
+ #: admin/includes/classes/class-rio-optimize-template.php:157
947
+ msgid "Thumbnails Optimized:"
948
+ msgstr "Оптимизированные миниатюры:"
949
+
950
+ #: admin/includes/classes/class-rio-optimize-template.php:161
951
+ msgid "Overall Saving:"
952
+ msgstr "Общее сохранение:"
953
+
954
+ #: admin/includes/classes/class-rio-optimize-template.php:166
955
+ msgid "Error Message:"
956
+ msgstr "Сообщение об ошибке:"
957
+
958
+ #: admin/includes/classes/class-rio-optimize-template.php:175
959
+ #: admin/includes/classes/class-rio-optimize-template.php:185
960
+ #: admin/includes/classes/class-rio-optimize-template.php:195
961
+ #: admin/includes/classes/class-rio-optimize-template.php:217
962
+ msgid "Optimization in progress"
963
+ msgstr "Выполняется оптимизация"
964
+
965
+ #: admin/includes/classes/class-rio-optimize-template.php:177
966
+ #: admin/includes/classes/class-rio-optimize-template.php:187
967
+ #: admin/includes/classes/class-rio-optimize-template.php:197
968
+ msgid "Re-Optimize to"
969
+ msgstr "Пережать в"
970
+
971
+ #: admin/includes/classes/class-rio-optimize-template.php:205
972
+ msgid "Recovery in progress"
973
+ msgstr "Восстанавливается"
974
+
975
+ #: admin/includes/classes/class-rio-optimize-template.php:206
976
+ msgid "Restore original"
977
+ msgstr "Восстановить оригинал"
978
+
979
+ #: admin/includes/classes/class-rio-optimize-template.php:219
980
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:41
981
+ msgid "Optimize"
982
+ msgstr "Оптимизировать"
983
+
984
+ #: libs/addons/views/modal-select-custom-folders.php:10
985
+ msgid ""
986
+ "Select a directory for optimization. All nested images and folders will be "
987
+ "optimized recursively."
988
+ msgstr ""
989
+
990
+ #: libs/addons/views/modal-select-custom-folders.php:13
991
+ msgid "The selected directory is being indexed. Found"
992
+ msgstr ""
993
+
994
+ #: libs/addons/views/modal-select-custom-folders.php:14
995
+ msgid "images."
996
+ msgstr "изображений."
997
+
998
+ #: libs/addons/views/modal-select-custom-folders.php:15
999
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:170
1000
+ msgid ""
1001
+ "Indexing complete. Directory successfully added and ready for optimization."
1002
+ msgstr ""
1003
+
1004
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:15
1005
+ msgid "Additional media folders"
1006
+ msgstr ""
1007
+
1008
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:16
1009
+ msgid ""
1010
+ "Use the add folder... button to select site folders. Robin image optimizer "
1011
+ "will optimize images from the specified folders and their subfolders. The "
1012
+ "optimization status for each image in these folders can be seen in the Other "
1013
+ "Media list, under the Media menu."
1014
+ msgstr ""
1015
+
1016
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:17
1017
+ msgid "Add custom folder"
1018
+ msgstr ""
1019
+
1020
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:25
1021
+ msgid "Folder"
1022
+ msgstr ""
1023
+
1024
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:35
1025
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:171
1026
+ #, php-format
1027
+ msgid "Compressed %d of %s<br>images"
1028
+ msgstr ""
1029
+
1030
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:42
1031
+ msgid "Sync"
1032
+ msgstr ""
1033
+
1034
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:43
1035
+ msgid "Recover images from backup?"
1036
+ msgstr ""
1037
+
1038
+ #: libs/addons/views/part-bulk-optimization-table-folders.php:44
1039
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:168
1040
+ msgid "Exclude directory from optimization?"
1041
+ msgstr ""
1042
+
1043
+ #: libs/addons/views/part-settings-page-webp-options.php:17
1044
+ msgid "You can only use WebP conversion when using a premium server"
1045
+ msgstr ""
1046
+
1047
+ #: libs/addons/views/part-settings-page-webp-options.php:28
1048
+ msgid "Select delivery mode"
1049
+ msgstr ""
1050
+
1051
+ #: libs/addons/views/part-settings-page-webp-options.php:30
1052
+ #, php-format
1053
+ msgid ""
1054
+ "Deliver the WebP versions of the images in the front-end <a href=\"%s\" "
1055
+ "target=\"_blank\">Read more</a>"
1056
+ msgstr ""
1057
+
1058
+ #: libs/addons/views/part-settings-page-webp-options.php:35
1059
+ msgid "Redirection (via .htaccess)"
1060
+ msgstr ""
1061
+
1062
+ #: libs/addons/views/part-settings-page-webp-options.php:38
1063
+ #, php-format
1064
+ msgid ""
1065
+ "This will add rules in the .htaccess that redirects directly to existing "
1066
+ "converted files. Best performance is achieved by redirecting in .htaccess. "
1067
+ "Based on testing your particular hosting configuration, we determined that "
1068
+ "your server <img width=\"30\" src=\"%s\"> serve the WEBP versions of the "
1069
+ "JPEG files seamlessly, via .htaccess."
1070
+ msgstr ""
1071
+
1072
+ #: libs/addons/views/part-settings-page-webp-options.php:40
1073
+ msgid "Server"
1074
+ msgstr ""
1075
+
1076
+ #: libs/addons/views/part-settings-page-webp-options.php:51
1077
+ msgid ""
1078
+ "Replace &lt;img&gt; tags with &lt;picture&gt; tags, adding the webp to "
1079
+ "srcset."
1080
+ msgstr ""
1081
+
1082
+ #: libs/addons/views/part-settings-page-webp-options.php:54
1083
+ msgid ""
1084
+ " Each &lt;img&gt; will be replaced with a &lt;picture&gt; tag that will also "
1085
+ "provide the WebP image as a choice for browsers that support it. Also loads "
1086
+ "the picturefill.js for browsers that don't support the &lt;picture&gt; tag. "
1087
+ "You don't need to activate this if you're using the Cache Enabler plugin "
1088
+ "because your WebP images are already handled by this plugin. <strong>Please "
1089
+ "make a test before using this option</strong>, as if the styles that your "
1090
+ "theme is using rely on the position of your &lt;img&gt; tag, you might "
1091
+ "experience display problems. <strong>You can revert anytime to the previous "
1092
+ "state by just deactivating the option.</strong>"
1093
+ msgstr ""
1094
+
1095
+ #: libs/addons/views/part-settings-page-webp-options.php:59
1096
+ msgid "Replace image URLs"
1097
+ msgstr ""
1098
+
1099
+ #: libs/addons/views/part-settings-page-webp-options.php:62
1100
+ msgid ""
1101
+ "\"Image URLs\" replaces the image URLs to point to the webp <i>rather "
1102
+ "than</i> the original. Handles src, srcset, common lazy-load attributes and "
1103
+ "even inline styles. Note that you will have to do something for the browsers "
1104
+ "that does not support webp. And that something is in most cases to enable "
1105
+ "the <i>Only do the replacements in webp enabled browsers</i> option, which "
1106
+ "will show up when you enable this option."
1107
+ msgstr ""
1108
+
1109
+ #: libs/addons/views/part-settings-page-webp-options.php:67
1110
+ msgid "No delivery"
1111
+ msgstr ""
1112
+
1113
+ #: libs/addons/views/part-settings-page-webp-options.php:70
1114
+ msgid ""
1115
+ " Plugin will not replace the source JPEG, PNG image on Webp version of the "
1116
+ "image in\n"
1117
+ " front-end."
1118
+ msgstr ""
1119
+
1120
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:69
1121
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:76
1122
+ msgid "Custom Folders"
1123
+ msgstr ""
1124
+
1125
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:163
1126
+ msgid "Select custom folder"
1127
+ msgstr ""
1128
+
1129
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:165
1130
+ msgid "Select"
1131
+ msgstr ""
1132
+
1133
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:167
1134
+ msgid "Remove"
1135
+ msgstr ""
1136
+
1137
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:169
1138
+ #, php-format
1139
+ msgid "Selected directory is being indexed. Found %d images."
1140
+ msgstr ""
1141
+
1142
+ #: libs/addons/admin/pages/class-rio-statistic-folders-page.php:172
1143
+ msgid "All images from custom folders are optimized."
1144
+ msgstr ""
1145
+
1146
+ #: libs/addons/admin/pages/class-rio-statistic-nextgen-page.php:61
1147
+ #: libs/addons/admin/pages/class-rio-statistic-nextgen-page.php:68
1148
+ msgid "NextGen Gallery"
1149
+ msgstr ""
1150
+
1151
+ #: libs/addons/includes/classes/class.custom-folders.php:319
1152
+ msgid "You need to add an custom folder to start optimization!"
1153
+ msgstr ""
1154
+
1155
+ #: libs/addons/includes/classes/class.folders-list-table.php:21
1156
+ msgctxt "Column label"
1157
+ msgid "Preview"
1158
+ msgstr ""
1159
+
1160
+ #: libs/addons/includes/classes/class.folders-list-table.php:22
1161
+ msgctxt "Column label"
1162
+ msgid "File path"
1163
+ msgstr ""
1164
+
1165
+ #: libs/addons/includes/classes/class.folders-list-table.php:23
1166
+ msgctxt "Column label"
1167
+ msgid "Folder"
1168
+ msgstr ""
1169
+
1170
+ #: libs/addons/includes/classes/class.folders-list-table.php:24
1171
+ msgctxt "Column label"
1172
+ msgid "Status"
1173
+ msgstr ""
1174
+
1175
+ #: libs/addons/includes/classes/class.folders-list-table.php:25
1176
+ msgctxt "Column label"
1177
+ msgid "Optimization"
1178
+ msgstr ""
1179
+
1180
+ #: libs/addons/includes/classes/class.folders-list-table.php:118
1181
+ msgid "Filter by folder"
1182
+ msgstr ""
1183
+
1184
+ #: libs/addons/includes/classes/class.folders-list-table.php:120
1185
+ msgid "All Folders"
1186
+ msgstr ""
1187
+
1188
+ #: libs/addons/includes/classes/class.folders-list-table.php:129
1189
+ msgid "Filter by status"
1190
+ msgstr ""
1191
+
1192
+ #: libs/addons/includes/classes/class.folders-list-table.php:131
1193
+ msgid "All Media Files"
1194
+ msgstr ""
1195
+
1196
+ #: libs/addons/includes/classes/class.folders-list-table.php:138
1197
+ msgid "Errors"
1198
+ msgstr ""
1199
+
1200
+ #: libs/addons/includes/classes/class.folders-list-table.php:235
1201
+ msgid "Success"
1202
+ msgstr ""
1203
+
1204
+ #: libs/addons/includes/classes/class.folders-list-table.php:237
1205
+ msgid "Processing"
1206
+ msgstr ""
1207
+
1208
+ #: libs/addons/includes/classes/class.folders-list-table.php:239
1209
+ msgid "Skipped"
1210
+ msgstr ""
1211
+
1212
+ #: libs/addons/includes/classes/class.image-nextgen.php:203
1213
+ #, fuzzy
1214
+ #| msgid "file not found"
1215
+ msgid "File not found"
1216
+ msgstr "файл не найден"
1217
+
1218
+ #. Description of the plugin
1219
+ msgid ""
1220
+ "Optimize images without losing quality, speed up your website load, improve "
1221
+ "SEO and save money on server and CDN bandwidth."
1222
+ msgstr ""
1223
+
1224
+ #. URI of the plugin
1225
+ msgid "https://wordpress.org/plugins/robin-image-optimizer/"
1226
+ msgstr ""
1227
+
1228
+ #. Author of the plugin
1229
+ msgid "Webcraftic <wordpress.webraftic@gmail.com>"
1230
+ msgstr ""
1231
+
1232
+ #. Author URI of the plugin
1233
+ msgid "https://robinoptimizer.com"
1234
+ msgstr ""
libs/addons/admin/assets/js/custom-folders.js CHANGED
@@ -86,10 +86,10 @@
86
  if( response.data && response.data.error_message ) {
87
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
88
  // может быть скомпилирован.
89
- var noticeId = $.wbcr_factory_clearfy_217.app.showNotice(response.data.error_message, 'danger');
90
 
91
  setTimeout(function() {
92
- $.wbcr_factory_clearfy_217.app.hideNotice(noticeId);
93
  }, 5000);
94
  }
95
  return;
@@ -150,10 +150,10 @@
150
  if( response.data && response.data.error_message ) {
151
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
152
  // может быть скомпилирован.
153
- var noticeId = $.wbcr_factory_clearfy_217.app.showNotice(response.data.error_message, 'danger');
154
 
155
  setTimeout(function() {
156
- $.wbcr_factory_clearfy_217.app.hideNotice(noticeId);
157
  }, 5000);
158
  }
159
  return;
86
  if( response.data && response.data.error_message ) {
87
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
88
  // может быть скомпилирован.
89
+ var noticeId = $.wbcr_factory_clearfy_227.app.showNotice(response.data.error_message, 'danger');
90
 
91
  setTimeout(function() {
92
+ $.wbcr_factory_clearfy_227.app.hideNotice(noticeId);
93
  }, 5000);
94
  }
95
  return;
150
  if( response.data && response.data.error_message ) {
151
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
152
  // может быть скомпилирован.
153
+ var noticeId = $.wbcr_factory_clearfy_227.app.showNotice(response.data.error_message, 'danger');
154
 
155
  setTimeout(function() {
156
+ $.wbcr_factory_clearfy_227.app.hideNotice(noticeId);
157
  }, 5000);
158
  }
159
  return;
libs/addons/admin/boot.php CHANGED
@@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  * Flush configuration after saving the settings
21
  *
22
  * @param WHM_Plugin $plugin
23
- * @param Wbcr_FactoryPages425_ImpressiveThemplate $page
24
  *
25
  * @return bool
26
  */
20
  * Flush configuration after saving the settings
21
  *
22
  * @param WHM_Plugin $plugin
23
+ * @param Wbcr_FactoryPages435_ImpressiveThemplate $page
24
  *
25
  * @return bool
26
  */
libs/addons/admin/filters/settings-page.php CHANGED
@@ -40,8 +40,9 @@ add_action( "wrio/settings_page/berfore_form_save", function () {
40
  add_action( "wrio/settings_page/conver_webp_options", function () {
41
  $allow_redirection_mode = Server::is_apache() && Server::server_use_htaccess();
42
  $delivery_mode = WRIO_Plugin::app()->getPopulateOption( 'webp_delivery_mode', WEBP_Delivery::DEFAULT_DELIVERY_MODE );
 
43
 
44
- $server = 'apache';
45
 
46
  if ( Server::is_apache() ) {
47
  $server = 'apache';
@@ -59,8 +60,9 @@ add_action( "wrio/settings_page/conver_webp_options", function () {
59
 
60
  $view->print_template( "part-settings-page-webp-options", [
61
  'server' => $server,
 
62
  'delivery_mode' => $delivery_mode,
63
  'allow_redirection_mode' => $allow_redirection_mode,
64
  'docs_url' => $docs_url
65
  ] );
66
- } );
40
  add_action( "wrio/settings_page/conver_webp_options", function () {
41
  $allow_redirection_mode = Server::is_apache() && Server::server_use_htaccess();
42
  $delivery_mode = WRIO_Plugin::app()->getPopulateOption( 'webp_delivery_mode', WEBP_Delivery::DEFAULT_DELIVERY_MODE );
43
+ $optimization_server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' );
44
 
45
+ $server = 'unknown';
46
 
47
  if ( Server::is_apache() ) {
48
  $server = 'apache';
60
 
61
  $view->print_template( "part-settings-page-webp-options", [
62
  'server' => $server,
63
+ 'optimization_server' => $optimization_server,
64
  'delivery_mode' => $delivery_mode,
65
  'allow_redirection_mode' => $allow_redirection_mode,
66
  'docs_url' => $docs_url
67
  ] );
68
+ } );
libs/addons/includes/classes/class.folder.php CHANGED
@@ -209,7 +209,17 @@ class WRIO_Folder {
209
  * @return array
210
  */
211
  public function getAllowedFilesExt() {
212
- $allowed = [ 'jpg', 'jpeg', 'png' ];
 
 
 
 
 
 
 
 
 
 
213
 
214
  return $allowed;
215
  }
209
  * @return array
210
  */
211
  public function getAllowedFilesExt() {
212
+ $allowed_formats = explode( ',', WRIO_Plugin::app()->getOption( 'allowed_formats', "image/jpeg,image/png,image/gif" ) );
213
+ $allowed = [];
214
+ foreach ( $allowed_formats as $format ) {
215
+ if ( $format == 'image/jpeg' ) {
216
+ $allowed[] = 'jpg';
217
+ $allowed[] = 'jpeg';
218
+ } elseif ( $format == 'image/png' ) {
219
+ $allowed[] = 'png';
220
+ }
221
+ }
222
+ //$allowed = [ 'jpg', 'jpeg', 'png' ];
223
 
224
  return $allowed;
225
  }
libs/addons/includes/classes/webp/class-webp-api.php CHANGED
@@ -1,30 +1,29 @@
1
  <?php
2
-
3
  /**
4
  * Class WRIO_WebP_Api processing images from processing queue, sends them to API and saves locally.
5
  *
6
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
7
  */
8
  class WRIO_WebP_Api {
9
-
10
  /**
11
  * @var string API url.
12
  */
13
  //private $_api_url = 'http://142.93.91.206/';
14
  private $_api_url = 'https://dashboard.robinoptimizer.com/';
15
-
16
-
17
  /**
18
  * @var int|null Attachment ID.
19
  */
20
  private $_models = null;
21
-
22
  /**
23
  * @var null|int UNIX epoch when last request was processed.
24
  */
25
  private $_last_request_tick = null;
26
-
27
-
28
  /**
29
  * WRIO_WebP_Api constructor.
30
  *
@@ -33,7 +32,7 @@
33
  public function __construct( $model ) {
34
  $this->_models = $model;
35
  }
36
-
37
  /**
38
  * Process image queue based on provided attachment ID.
39
  *
@@ -44,27 +43,27 @@
44
  * @return bool true on success execution, false on failure or missing item in queue.
45
  */
46
  public function process_image_queue() {
47
-
48
  foreach ( $this->_models as $model ) {
49
  /**
50
  * @var RIOP_WebP_Extra_Data $extra_data
51
  */
52
  $extra_data = $model->get_extra_data();
53
-
54
  if ( $extra_data === null ) {
55
  continue;
56
  }
57
-
58
  $response = $this->request( $model );
59
-
60
  if ( $this->can_save( $response ) && $this->save_file( $response, $model ) ) {
61
  $this->update( $model );
62
  }
63
  }
64
-
65
  return true;
66
  }
67
-
68
  /**
69
  * Request API
70
  *
@@ -73,7 +72,7 @@
73
  * @return array|bool|WP_Error
74
  */
75
  public function request( $model ) {
76
-
77
  if ( $this->_last_request_tick === null ) {
78
  $this->_last_request_tick = time();
79
  } else {
@@ -81,63 +80,69 @@
81
  // Need to have some rest before calling REST :D to comply with API request limit
82
  sleep( 2 );
83
  }
84
-
85
  $this->_last_request_tick = time();
86
  }
87
-
 
 
 
 
 
 
88
  if ( ! wrio_is_license_activate() ) {
89
  WRIO_Logger::error( "Unable to get license to make proper request to the API" );
90
-
91
  return false;
92
  }
93
-
94
  $transient_string = md5( WRIO_Plugin::app()->getPrefix() . '_processing_image' . $model->get_item_hash() );
95
-
96
  $transient_value = get_transient( $transient_string );
97
-
98
  if ( is_numeric( $transient_value ) && (int) $transient_value === 1 ) {
99
  WRIO_Logger::info( sprintf( 'Skipping to wp_remote_get() as transient "%s" already exist. Usually it means that no request was returned yet', $transient_string ) );
100
-
101
  return false;
102
  }
103
-
104
  set_transient( $transient_string, 1 );
105
-
106
  $url = $this->_api_url . 'v1/image/convert?';
107
-
108
  $url .= http_build_query( [ 'format' => 'webp' ] );
109
-
110
  /**
111
  * @var RIOP_WebP_Extra_Data $extra_data
112
  */
113
  $extra_data = $model->get_extra_data();
114
-
115
  $multipartBoundary = '--------------------------' . microtime( true );
116
-
117
  $file_contents = file_get_contents( $extra_data->get_source_path() );
118
-
119
  $body = "--" . $multipartBoundary . "\r\n" . "Content-Disposition: form-data; name=\"file\"; filename=\"" . basename( $extra_data->get_source_path() ) . "\"\r\n" . "Content-Type: " . $model->get_original_mime_type() . "\r\n\r\n" . $file_contents . "\r\n";
120
-
121
  $body .= "--" . $multipartBoundary . "--\r\n";
122
-
123
  $headers = [
124
  // should be base64 encoded, otherwise API would fail authentication
125
  'Authorization' => 'Bearer ' . base64_encode( wrio_get_license_key() ),
126
  'PluginId' => wrio_get_freemius_plugin_id(),
127
  'Content-Type' => 'multipart/form-data; boundary=' . $multipartBoundary,
128
  ];
129
-
130
  $response = wp_remote_post( $url, [
131
  'timeout' => 60,
132
  'headers' => $headers,
133
  'body' => $body,
134
  ] );
135
-
136
  delete_transient( $transient_string );
137
-
138
  return $response;
139
  }
140
-
141
  /**
142
  * Process response from API.
143
  *
@@ -148,55 +153,55 @@
148
  public function can_save( $response ) {
149
  \WRIO_Logger::info( 'WebP convertation: Checks to save a webp by response.' );
150
  //\WRIO_Logger::debug( var_export( $response, true ) );
151
-
152
  if ( is_wp_error( $response ) ) {
153
  WRIO_Logger::error( sprintf( 'Error response from API. Code: %s, error: %s', $response->get_error_code(), $response->get_error_message() ) );
154
-
155
  return false;
156
  }
157
-
158
  if ( false === $response ) {
159
  WRIO_Logger::error( 'Unknown response returned from API or it was not requested, failing to process response' );
160
-
161
  return false;
162
  }
163
-
164
  $content_disposition = wp_remote_retrieve_header( $response, 'content-disposition' );
165
-
166
  if ( 0 === strpos( $content_disposition, 'attachment;' ) ) {
167
-
168
  $body = wp_remote_retrieve_body( $response );
169
-
170
  if ( empty( $body ) ) {
171
  WRIO_Logger::error( 'Response returned content-disposition header as "attachment;", but empty body returned, failing to proceed' );
172
-
173
  return false;
174
  }
175
-
176
  \WRIO_Logger::info( 'WebP convertation: Image can be saved. ' );
177
-
178
  return true;
179
  }
180
-
181
  $response_text = wp_remote_retrieve_body( $response );
182
-
183
  if ( ! empty( $response_text ) ) {
184
  $response_json = json_decode( $response_text );
185
-
186
  if ( ! empty( $response_json ) ) {
187
  if ( isset( $response_json->error ) && ! empty( $response_json->error ) ) {
188
  WRIO_Logger::error( sprintf( 'Unable to convert attachment as API returned error: "%s"', $response_json->error ) );
189
  }
190
-
191
  if ( isset( $response_json->status ) && 401 === (int) $response_json->status ) {
192
  WRIO_Logger::error( sprintf( 'Error response from API. Code: %s, error: %s', $response_json->message, $response_json->code ) );
193
  }
194
  }
195
  }
196
-
197
  return false;
198
  }
199
-
200
  /**
201
  * Save file from response.
202
  *
@@ -210,36 +215,36 @@
210
  *
211
  */
212
  public function save_file( $response, $queue_model ) {
213
-
214
  try {
215
  $save_path = static::get_save_path( $queue_model );
216
  } catch( \Exception $exception ) {
217
  WRIO_Logger::error( sprintf( 'Unable to process response failed to get save path: "%s"', $exception->getMessage() ) );
218
-
219
  return false;
220
  }
221
-
222
  \WRIO_Logger::info( sprintf( 'WebP convertation: Try to save webp image in %s.', $save_path ) );
223
-
224
  $body = wp_remote_retrieve_body( $response );
225
-
226
  $file_saved = @file_put_contents( $save_path, $body );
227
-
228
  if ( ! $file_saved ) {
229
  /**
230
  * @var $http_response WP_HTTP_Requests_Response
231
  */
232
  $http_response = $response['http_response'];
233
  WRIO_Logger::error( sprintf( 'Failed to save file "%s" under %s with file_put_contents()', $save_path, $http_response->get_response_object()->url ) );
234
-
235
  return false;
236
  }
237
-
238
  \WRIO_Logger::info( 'WebP convertation: Image saved successfully!' );
239
-
240
  return true;
241
  }
242
-
243
  /**
244
  * Update processing item data to finish its cycle.
245
  *
@@ -248,27 +253,27 @@
248
  * @return bool
249
  */
250
  public function update( $queue_model ) {
251
-
252
  try {
253
  $save_path = static::get_save_path( $queue_model );
254
  } catch( \Exception $exception ) {
255
  WRIO_Logger::error( sprintf( 'Unable to update queue model #%s as of exception: %s', $queue_model->get_id(), $exception->getMessage() ) );
256
-
257
  return false;
258
  }
259
-
260
  $queue_model->result_status = RIO_Process_Queue::STATUS_SUCCESS;
261
  $queue_model->final_size = filesize( $save_path );
262
-
263
  /**
264
  * @var RIOP_WebP_Extra_Data $updated_extra_data
265
  */
266
  $updated_extra_data = $queue_model->get_extra_data();
267
  $updated_extra_data->set_converted_src( $this->get_save_url( $queue_model ) );
268
  $updated_extra_data->set_converted_path( $save_path );
269
-
270
  $queue_model->extra_data = $updated_extra_data;
271
-
272
  /**
273
  * Хук срабатывает после успешной конвертации в WebP
274
  *
@@ -278,10 +283,10 @@
278
  *
279
  */
280
  do_action( 'wbcr/rio/webp_success', $queue_model );
281
-
282
  return $queue_model->save();
283
  }
284
-
285
  /**
286
  * Get complete save url.
287
  *
@@ -294,19 +299,19 @@
294
  * @var $extra_data RIOP_WebP_Extra_Data
295
  */
296
  $extra_data = $queue_model->get_extra_data();
297
-
298
  if ( empty( $extra_data ) ) {
299
  WRIO_Logger::error( sprintf( 'Unable to get extra data for queue item #%s', $queue_model->get_id() ) );
300
-
301
  return null;
302
  }
303
-
304
  $origin_file_name = wp_basename( $extra_data->get_source_src() );
305
  $webp_file_name = trim( wp_basename( $extra_data->get_source_path() ) ) . '.webp';
306
-
307
  return str_replace( $origin_file_name, $webp_file_name, $extra_data->get_source_src() );
308
  }
309
-
310
  /**
311
  * Get absolute save path.
312
  *
@@ -320,22 +325,22 @@
320
  * @var $extra_data RIOP_WebP_Extra_Data
321
  */
322
  $extra_data = $queue_model->get_extra_data();
323
-
324
  if ( empty( $extra_data ) ) {
325
  WRIO_Logger::error( sprintf( 'Unable to get extra data for queue item #%s', $queue_model->get_id() ) );
326
-
327
  return null;
328
  }
329
-
330
  $path = dirname( $extra_data->get_source_path() );
331
-
332
  // Create DIR when does not exist
333
  if ( ! file_exists( $path ) ) {
334
  $message = sprintf( 'Failed to create directory %s with mode %s recursively', $path, 0755 );
335
  WRIO_Logger::error( $message );
336
  throw new \Exception( $message );
337
  }
338
-
339
  return trailingslashit( $path ) . trim( wp_basename( $extra_data->get_source_path() ) ) . '.webp';
340
  }
341
  }
1
  <?php
2
+
3
  /**
4
  * Class WRIO_WebP_Api processing images from processing queue, sends them to API and saves locally.
5
  *
6
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
7
  */
8
  class WRIO_WebP_Api {
9
+
10
  /**
11
  * @var string API url.
12
  */
13
  //private $_api_url = 'http://142.93.91.206/';
14
  private $_api_url = 'https://dashboard.robinoptimizer.com/';
15
+
 
16
  /**
17
  * @var int|null Attachment ID.
18
  */
19
  private $_models = null;
20
+
21
  /**
22
  * @var null|int UNIX epoch when last request was processed.
23
  */
24
  private $_last_request_tick = null;
25
+
26
+
27
  /**
28
  * WRIO_WebP_Api constructor.
29
  *
32
  public function __construct( $model ) {
33
  $this->_models = $model;
34
  }
35
+
36
  /**
37
  * Process image queue based on provided attachment ID.
38
  *
43
  * @return bool true on success execution, false on failure or missing item in queue.
44
  */
45
  public function process_image_queue() {
46
+
47
  foreach ( $this->_models as $model ) {
48
  /**
49
  * @var RIOP_WebP_Extra_Data $extra_data
50
  */
51
  $extra_data = $model->get_extra_data();
52
+
53
  if ( $extra_data === null ) {
54
  continue;
55
  }
56
+
57
  $response = $this->request( $model );
58
+
59
  if ( $this->can_save( $response ) && $this->save_file( $response, $model ) ) {
60
  $this->update( $model );
61
  }
62
  }
63
+
64
  return true;
65
  }
66
+
67
  /**
68
  * Request API
69
  *
72
  * @return array|bool|WP_Error
73
  */
74
  public function request( $model ) {
75
+
76
  if ( $this->_last_request_tick === null ) {
77
  $this->_last_request_tick = time();
78
  } else {
80
  // Need to have some rest before calling REST :D to comply with API request limit
81
  sleep( 2 );
82
  }
83
+
84
  $this->_last_request_tick = time();
85
  }
86
+
87
+ $optimization_server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' );
88
+ if($optimization_server !== 'server_5') {
89
+ WRIO_Logger::warning( 'To use webp compression you need to switch to using a premium server' );
90
+ return false;
91
+ }
92
+
93
  if ( ! wrio_is_license_activate() ) {
94
  WRIO_Logger::error( "Unable to get license to make proper request to the API" );
95
+
96
  return false;
97
  }
98
+
99
  $transient_string = md5( WRIO_Plugin::app()->getPrefix() . '_processing_image' . $model->get_item_hash() );
100
+
101
  $transient_value = get_transient( $transient_string );
102
+
103
  if ( is_numeric( $transient_value ) && (int) $transient_value === 1 ) {
104
  WRIO_Logger::info( sprintf( 'Skipping to wp_remote_get() as transient "%s" already exist. Usually it means that no request was returned yet', $transient_string ) );
105
+
106
  return false;
107
  }
108
+
109
  set_transient( $transient_string, 1 );
110
+
111
  $url = $this->_api_url . 'v1/image/convert?';
112
+
113
  $url .= http_build_query( [ 'format' => 'webp' ] );
114
+
115
  /**
116
  * @var RIOP_WebP_Extra_Data $extra_data
117
  */
118
  $extra_data = $model->get_extra_data();
119
+
120
  $multipartBoundary = '--------------------------' . microtime( true );
121
+
122
  $file_contents = file_get_contents( $extra_data->get_source_path() );
123
+
124
  $body = "--" . $multipartBoundary . "\r\n" . "Content-Disposition: form-data; name=\"file\"; filename=\"" . basename( $extra_data->get_source_path() ) . "\"\r\n" . "Content-Type: " . $model->get_original_mime_type() . "\r\n\r\n" . $file_contents . "\r\n";
125
+
126
  $body .= "--" . $multipartBoundary . "--\r\n";
127
+
128
  $headers = [
129
  // should be base64 encoded, otherwise API would fail authentication
130
  'Authorization' => 'Bearer ' . base64_encode( wrio_get_license_key() ),
131
  'PluginId' => wrio_get_freemius_plugin_id(),
132
  'Content-Type' => 'multipart/form-data; boundary=' . $multipartBoundary,
133
  ];
134
+
135
  $response = wp_remote_post( $url, [
136
  'timeout' => 60,
137
  'headers' => $headers,
138
  'body' => $body,
139
  ] );
140
+
141
  delete_transient( $transient_string );
142
+
143
  return $response;
144
  }
145
+
146
  /**
147
  * Process response from API.
148
  *
153
  public function can_save( $response ) {
154
  \WRIO_Logger::info( 'WebP convertation: Checks to save a webp by response.' );
155
  //\WRIO_Logger::debug( var_export( $response, true ) );
156
+
157
  if ( is_wp_error( $response ) ) {
158
  WRIO_Logger::error( sprintf( 'Error response from API. Code: %s, error: %s', $response->get_error_code(), $response->get_error_message() ) );
159
+
160
  return false;
161
  }
162
+
163
  if ( false === $response ) {
164
  WRIO_Logger::error( 'Unknown response returned from API or it was not requested, failing to process response' );
165
+
166
  return false;
167
  }
168
+
169
  $content_disposition = wp_remote_retrieve_header( $response, 'content-disposition' );
170
+
171
  if ( 0 === strpos( $content_disposition, 'attachment;' ) ) {
172
+
173
  $body = wp_remote_retrieve_body( $response );
174
+
175
  if ( empty( $body ) ) {
176
  WRIO_Logger::error( 'Response returned content-disposition header as "attachment;", but empty body returned, failing to proceed' );
177
+
178
  return false;
179
  }
180
+
181
  \WRIO_Logger::info( 'WebP convertation: Image can be saved. ' );
182
+
183
  return true;
184
  }
185
+
186
  $response_text = wp_remote_retrieve_body( $response );
187
+
188
  if ( ! empty( $response_text ) ) {
189
  $response_json = json_decode( $response_text );
190
+
191
  if ( ! empty( $response_json ) ) {
192
  if ( isset( $response_json->error ) && ! empty( $response_json->error ) ) {
193
  WRIO_Logger::error( sprintf( 'Unable to convert attachment as API returned error: "%s"', $response_json->error ) );
194
  }
195
+
196
  if ( isset( $response_json->status ) && 401 === (int) $response_json->status ) {
197
  WRIO_Logger::error( sprintf( 'Error response from API. Code: %s, error: %s', $response_json->message, $response_json->code ) );
198
  }
199
  }
200
  }
201
+
202
  return false;
203
  }
204
+
205
  /**
206
  * Save file from response.
207
  *
215
  *
216
  */
217
  public function save_file( $response, $queue_model ) {
218
+
219
  try {
220
  $save_path = static::get_save_path( $queue_model );
221
  } catch( \Exception $exception ) {
222
  WRIO_Logger::error( sprintf( 'Unable to process response failed to get save path: "%s"', $exception->getMessage() ) );
223
+
224
  return false;
225
  }
226
+
227
  \WRIO_Logger::info( sprintf( 'WebP convertation: Try to save webp image in %s.', $save_path ) );
228
+
229
  $body = wp_remote_retrieve_body( $response );
230
+
231
  $file_saved = @file_put_contents( $save_path, $body );
232
+
233
  if ( ! $file_saved ) {
234
  /**
235
  * @var $http_response WP_HTTP_Requests_Response
236
  */
237
  $http_response = $response['http_response'];
238
  WRIO_Logger::error( sprintf( 'Failed to save file "%s" under %s with file_put_contents()', $save_path, $http_response->get_response_object()->url ) );
239
+
240
  return false;
241
  }
242
+
243
  \WRIO_Logger::info( 'WebP convertation: Image saved successfully!' );
244
+
245
  return true;
246
  }
247
+
248
  /**
249
  * Update processing item data to finish its cycle.
250
  *
253
  * @return bool
254
  */
255
  public function update( $queue_model ) {
256
+
257
  try {
258
  $save_path = static::get_save_path( $queue_model );
259
  } catch( \Exception $exception ) {
260
  WRIO_Logger::error( sprintf( 'Unable to update queue model #%s as of exception: %s', $queue_model->get_id(), $exception->getMessage() ) );
261
+
262
  return false;
263
  }
264
+
265
  $queue_model->result_status = RIO_Process_Queue::STATUS_SUCCESS;
266
  $queue_model->final_size = filesize( $save_path );
267
+
268
  /**
269
  * @var RIOP_WebP_Extra_Data $updated_extra_data
270
  */
271
  $updated_extra_data = $queue_model->get_extra_data();
272
  $updated_extra_data->set_converted_src( $this->get_save_url( $queue_model ) );
273
  $updated_extra_data->set_converted_path( $save_path );
274
+
275
  $queue_model->extra_data = $updated_extra_data;
276
+
277
  /**
278
  * Хук срабатывает после успешной конвертации в WebP
279
  *
283
  *
284
  */
285
  do_action( 'wbcr/rio/webp_success', $queue_model );
286
+
287
  return $queue_model->save();
288
  }
289
+
290
  /**
291
  * Get complete save url.
292
  *
299
  * @var $extra_data RIOP_WebP_Extra_Data
300
  */
301
  $extra_data = $queue_model->get_extra_data();
302
+
303
  if ( empty( $extra_data ) ) {
304
  WRIO_Logger::error( sprintf( 'Unable to get extra data for queue item #%s', $queue_model->get_id() ) );
305
+
306
  return null;
307
  }
308
+
309
  $origin_file_name = wp_basename( $extra_data->get_source_src() );
310
  $webp_file_name = trim( wp_basename( $extra_data->get_source_path() ) ) . '.webp';
311
+
312
  return str_replace( $origin_file_name, $webp_file_name, $extra_data->get_source_src() );
313
  }
314
+
315
  /**
316
  * Get absolute save path.
317
  *
325
  * @var $extra_data RIOP_WebP_Extra_Data
326
  */
327
  $extra_data = $queue_model->get_extra_data();
328
+
329
  if ( empty( $extra_data ) ) {
330
  WRIO_Logger::error( sprintf( 'Unable to get extra data for queue item #%s', $queue_model->get_id() ) );
331
+
332
  return null;
333
  }
334
+
335
  $path = dirname( $extra_data->get_source_path() );
336
+
337
  // Create DIR when does not exist
338
  if ( ! file_exists( $path ) ) {
339
  $message = sprintf( 'Failed to create directory %s with mode %s recursively', $path, 0755 );
340
  WRIO_Logger::error( $message );
341
  throw new \Exception( $message );
342
  }
343
+
344
  return trailingslashit( $path ) . trim( wp_basename( $extra_data->get_source_path() ) ) . '.webp';
345
  }
346
  }
libs/addons/includes/classes/webp/vendor/autoload.php CHANGED
@@ -1,7 +1,7 @@
1
- <?php
2
-
3
- // autoload.php @generated by Composer
4
-
5
- require_once __DIR__ . '/composer/autoload_real.php';
6
-
7
- return ComposerAutoloaderInit72ef64d1632393e46c77b12f00f8e9be::getLoader();
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit84320a6a225dd65e40820c51b32fdca4::getLoader();
libs/addons/includes/classes/webp/vendor/composer/ClassLoader.php CHANGED
@@ -1,445 +1,445 @@
1
- <?php
2
-
3
- /*
4
- * This file is part of Composer.
5
- *
6
- * (c) Nils Adermann <naderman@naderman.de>
7
- * Jordi Boggiano <j.boggiano@seld.be>
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
-
13
- namespace Composer\Autoload;
14
-
15
- /**
16
- * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
- *
18
- * $loader = new \Composer\Autoload\ClassLoader();
19
- *
20
- * // register classes with namespaces
21
- * $loader->add('Symfony\Component', __DIR__.'/component');
22
- * $loader->add('Symfony', __DIR__.'/framework');
23
- *
24
- * // activate the autoloader
25
- * $loader->register();
26
- *
27
- * // to enable searching the include path (eg. for PEAR packages)
28
- * $loader->setUseIncludePath(true);
29
- *
30
- * In this example, if you try to use a class in the Symfony\Component
31
- * namespace or one of its children (Symfony\Component\Console for instance),
32
- * the autoloader will first look for the class under the component/
33
- * directory, and it will then fallback to the framework/ directory if not
34
- * found before giving up.
35
- *
36
- * This class is loosely based on the Symfony UniversalClassLoader.
37
- *
38
- * @author Fabien Potencier <fabien@symfony.com>
39
- * @author Jordi Boggiano <j.boggiano@seld.be>
40
- * @see http://www.php-fig.org/psr/psr-0/
41
- * @see http://www.php-fig.org/psr/psr-4/
42
- */
43
- class ClassLoader
44
- {
45
- // PSR-4
46
- private $prefixLengthsPsr4 = array();
47
- private $prefixDirsPsr4 = array();
48
- private $fallbackDirsPsr4 = array();
49
-
50
- // PSR-0
51
- private $prefixesPsr0 = array();
52
- private $fallbackDirsPsr0 = array();
53
-
54
- private $useIncludePath = false;
55
- private $classMap = array();
56
- private $classMapAuthoritative = false;
57
- private $missingClasses = array();
58
- private $apcuPrefix;
59
-
60
- public function getPrefixes()
61
- {
62
- if (!empty($this->prefixesPsr0)) {
63
- return call_user_func_array('array_merge', $this->prefixesPsr0);
64
- }
65
-
66
- return array();
67
- }
68
-
69
- public function getPrefixesPsr4()
70
- {
71
- return $this->prefixDirsPsr4;
72
- }
73
-
74
- public function getFallbackDirs()
75
- {
76
- return $this->fallbackDirsPsr0;
77
- }
78
-
79
- public function getFallbackDirsPsr4()
80
- {
81
- return $this->fallbackDirsPsr4;
82
- }
83
-
84
- public function getClassMap()
85
- {
86
- return $this->classMap;
87
- }
88
-
89
- /**
90
- * @param array $classMap Class to filename map
91
- */
92
- public function addClassMap(array $classMap)
93
- {
94
- if ($this->classMap) {
95
- $this->classMap = array_merge($this->classMap, $classMap);
96
- } else {
97
- $this->classMap = $classMap;
98
- }
99
- }
100
-
101
- /**
102
- * Registers a set of PSR-0 directories for a given prefix, either
103
- * appending or prepending to the ones previously set for this prefix.
104
- *
105
- * @param string $prefix The prefix
106
- * @param array|string $paths The PSR-0 root directories
107
- * @param bool $prepend Whether to prepend the directories
108
- */
109
- public function add($prefix, $paths, $prepend = false)
110
- {
111
- if (!$prefix) {
112
- if ($prepend) {
113
- $this->fallbackDirsPsr0 = array_merge(
114
- (array) $paths,
115
- $this->fallbackDirsPsr0
116
- );
117
- } else {
118
- $this->fallbackDirsPsr0 = array_merge(
119
- $this->fallbackDirsPsr0,
120
- (array) $paths
121
- );
122
- }
123
-
124
- return;
125
- }
126
-
127
- $first = $prefix[0];
128
- if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
-
131
- return;
132
- }
133
- if ($prepend) {
134
- $this->prefixesPsr0[$first][$prefix] = array_merge(
135
- (array) $paths,
136
- $this->prefixesPsr0[$first][$prefix]
137
- );
138
- } else {
139
- $this->prefixesPsr0[$first][$prefix] = array_merge(
140
- $this->prefixesPsr0[$first][$prefix],
141
- (array) $paths
142
- );
143
- }
144
- }
145
-
146
- /**
147
- * Registers a set of PSR-4 directories for a given namespace, either
148
- * appending or prepending to the ones previously set for this namespace.
149
- *
150
- * @param string $prefix The prefix/namespace, with trailing '\\'
151
- * @param array|string $paths The PSR-4 base directories
152
- * @param bool $prepend Whether to prepend the directories
153
- *
154
- * @throws \InvalidArgumentException
155
- */
156
- public function addPsr4($prefix, $paths, $prepend = false)
157
- {
158
- if (!$prefix) {
159
- // Register directories for the root namespace.
160
- if ($prepend) {
161
- $this->fallbackDirsPsr4 = array_merge(
162
- (array) $paths,
163
- $this->fallbackDirsPsr4
164
- );
165
- } else {
166
- $this->fallbackDirsPsr4 = array_merge(
167
- $this->fallbackDirsPsr4,
168
- (array) $paths
169
- );
170
- }
171
- } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
- // Register directories for a new namespace.
173
- $length = strlen($prefix);
174
- if ('\\' !== $prefix[$length - 1]) {
175
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
- }
177
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
- } elseif ($prepend) {
180
- // Prepend directories for an already registered namespace.
181
- $this->prefixDirsPsr4[$prefix] = array_merge(
182
- (array) $paths,
183
- $this->prefixDirsPsr4[$prefix]
184
- );
185
- } else {
186
- // Append directories for an already registered namespace.
187
- $this->prefixDirsPsr4[$prefix] = array_merge(
188
- $this->prefixDirsPsr4[$prefix],
189
- (array) $paths
190
- );
191
- }
192
- }
193
-
194
- /**
195
- * Registers a set of PSR-0 directories for a given prefix,
196
- * replacing any others previously set for this prefix.
197
- *
198
- * @param string $prefix The prefix
199
- * @param array|string $paths The PSR-0 base directories
200
- */
201
- public function set($prefix, $paths)
202
- {
203
- if (!$prefix) {
204
- $this->fallbackDirsPsr0 = (array) $paths;
205
- } else {
206
- $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
- }
208
- }
209
-
210
- /**
211
- * Registers a set of PSR-4 directories for a given namespace,
212
- * replacing any others previously set for this namespace.
213
- *
214
- * @param string $prefix The prefix/namespace, with trailing '\\'
215
- * @param array|string $paths The PSR-4 base directories
216
- *
217
- * @throws \InvalidArgumentException
218
- */
219
- public function setPsr4($prefix, $paths)
220
- {
221
- if (!$prefix) {
222
- $this->fallbackDirsPsr4 = (array) $paths;
223
- } else {
224
- $length = strlen($prefix);
225
- if ('\\' !== $prefix[$length - 1]) {
226
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
- }
228
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
- }
231
- }
232
-
233
- /**
234
- * Turns on searching the include path for class files.
235
- *
236
- * @param bool $useIncludePath
237
- */
238
- public function setUseIncludePath($useIncludePath)
239
- {
240
- $this->useIncludePath = $useIncludePath;
241
- }
242
-
243
- /**
244
- * Can be used to check if the autoloader uses the include path to check
245
- * for classes.
246
- *
247
- * @return bool
248
- */
249
- public function getUseIncludePath()
250
- {
251
- return $this->useIncludePath;
252
- }
253
-
254
- /**
255
- * Turns off searching the prefix and fallback directories for classes
256
- * that have not been registered with the class map.
257
- *
258
- * @param bool $classMapAuthoritative
259
- */
260
- public function setClassMapAuthoritative($classMapAuthoritative)
261
- {
262
- $this->classMapAuthoritative = $classMapAuthoritative;
263
- }
264
-
265
- /**
266
- * Should class lookup fail if not found in the current class map?
267
- *
268
- * @return bool
269
- */
270
- public function isClassMapAuthoritative()
271
- {
272
- return $this->classMapAuthoritative;
273
- }
274
-
275
- /**
276
- * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
- *
278
- * @param string|null $apcuPrefix
279
- */
280
- public function setApcuPrefix($apcuPrefix)
281
- {
282
- $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
- }
284
-
285
- /**
286
- * The APCu prefix in use, or null if APCu caching is not enabled.
287
- *
288
- * @return string|null
289
- */
290
- public function getApcuPrefix()
291
- {
292
- return $this->apcuPrefix;
293
- }
294
-
295
- /**
296
- * Registers this instance as an autoloader.
297
- *
298
- * @param bool $prepend Whether to prepend the autoloader or not
299
- */
300
- public function register($prepend = false)
301
- {
302
- spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
- }
304
-
305
- /**
306
- * Unregisters this instance as an autoloader.
307
- */
308
- public function unregister()
309
- {
310
- spl_autoload_unregister(array($this, 'loadClass'));
311
- }
312
-
313
- /**
314
- * Loads the given class or interface.
315
- *
316
- * @param string $class The name of the class
317
- * @return bool|null True if loaded, null otherwise
318
- */
319
- public function loadClass($class)
320
- {
321
- if ($file = $this->findFile($class)) {
322
- includeFile($file);
323
-
324
- return true;
325
- }
326
- }
327
-
328
- /**
329
- * Finds the path to the file where the class is defined.
330
- *
331
- * @param string $class The name of the class
332
- *
333
- * @return string|false The path if found, false otherwise
334
- */
335
- public function findFile($class)
336
- {
337
- // class map lookup
338
- if (isset($this->classMap[$class])) {
339
- return $this->classMap[$class];
340
- }
341
- if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
- return false;
343
- }
344
- if (null !== $this->apcuPrefix) {
345
- $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
- if ($hit) {
347
- return $file;
348
- }
349
- }
350
-
351
- $file = $this->findFileWithExtension($class, '.php');
352
-
353
- // Search for Hack files if we are running on HHVM
354
- if (false === $file && defined('HHVM_VERSION')) {
355
- $file = $this->findFileWithExtension($class, '.hh');
356
- }
357
-
358
- if (null !== $this->apcuPrefix) {
359
- apcu_add($this->apcuPrefix.$class, $file);
360
- }
361
-
362
- if (false === $file) {
363
- // Remember that this class does not exist.
364
- $this->missingClasses[$class] = true;
365
- }
366
-
367
- return $file;
368
- }
369
-
370
- private function findFileWithExtension($class, $ext)
371
- {
372
- // PSR-4 lookup
373
- $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
-
375
- $first = $class[0];
376
- if (isset($this->prefixLengthsPsr4[$first])) {
377
- $subPath = $class;
378
- while (false !== $lastPos = strrpos($subPath, '\\')) {
379
- $subPath = substr($subPath, 0, $lastPos);
380
- $search = $subPath . '\\';
381
- if (isset($this->prefixDirsPsr4[$search])) {
382
- $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
- foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
- if (file_exists($file = $dir . $pathEnd)) {
385
- return $file;
386
- }
387
- }
388
- }
389
- }
390
- }
391
-
392
- // PSR-4 fallback dirs
393
- foreach ($this->fallbackDirsPsr4 as $dir) {
394
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
- return $file;
396
- }
397
- }
398
-
399
- // PSR-0 lookup
400
- if (false !== $pos = strrpos($class, '\\')) {
401
- // namespaced class name
402
- $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
- . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
- } else {
405
- // PEAR-like class name
406
- $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
- }
408
-
409
- if (isset($this->prefixesPsr0[$first])) {
410
- foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
- if (0 === strpos($class, $prefix)) {
412
- foreach ($dirs as $dir) {
413
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
- return $file;
415
- }
416
- }
417
- }
418
- }
419
- }
420
-
421
- // PSR-0 fallback dirs
422
- foreach ($this->fallbackDirsPsr0 as $dir) {
423
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
- return $file;
425
- }
426
- }
427
-
428
- // PSR-0 include paths.
429
- if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
- return $file;
431
- }
432
-
433
- return false;
434
- }
435
- }
436
-
437
- /**
438
- * Scope isolated include.
439
- *
440
- * Prevents access to $this/self from included files.
441
- */
442
- function includeFile($file)
443
- {
444
- include $file;
445
- }
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see https://www.php-fig.org/psr/psr-0/
41
+ * @see https://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath . '\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
libs/addons/includes/classes/webp/vendor/composer/InstalledVersions.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer;
4
+
5
+ use Composer\Semver\VersionParser;
6
+
7
+
8
+
9
+
10
+
11
+
12
+ class InstalledVersions
13
+ {
14
+ private static $installed = array (
15
+ 'root' =>
16
+ array (
17
+ 'pretty_version' => 'dev-master',
18
+ 'version' => 'dev-master',
19
+ 'aliases' =>
20
+ array (
21
+ 0 => '9999999-dev',
22
+ ),
23
+ 'reference' => '3d4062ddde198994093315acc55c6232067ce027',
24
+ 'name' => '__root__',
25
+ ),
26
+ 'versions' =>
27
+ array (
28
+ '__root__' =>
29
+ array (
30
+ 'pretty_version' => 'dev-master',
31
+ 'version' => 'dev-master',
32
+ 'aliases' =>
33
+ array (
34
+ 0 => '9999999-dev',
35
+ ),
36
+ 'reference' => '3d4062ddde198994093315acc55c6232067ce027',
37
+ ),
38
+ 'rosell-dk/dom-util-for-webp' =>
39
+ array (
40
+ 'pretty_version' => '0.3.1',
41
+ 'version' => '0.3.1.0',
42
+ 'aliases' =>
43
+ array (
44
+ ),
45
+ 'reference' => 'bae8f4a9b666726359d28bfb227d886c12f136a9',
46
+ ),
47
+ ),
48
+ );
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+ public static function getInstalledPackages()
57
+ {
58
+ return array_keys(self::$installed['versions']);
59
+ }
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+ public static function isInstalled($packageName)
70
+ {
71
+ return isset(self::$installed['versions'][$packageName]);
72
+ }
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
88
+ {
89
+ $constraint = $parser->parseConstraints($constraint);
90
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
91
+
92
+ return $provided->matches($constraint);
93
+ }
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+ public static function getVersionRanges($packageName)
105
+ {
106
+ if (!isset(self::$installed['versions'][$packageName])) {
107
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
108
+ }
109
+
110
+ $ranges = array();
111
+ if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
112
+ $ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
113
+ }
114
+ if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
115
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
116
+ }
117
+ if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
118
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
119
+ }
120
+ if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
121
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
122
+ }
123
+
124
+ return implode(' || ', $ranges);
125
+ }
126
+
127
+
128
+
129
+
130
+
131
+ public static function getVersion($packageName)
132
+ {
133
+ if (!isset(self::$installed['versions'][$packageName])) {
134
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
135
+ }
136
+
137
+ if (!isset(self::$installed['versions'][$packageName]['version'])) {
138
+ return null;
139
+ }
140
+
141
+ return self::$installed['versions'][$packageName]['version'];
142
+ }
143
+
144
+
145
+
146
+
147
+
148
+ public static function getPrettyVersion($packageName)
149
+ {
150
+ if (!isset(self::$installed['versions'][$packageName])) {
151
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
152
+ }
153
+
154
+ if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
155
+ return null;
156
+ }
157
+
158
+ return self::$installed['versions'][$packageName]['pretty_version'];
159
+ }
160
+
161
+
162
+
163
+
164
+
165
+ public static function getReference($packageName)
166
+ {
167
+ if (!isset(self::$installed['versions'][$packageName])) {
168
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
169
+ }
170
+
171
+ if (!isset(self::$installed['versions'][$packageName]['reference'])) {
172
+ return null;
173
+ }
174
+
175
+ return self::$installed['versions'][$packageName]['reference'];
176
+ }
177
+
178
+
179
+
180
+
181
+
182
+ public static function getRootPackage()
183
+ {
184
+ return self::$installed['root'];
185
+ }
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+ public static function getRawData()
194
+ {
195
+ return self::$installed;
196
+ }
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+ public static function reload($data)
217
+ {
218
+ self::$installed = $data;
219
+ }
220
+ }
libs/addons/includes/classes/webp/vendor/composer/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
-
2
- Copyright (c) Nils Adermann, Jordi Boggiano
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy
5
- of this software and associated documentation files (the "Software"), to deal
6
- in the Software without restriction, including without limitation the rights
7
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the Software is furnished
9
- to do so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- THE SOFTWARE.
21
-
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
libs/addons/includes/classes/webp/vendor/composer/autoload_classmap.php CHANGED
@@ -1,9 +1,10 @@
1
- <?php
2
-
3
- // autoload_classmap.php @generated by Composer
4
-
5
- $vendorDir = dirname(dirname(__FILE__));
6
- $baseDir = dirname($vendorDir);
7
-
8
- return array(
9
- );
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
+ );
libs/addons/includes/classes/webp/vendor/composer/autoload_namespaces.php CHANGED
@@ -1,9 +1,9 @@
1
- <?php
2
-
3
- // autoload_namespaces.php @generated by Composer
4
-
5
- $vendorDir = dirname(dirname(__FILE__));
6
- $baseDir = dirname($vendorDir);
7
-
8
- return array(
9
- );
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
libs/addons/includes/classes/webp/vendor/composer/autoload_psr4.php CHANGED
@@ -1,10 +1,10 @@
1
- <?php
2
-
3
- // autoload_psr4.php @generated by Composer
4
-
5
- $vendorDir = dirname(dirname(__FILE__));
6
- $baseDir = dirname($vendorDir);
7
-
8
- return array(
9
- 'DOMUtilForWebP\\' => array($vendorDir . '/rosell-dk/dom-util-for-webp/src'),
10
- );
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'DOMUtilForWebP\\' => array($vendorDir . '/rosell-dk/dom-util-for-webp/src'),
10
+ );
libs/addons/includes/classes/webp/vendor/composer/autoload_real.php CHANGED
@@ -1,52 +1,55 @@
1
- <?php
2
-
3
- // autoload_real.php @generated by Composer
4
-
5
- class ComposerAutoloaderInit72ef64d1632393e46c77b12f00f8e9be
6
- {
7
- private static $loader;
8
-
9
- public static function loadClassLoader($class)
10
- {
11
- if ('Composer\Autoload\ClassLoader' === $class) {
12
- require __DIR__ . '/ClassLoader.php';
13
- }
14
- }
15
-
16
- public static function getLoader()
17
- {
18
- if (null !== self::$loader) {
19
- return self::$loader;
20
- }
21
-
22
- spl_autoload_register(array('ComposerAutoloaderInit72ef64d1632393e46c77b12f00f8e9be', 'loadClassLoader'), true, true);
23
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit72ef64d1632393e46c77b12f00f8e9be', 'loadClassLoader'));
25
-
26
- $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
- if ($useStaticLoader) {
28
- require_once __DIR__ . '/autoload_static.php';
29
-
30
- call_user_func(\Composer\Autoload\ComposerStaticInit72ef64d1632393e46c77b12f00f8e9be::getInitializer($loader));
31
- } else {
32
- $map = require __DIR__ . '/autoload_namespaces.php';
33
- foreach ($map as $namespace => $path) {
34
- $loader->set($namespace, $path);
35
- }
36
-
37
- $map = require __DIR__ . '/autoload_psr4.php';
38
- foreach ($map as $namespace => $path) {
39
- $loader->setPsr4($namespace, $path);
40
- }
41
-
42
- $classMap = require __DIR__ . '/autoload_classmap.php';
43
- if ($classMap) {
44
- $loader->addClassMap($classMap);
45
- }
46
- }
47
-
48
- $loader->register(true);
49
-
50
- return $loader;
51
- }
52
- }
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit84320a6a225dd65e40820c51b32fdca4
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ spl_autoload_register(array('ComposerAutoloaderInit84320a6a225dd65e40820c51b32fdca4', 'loadClassLoader'), true, true);
26
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit84320a6a225dd65e40820c51b32fdca4', 'loadClassLoader'));
28
+
29
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
+ if ($useStaticLoader) {
31
+ require __DIR__ . '/autoload_static.php';
32
+
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit84320a6a225dd65e40820c51b32fdca4::getInitializer($loader));
34
+ } else {
35
+ $map = require __DIR__ . '/autoload_namespaces.php';
36
+ foreach ($map as $namespace => $path) {
37
+ $loader->set($namespace, $path);
38
+ }
39
+
40
+ $map = require __DIR__ . '/autoload_psr4.php';
41
+ foreach ($map as $namespace => $path) {
42
+ $loader->setPsr4($namespace, $path);
43
+ }
44
+
45
+ $classMap = require __DIR__ . '/autoload_classmap.php';
46
+ if ($classMap) {
47
+ $loader->addClassMap($classMap);
48
+ }
49
+ }
50
+
51
+ $loader->register(true);
52
+
53
+ return $loader;
54
+ }
55
+ }
libs/addons/includes/classes/webp/vendor/composer/autoload_static.php CHANGED
@@ -1,31 +1,36 @@
1
- <?php
2
-
3
- // autoload_static.php @generated by Composer
4
-
5
- namespace Composer\Autoload;
6
-
7
- class ComposerStaticInit72ef64d1632393e46c77b12f00f8e9be
8
- {
9
- public static $prefixLengthsPsr4 = array (
10
- 'D' =>
11
- array (
12
- 'DOMUtilForWebP\\' => 15,
13
- ),
14
- );
15
-
16
- public static $prefixDirsPsr4 = array (
17
- 'DOMUtilForWebP\\' =>
18
- array (
19
- 0 => __DIR__ . '/..' . '/rosell-dk/dom-util-for-webp/src',
20
- ),
21
- );
22
-
23
- public static function getInitializer(ClassLoader $loader)
24
- {
25
- return \Closure::bind(function () use ($loader) {
26
- $loader->prefixLengthsPsr4 = ComposerStaticInit72ef64d1632393e46c77b12f00f8e9be::$prefixLengthsPsr4;
27
- $loader->prefixDirsPsr4 = ComposerStaticInit72ef64d1632393e46c77b12f00f8e9be::$prefixDirsPsr4;
28
-
29
- }, null, ClassLoader::class);
30
- }
31
- }
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit84320a6a225dd65e40820c51b32fdca4
8
+ {
9
+ public static $prefixLengthsPsr4 = array (
10
+ 'D' =>
11
+ array (
12
+ 'DOMUtilForWebP\\' => 15,
13
+ ),
14
+ );
15
+
16
+ public static $prefixDirsPsr4 = array (
17
+ 'DOMUtilForWebP\\' =>
18
+ array (
19
+ 0 => __DIR__ . '/..' . '/rosell-dk/dom-util-for-webp/src',
20
+ ),
21
+ );
22
+
23
+ public static $classMap = array (
24
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
25
+ );
26
+
27
+ public static function getInitializer(ClassLoader $loader)
28
+ {
29
+ return \Closure::bind(function () use ($loader) {
30
+ $loader->prefixLengthsPsr4 = ComposerStaticInit84320a6a225dd65e40820c51b32fdca4::$prefixLengthsPsr4;
31
+ $loader->prefixDirsPsr4 = ComposerStaticInit84320a6a225dd65e40820c51b32fdca4::$prefixDirsPsr4;
32
+ $loader->classMap = ComposerStaticInit84320a6a225dd65e40820c51b32fdca4::$classMap;
33
+
34
+ }, null, ClassLoader::class);
35
+ }
36
+ }
libs/addons/includes/classes/webp/vendor/composer/installed.json CHANGED
@@ -1,59 +1,63 @@
1
- [
2
- {
3
- "name": "rosell-dk/dom-util-for-webp",
4
- "version": "0.3.1",
5
- "version_normalized": "0.3.1.0",
6
- "source": {
7
- "type": "git",
8
- "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
9
- "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9"
10
- },
11
- "dist": {
12
- "type": "zip",
13
- "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/bae8f4a9b666726359d28bfb227d886c12f136a9",
14
- "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9",
15
- "shasum": ""
16
- },
17
- "require-dev": {
18
- "friendsofphp/php-cs-fixer": "^2.11",
19
- "phpunit/phpunit": "5.7.27",
20
- "squizlabs/php_codesniffer": "3.*"
21
- },
22
- "time": "2019-07-31T14:17:18+00:00",
23
- "type": "library",
24
- "extra": {
25
- "scripts-descriptions": {
26
- "ci": "Run tests before CI",
27
- "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
28
- "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
29
- "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
30
- "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
31
- "test": "Launches the preconfigured PHPUnit"
32
- }
33
- },
34
- "installation-source": "dist",
35
- "autoload": {
36
- "psr-4": {
37
- "DOMUtilForWebP\\": "src/"
38
- }
39
- },
40
- "notification-url": "https://packagist.org/downloads/",
41
- "license": [
42
- "MIT"
43
- ],
44
- "authors": [
45
- {
46
- "name": "Bjørn Rosell",
47
- "homepage": "https://www.bitwise-it.dk/contact",
48
- "role": "Project Author"
49
- }
50
- ],
51
- "description": "Replace image URLs found in HTML",
52
- "keywords": [
53
- "Webp",
54
- "html",
55
- "images",
56
- "replace"
57
- ]
58
- }
59
- ]
 
 
 
 
1
+ {
2
+ "packages": [
3
+ {
4
+ "name": "rosell-dk/dom-util-for-webp",
5
+ "version": "0.3.1",
6
+ "version_normalized": "0.3.1.0",
7
+ "source": {
8
+ "type": "git",
9
+ "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
10
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9"
11
+ },
12
+ "dist": {
13
+ "type": "zip",
14
+ "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/bae8f4a9b666726359d28bfb227d886c12f136a9",
15
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9",
16
+ "shasum": ""
17
+ },
18
+ "require-dev": {
19
+ "friendsofphp/php-cs-fixer": "^2.11",
20
+ "phpunit/phpunit": "5.7.27",
21
+ "squizlabs/php_codesniffer": "3.*"
22
+ },
23
+ "time": "2019-07-31T14:17:18+00:00",
24
+ "type": "library",
25
+ "extra": {
26
+ "scripts-descriptions": {
27
+ "ci": "Run tests before CI",
28
+ "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
29
+ "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
30
+ "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
31
+ "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
32
+ "test": "Launches the preconfigured PHPUnit"
33
+ }
34
+ },
35
+ "installation-source": "dist",
36
+ "autoload": {
37
+ "psr-4": {
38
+ "DOMUtilForWebP\\": "src/"
39
+ }
40
+ },
41
+ "notification-url": "https://packagist.org/downloads/",
42
+ "license": [
43
+ "MIT"
44
+ ],
45
+ "authors": [
46
+ {
47
+ "name": "Bjørn Rosell",
48
+ "homepage": "https://www.bitwise-it.dk/contact",
49
+ "role": "Project Author"
50
+ }
51
+ ],
52
+ "description": "Replace image URLs found in HTML",
53
+ "keywords": [
54
+ "Webp",
55
+ "html",
56
+ "images",
57
+ "replace"
58
+ ],
59
+ "install-path": "../rosell-dk/dom-util-for-webp"
60
+ }
61
+ ],
62
+ "dev": true
63
+ }
libs/addons/includes/classes/webp/vendor/composer/installed.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php return array (
2
+ 'root' =>
3
+ array (
4
+ 'pretty_version' => 'dev-master',
5
+ 'version' => 'dev-master',
6
+ 'aliases' =>
7
+ array (
8
+ 0 => '9999999-dev',
9
+ ),
10
+ 'reference' => '3d4062ddde198994093315acc55c6232067ce027',
11
+ 'name' => '__root__',
12
+ ),
13
+ 'versions' =>
14
+ array (
15
+ '__root__' =>
16
+ array (
17
+ 'pretty_version' => 'dev-master',
18
+ 'version' => 'dev-master',
19
+ 'aliases' =>
20
+ array (
21
+ 0 => '9999999-dev',
22
+ ),
23
+ 'reference' => '3d4062ddde198994093315acc55c6232067ce027',
24
+ ),
25
+ 'rosell-dk/dom-util-for-webp' =>
26
+ array (
27
+ 'pretty_version' => '0.3.1',
28
+ 'version' => '0.3.1.0',
29
+ 'aliases' =>
30
+ array (
31
+ ),
32
+ 'reference' => 'bae8f4a9b666726359d28bfb227d886c12f136a9',
33
+ ),
34
+ ),
35
+ );
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/.php_cs.dist CHANGED
@@ -1,19 +1,19 @@
1
- <?php
2
-
3
- $finder = PhpCsFixer\Finder::create()
4
- ->exclude('tests')
5
- ->in(__DIR__)
6
- ;
7
-
8
- $config = PhpCsFixer\Config::create();
9
- $config
10
- ->setRules([
11
- '@PSR2' => true,
12
- 'array_syntax' => [
13
- 'syntax' => 'short',
14
- ],
15
- ])
16
- ->setFinder($finder)
17
- ;
18
-
19
- return $config;
1
+ <?php
2
+
3
+ $finder = PhpCsFixer\Finder::create()
4
+ ->exclude('tests')
5
+ ->in(__DIR__)
6
+ ;
7
+
8
+ $config = PhpCsFixer\Config::create();
9
+ $config
10
+ ->setRules([
11
+ '@PSR2' => true,
12
+ 'array_syntax' => [
13
+ 'syntax' => 'short',
14
+ ],
15
+ ])
16
+ ->setFinder($finder)
17
+ ;
18
+
19
+ return $config;
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/README.md CHANGED
@@ -1,161 +1,161 @@
1
- # dom-util-for-webp
2
-
3
- [![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/image-mime-type-guesser.svg?style=flat-square)](https://packagist.org/packages/rosell-dk/dom-util-for-webp)
4
- [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net)
5
- [![Build Status](https://img.shields.io/travis/rosell-dk/dom-util-for-webp/master.svg?style=flat-square)](https://travis-ci.org/rosell-dk/dom-util-for-webp)
6
- [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/code-structure/master)
7
- [![Quality Score](https://img.shields.io/scrutinizer/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/)
8
- [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/blob/master/LICENSE)
9
-
10
- *Replace image URLs found in HTML*
11
-
12
- This library can do two things:
13
-
14
- 1) Replace image URLs in HTML
15
- 2) Replace *&lt;img&gt;* tags with *&lt;picture&gt;* tags, adding webp versions to sources
16
-
17
- To setup with composer, run ```composer require rosell-dk/dom-util-for-webp```.
18
-
19
- ## 1. Replacing image URLs in HTML
20
-
21
- The *ImageUrlReplacer::replace($html)* method accepts a piece of HTML and returns HTML where where all image URLs have been replaced - even those in inline styles.
22
-
23
- *Usage:*
24
-
25
- ```php
26
- $modifiedHtml = ImageUrlReplacer::replace($html);
27
- ```
28
-
29
- ### Example replacements:
30
-
31
- *input:*
32
-
33
- ```html
34
- <img src="image.jpg">
35
- <img src="1.jpg" srcset="2.jpg 1000w">
36
- <picture>
37
- <source srcset="1.jpg" type="image/webp">
38
- <source srcset="2.png" type="image/webp">
39
- <source src="3.gif"> <!-- gifs are skipped in default behaviour -->
40
- <source src="4.jpg?width=200"> <!-- urls with query string are skipped in default behaviour -->
41
- </picture>
42
- <div style="background-image: url('image.jpeg')"></div>
43
- <style>
44
- #hero {
45
- background: lightblue url("image.png") no-repeat fixed center;;
46
- }
47
- </style>
48
- <input type="button" src="1.jpg">
49
- <img data-src="image.jpg"> <!-- any attribute starting with "data-" are replaced (if it ends with "jpg", "jpeg" or "png"). For lazy-loading -->
50
- ```
51
-
52
- *output:*
53
-
54
- ```html
55
- <img src="image.jpg.webp">
56
- <img src="1.jpg.webp" srcset="2.jpg.webp 1000w">
57
- <picture>
58
- <source srcset="1.jpg.webp" type="image/webp">
59
- <source srcset="2.jpg.webp" type="image/webp">
60
- <source srcset="3.gif"> <!-- gifs are skipped in default behaviour -->
61
- <source srcset="4.jpg?width=200"> <!-- urls with query string are skipped in default behaviour -->
62
- </picture>
63
- <div style="background-image: url('image.jpeg.webp')"></div>
64
- <style>
65
- #hero {
66
- background: lightblue url("image.png.webp") no-repeat fixed center;;
67
- }
68
- </style>
69
- <input type="button" src="1.jpg.webp">
70
- <img data-src="image.jpg.webp"> <!-- any attribute starting with "data-" are replaced (if it ends with "jpg", "jpeg" or "png"). For lazy-loading -->
71
- ```
72
-
73
- Default behaviour of *ImageUrlReplacer::replace*:
74
- - The modified URL is the same as the original, with ".webp" appended (to change, override the `replaceUrl` function)
75
- - Only replaces URLs that ends with "png", "jpg" or "jpeg" (no query strings either) (to change, override the `replaceUrl` function)
76
- - Attribute search/replace limits to these tags: *&lt;img&gt;*, *&lt;source&gt;*, *&lt;input&gt;* and *&lt;iframe&gt;* (to change, override the `$searchInTags` property)
77
- - Attribute search/replace limits to these attributes: "src", "src-set" and any attribute starting with "data-" (to change, override the `attributeFilter` function)
78
- - Urls inside styles are replaced too (*background-image* and *background* properties)
79
-
80
- The behaviour can be modified by extending *ImageUrlReplacer* and overriding public methods such as *replaceUrl*
81
-
82
- ImageUrlReplacer uses the `Sunra\PhpSimple\HtmlDomParser`[library](https://github.com/sunra/php-simple-html-dom-parser) for parsing and modifying HTML. It wraps [simplehtmldom](http://simplehtmldom.sourceforge.net/). Simplehtmldom supports invalid HTML (it does not touch the invalid parts)
83
-
84
-
85
- ### Example: Customized behaviour
86
-
87
- ```php
88
- class ImageUrlReplacerCustomReplacer extends ImageUrlReplacer
89
- {
90
- public function replaceUrl($url) {
91
- // Only accept urls ending with "png", "jpg", "jpeg" and "gif"
92
- if (!preg_match('#(png|jpe?g|gif)$#', $url)) {
93
- return;
94
- }
95
-
96
- // Only accept full urls (beginning with http:// or https://)
97
- if (!preg_match('#^https?://#', $url)) {
98
- return;
99
- }
100
-
101
- // PS: You probably want to filter out external images too...
102
-
103
- // Simply append ".webp" after current extension.
104
- // This strategy ensures that "logo.jpg" and "logo.gif" gets counterparts with unique names
105
- return $url . '.webp';
106
- }
107
-
108
- public function attributeFilter($attrName) {
109
- // Don't allow any "data-" attribute, but limit to attributes that smells like they are used for images
110
- // The following rule matches all attributes used for lazy loading images that we know of
111
- return preg_match('#^(src|srcset|(data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*))$#i', $attrName);
112
-
113
- // If you want to limit it further, only allowing attributes known to be used for lazy load,
114
- // use the following regex instead:
115
- //return preg_match('#^(src|srcset|data-(src|srcset|cvpsrc|cvpset|thumb|bg-url|large_image|lazyload|source-url|srcsmall|srclarge|srcfull|slide-img|lazy-original))$#i', $attrName);
116
- }
117
- }
118
-
119
- $modifiedHtml = ImageUrlReplacerCustomReplacer::replace($html);
120
- ```
121
-
122
-
123
- ## 2. Replacing *&lt;img&gt;* tags with *&lt;picture&gt;* tags
124
-
125
- The *PictureTags::replace($html)* method accepts a piece of HTML and returns HTML where where all &lt;img&gt; tags have been replaced with &lt;picture&gt; tags, adding webp versions to sources
126
-
127
- Usage:
128
-
129
- ```php
130
- $modifiedHtml = PictureTags::replace($html);
131
- ```
132
-
133
- #### Example replacements:
134
-
135
- *Input:*
136
- ```html
137
- <img src="1.png">
138
- <img srcset="3.jpg 1000w" src="3.jpg">
139
- <img data-lazy-src="9.jpg" style="border:2px solid red" class="something">
140
- <figure class="wp-block-image">
141
- <img src="12.jpg" alt="" class="wp-image-6" srcset="12.jpg 492w, 12-300x265.jpg 300w" sizes="(max-width: 492px) 100vw, 492px">
142
- </figure>
143
- ```
144
-
145
- *Output*:
146
- ```html
147
- <picture><source srcset="1.png.webp" type="image/webp"><img src="1.png" class="webpexpress-processed"></picture>
148
- <picture><source srcset="3.jpg.webp 1000w" type="image/webp"><img srcset="3.jpg 1000w" src="3.jpg" class="webpexpress-processed"></picture>
149
- <picture><source data-lazy-src="9.jpg.webp" type="image/webp"><img data-lazy-src="9.jpg" style="border:2px solid red" class="something webpexpress-processed"></picture>
150
- <figure class="wp-block-image">
151
- <picture><source srcset="12.jpg.webp 492w, 12-300x265.jpg.webp 300w" sizes="(max-width: 492px) 100vw, 492px" type="image/webp"><img src="12.jpg" alt="" class="wp-image-6 webpexpress-processed" srcset="12.jpg 492w, 12-300x265.jpg 300w" sizes="(max-width: 492px) 100vw, 492px"></picture>
152
- </figure>'
153
- ```
154
-
155
- Note that with the picture tags, it is still the img tag that shows the selected image. The picture tag is just a wrapper.
156
- So it is correct behaviour not to copy the *style*, *width*, *class* or any other attributes to the picture tag. See [issue #9](https://github.com/rosell-dk/dom-util-for-webp/issues/9).
157
-
158
-
159
- As with `ImageUrlReplacer`, you can override the *replaceUrl* function. There is however currently no other methods to override.
160
-
161
- `PictureTags` currently uses regular expressions to do the replacing. There are plans to change implementation to use `Sunra\PhpSimple\HtmlDomParser`, like our `ImageUrlReplacer` class does.
1
+ # dom-util-for-webp
2
+
3
+ [![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/image-mime-type-guesser.svg?style=flat-square)](https://packagist.org/packages/rosell-dk/dom-util-for-webp)
4
+ [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net)
5
+ [![Build Status](https://img.shields.io/travis/rosell-dk/dom-util-for-webp/master.svg?style=flat-square)](https://travis-ci.org/rosell-dk/dom-util-for-webp)
6
+ [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/code-structure/master)
7
+ [![Quality Score](https://img.shields.io/scrutinizer/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/)
8
+ [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/blob/master/LICENSE)
9
+
10
+ *Replace image URLs found in HTML*
11
+
12
+ This library can do two things:
13
+
14
+ 1) Replace image URLs in HTML
15
+ 2) Replace *&lt;img&gt;* tags with *&lt;picture&gt;* tags, adding webp versions to sources
16
+
17
+ To setup with composer, run ```composer require rosell-dk/dom-util-for-webp```.
18
+
19
+ ## 1. Replacing image URLs in HTML
20
+
21
+ The *ImageUrlReplacer::replace($html)* method accepts a piece of HTML and returns HTML where where all image URLs have been replaced - even those in inline styles.
22
+
23
+ *Usage:*
24
+
25
+ ```php
26
+ $modifiedHtml = ImageUrlReplacer::replace($html);
27
+ ```
28
+
29
+ ### Example replacements:
30
+
31
+ *input:*
32
+
33
+ ```html
34
+ <img src="image.jpg">
35
+ <img src="1.jpg" srcset="2.jpg 1000w">
36
+ <picture>
37
+ <source srcset="1.jpg" type="image/webp">
38
+ <source srcset="2.png" type="image/webp">
39
+ <source src="3.gif"> <!-- gifs are skipped in default behaviour -->
40
+ <source src="4.jpg?width=200"> <!-- urls with query string are skipped in default behaviour -->
41
+ </picture>
42
+ <div style="background-image: url('image.jpeg')"></div>
43
+ <style>
44
+ #hero {
45
+ background: lightblue url("image.png") no-repeat fixed center;;
46
+ }
47
+ </style>
48
+ <input type="button" src="1.jpg">
49
+ <img data-src="image.jpg"> <!-- any attribute starting with "data-" are replaced (if it ends with "jpg", "jpeg" or "png"). For lazy-loading -->
50
+ ```
51
+
52
+ *output:*
53
+
54
+ ```html
55
+ <img src="image.jpg.webp">
56
+ <img src="1.jpg.webp" srcset="2.jpg.webp 1000w">
57
+ <picture>
58
+ <source srcset="1.jpg.webp" type="image/webp">
59
+ <source srcset="2.jpg.webp" type="image/webp">
60
+ <source srcset="3.gif"> <!-- gifs are skipped in default behaviour -->
61
+ <source srcset="4.jpg?width=200"> <!-- urls with query string are skipped in default behaviour -->
62
+ </picture>
63
+ <div style="background-image: url('image.jpeg.webp')"></div>
64
+ <style>
65
+ #hero {
66
+ background: lightblue url("image.png.webp") no-repeat fixed center;;
67
+ }
68
+ </style>
69
+ <input type="button" src="1.jpg.webp">
70
+ <img data-src="image.jpg.webp"> <!-- any attribute starting with "data-" are replaced (if it ends with "jpg", "jpeg" or "png"). For lazy-loading -->
71
+ ```
72
+
73
+ Default behaviour of *ImageUrlReplacer::replace*:
74
+ - The modified URL is the same as the original, with ".webp" appended (to change, override the `replaceUrl` function)
75
+ - Only replaces URLs that ends with "png", "jpg" or "jpeg" (no query strings either) (to change, override the `replaceUrl` function)
76
+ - Attribute search/replace limits to these tags: *&lt;img&gt;*, *&lt;source&gt;*, *&lt;input&gt;* and *&lt;iframe&gt;* (to change, override the `$searchInTags` property)
77
+ - Attribute search/replace limits to these attributes: "src", "src-set" and any attribute starting with "data-" (to change, override the `attributeFilter` function)
78
+ - Urls inside styles are replaced too (*background-image* and *background* properties)
79
+
80
+ The behaviour can be modified by extending *ImageUrlReplacer* and overriding public methods such as *replaceUrl*
81
+
82
+ ImageUrlReplacer uses the `Sunra\PhpSimple\HtmlDomParser`[library](https://github.com/sunra/php-simple-html-dom-parser) for parsing and modifying HTML. It wraps [simplehtmldom](http://simplehtmldom.sourceforge.net/). Simplehtmldom supports invalid HTML (it does not touch the invalid parts)
83
+
84
+
85
+ ### Example: Customized behaviour
86
+
87
+ ```php
88
+ class ImageUrlReplacerCustomReplacer extends ImageUrlReplacer
89
+ {
90
+ public function replaceUrl($url) {
91
+ // Only accept urls ending with "png", "jpg", "jpeg" and "gif"
92
+ if (!preg_match('#(png|jpe?g|gif)$#', $url)) {
93
+ return;
94
+ }
95
+
96
+ // Only accept full urls (beginning with http:// or https://)
97
+ if (!preg_match('#^https?://#', $url)) {
98
+ return;
99
+ }
100
+
101
+ // PS: You probably want to filter out external images too...
102
+
103
+ // Simply append ".webp" after current extension.
104
+ // This strategy ensures that "logo.jpg" and "logo.gif" gets counterparts with unique names
105
+ return $url . '.webp';
106
+ }
107
+
108
+ public function attributeFilter($attrName) {
109
+ // Don't allow any "data-" attribute, but limit to attributes that smells like they are used for images
110
+ // The following rule matches all attributes used for lazy loading images that we know of
111
+ return preg_match('#^(src|srcset|(data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*))$#i', $attrName);
112
+
113
+ // If you want to limit it further, only allowing attributes known to be used for lazy load,
114
+ // use the following regex instead:
115
+ //return preg_match('#^(src|srcset|data-(src|srcset|cvpsrc|cvpset|thumb|bg-url|large_image|lazyload|source-url|srcsmall|srclarge|srcfull|slide-img|lazy-original))$#i', $attrName);
116
+ }
117
+ }
118
+
119
+ $modifiedHtml = ImageUrlReplacerCustomReplacer::replace($html);
120
+ ```
121
+
122
+
123
+ ## 2. Replacing *&lt;img&gt;* tags with *&lt;picture&gt;* tags
124
+
125
+ The *PictureTags::replace($html)* method accepts a piece of HTML and returns HTML where where all &lt;img&gt; tags have been replaced with &lt;picture&gt; tags, adding webp versions to sources
126
+
127
+ Usage:
128
+
129
+ ```php
130
+ $modifiedHtml = PictureTags::replace($html);
131
+ ```
132
+
133
+ #### Example replacements:
134
+
135
+ *Input:*
136
+ ```html
137
+ <img src="1.png">
138
+ <img srcset="3.jpg 1000w" src="3.jpg">
139
+ <img data-lazy-src="9.jpg" style="border:2px solid red" class="something">
140
+ <figure class="wp-block-image">
141
+ <img src="12.jpg" alt="" class="wp-image-6" srcset="12.jpg 492w, 12-300x265.jpg 300w" sizes="(max-width: 492px) 100vw, 492px">
142
+ </figure>
143
+ ```
144
+
145
+ *Output*:
146
+ ```html
147
+ <picture><source srcset="1.png.webp" type="image/webp"><img src="1.png" class="webpexpress-processed"></picture>
148
+ <picture><source srcset="3.jpg.webp 1000w" type="image/webp"><img srcset="3.jpg 1000w" src="3.jpg" class="webpexpress-processed"></picture>
149
+ <picture><source data-lazy-src="9.jpg.webp" type="image/webp"><img data-lazy-src="9.jpg" style="border:2px solid red" class="something webpexpress-processed"></picture>
150
+ <figure class="wp-block-image">
151
+ <picture><source srcset="12.jpg.webp 492w, 12-300x265.jpg.webp 300w" sizes="(max-width: 492px) 100vw, 492px" type="image/webp"><img src="12.jpg" alt="" class="wp-image-6 webpexpress-processed" srcset="12.jpg 492w, 12-300x265.jpg 300w" sizes="(max-width: 492px) 100vw, 492px"></picture>
152
+ </figure>'
153
+ ```
154
+
155
+ Note that with the picture tags, it is still the img tag that shows the selected image. The picture tag is just a wrapper.
156
+ So it is correct behaviour not to copy the *style*, *width*, *class* or any other attributes to the picture tag. See [issue #9](https://github.com/rosell-dk/dom-util-for-webp/issues/9).
157
+
158
+
159
+ As with `ImageUrlReplacer`, you can override the *replaceUrl* function. There is however currently no other methods to override.
160
+
161
+ `PictureTags` currently uses regular expressions to do the replacing. There are plans to change implementation to use `Sunra\PhpSimple\HtmlDomParser`, like our `ImageUrlReplacer` class does.
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/composer.json CHANGED
@@ -1,60 +1,60 @@
1
- {
2
- "name": "rosell-dk/dom-util-for-webp",
3
- "description": "Replace image URLs found in HTML",
4
- "type": "library",
5
- "license": "MIT",
6
- "minimum-stability": "stable",
7
- "keywords": ["webp", "replace", "images", "html"],
8
- "scripts": {
9
- "ci": [
10
- "@build",
11
- "@test",
12
- "@phpcs-all",
13
- "@composer validate --no-check-all --strict",
14
- "@phpstan-global"
15
- ],
16
- "cs-fix-all": [
17
- "php-cs-fixer fix src"
18
- ],
19
- "cs-fix": "php-cs-fixer fix",
20
- "cs-dry": "php-cs-fixer fix --dry-run --diff",
21
- "test": "phpunit --coverage-text --coverage-clover=coverage.clover",
22
- "phpcs": "phpcs --standard=PSR2",
23
- "phpcbf": "phpcbf --standard=PSR2",
24
- "phpstan": "vendor/bin/phpstan analyse src --level=4",
25
- "phpstan-global": "~/.composer/vendor/bin/phpstan analyse src --level=4"
26
- },
27
- "extra": {
28
- "scripts-descriptions": {
29
- "ci": "Run tests before CI",
30
- "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
31
- "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
32
- "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
33
- "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
34
- "test": "Launches the preconfigured PHPUnit"
35
- }
36
- },
37
- "autoload": {
38
- "psr-4": { "DOMUtilForWebP\\": "src/" }
39
- },
40
- "autoload-dev": {
41
- "psr-4": { "DOMUtilForWebPTests\\": "tests/" }
42
- },
43
- "authors": [
44
- {
45
- "name": "Bjørn Rosell",
46
- "homepage": "https://www.bitwise-it.dk/contact",
47
- "role": "Project Author"
48
- }
49
- ],
50
- "require-dev": {
51
- "friendsofphp/php-cs-fixer": "^2.11",
52
- "phpunit/phpunit": "5.7.27",
53
- "squizlabs/php_codesniffer": "3.*"
54
- },
55
- "config": {
56
- "sort-packages": true
57
- },
58
- "require": {
59
- }
60
- }
1
+ {
2
+ "name": "rosell-dk/dom-util-for-webp",
3
+ "description": "Replace image URLs found in HTML",
4
+ "type": "library",
5
+ "license": "MIT",
6
+ "minimum-stability": "stable",
7
+ "keywords": ["webp", "replace", "images", "html"],
8
+ "scripts": {
9
+ "ci": [
10
+ "@build",
11
+ "@test",
12
+ "@phpcs-all",
13
+ "@composer validate --no-check-all --strict",
14
+ "@phpstan-global"
15
+ ],
16
+ "cs-fix-all": [
17
+ "php-cs-fixer fix src"
18
+ ],
19
+ "cs-fix": "php-cs-fixer fix",
20
+ "cs-dry": "php-cs-fixer fix --dry-run --diff",
21
+ "test": "phpunit --coverage-text --coverage-clover=coverage.clover",
22
+ "phpcs": "phpcs --standard=PSR2",
23
+ "phpcbf": "phpcbf --standard=PSR2",
24
+ "phpstan": "vendor/bin/phpstan analyse src --level=4",
25
+ "phpstan-global": "~/.composer/vendor/bin/phpstan analyse src --level=4"
26
+ },
27
+ "extra": {
28
+ "scripts-descriptions": {
29
+ "ci": "Run tests before CI",
30
+ "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
31
+ "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
32
+ "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
33
+ "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
34
+ "test": "Launches the preconfigured PHPUnit"
35
+ }
36
+ },
37
+ "autoload": {
38
+ "psr-4": { "DOMUtilForWebP\\": "src/" }
39
+ },
40
+ "autoload-dev": {
41
+ "psr-4": { "DOMUtilForWebPTests\\": "tests/" }
42
+ },
43
+ "authors": [
44
+ {
45
+ "name": "Bjørn Rosell",
46
+ "homepage": "https://www.bitwise-it.dk/contact",
47
+ "role": "Project Author"
48
+ }
49
+ ],
50
+ "require-dev": {
51
+ "friendsofphp/php-cs-fixer": "^2.11",
52
+ "phpunit/phpunit": "5.7.27",
53
+ "squizlabs/php_codesniffer": "3.*"
54
+ },
55
+ "config": {
56
+ "sort-packages": true
57
+ },
58
+ "require": {
59
+ }
60
+ }
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpstan.neon CHANGED
@@ -1,3 +1,3 @@
1
- parameters:
2
- ignoreErrors:
3
- - '#Function str_get_html not found.#'
1
+ parameters:
2
+ ignoreErrors:
3
+ - '#Function str_get_html not found.#'
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src-vendor/simple_html_dom/simple_html_dom.inc CHANGED
@@ -1,2930 +1,2930 @@
1
- <?php
2
- /**
3
- * Website: http://sourceforge.net/projects/simplehtmldom/
4
- * Additional projects: http://sourceforge.net/projects/debugobject/
5
- * Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
6
- * Contributions by:
7
- * Yousuke Kumakura (Attribute filters)
8
- * Vadim Voituk (Negative indexes supports of "find" method)
9
- * Antcs (Constructor with automatically load contents either text or file/url)
10
- *
11
- * all affected sections have comments starting with "PaperG"
12
- *
13
- * Paperg - Added case insensitive testing of the value of the selector.
14
- *
15
- * Paperg - Added tag_start for the starting index of tags - NOTE: This works
16
- * but not accurately. This tag_start gets counted AFTER \r\n have been crushed
17
- * out, and after the remove_noice calls so it will not reflect the REAL
18
- * position of the tag in the source, it will almost always be smaller by some
19
- * amount. We use this to determine how far into the file the tag in question
20
- * is. This "percentage" will never be accurate as the $dom->size is the "real"
21
- * number of bytes the dom was created from. But for most purposes, it's a
22
- * really good estimation.
23
- *
24
- * Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags
25
- * closed is great for malformed html, but it CAN lead to parsing errors.
26
- *
27
- * Allow the user to tell us how much they trust the html.
28
- *
29
- * Paperg add the text and plaintext to the selectors for the find syntax.
30
- * plaintext implies text in the innertext of a node. text implies that the
31
- * tag is a text node. This allows for us to find tags based on the text they
32
- * contain.
33
- *
34
- * Create find_ancestor_tag to see if a tag is - at any level - inside of
35
- * another specific tag.
36
- *
37
- * Paperg: added parse_charset so that we know about the character set of
38
- * the source document. NOTE: If the user's system has a routine called
39
- * get_last_retrieve_url_contents_content_type availalbe, we will assume it's
40
- * returning the content-type header from the last transfer or curl_exec, and
41
- * we will parse that and use it in preference to any other method of charset
42
- * detection.
43
- *
44
- * Found infinite loop in the case of broken html in restore_noise. Rewrote to
45
- * protect from that.
46
- *
47
- * PaperG (John Schlick) Added get_display_size for "IMG" tags.
48
- *
49
- * Licensed under The MIT License
50
- * Redistributions of files must retain the above copyright notice.
51
- *
52
- * @author S.C. Chen <me578022@gmail.com>
53
- * @author John Schlick
54
- * @author Rus Carroll
55
- * @version Rev. 1.8.1 (247)
56
- * @package PlaceLocalInclude
57
- * @subpackage simple_html_dom
58
- */
59
-
60
- /**
61
- * All of the Defines for the classes below.
62
- * @author S.C. Chen <me578022@gmail.com>
63
- */
64
- define('HDOM_TYPE_ELEMENT', 1);
65
- define('HDOM_TYPE_COMMENT', 2);
66
- define('HDOM_TYPE_TEXT', 3);
67
- define('HDOM_TYPE_ENDTAG', 4);
68
- define('HDOM_TYPE_ROOT', 5);
69
- define('HDOM_TYPE_UNKNOWN', 6);
70
- define('HDOM_QUOTE_DOUBLE', 0);
71
- define('HDOM_QUOTE_SINGLE', 1);
72
- define('HDOM_QUOTE_NO', 3);
73
- define('HDOM_INFO_BEGIN', 0);
74
- define('HDOM_INFO_END', 1);
75
- define('HDOM_INFO_QUOTE', 2);
76
- define('HDOM_INFO_SPACE', 3);
77
- define('HDOM_INFO_TEXT', 4);
78
- define('HDOM_INFO_INNER', 5);
79
- define('HDOM_INFO_OUTER', 6);
80
- define('HDOM_INFO_ENDSPACE', 7);
81
-
82
- /** The default target charset */
83
- defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
84
-
85
- /** The default <br> text used instead of <br> tags when returning text */
86
- defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
87
-
88
- /** The default <span> text used instead of <span> tags when returning text */
89
- defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
90
-
91
- /** The maximum file size the parser should load */
92
- defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
93
-
94
- /** Contents between curly braces "{" and "}" are interpreted as text */
95
- define('HDOM_SMARTY_AS_TEXT', 1);
96
-
97
- // helper functions
98
- // -----------------------------------------------------------------------------
99
- // get html dom from file
100
- // $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
101
- function file_get_html(
102
- $url,
103
- $use_include_path = false,
104
- $context = null,
105
- $offset = 0,
106
- $maxLen = -1,
107
- $lowercase = true,
108
- $forceTagsClosed = true,
109
- $target_charset = DEFAULT_TARGET_CHARSET,
110
- $stripRN = true,
111
- $defaultBRText = DEFAULT_BR_TEXT,
112
- $defaultSpanText = DEFAULT_SPAN_TEXT
113
- ) {
114
- // Ensure maximum length is greater than zero
115
- if ($maxLen <= 0) {
116
- $maxLen = MAX_FILE_SIZE;
117
- }
118
-
119
- // We DO force the tags to be terminated.
120
- $dom = new simple_html_dom(
121
- null,
122
- $lowercase,
123
- $forceTagsClosed,
124
- $target_charset,
125
- $stripRN,
126
- $defaultBRText,
127
- $defaultSpanText
128
- );
129
-
130
- /**
131
- * For sourceforge users: uncomment the next line and comment the
132
- * retrieve_url_contents line 2 lines down if it is not already done.
133
- */
134
- $contents = file_get_contents(
135
- $url,
136
- $use_include_path,
137
- $context,
138
- $offset,
139
- $maxLen
140
- );
141
-
142
- // Paperg - use our own mechanism for getting the contents as we want to
143
- // control the timeout.
144
- // $contents = retrieve_url_contents($url);
145
- if (empty($contents) || strlen($contents) > $maxLen) {
146
- return false;
147
- }
148
-
149
- // The second parameter can force the selectors to all be lowercase.
150
- $dom->load($contents, $lowercase, $stripRN);
151
- return $dom;
152
- }
153
-
154
- // get html dom from string
155
- function str_get_html(
156
- $str,
157
- $lowercase = true,
158
- $forceTagsClosed = true,
159
- $target_charset = DEFAULT_TARGET_CHARSET,
160
- $stripRN = true,
161
- $defaultBRText = DEFAULT_BR_TEXT,
162
- $defaultSpanText = DEFAULT_SPAN_TEXT
163
- ) {
164
- $dom = new simple_html_dom(
165
- null,
166
- $lowercase,
167
- $forceTagsClosed,
168
- $target_charset,
169
- $stripRN,
170
- $defaultBRText,
171
- $defaultSpanText
172
- );
173
-
174
- if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
175
- $dom->clear();
176
- return false;
177
- }
178
-
179
- $dom->load($str, $lowercase, $stripRN);
180
- return $dom;
181
- }
182
-
183
- // dump html dom tree
184
- function dump_html_tree($node, $show_attr = true, $deep = 0)
185
- {
186
- $node->dump($node);
187
- }
188
-
189
- /**
190
- * simple html dom node
191
- * PaperG - added ability for "find" routine to lowercase the value of the
192
- * selector.
193
- *
194
- * PaperG - added $tag_start to track the start position of the tag in the total
195
- * byte index
196
- *
197
- * @package PlaceLocalInclude
198
- */
199
- class simple_html_dom_node
200
- {
201
- /**
202
- * Node type
203
- *
204
- * Default is {@see HDOM_TYPE_TEXT}
205
- *
206
- * @var int
207
- */
208
- public $nodetype = HDOM_TYPE_TEXT;
209
-
210
- /**
211
- * Tag name
212
- *
213
- * Default is 'text'
214
- *
215
- * @var string
216
- */
217
- public $tag = 'text';
218
-
219
- /**
220
- * List of attributes
221
- *
222
- * @var array
223
- */
224
- public $attr = array();
225
-
226
- /**
227
- * List of child node objects
228
- *
229
- * @var array
230
- */
231
- public $children = array();
232
- public $nodes = array();
233
-
234
- /**
235
- * The parent node object
236
- *
237
- * @var object|null
238
- */
239
- public $parent = null;
240
-
241
- // The "info" array - see HDOM_INFO_... for what each element contains.
242
- public $_ = array();
243
-
244
- /**
245
- * Start position of the tag in the document
246
- *
247
- * @var int
248
- */
249
- public $tag_start = 0;
250
-
251
- /**
252
- * The DOM object
253
- *
254
- * @var object|null
255
- */
256
- private $dom = null;
257
-
258
- /**
259
- * Construct new node object
260
- *
261
- * Adds itself to the list of DOM Nodes {@see simple_html_dom::$nodes}
262
- */
263
- function __construct($dom)
264
- {
265
- $this->dom = $dom;
266
- $dom->nodes[] = $this;
267
- }
268
-
269
- function __destruct()
270
- {
271
- $this->clear();
272
- }
273
-
274
- function __toString()
275
- {
276
- return $this->outertext();
277
- }
278
-
279
- // clean up memory due to php5 circular references memory leak...
280
- function clear()
281
- {
282
- $this->dom = null;
283
- $this->nodes = null;
284
- $this->parent = null;
285
- $this->children = null;
286
- }
287
-
288
- // dump node's tree
289
- function dump($show_attr = true, $deep = 0)
290
- {
291
- $lead = str_repeat(' ', $deep);
292
-
293
- echo $lead . $this->tag;
294
-
295
- if ($show_attr && count($this->attr) > 0) {
296
- echo '(';
297
- foreach ($this->attr as $k => $v) {
298
- echo "[$k]=>\"" . $this->$k . '", ';
299
- }
300
- echo ')';
301
- }
302
-
303
- echo "\n";
304
-
305
- if ($this->nodes) {
306
- foreach ($this->nodes as $c) {
307
- $c->dump($show_attr, $deep + 1);
308
- }
309
- }
310
- }
311
-
312
-
313
- // Debugging function to dump a single dom node with a bunch of information about it.
314
- function dump_node($echo = true)
315
- {
316
- $string = $this->tag;
317
-
318
- if (count($this->attr) > 0) {
319
- $string .= '(';
320
- foreach ($this->attr as $k => $v) {
321
- $string .= "[$k]=>\"" . $this->$k . '", ';
322
- }
323
- $string .= ')';
324
- }
325
-
326
- if (count($this->_) > 0) {
327
- $string .= ' $_ (';
328
- foreach ($this->_ as $k => $v) {
329
- if (is_array($v)) {
330
- $string .= "[$k]=>(";
331
- foreach ($v as $k2 => $v2) {
332
- $string .= "[$k2]=>\"" . $v2 . '", ';
333
- }
334
- $string .= ')';
335
- } else {
336
- $string .= "[$k]=>\"" . $v . '", ';
337
- }
338
- }
339
- $string .= ')';
340
- }
341
-
342
- if (isset($this->text)) {
343
- $string .= ' text: (' . $this->text . ')';
344
- }
345
-
346
- $string .= " HDOM_INNER_INFO: '";
347
-
348
- if (isset($node->_[HDOM_INFO_INNER])) {
349
- $string .= $node->_[HDOM_INFO_INNER] . "'";
350
- } else {
351
- $string .= ' NULL ';
352
- }
353
-
354
- $string .= ' children: ' . count($this->children);
355
- $string .= ' nodes: ' . count($this->nodes);
356
- $string .= ' tag_start: ' . $this->tag_start;
357
- $string .= "\n";
358
-
359
- if ($echo) {
360
- echo $string;
361
- return;
362
- } else {
363
- return $string;
364
- }
365
- }
366
-
367
- /**
368
- * Return or set parent node
369
- *
370
- * @param object|null $parent (optional) The parent node, `null` to return
371
- * the current parent node.
372
- * @return object|null The parent node
373
- */
374
- function parent($parent = null)
375
- {
376
- // I am SURE that this doesn't work properly.
377
- // It fails to unset the current node from it's current parents nodes or
378
- // children list first.
379
- if ($parent !== null) {
380
- $this->parent = $parent;
381
- $this->parent->nodes[] = $this;
382
- $this->parent->children[] = $this;
383
- }
384
-
385
- return $this->parent;
386
- }
387
-
388
- /**
389
- * @return bool True if the node has at least one child node
390
- */
391
- function has_child()
392
- {
393
- return !empty($this->children);
394
- }
395
-
396
- /**
397
- * Get child node at specified index
398
- *
399
- * @param int $idx The index of the child node to return, `-1` to return all
400
- * child nodes.
401
- * @return object|array|null The child node at the specified index, all child
402
- * nodes or null if the index is invalid.
403
- */
404
- function children($idx = -1)
405
- {
406
- if ($idx === -1) {
407
- return $this->children;
408
- }
409
-
410
- if (isset($this->children[$idx])) {
411
- return $this->children[$idx];
412
- }
413
-
414
- return null;
415
- }
416
-
417
- /**
418
- * Get first child node
419
- *
420
- * @return object|null The first child node or null if the current node has
421
- * no child nodes.
422
- *
423
- * @todo Use `empty()` instead of `count()` to improve performance on large
424
- * arrays.
425
- */
426
- function first_child()
427
- {
428
- if (count($this->children) > 0) {
429
- return $this->children[0];
430
- }
431
- return null;
432
- }
433
-
434
- /**
435
- * Get last child node
436
- *
437
- * @return object|null The last child node or null if the current node has
438
- * no child nodes.
439
- *
440
- * @todo Use `end()` to slightly improve performance on large arrays.
441
- */
442
- function last_child()
443
- {
444
- if (($count = count($this->children)) > 0) {
445
- return $this->children[$count - 1];
446
- }
447
- return null;
448
- }
449
-
450
- /**
451
- * Get next sibling node
452
- *
453
- * @return object|null The sibling node or null if the current node has no
454
- * sibling nodes.
455
- */
456
- function next_sibling()
457
- {
458
- if ($this->parent === null) {
459
- return null;
460
- }
461
-
462
- $idx = 0;
463
- $count = count($this->parent->children);
464
-
465
- while ($idx < $count && $this !== $this->parent->children[$idx]) {
466
- ++$idx;
467
- }
468
-
469
- if (++$idx >= $count) {
470
- return null;
471
- }
472
-
473
- return $this->parent->children[$idx];
474
- }
475
-
476
- /**
477
- * Get previous sibling node
478
- *
479
- * @return object|null The sibling node or null if the current node has no
480
- * sibling nodes.
481
- */
482
- function prev_sibling()
483
- {
484
- if ($this->parent === null) {
485
- return null;
486
- }
487
-
488
- $idx = 0;
489
- $count = count($this->parent->children);
490
-
491
- while ($idx < $count && $this !== $this->parent->children[$idx]) {
492
- ++$idx;
493
- }
494
-
495
- if (--$idx < 0) {
496
- return null;
497
- }
498
-
499
- return $this->parent->children[$idx];
500
- }
501
-
502
- /**
503
- * Traverse ancestors to the first matching tag.
504
- *
505
- * @param string $tag Tag to find
506
- * @return object|null First matching node in the DOM tree or null if no
507
- * match was found.
508
- *
509
- * @todo Null is returned implicitly by calling ->parent on the root node.
510
- * This behaviour could change at any time, rendering this function invalid.
511
- */
512
- function find_ancestor_tag($tag)
513
- {
514
- global $debug_object;
515
- if (is_object($debug_object)) {
516
- $debug_object->debug_log_entry(1);
517
- }
518
-
519
- // Start by including ourselves in the comparison.
520
- $returnDom = $this;
521
-
522
- while (!is_null($returnDom)) {
523
- if (is_object($debug_object)) {
524
- $debug_object->debug_log(2, 'Current tag is: ' . $returnDom->tag);
525
- }
526
-
527
- if ($returnDom->tag == $tag) {
528
- break;
529
- }
530
-
531
- $returnDom = $returnDom->parent;
532
- }
533
-
534
- return $returnDom;
535
- }
536
-
537
- /**
538
- * Get node's inner text (everything inside the opening and closing tags)
539
- *
540
- * @return string
541
- */
542
- function innertext()
543
- {
544
- if (isset($this->_[HDOM_INFO_INNER])) {
545
- return $this->_[HDOM_INFO_INNER];
546
- }
547
-
548
- if (isset($this->_[HDOM_INFO_TEXT])) {
549
- return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
550
- }
551
-
552
- $ret = '';
553
-
554
- foreach ($this->nodes as $n) {
555
- $ret .= $n->outertext();
556
- }
557
-
558
- return $ret;
559
- }
560
-
561
- /**
562
- * Get node's outer text (everything including the opening and closing tags)
563
- *
564
- * @return string
565
- */
566
- function outertext()
567
- {
568
- global $debug_object;
569
-
570
- if (is_object($debug_object)) {
571
- $text = '';
572
-
573
- if ($this->tag === 'text') {
574
- if (!empty($this->text)) {
575
- $text = ' with text: ' . $this->text;
576
- }
577
- }
578
-
579
- $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
580
- }
581
-
582
- if ($this->tag === 'root') {
583
- return $this->innertext();
584
- }
585
-
586
- // trigger callback
587
- if ($this->dom && $this->dom->callback !== null) {
588
- call_user_func_array($this->dom->callback, array($this));
589
- }
590
-
591
- if (isset($this->_[HDOM_INFO_OUTER])) {
592
- return $this->_[HDOM_INFO_OUTER];
593
- }
594
-
595
- if (isset($this->_[HDOM_INFO_TEXT])) {
596
- return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
597
- }
598
-
599
- // render begin tag
600
- if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
601
- $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
602
- } else {
603
- $ret = '';
604
- }
605
-
606
- // render inner text
607
- if (isset($this->_[HDOM_INFO_INNER])) {
608
- // If it's a br tag... don't return the HDOM_INNER_INFO that we
609
- // may or may not have added.
610
- if ($this->tag !== 'br') {
611
- $ret .= $this->_[HDOM_INFO_INNER];
612
- }
613
- } else {
614
- if ($this->nodes) {
615
- foreach ($this->nodes as $n) {
616
- $ret .= $this->convert_text($n->outertext());
617
- }
618
- }
619
- }
620
-
621
- // render end tag
622
- if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
623
- $ret .= '</' . $this->tag . '>';
624
- }
625
-
626
- return $ret;
627
- }
628
-
629
- /**
630
- * Get node's plain text (everything excluding all tags)
631
- *
632
- * @return string
633
- */
634
- function text()
635
- {
636
- if (isset($this->_[HDOM_INFO_INNER])) {
637
- return $this->_[HDOM_INFO_INNER];
638
- }
639
-
640
- switch ($this->nodetype) {
641
- case HDOM_TYPE_TEXT:
642
- return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
643
- case HDOM_TYPE_COMMENT:
644
- return '';
645
- case HDOM_TYPE_UNKNOWN:
646
- return '';
647
- }
648
-
649
- if (strcasecmp($this->tag, 'script') === 0) {
650
- return '';
651
- }
652
- if (strcasecmp($this->tag, 'style') === 0) {
653
- return '';
654
- }
655
-
656
- $ret = '';
657
-
658
- // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed
659
- // for some span tags, and some p tags) $this->nodes is set to NULL.
660
- // NOTE: This indicates that there is a problem where it's set to NULL
661
- // without a clear happening.
662
- // WHY is this happening?
663
- if (!is_null($this->nodes)) {
664
- foreach ($this->nodes as $n) {
665
- // Start paragraph after a blank line
666
- if ($n->tag === 'p') {
667
- $ret .= "\n\n";
668
- }
669
-
670
- $ret .= $this->convert_text($n->text());
671
-
672
- // If this node is a span... add a space at the end of it so
673
- // multiple spans don't run into each other. This is plaintext
674
- // after all.
675
- if ($n->tag === 'span') {
676
- $ret .= $this->dom->default_span_text;
677
- }
678
- }
679
- }
680
- return trim($ret);
681
- }
682
-
683
- /**
684
- * Get node's xml text (inner text as a CDATA section)
685
- *
686
- * @return string
687
- */
688
- function xmltext()
689
- {
690
- $ret = $this->innertext();
691
- $ret = str_ireplace('<![CDATA[', '', $ret);
692
- $ret = str_replace(']]>', '', $ret);
693
- return $ret;
694
- }
695
-
696
- // build node's text with tag
697
- function makeup()
698
- {
699
- // text, comment, unknown
700
- if (isset($this->_[HDOM_INFO_TEXT])) {
701
- return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
702
- }
703
-
704
- $ret = '<' . $this->tag;
705
- $i = -1;
706
-
707
- foreach ($this->attr as $key => $val) {
708
- ++$i;
709
-
710
- // skip removed attribute
711
- if ($val === null || $val === false) {
712
- continue;
713
- }
714
-
715
- $ret .= $this->_[HDOM_INFO_SPACE][$i][0];
716
-
717
- //no value attr: nowrap, checked selected...
718
- if ($val === true) {
719
- $ret .= $key;
720
- } else {
721
- switch ($this->_[HDOM_INFO_QUOTE][$i]) {
722
- case HDOM_QUOTE_DOUBLE:
723
- $quote = '"';
724
- break;
725
- case HDOM_QUOTE_SINGLE:
726
- $quote = '\'';
727
- break;
728
- default:
729
- $quote = '';
730
- }
731
-
732
- $ret .= $key
733
- . $this->_[HDOM_INFO_SPACE][$i][1]
734
- . '='
735
- . $this->_[HDOM_INFO_SPACE][$i][2]
736
- . $quote
737
- . $val
738
- . $quote;
739
- }
740
- }
741
-
742
- $ret = $this->dom->restore_noise($ret);
743
- return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
744
- }
745
-
746
- /**
747
- * Find elements by CSS selector
748
- *
749
- * @param string $selector The CSS selector
750
- * @param int|null $idx Index of element to return form the list of matching
751
- * elements (default: `null` = disabled).
752
- * @param bool $lowercase Matches tag names case insensitive (lowercase) if
753
- * enabled (default: `false`)
754
- * @return array|object|null A list of elements matching the specified CSS
755
- * selector or a single element if $idx is specified or null if no element
756
- * was found.
757
- */
758
- function find($selector, $idx = null, $lowercase = false)
759
- {
760
- $selectors = $this->parse_selector($selector);
761
- if (($count = count($selectors)) === 0) {
762
- return array();
763
- }
764
- $found_keys = array();
765
-
766
- // find each selector
767
- for ($c = 0; $c < $count; ++$c) {
768
- // The change on the below line was documented on the sourceforge
769
- // code tracker id 2788009
770
- // used to be: if (($levle=count($selectors[0]))===0) return array();
771
- if (($levle = count($selectors[$c])) === 0) {
772
- return array();
773
- }
774
- if (!isset($this->_[HDOM_INFO_BEGIN])) {
775
- return array();
776
- }
777
-
778
- $head = array($this->_[HDOM_INFO_BEGIN] => 1);
779
- $cmd = ' '; // Combinator
780
-
781
- // handle descendant selectors, no recursive!
782
- for ($l = 0; $l < $levle; ++$l) {
783
- $ret = array();
784
-
785
- foreach ($head as $k => $v) {
786
- $n = ($k === -1) ? $this->dom->root : $this->dom->nodes[$k];
787
- //PaperG - Pass this optional parameter on to the seek function.
788
- $n->seek($selectors[$c][$l], $ret, $cmd, $lowercase);
789
- }
790
-
791
- $head = $ret;
792
- $cmd = $selectors[$c][$l][4]; // Next Combinator
793
- }
794
-
795
- foreach ($head as $k => $v) {
796
- if (!isset($found_keys[$k])) {
797
- $found_keys[$k] = 1;
798
- }
799
- }
800
- }
801
-
802
- // sort keys
803
- ksort($found_keys);
804
-
805
- $found = array();
806
- foreach ($found_keys as $k => $v) {
807
- $found[] = $this->dom->nodes[$k];
808
- }
809
-
810
- // return nth-element or array
811
- if (is_null($idx)) {
812
- return $found;
813
- } elseif ($idx < 0) {
814
- $idx = count($found) + $idx;
815
- }
816
- return (isset($found[$idx])) ? $found[$idx] : null;
817
- }
818
-
819
- /**
820
- * Seek DOM elements by selector
821
- *
822
- * **Note**
823
- * The selector element must be compatible to a selector from
824
- * {@see simple_html_dom_node::parse_selector()}
825
- *
826
- * @param array $selector A selector element
827
- * @param array $ret An array of matches
828
- * @param bool $lowercase Matches tag names case insensitive (lowercase) if
829
- * enabled (default: `false`)
830
- * @return void
831
- */
832
- protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
833
- {
834
- global $debug_object;
835
- if (is_object($debug_object)) {
836
- $debug_object->debug_log_entry(1);
837
- }
838
-
839
- list($tag, $id, $class, $attributes, $cmb) = $selector;
840
- $nodes = array();
841
-
842
- if ($parent_cmd === ' ') { // Descendant Combinator
843
- // Find parent closing tag if the current element doesn't have a closing
844
- // tag (i.e. void element)
845
- $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
846
- if ($end == 0) {
847
- $parent = $this->parent;
848
- while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) {
849
- $end -= 1;
850
- $parent = $parent->parent;
851
- }
852
- $end += $parent->_[HDOM_INFO_END];
853
- }
854
-
855
- // Get list of target nodes
856
- $nodes_start = $this->_[HDOM_INFO_BEGIN] + 1;
857
- $nodes_count = $end - $nodes_start;
858
- $nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true);
859
- } elseif ($parent_cmd === '>') { // Child Combinator
860
- $nodes = $this->children;
861
- } elseif ($parent_cmd === '+'
862
- && $this->parent
863
- && in_array($this, $this->parent->children)) { // Next-Sibling Combinator
864
- $index = array_search($this, $this->parent->children, true) + 1;
865
- $nodes[] = $this->parent->children[$index];
866
- } elseif ($parent_cmd === '~'
867
- && $this->parent
868
- && in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
869
- $index = array_search($this, $this->parent->children, true);
870
- $nodes = array_slice($this->parent->children, $index);
871
- }
872
-
873
- // Go throgh each element starting at this element until the end tag
874
- // Note: If this element is a void tag, any previous void element is
875
- // skipped.
876
- foreach ($nodes as $node) {
877
- $pass = true;
878
-
879
- // Skip root nodes
880
- if (!$node->parent) {
881
- $pass = false;
882
- }
883
-
884
- // Skip if node isn't a child node (i.e. text nodes)
885
- if ($pass && !in_array($node, $node->parent->children, true)) {
886
- $pass = false;
887
- }
888
-
889
- // Skip if tag doesn't match
890
- if ($pass && $tag !== '' && $tag !== $node->tag && $tag !== '*') {
891
- $pass = false;
892
- }
893
-
894
- // Skip if ID doesn't exist
895
- if ($pass && $id !== '' && !isset($node->attr['id'])) {
896
- $pass = false;
897
- }
898
-
899
- // Check if ID matches
900
- if ($pass && $id !== '' && isset($node->attr['id'])) {
901
- // Note: Only consider the first ID (as browsers do)
902
- $node_id = explode(' ', trim($node->attr['id']))[0];
903
-
904
- if ($id !== $node_id) {
905
- $pass = false;
906
- }
907
- }
908
-
909
- // Check if all class(es) exist
910
- if ($pass && $class !== '' && is_array($class) && !empty($class)) {
911
- if (isset($node->attr['class'])) {
912
- $node_classes = explode(' ', $node->attr['class']);
913
-
914
- if ($lowercase) {
915
- $node_classes = array_map('strtolower', $node_classes);
916
- }
917
-
918
- foreach ($class as $c) {
919
- if (!in_array($c, $node_classes)) {
920
- $pass = false;
921
- break;
922
- }
923
- }
924
- } else {
925
- $pass = false;
926
- }
927
- }
928
-
929
- // Check attributes
930
- if ($pass
931
- && $attributes !== ''
932
- && is_array($attributes)
933
- && !empty($attributes)) {
934
- foreach ($attributes as $a) {
935
- list (
936
- $att_name,
937
- $att_expr,
938
- $att_val,
939
- $att_inv,
940
- $att_case_sensitivity
941
- ) = $a;
942
-
943
- // Handle indexing attributes (i.e. "[2]")
944
- /**
945
- * Note: This is not supported by the CSS Standard but adds
946
- * the ability to select items compatible to XPath (i.e.
947
- * the 3rd element within it's parent).
948
- *
949
- * Note: This doesn't conflict with the CSS Standard which
950
- * doesn't work on numeric attributes anyway.
951
- */
952
- if (is_numeric($att_name)
953
- && $att_expr === ''
954
- && $att_val === '') {
955
- $count = 0;
956
-
957
- // Find index of current element in parent
958
- foreach ($node->parent->children as $c) {
959
- if ($c->tag === $node->tag) {
960
- ++$count;
961
- }
962
- if ($c === $node) {
963
- break;
964
- }
965
- }
966
-
967
- // If this is the correct node, continue with next
968
- // attribute
969
- if ($count === (int)$att_name) {
970
- continue;
971
- }
972
- }
973
-
974
- // Check attribute availability
975
- if ($att_inv) { // Attribute should NOT be set
976
- if (isset($node->attr[$att_name])) {
977
- $pass = false;
978
- break;
979
- }
980
- } else { // Attribute should be set
981
- // todo: "plaintext" is not a valid CSS selector!
982
- if ($att_name !== 'plaintext'
983
- && !isset($node->attr[$att_name])) {
984
- $pass = false;
985
- break;
986
- }
987
- }
988
-
989
- // Continue with next attribute if expression isn't defined
990
- if ($att_expr === '') {
991
- continue;
992
- }
993
-
994
- // If they have told us that this is a "plaintext"
995
- // search then we want the plaintext of the node - right?
996
- // todo "plaintext" is not a valid CSS selector!
997
- if ($att_name === 'plaintext') {
998
- $nodeKeyValue = $node->text();
999
- } else {
1000
- $nodeKeyValue = $node->attr[$att_name];
1001
- }
1002
-
1003
- if (is_object($debug_object)) {
1004
- $debug_object->debug_log(
1005
- 2,
1006
- 'testing node: '
1007
- . $node->tag
1008
- . ' for attribute: '
1009
- . $att_name
1010
- . $att_expr
1011
- . $att_val
1012
- . ' where nodes value is: '
1013
- . $nodeKeyValue
1014
- );
1015
- }
1016
-
1017
- // If lowercase is set, do a case insensitive test of
1018
- // the value of the selector.
1019
- if ($lowercase) {
1020
- $check = $this->match(
1021
- $att_expr,
1022
- strtolower($att_val),
1023
- strtolower($nodeKeyValue),
1024
- $att_case_sensitivity
1025
- );
1026
- } else {
1027
- $check = $this->match(
1028
- $att_expr,
1029
- $att_val,
1030
- $nodeKeyValue,
1031
- $att_case_sensitivity
1032
- );
1033
- }
1034
-
1035
- if (is_object($debug_object)) {
1036
- $debug_object->debug_log(
1037
- 2,
1038
- 'after match: '
1039
- . ($check ? 'true' : 'false')
1040
- );
1041
- }
1042
-
1043
- if (!$check) {
1044
- $pass = false;
1045
- break;
1046
- }
1047
- }
1048
- }
1049
-
1050
- // Found a match. Add to list and clear node
1051
- if ($pass) {
1052
- $ret[$node->_[HDOM_INFO_BEGIN]] = 1;
1053
- }
1054
- unset($node);
1055
- }
1056
- // It's passed by reference so this is actually what this function returns.
1057
- if (is_object($debug_object)) {
1058
- $debug_object->debug_log(1, 'EXIT - ret: ', $ret);
1059
- }
1060
- }
1061
-
1062
- /**
1063
- * Match value and pattern for a given CSS expression
1064
- *
1065
- * **Supported Expressions**
1066
- *
1067
- * | Expression | Description
1068
- * | ---------- | -----------
1069
- * | `=` | $value and $pattern must be equal
1070
- * | `!=` | $value and $pattern must not be equal
1071
- * | `^=` | $value must start with $pattern
1072
- * | `$=` | $value must end with $pattern
1073
- * | `*=` | $value must contain $pattern
1074
- *
1075
- * @param string $exp The expression.
1076
- * @param string $pattern The pattern
1077
- * @param string $value The value
1078
- * @value bool True if $value matches $pattern
1079
- */
1080
- protected function match($exp, $pattern, $value, $case_sensitivity)
1081
- {
1082
- global $debug_object;
1083
- if (is_object($debug_object)) {
1084
- $debug_object->debug_log_entry(1);
1085
- }
1086
-
1087
- if ($case_sensitivity === 'i') {
1088
- $pattern = strtolower($pattern);
1089
- $value = strtolower($value);
1090
- }
1091
-
1092
- switch ($exp) {
1093
- case '=':
1094
- return ($value === $pattern);
1095
- case '!=':
1096
- return ($value !== $pattern);
1097
- case '^=':
1098
- return preg_match('/^' . preg_quote($pattern, '/') . '/', $value);
1099
- case '$=':
1100
- return preg_match('/' . preg_quote($pattern, '/') . '$/', $value);
1101
- case '*=':
1102
- return preg_match('/' . preg_quote($pattern, '/') . '/', $value);
1103
- case '|=':
1104
- /**
1105
- * [att|=val]
1106
- *
1107
- * Represents an element with the att attribute, its value
1108
- * either being exactly "val" or beginning with "val"
1109
- * immediately followed by "-" (U+002D).
1110
- */
1111
- return strpos($value, $pattern) === 0;
1112
- case '~=':
1113
- /**
1114
- * [att~=val]
1115
- *
1116
- * Represents an element with the att attribute whose value is a
1117
- * whitespace-separated list of words, one of which is exactly
1118
- * "val". If "val" contains whitespace, it will never represent
1119
- * anything (since the words are separated by spaces). Also if
1120
- * "val" is the empty string, it will never represent anything.
1121
- */
1122
- return in_array($pattern, explode(' ', trim($value)), true);
1123
- }
1124
- return false;
1125
- }
1126
-
1127
- /**
1128
- * Parse CSS selector
1129
- *
1130
- * @param string $selector_string CSS selector string
1131
- * @return array List of CSS selectors. The format depends on the type of
1132
- * selector:
1133
- *
1134
- * ```php
1135
- *
1136
- * array( // list of selectors (each separated by a comma), i.e. 'img, p, div'
1137
- * array( // list of combinator selectors, i.e. 'img > p > div'
1138
- * array( // selector element
1139
- * [0], // (string) The element tag
1140
- * [1], // (string) The element id
1141
- * [2], // (array<string>) The element classes
1142
- * [3], // (array<array<string>>) The list of attributes, each
1143
- * // with four elements: name, expression, value, inverted
1144
- * [4] // (string) The selector combinator (' ' | '>' | '+' | '~')
1145
- * )
1146
- * )
1147
- * )
1148
- * ```
1149
- *
1150
- * @link https://www.w3.org/TR/selectors/#compound Compound selector
1151
- */
1152
- protected function parse_selector($selector_string)
1153
- {
1154
- global $debug_object;
1155
- if (is_object($debug_object)) {
1156
- $debug_object->debug_log_entry(1);
1157
- }
1158
-
1159
- /**
1160
- * Pattern of CSS selectors, modified from mootools (https://mootools.net/)
1161
- *
1162
- * Paperg: Add the colon to the attribute, so that it properly finds
1163
- * <tag attr:ibute="something" > like google does.
1164
- *
1165
- * Note: if you try to look at this attribute, you MUST use getAttribute
1166
- * since $dom->x:y will fail the php syntax check.
1167
- *
1168
- * Notice the \[ starting the attribute? and the @? following? This
1169
- * implies that an attribute can begin with an @ sign that is not
1170
- * captured. This implies that an html attribute specifier may start
1171
- * with an @ sign that is NOT captured by the expression. Farther study
1172
- * is required to determine of this should be documented or removed.
1173
- *
1174
- * Matches selectors in this order:
1175
- *
1176
- * [0] - full match
1177
- *
1178
- * [1] - tag name
1179
- * ([\w:\*-]*)
1180
- * Matches the tag name consisting of zero or more words, colons,
1181
- * asterisks and hyphens.
1182
- *
1183
- * [2] - id name
1184
- * (?:\#([\w-]+))
1185
- * Optionally matches a id name, consisting of an "#" followed by
1186
- * the id name (one or more words and hyphens).
1187
- *
1188
- * [3] - class names (including dots)
1189
- * (?:\.([\w\.-]+))?
1190
- * Optionally matches a list of classs, consisting of an "."
1191
- * followed by the class name (one or more words and hyphens)
1192
- * where multiple classes can be chained (i.e. ".foo.bar.baz")
1193
- *
1194
- * [4] - attributes
1195
- * ((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?
1196
- * Optionally matches the attributes list
1197
- *
1198
- * [5] - separator
1199
- * ([\/, >+~]+)
1200
- * Matches the selector list separator
1201
- */
1202
- // phpcs:ignore Generic.Files.LineLength
1203
- $pattern = "/([\w:\*-]*)(?:\#([\w-]+))?(?:|\.([\w\.-]+))?((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?([\/, >+~]+)/is";
1204
-
1205
- preg_match_all(
1206
- $pattern,
1207
- trim($selector_string) . ' ', // Add final ' ' as pseudo separator
1208
- $matches,
1209
- PREG_SET_ORDER
1210
- );
1211
-
1212
- if (is_object($debug_object)) {
1213
- $debug_object->debug_log(2, 'Matches Array: ', $matches);
1214
- }
1215
-
1216
- $selectors = array();
1217
- $result = array();
1218
-
1219
- foreach ($matches as $m) {
1220
- $m[0] = trim($m[0]);
1221
-
1222
- // Skip NoOps
1223
- if ($m[0] === '' || $m[0] === '/' || $m[0] === '//') {
1224
- continue;
1225
- }
1226
-
1227
- // Convert to lowercase
1228
- if ($this->dom->lowercase) {
1229
- $m[1] = strtolower($m[1]);
1230
- }
1231
-
1232
- // Extract classes
1233
- if ($m[3] !== '') {
1234
- $m[3] = explode('.', $m[3]);
1235
- }
1236
-
1237
- /* Extract attributes (pattern based on the pattern above!)
1238
-
1239
- * [0] - full match
1240
- * [1] - attribute name
1241
- * [2] - attribute expression
1242
- * [3] - attribute value
1243
- * [4] - case sensitivity
1244
- *
1245
- * Note: Attributes can be negated with a "!" prefix to their name
1246
- */
1247
- if ($m[4] !== '') {
1248
- preg_match_all(
1249
- "/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s*?([iIsS])?)?\]/is",
1250
- trim($m[4]),
1251
- $attributes,
1252
- PREG_SET_ORDER
1253
- );
1254
-
1255
- // Replace element by array
1256
- $m[4] = array();
1257
-
1258
- foreach ($attributes as $att) {
1259
- // Skip empty matches
1260
- if (trim($att[0]) === '') {
1261
- continue;
1262
- }
1263
-
1264
- $inverted = (isset($att[1][0]) && $att[1][0] === '!');
1265
- $m[4][] = array(
1266
- $inverted ? substr($att[1], 1) : $att[1], // Name
1267
- (isset($att[2])) ? $att[2] : '', // Expression
1268
- (isset($att[3])) ? $att[3] : '', // Value
1269
- $inverted, // Inverted Flag
1270
- (isset($att[4])) ? strtolower($att[4]) : '', // Case-Sensitivity
1271
- );
1272
- }
1273
- }
1274
-
1275
- // Sanitize Separator
1276
- if ($m[5] !== '' && trim($m[5]) === '') { // Descendant Separator
1277
- $m[5] = ' ';
1278
- } else { // Other Separator
1279
- $m[5] = trim($m[5]);
1280
- }
1281
-
1282
- // Clear Separator if it's a Selector List
1283
- if ($is_list = ($m[5] === ',')) {
1284
- $m[5] = '';
1285
- }
1286
-
1287
- // Remove full match before adding to results
1288
- array_shift($m);
1289
- $result[] = $m;
1290
-
1291
- if ($is_list) { // Selector List
1292
- $selectors[] = $result;
1293
- $result = array();
1294
- }
1295
- }
1296
-
1297
- if (count($result) > 0) {
1298
- $selectors[] = $result;
1299
- }
1300
- return $selectors;
1301
- }
1302
-
1303
- function __get($name)
1304
- {
1305
- if (isset($this->attr[$name])) {
1306
- return $this->convert_text($this->attr[$name]);
1307
- }
1308
- switch ($name) {
1309
- case 'outertext':
1310
- return $this->outertext();
1311
- case 'innertext':
1312
- return $this->innertext();
1313
- case 'plaintext':
1314
- return $this->text();
1315
- case 'xmltext':
1316
- return $this->xmltext();
1317
- default:
1318
- return array_key_exists($name, $this->attr);
1319
- }
1320
- }
1321
-
1322
- function __set($name, $value)
1323
- {
1324
- global $debug_object;
1325
- if (is_object($debug_object)) {
1326
- $debug_object->debug_log_entry(1);
1327
- }
1328
-
1329
- switch ($name) {
1330
- case 'outertext':
1331
- return $this->_[HDOM_INFO_OUTER] = $value;
1332
- case 'innertext':
1333
- if (isset($this->_[HDOM_INFO_TEXT])) {
1334
- return $this->_[HDOM_INFO_TEXT] = $value;
1335
- }
1336
- return $this->_[HDOM_INFO_INNER] = $value;
1337
- }
1338
-
1339
- if (!isset($this->attr[$name])) {
1340
- $this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
1341
- $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
1342
- }
1343
-
1344
- $this->attr[$name] = $value;
1345
- }
1346
-
1347
- function __isset($name)
1348
- {
1349
- switch ($name) {
1350
- case 'outertext':
1351
- return true;
1352
- case 'innertext':
1353
- return true;
1354
- case 'plaintext':
1355
- return true;
1356
- }
1357
- //no value attr: nowrap, checked selected...
1358
- return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
1359
- }
1360
-
1361
- function __unset($name)
1362
- {
1363
- if (isset($this->attr[$name])) {
1364
- unset($this->attr[$name]);
1365
- }
1366
- }
1367
-
1368
- // PaperG - Function to convert the text from one character set to another
1369
- // if the two sets are not the same.
1370
- function convert_text($text)
1371
- {
1372
- global $debug_object;
1373
- if (is_object($debug_object)) {
1374
- $debug_object->debug_log_entry(1);
1375
- }
1376
-
1377
- $converted_text = $text;
1378
-
1379
- $sourceCharset = '';
1380
- $targetCharset = '';
1381
-
1382
- if ($this->dom) {
1383
- $sourceCharset = strtoupper($this->dom->_charset);
1384
- $targetCharset = strtoupper($this->dom->_target_charset);
1385
- }
1386
-
1387
- if (is_object($debug_object)) {
1388
- $debug_object->debug_log(
1389
- 3,
1390
- 'source charset: '
1391
- . $sourceCharset
1392
- . ' target charaset: '
1393
- . $targetCharset
1394
- );
1395
- }
1396
-
1397
- if (!empty($sourceCharset)
1398
- && !empty($targetCharset)
1399
- && (strcasecmp($sourceCharset, $targetCharset) != 0)) {
1400
- // Check if the reported encoding could have been incorrect and the text is actually already UTF-8
1401
- if ((strcasecmp($targetCharset, 'UTF-8') == 0)
1402
- && ($this->is_utf8($text))) {
1403
- $converted_text = $text;
1404
- } else {
1405
- $converted_text = iconv($sourceCharset, $targetCharset, $text);
1406
- }
1407
- }
1408
-
1409
- // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
1410
- if ($targetCharset === 'UTF-8') {
1411
- if (substr($converted_text, 0, 3) === "\xef\xbb\xbf") {
1412
- $converted_text = substr($converted_text, 3);
1413
- }
1414
-
1415
- if (substr($converted_text, -3) === "\xef\xbb\xbf") {
1416
- $converted_text = substr($converted_text, 0, -3);
1417
- }
1418
- }
1419
-
1420
- return $converted_text;
1421
- }
1422
-
1423
- /**
1424
- * Returns true if $string is valid UTF-8 and false otherwise.
1425
- *
1426
- * @param mixed $str String to be tested
1427
- * @return boolean
1428
- */
1429
- static function is_utf8($str)
1430
- {
1431
- $c = 0;
1432
- $b = 0;
1433
- $bits = 0;
1434
- $len = strlen($str);
1435
- for ($i = 0; $i < $len; $i++) {
1436
- $c = ord($str[$i]);
1437
- if ($c > 128) {
1438
- if (($c >= 254)) {
1439
- return false;
1440
- } elseif ($c >= 252) {
1441
- $bits = 6;
1442
- } elseif ($c >= 248) {
1443
- $bits = 5;
1444
- } elseif ($c >= 240) {
1445
- $bits = 4;
1446
- } elseif ($c >= 224) {
1447
- $bits = 3;
1448
- } elseif ($c >= 192) {
1449
- $bits = 2;
1450
- } else {
1451
- return false;
1452
- }
1453
- if (($i + $bits) > $len) {
1454
- return false;
1455
- }
1456
- while ($bits > 1) {
1457
- $i++;
1458
- $b = ord($str[$i]);
1459
- if ($b < 128 || $b > 191) {
1460
- return false;
1461
- }
1462
- $bits--;
1463
- }
1464
- }
1465
- }
1466
- return true;
1467
- }
1468
-
1469
- /**
1470
- * Function to try a few tricks to determine the displayed size of an img on
1471
- * the page. NOTE: This will ONLY work on an IMG tag. Returns FALSE on all
1472
- * other tag types.
1473
- *
1474
- * @author John Schlick
1475
- * @version April 19 2012
1476
- * @return array an array containing the 'height' and 'width' of the image
1477
- * on the page or -1 if we can't figure it out.
1478
- */
1479
- function get_display_size()
1480
- {
1481
- global $debug_object;
1482
-
1483
- $width = -1;
1484
- $height = -1;
1485
-
1486
- if ($this->tag !== 'img') {
1487
- return false;
1488
- }
1489
-
1490
- // See if there is aheight or width attribute in the tag itself.
1491
- if (isset($this->attr['width'])) {
1492
- $width = $this->attr['width'];
1493
- }
1494
-
1495
- if (isset($this->attr['height'])) {
1496
- $height = $this->attr['height'];
1497
- }
1498
-
1499
- // Now look for an inline style.
1500
- if (isset($this->attr['style'])) {
1501
- // Thanks to user gnarf from stackoverflow for this regular expression.
1502
- $attributes = array();
1503
-
1504
- preg_match_all(
1505
- '/([\w-]+)\s*:\s*([^;]+)\s*;?/',
1506
- $this->attr['style'],
1507
- $matches,
1508
- PREG_SET_ORDER
1509
- );
1510
-
1511
- foreach ($matches as $match) {
1512
- $attributes[$match[1]] = $match[2];
1513
- }
1514
-
1515
- // If there is a width in the style attributes:
1516
- if (isset($attributes['width']) && $width == -1) {
1517
- // check that the last two characters are px (pixels)
1518
- if (strtolower(substr($attributes['width'], -2)) === 'px') {
1519
- $proposed_width = substr($attributes['width'], 0, -2);
1520
- // Now make sure that it's an integer and not something stupid.
1521
- if (filter_var($proposed_width, FILTER_VALIDATE_INT)) {
1522
- $width = $proposed_width;
1523
- }
1524
- }
1525
- }
1526
-
1527
- // If there is a width in the style attributes:
1528
- if (isset($attributes['height']) && $height == -1) {
1529
- // check that the last two characters are px (pixels)
1530
- if (strtolower(substr($attributes['height'], -2)) == 'px') {
1531
- $proposed_height = substr($attributes['height'], 0, -2);
1532
- // Now make sure that it's an integer and not something stupid.
1533
- if (filter_var($proposed_height, FILTER_VALIDATE_INT)) {
1534
- $height = $proposed_height;
1535
- }
1536
- }
1537
- }
1538
- }
1539
-
1540
- // Future enhancement:
1541
- // Look in the tag to see if there is a class or id specified that has
1542
- // a height or width attribute to it.
1543
-
1544
- // Far future enhancement
1545
- // Look at all the parent tags of this image to see if they specify a
1546
- // class or id that has an img selector that specifies a height or width
1547
- // Note that in this case, the class or id will have the img subselector
1548
- // for it to apply to the image.
1549
-
1550
- // ridiculously far future development
1551
- // If the class or id is specified in a SEPARATE css file thats not on
1552
- // the page, go get it and do what we were just doing for the ones on
1553
- // the page.
1554
-
1555
- $result = array(
1556
- 'height' => $height,
1557
- 'width' => $width
1558
- );
1559
-
1560
- return $result;
1561
- }
1562
-
1563
- // camel naming conventions
1564
- function getAllAttributes()
1565
- {
1566
- return $this->attr;
1567
- }
1568
-
1569
- function getAttribute($name)
1570
- {
1571
- return $this->__get($name);
1572
- }
1573
-
1574
- function setAttribute($name, $value)
1575
- {
1576
- $this->__set($name, $value);
1577
- }
1578
-
1579
- function hasAttribute($name)
1580
- {
1581
- return $this->__isset($name);
1582
- }
1583
-
1584
- function removeAttribute($name)
1585
- {
1586
- $this->__set($name, null);
1587
- }
1588
-
1589
- function getElementById($id)
1590
- {
1591
- return $this->find("#$id", 0);
1592
- }
1593
-
1594
- function getElementsById($id, $idx = null)
1595
- {
1596
- return $this->find("#$id", $idx);
1597
- }
1598
-
1599
- function getElementByTagName($name)
1600
- {
1601
- return $this->find($name, 0);
1602
- }
1603
-
1604
- function getElementsByTagName($name, $idx = null)
1605
- {
1606
- return $this->find($name, $idx);
1607
- }
1608
-
1609
- function parentNode()
1610
- {
1611
- return $this->parent();
1612
- }
1613
-
1614
- function childNodes($idx = -1)
1615
- {
1616
- return $this->children($idx);
1617
- }
1618
-
1619
- function firstChild()
1620
- {
1621
- return $this->first_child();
1622
- }
1623
-
1624
- function lastChild()
1625
- {
1626
- return $this->last_child();
1627
- }
1628
-
1629
- function nextSibling()
1630
- {
1631
- return $this->next_sibling();
1632
- }
1633
-
1634
- function previousSibling()
1635
- {
1636
- return $this->prev_sibling();
1637
- }
1638
-
1639
- function hasChildNodes()
1640
- {
1641
- return $this->has_child();
1642
- }
1643
-
1644
- function nodeName()
1645
- {
1646
- return $this->tag;
1647
- }
1648
-
1649
- function appendChild($node)
1650
- {
1651
- $node->parent($this);
1652
- return $node;
1653
- }
1654
- }
1655
-
1656
- /**
1657
- * simple html dom parser
1658
- *
1659
- * Paperg - in the find routine: allow us to specify that we want case
1660
- * insensitive testing of the value of the selector.
1661
- *
1662
- * Paperg - change $size from protected to public so we can easily access it
1663
- *
1664
- * Paperg - added ForceTagsClosed in the constructor which tells us whether we
1665
- * trust the html or not. Default is to NOT trust it.
1666
- *
1667
- * @package PlaceLocalInclude
1668
- */
1669
- class simple_html_dom
1670
- {
1671
- /**
1672
- * The root node of the document
1673
- *
1674
- * @var object
1675
- */
1676
- public $root = null;
1677
-
1678
- /**
1679
- * List of nodes in the current DOM
1680
- *
1681
- * @var array
1682
- */
1683
- public $nodes = array();
1684
-
1685
- /**
1686
- * Callback function to run for each element in the DOM.
1687
- *
1688
- * @var callable|null
1689
- */
1690
- public $callback = null;
1691
-
1692
- /**
1693
- * Indicates how tags and attributes are matched
1694
- *
1695
- * @var bool When set to **true** tags and attributes will be converted to
1696
- * lowercase before matching.
1697
- */
1698
- public $lowercase = false;
1699
-
1700
- /**
1701
- * Original document size
1702
- *
1703
- * Holds the original document size.
1704
- *
1705
- * @var int
1706
- */
1707
- public $original_size;
1708
-
1709
- /**
1710
- * Current document size
1711
- *
1712
- * Holds the current document size. The document size is determined by the
1713
- * string length of ({@see simple_html_dom::$doc}).
1714
- *
1715
- * _Note_: Using this variable is more efficient than calling `strlen($doc)`
1716
- *
1717
- * @var int
1718
- * */
1719
- public $size;
1720
-
1721
- /**
1722
- * Current position in the document
1723
- *
1724
- * @var int
1725
- */
1726
- protected $pos;
1727
-
1728
- /**
1729
- * The document
1730
- *
1731
- * @var string
1732
- */
1733
- protected $doc;
1734
-
1735
- /**
1736
- * Current character
1737
- *
1738
- * Holds the current character at position {@see simple_html_dom::$pos} in
1739
- * the document {@see simple_html_dom::$doc}
1740
- *
1741
- * _Note_: Using this variable is more efficient than calling
1742
- * `substr($doc, $pos, 1)`
1743
- *
1744
- * @var string
1745
- */
1746
- protected $char;
1747
-
1748
- protected $cursor;
1749
-
1750
- /**
1751
- * Parent node of the next node detected by the parser
1752
- *
1753
- * @var object
1754
- */
1755
- protected $parent;
1756
- protected $noise = array();
1757
-
1758
- /**
1759
- * Tokens considered blank in HTML
1760
- *
1761
- * @var string
1762
- */
1763
- protected $token_blank = " \t\r\n";
1764
-
1765
- /**
1766
- * Tokens to identify the equal sign for attributes, stopping either at the
1767
- * closing tag ("/" i.e. "<html />") or the end of an opening tag (">" i.e.
1768
- * "<html>")
1769
- *
1770
- * @var string
1771
- */
1772
- protected $token_equal = ' =/>';
1773
-
1774
- /**
1775
- * Tokens to identify the end of a tag name. A tag name either ends on the
1776
- * ending slash ("/" i.e. "<html/>") or whitespace ("\s\r\n\t")
1777
- *
1778
- * @var string
1779
- */
1780
- protected $token_slash = " />\r\n\t";
1781
-
1782
- /**
1783
- * Tokens to identify the end of an attribute
1784
- *
1785
- * @var string
1786
- */
1787
- protected $token_attr = ' >';
1788
-
1789
- // Note that this is referenced by a child node, and so it needs to be
1790
- // public for that node to see this information.
1791
- public $_charset = '';
1792
- public $_target_charset = '';
1793
-
1794
- /**
1795
- * Innertext for <br> elements
1796
- *
1797
- * @var string
1798
- */
1799
- protected $default_br_text = '';
1800
-
1801
- /**
1802
- * Suffix for <span> elements
1803
- *
1804
- * @var string
1805
- */
1806
- public $default_span_text = '';
1807
-
1808
- /**
1809
- * Defines a list of self-closing tags (Void elements) according to the HTML
1810
- * Specification
1811
- *
1812
- * _Remarks_:
1813
- * - Use `isset()` instead of `in_array()` on array elements to boost
1814
- * performance about 30%
1815
- * - Sort elements by name for better readability!
1816
- *
1817
- * @link https://www.w3.org/TR/html HTML Specification
1818
- * @link https://www.w3.org/TR/html/syntax.html#void-elements Void elements
1819
- */
1820
- protected $self_closing_tags = array(
1821
- 'area' => 1,
1822
- 'base' => 1,
1823
- 'br' => 1,
1824
- 'col' => 1,
1825
- 'embed' => 1,
1826
- 'hr' => 1,
1827
- 'img' => 1,
1828
- 'input' => 1,
1829
- 'link' => 1,
1830
- 'meta' => 1,
1831
- 'param' => 1,
1832
- 'source' => 1,
1833
- 'track' => 1,
1834
- 'wbr' => 1
1835
- );
1836
-
1837
- /**
1838
- * Defines a list of tags which - if closed - close all optional closing
1839
- * elements within if they haven't been closed yet. (So, an element where
1840
- * neither opening nor closing tag is omissible consistently closes every
1841
- * optional closing element within)
1842
- *
1843
- * _Remarks_:
1844
- * - Use `isset()` instead of `in_array()` on array elements to boost
1845
- * performance about 30%
1846
- * - Sort elements by name for better readability!
1847
- */
1848
- protected $block_tags = array(
1849
- 'body' => 1,
1850
- 'div' => 1,
1851
- 'form' => 1,
1852
- 'root' => 1,
1853
- 'span' => 1,
1854
- 'table' => 1
1855
- );
1856
-
1857
- /**
1858
- * Defines elements whose end tag is omissible.
1859
- *
1860
- * * key = Name of an element whose end tag is omissible.
1861
- * * value = Names of elements whose end tag is omissible, that are closed
1862
- * by the current element.
1863
- *
1864
- * _Remarks_:
1865
- * - Use `isset()` instead of `in_array()` on array elements to boost
1866
- * performance about 30%
1867
- * - Sort elements by name for better readability!
1868
- *
1869
- * **Example**
1870
- *
1871
- * An `li` element’s end tag may be omitted if the `li` element is immediately
1872
- * followed by another `li` element. To do that, add following element to the
1873
- * array:
1874
- *
1875
- * ```php
1876
- * 'li' => array('li'),
1877
- * ```
1878
- *
1879
- * With this, the following two examples are considered equal. Note that the
1880
- * second example is missing the closing tags on `li` elements.
1881
- *
1882
- * ```html
1883
- * <ul><li>First Item</li><li>Second Item</li></ul>
1884
- * ```
1885
- *
1886
- * <ul><li>First Item</li><li>Second Item</li></ul>
1887
- *
1888
- * ```html
1889
- * <ul><li>First Item<li>Second Item</ul>
1890
- * ```
1891
- *
1892
- * <ul><li>First Item<li>Second Item</ul>
1893
- *
1894
- * @var array A two-dimensional array where the key is the name of an
1895
- * element whose end tag is omissible and the value is an array of elements
1896
- * whose end tag is omissible, that are closed by the current element.
1897
- *
1898
- * @link https://www.w3.org/TR/html/syntax.html#optional-tags Optional tags
1899
- *
1900
- * @todo The implementation of optional closing tags doesn't work in all cases
1901
- * because it only consideres elements who close other optional closing
1902
- * tags, not taking into account that some (non-blocking) tags should close
1903
- * these optional closing tags. For example, the end tag for "p" is omissible
1904
- * and can be closed by an "address" element, whose end tag is NOT omissible.
1905
- * Currently a "p" element without closing tag stops at the next "p" element
1906
- * or blocking tag, even if it contains other elements.
1907
- *
1908
- * @todo Known sourceforge issue #2977341
1909
- * B tags that are not closed cause us to return everything to the end of
1910
- * the document.
1911
- */
1912
- protected $optional_closing_tags = array(
1913
- // Not optional, see
1914
- // https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
1915
- 'b' => array('b' => 1),
1916
- 'dd' => array('dd' => 1, 'dt' => 1),
1917
- // Not optional, see
1918
- // https://www.w3.org/TR/html/grouping-content.html#the-dl-element
1919
- 'dl' => array('dd' => 1, 'dt' => 1),
1920
- 'dt' => array('dd' => 1, 'dt' => 1),
1921
- 'li' => array('li' => 1),
1922
- 'optgroup' => array('optgroup' => 1, 'option' => 1),
1923
- 'option' => array('optgroup' => 1, 'option' => 1),
1924
- 'p' => array('p' => 1),
1925
- 'rp' => array('rp' => 1, 'rt' => 1),
1926
- 'rt' => array('rp' => 1, 'rt' => 1),
1927
- 'td' => array('td' => 1, 'th' => 1),
1928
- 'th' => array('td' => 1, 'th' => 1),
1929
- 'tr' => array('td' => 1, 'th' => 1, 'tr' => 1),
1930
- );
1931
-
1932
- function __construct(
1933
- $str = null,
1934
- $lowercase = true,
1935
- $forceTagsClosed = true,
1936
- $target_charset = DEFAULT_TARGET_CHARSET,
1937
- $stripRN = true,
1938
- $defaultBRText = DEFAULT_BR_TEXT,
1939
- $defaultSpanText = DEFAULT_SPAN_TEXT,
1940
- $options = 0
1941
- ) {
1942
- if ($str) {
1943
- if (preg_match('/^http:\/\//i', $str) || is_file($str)) {
1944
- $this->load_file($str);
1945
- } else {
1946
- $this->load(
1947
- $str,
1948
- $lowercase,
1949
- $stripRN,
1950
- $defaultBRText,
1951
- $defaultSpanText,
1952
- $options
1953
- );
1954
- }
1955
- }
1956
- // Forcing tags to be closed implies that we don't trust the html, but
1957
- // it can lead to parsing errors if we SHOULD trust the html.
1958
- if (!$forceTagsClosed) {
1959
- $this->optional_closing_array = array();
1960
- }
1961
-
1962
- $this->_target_charset = $target_charset;
1963
- }
1964
-
1965
- function __destruct()
1966
- {
1967
- $this->clear();
1968
- }
1969
-
1970
- // load html from string
1971
- function load(
1972
- $str,
1973
- $lowercase = true,
1974
- $stripRN = true,
1975
- $defaultBRText = DEFAULT_BR_TEXT,
1976
- $defaultSpanText = DEFAULT_SPAN_TEXT,
1977
- $options = 0
1978
- ) {
1979
- global $debug_object;
1980
-
1981
- // prepare
1982
- $this->prepare($str, $lowercase, $defaultBRText, $defaultSpanText);
1983
-
1984
- // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
1985
- // Script tags removal now preceeds style tag removal.
1986
- // strip out <script> tags
1987
- $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
1988
- $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
1989
-
1990
- // strip out the \r \n's if we are told to.
1991
- if ($stripRN) {
1992
- $this->doc = str_replace("\r", ' ', $this->doc);
1993
- $this->doc = str_replace("\n", ' ', $this->doc);
1994
-
1995
- // set the length of content since we have changed it.
1996
- $this->size = strlen($this->doc);
1997
- }
1998
-
1999
- // strip out cdata
2000
- $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
2001
- // strip out comments
2002
- $this->remove_noise("'<!--(.*?)-->'is");
2003
- // strip out <style> tags
2004
- $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
2005
- $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
2006
- // strip out preformatted tags
2007
- $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
2008
- // strip out server side scripts
2009
- $this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
2010
-
2011
- if ($options & HDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts
2012
- $this->remove_noise("'(\{\w)(.*?)(\})'s", true);
2013
- }
2014
-
2015
- // parsing
2016
- $this->parse();
2017
- // end
2018
- $this->root->_[HDOM_INFO_END] = $this->cursor;
2019
- $this->parse_charset();
2020
-
2021
- // make load function chainable
2022
- return $this;
2023
- }
2024
-
2025
- // load html from file
2026
- function load_file()
2027
- {
2028
- $args = func_get_args();
2029
-
2030
- if (($doc = call_user_func_array('file_get_contents', $args)) !== false) {
2031
- $this->load($doc, true);
2032
- } else {
2033
- return false;
2034
- }
2035
- }
2036
-
2037
- /**
2038
- * Set the callback function
2039
- *
2040
- * @param callable $function_name Callback function to run for each element
2041
- * in the DOM.
2042
- * @return void
2043
- */
2044
- function set_callback($function_name)
2045
- {
2046
- $this->callback = $function_name;
2047
- }
2048
-
2049
- /**
2050
- * Remove callback function
2051
- *
2052
- * @return void
2053
- */
2054
- function remove_callback()
2055
- {
2056
- $this->callback = null;
2057
- }
2058
-
2059
- // save dom as string
2060
- function save($filepath = '')
2061
- {
2062
- $ret = $this->root->innertext();
2063
- if ($filepath !== '') {
2064
- file_put_contents($filepath, $ret, LOCK_EX);
2065
- }
2066
- return $ret;
2067
- }
2068
-
2069
- // find dom node by css selector
2070
- // Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
2071
- function find($selector, $idx = null, $lowercase = false)
2072
- {
2073
- return $this->root->find($selector, $idx, $lowercase);
2074
- }
2075
-
2076
- // clean up memory due to php5 circular references memory leak...
2077
- function clear()
2078
- {
2079
- foreach ($this->nodes as $n) {
2080
- $n->clear();
2081
- $n = null;
2082
- }
2083
-
2084
- // This add next line is documented in the sourceforge repository.
2085
- // 2977248 as a fix for ongoing memory leaks that occur even with the
2086
- // use of clear.
2087
- if (isset($this->children)) {
2088
- foreach ($this->children as $n) {
2089
- $n->clear();
2090
- $n = null;
2091
- }
2092
- }
2093
-
2094
- if (isset($this->parent)) {
2095
- $this->parent->clear();
2096
- unset($this->parent);
2097
- }
2098
-
2099
- if (isset($this->root)) {
2100
- $this->root->clear();
2101
- unset($this->root);
2102
- }
2103
-
2104
- unset($this->doc);
2105
- unset($this->noise);
2106
- }
2107
-
2108
- function dump($show_attr = true)
2109
- {
2110
- $this->root->dump($show_attr);
2111
- }
2112
-
2113
- // prepare HTML data and init everything
2114
- protected function prepare(
2115
- $str,
2116
- $lowercase = true,
2117
- $defaultBRText = DEFAULT_BR_TEXT,
2118
- $defaultSpanText = DEFAULT_SPAN_TEXT
2119
- ) {
2120
- $this->clear();
2121
-
2122
- $this->doc = trim($str);
2123
- $this->size = strlen($this->doc);
2124
- $this->original_size = $this->size; // original size of the html
2125
- $this->pos = 0;
2126
- $this->cursor = 1;
2127
- $this->noise = array();
2128
- $this->nodes = array();
2129
- $this->lowercase = $lowercase;
2130
- $this->default_br_text = $defaultBRText;
2131
- $this->default_span_text = $defaultSpanText;
2132
- $this->root = new simple_html_dom_node($this);
2133
- $this->root->tag = 'root';
2134
- $this->root->_[HDOM_INFO_BEGIN] = -1;
2135
- $this->root->nodetype = HDOM_TYPE_ROOT;
2136
- $this->parent = $this->root;
2137
- if ($this->size > 0) {
2138
- $this->char = $this->doc[0];
2139
- }
2140
- }
2141
-
2142
- /**
2143
- * Parse HTML content
2144
- *
2145
- * @return bool True on success
2146
- */
2147
- protected function parse()
2148
- {
2149
- while (true) {
2150
- // Read next tag if there is no text between current position and the
2151
- // next opening tag.
2152
- if (($s = $this->copy_until_char('<')) === '') {
2153
- if ($this->read_tag()) {
2154
- continue;
2155
- } else {
2156
- return true;
2157
- }
2158
- }
2159
-
2160
- // Add a text node for text between tags
2161
- $node = new simple_html_dom_node($this);
2162
- ++$this->cursor;
2163
- $node->_[HDOM_INFO_TEXT] = $s;
2164
- $this->link_nodes($node, false);
2165
- }
2166
- }
2167
-
2168
- // PAPERG - dkchou - added this to try to identify the character set of the
2169
- // page we have just parsed so we know better how to spit it out later.
2170
- // NOTE: IF you provide a routine called
2171
- // get_last_retrieve_url_contents_content_type which returns the
2172
- // CURLINFO_CONTENT_TYPE from the last curl_exec
2173
- // (or the content_type header from the last transfer), we will parse THAT,
2174
- // and if a charset is specified, we will use it over any other mechanism.
2175
- protected function parse_charset()
2176
- {
2177
- global $debug_object;
2178
-
2179
- $charset = null;
2180
-
2181
- if (function_exists('get_last_retrieve_url_contents_content_type')) {
2182
- $contentTypeHeader = get_last_retrieve_url_contents_content_type();
2183
- $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
2184
- if ($success) {
2185
- $charset = $matches[1];
2186
- if (is_object($debug_object)) {
2187
- $debug_object->debug_log(
2188
- 2,
2189
- 'header content-type found charset of: '
2190
- . $charset
2191
- );
2192
- }
2193
- }
2194
- }
2195
-
2196
- if (empty($charset)) {
2197
- $el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
2198
-
2199
- if (!empty($el)) {
2200
- $fullvalue = $el->content;
2201
- if (is_object($debug_object)) {
2202
- $debug_object->debug_log(
2203
- 2,
2204
- 'meta content-type tag found'
2205
- . $fullvalue
2206
- );
2207
- }
2208
-
2209
- if (!empty($fullvalue)) {
2210
- $success = preg_match(
2211
- '/charset=(.+)/i',
2212
- $fullvalue,
2213
- $matches
2214
- );
2215
-
2216
- if ($success) {
2217
- $charset = $matches[1];
2218
- } else {
2219
- // If there is a meta tag, and they don't specify the
2220
- // character set, research says that it's typically
2221
- // ISO-8859-1
2222
- if (is_object($debug_object)) {
2223
- $debug_object->debug_log(
2224
- 2,
2225
- 'meta content-type tag couldn\'t be parsed. using iso-8859 default.'
2226
- );
2227
- }
2228
-
2229
- $charset = 'ISO-8859-1';
2230
- }
2231
- }
2232
- }
2233
- }
2234
-
2235
- // If we couldn't find a charset above, then lets try to detect one
2236
- // based on the text we got...
2237
- if (empty($charset)) {
2238
- // Use this in case mb_detect_charset isn't installed/loaded on
2239
- // this machine.
2240
- $charset = false;
2241
- if (function_exists('mb_detect_encoding')) {
2242
- // Have php try to detect the encoding from the text given to us.
2243
- $charset = mb_detect_encoding(
2244
- $this->doc . 'ascii',
2245
- $encoding_list = array( 'UTF-8', 'CP1252' )
2246
- );
2247
-
2248
- if (is_object($debug_object)) {
2249
- $debug_object->debug_log(2, 'mb_detect found: ' . $charset);
2250
- }
2251
- }
2252
-
2253
- // and if this doesn't work... then we need to just wrongheadedly
2254
- // assume it's UTF-8 so that we can move on - cause this will
2255
- // usually give us most of what we need...
2256
- if ($charset === false) {
2257
- if (is_object($debug_object)) {
2258
- $debug_object->debug_log(
2259
- 2,
2260
- 'since mb_detect failed - using default of utf-8'
2261
- );
2262
- }
2263
-
2264
- $charset = 'UTF-8';
2265
- }
2266
- }
2267
-
2268
- // Since CP1252 is a superset, if we get one of it's subsets, we want
2269
- // it instead.
2270
- if ((strtolower($charset) == strtolower('ISO-8859-1'))
2271
- || (strtolower($charset) == strtolower('Latin1'))
2272
- || (strtolower($charset) == strtolower('Latin-1'))) {
2273
- if (is_object($debug_object)) {
2274
- $debug_object->debug_log(
2275
- 2,
2276
- 'replacing ' . $charset . ' with CP1252 as its a superset'
2277
- );
2278
- }
2279
-
2280
- $charset = 'CP1252';
2281
- }
2282
-
2283
- if (is_object($debug_object)) {
2284
- $debug_object->debug_log(1, 'EXIT - ' . $charset);
2285
- }
2286
-
2287
- return $this->_charset = $charset;
2288
- }
2289
-
2290
- /**
2291
- * Parse tag from current document position.
2292
- *
2293
- * @return bool True if a tag was found, false otherwise
2294
- */
2295
- protected function read_tag()
2296
- {
2297
- // Set end position if no further tags found
2298
- if ($this->char !== '<') {
2299
- $this->root->_[HDOM_INFO_END] = $this->cursor;
2300
- return false;
2301
- }
2302
-
2303
- $begin_tag_pos = $this->pos;
2304
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2305
-
2306
- // end tag
2307
- if ($this->char === '/') {
2308
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2309
-
2310
- // Skip whitespace in end tags (i.e. in "</ html>")
2311
- $this->skip($this->token_blank);
2312
- $tag = $this->copy_until_char('>');
2313
-
2314
- // Skip attributes in end tags
2315
- if (($pos = strpos($tag, ' ')) !== false) {
2316
- $tag = substr($tag, 0, $pos);
2317
- }
2318
-
2319
- $parent_lower = strtolower($this->parent->tag);
2320
- $tag_lower = strtolower($tag);
2321
-
2322
- // The end tag is supposed to close the parent tag. Handle situations
2323
- // when it doesn't
2324
- if ($parent_lower !== $tag_lower) {
2325
- // Parent tag does not have to be closed necessarily (optional closing tag)
2326
- // Current tag is a block tag, so it may close an ancestor
2327
- if (isset($this->optional_closing_tags[$parent_lower])
2328
- && isset($this->block_tags[$tag_lower])) {
2329
- $this->parent->_[HDOM_INFO_END] = 0;
2330
- $org_parent = $this->parent;
2331
-
2332
- // Traverse ancestors to find a matching opening tag
2333
- // Stop at root node
2334
- while (($this->parent->parent)
2335
- && strtolower($this->parent->tag) !== $tag_lower
2336
- ) {
2337
- $this->parent = $this->parent->parent;
2338
- }
2339
-
2340
- // If we don't have a match add current tag as text node
2341
- if (strtolower($this->parent->tag) !== $tag_lower) {
2342
- $this->parent = $org_parent; // restore origonal parent
2343
-
2344
- if ($this->parent->parent) {
2345
- $this->parent = $this->parent->parent;
2346
- }
2347
-
2348
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
2349
- return $this->as_text_node($tag);
2350
- }
2351
- } elseif (($this->parent->parent)
2352
- && isset($this->block_tags[$tag_lower])
2353
- ) {
2354
- // Grandparent exists and current tag is a block tag, so our
2355
- // parent doesn't have an end tag
2356
- $this->parent->_[HDOM_INFO_END] = 0; // No end tag
2357
- $org_parent = $this->parent;
2358
-
2359
- // Traverse ancestors to find a matching opening tag
2360
- // Stop at root node
2361
- while (($this->parent->parent)
2362
- && strtolower($this->parent->tag) !== $tag_lower
2363
- ) {
2364
- $this->parent = $this->parent->parent;
2365
- }
2366
-
2367
- // If we don't have a match add current tag as text node
2368
- if (strtolower($this->parent->tag) !== $tag_lower) {
2369
- $this->parent = $org_parent; // restore origonal parent
2370
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
2371
- return $this->as_text_node($tag);
2372
- }
2373
- } elseif (($this->parent->parent)
2374
- && strtolower($this->parent->parent->tag) === $tag_lower
2375
- ) { // Grandparent exists and current tag closes it
2376
- $this->parent->_[HDOM_INFO_END] = 0;
2377
- $this->parent = $this->parent->parent;
2378
- } else { // Random tag, add as text node
2379
- return $this->as_text_node($tag);
2380
- }
2381
- }
2382
-
2383
- // Set end position of parent tag to current cursor position
2384
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
2385
-
2386
- if ($this->parent->parent) {
2387
- $this->parent = $this->parent->parent;
2388
- }
2389
-
2390
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2391
- return true;
2392
- }
2393
-
2394
- // start tag
2395
- $node = new simple_html_dom_node($this);
2396
- $node->_[HDOM_INFO_BEGIN] = $this->cursor;
2397
- ++$this->cursor;
2398
- $tag = $this->copy_until($this->token_slash); // Get tag name
2399
- $node->tag_start = $begin_tag_pos;
2400
-
2401
- // doctype, cdata & comments...
2402
- // <!DOCTYPE html>
2403
- // <![CDATA[ ... ]]>
2404
- // <!-- Comment -->
2405
- if (isset($tag[0]) && $tag[0] === '!') {
2406
- $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
2407
-
2408
- if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--")
2409
- $node->nodetype = HDOM_TYPE_COMMENT;
2410
- $node->tag = 'comment';
2411
- } else { // Could be doctype or CDATA but we don't care
2412
- $node->nodetype = HDOM_TYPE_UNKNOWN;
2413
- $node->tag = 'unknown';
2414
- }
2415
-
2416
- if ($this->char === '>') {
2417
- $node->_[HDOM_INFO_TEXT] .= '>';
2418
- }
2419
-
2420
- $this->link_nodes($node, true);
2421
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2422
- return true;
2423
- }
2424
-
2425
- // The start tag cannot contain another start tag, if so add as text
2426
- // i.e. "<<html>"
2427
- if ($pos = strpos($tag, '<') !== false) {
2428
- $tag = '<' . substr($tag, 0, -1);
2429
- $node->_[HDOM_INFO_TEXT] = $tag;
2430
- $this->link_nodes($node, false);
2431
- $this->char = $this->doc[--$this->pos]; // prev
2432
- return true;
2433
- }
2434
-
2435
- // Handle invalid tag names (i.e. "<html#doc>")
2436
- if (!preg_match('/^\w[\w:-]*$/', $tag)) {
2437
- $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
2438
-
2439
- // Next char is the beginning of a new tag, don't touch it.
2440
- if ($this->char === '<') {
2441
- $this->link_nodes($node, false);
2442
- return true;
2443
- }
2444
-
2445
- // Next char closes current tag, add and be done with it.
2446
- if ($this->char === '>') {
2447
- $node->_[HDOM_INFO_TEXT] .= '>';
2448
- }
2449
- $this->link_nodes($node, false);
2450
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2451
- return true;
2452
- }
2453
-
2454
- // begin tag, add new node
2455
- $node->nodetype = HDOM_TYPE_ELEMENT;
2456
- $tag_lower = strtolower($tag);
2457
- $node->tag = ($this->lowercase) ? $tag_lower : $tag;
2458
-
2459
- // handle optional closing tags
2460
- if (isset($this->optional_closing_tags[$tag_lower])) {
2461
- // Traverse ancestors to close all optional closing tags
2462
- while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
2463
- $this->parent->_[HDOM_INFO_END] = 0;
2464
- $this->parent = $this->parent->parent;
2465
- }
2466
- $node->parent = $this->parent;
2467
- }
2468
-
2469
- $guard = 0; // prevent infinity loop
2470
-
2471
- // [0] Space between tag and first attribute
2472
- $space = array($this->copy_skip($this->token_blank), '', '');
2473
-
2474
- // attributes
2475
- do {
2476
- // Everything until the first equal sign should be the attribute name
2477
- $name = $this->copy_until($this->token_equal);
2478
-
2479
- if ($name === '' && $this->char !== null && $space[0] === '') {
2480
- break;
2481
- }
2482
-
2483
- if ($guard === $this->pos) { // Escape infinite loop
2484
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2485
- continue;
2486
- }
2487
-
2488
- $guard = $this->pos;
2489
-
2490
- // handle endless '<'
2491
- // Out of bounds before the tag ended
2492
- if ($this->pos >= $this->size - 1 && $this->char !== '>') {
2493
- $node->nodetype = HDOM_TYPE_TEXT;
2494
- $node->_[HDOM_INFO_END] = 0;
2495
- $node->_[HDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name;
2496
- $node->tag = 'text';
2497
- $this->link_nodes($node, false);
2498
- return true;
2499
- }
2500
-
2501
- // handle mismatch '<'
2502
- // Attributes cannot start after opening tag
2503
- if ($this->doc[$this->pos - 1] == '<') {
2504
- $node->nodetype = HDOM_TYPE_TEXT;
2505
- $node->tag = 'text';
2506
- $node->attr = array();
2507
- $node->_[HDOM_INFO_END] = 0;
2508
- $node->_[HDOM_INFO_TEXT] = substr(
2509
- $this->doc,
2510
- $begin_tag_pos,
2511
- $this->pos - $begin_tag_pos - 1
2512
- );
2513
- $this->pos -= 2;
2514
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2515
- $this->link_nodes($node, false);
2516
- return true;
2517
- }
2518
-
2519
- if ($name !== '/' && $name !== '') { // this is a attribute name
2520
- // [1] Whitespace after attribute name
2521
- $space[1] = $this->copy_skip($this->token_blank);
2522
-
2523
- $name = $this->restore_noise($name); // might be a noisy name
2524
-
2525
- if ($this->lowercase) {
2526
- $name = strtolower($name);
2527
- }
2528
-
2529
- if ($this->char === '=') { // attribute with value
2530
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2531
- $this->parse_attr($node, $name, $space); // get attribute value
2532
- } else {
2533
- //no value attr: nowrap, checked selected...
2534
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
2535
- $node->attr[$name] = true;
2536
- if ($this->char != '>') {
2537
- $this->char = $this->doc[--$this->pos];
2538
- } // prev
2539
- }
2540
-
2541
- $node->_[HDOM_INFO_SPACE][] = $space;
2542
-
2543
- // prepare for next attribute
2544
- $space = array(
2545
- $this->copy_skip($this->token_blank),
2546
- '',
2547
- ''
2548
- );
2549
- } else { // no more attributes
2550
- break;
2551
- }
2552
- } while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended
2553
-
2554
- $this->link_nodes($node, true);
2555
- $node->_[HDOM_INFO_ENDSPACE] = $space[0];
2556
-
2557
- // handle empty tags (i.e. "<div/>")
2558
- if ($this->copy_until_char('>') === '/') {
2559
- $node->_[HDOM_INFO_ENDSPACE] .= '/';
2560
- $node->_[HDOM_INFO_END] = 0;
2561
- } else {
2562
- // reset parent
2563
- if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
2564
- $this->parent = $node;
2565
- }
2566
- }
2567
-
2568
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2569
-
2570
- // If it's a BR tag, we need to set it's text to the default text.
2571
- // This way when we see it in plaintext, we can generate formatting that the user wants.
2572
- // since a br tag never has sub nodes, this works well.
2573
- if ($node->tag === 'br') {
2574
- $node->_[HDOM_INFO_INNER] = $this->default_br_text;
2575
- }
2576
-
2577
- return true;
2578
- }
2579
-
2580
- /**
2581
- * Parse attribute from current document position
2582
- *
2583
- * @param object $node Node for the attributes
2584
- * @param string $name Name of the current attribute
2585
- * @param array $space Array for spacing information
2586
- * @return void
2587
- */
2588
- protected function parse_attr($node, $name, &$space)
2589
- {
2590
- // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
2591
- // If the attribute is already defined inside a tag, only pay attention
2592
- // to the first one as opposed to the last one.
2593
- // https://stackoverflow.com/a/26341866
2594
- if (isset($node->attr[$name])) {
2595
- return;
2596
- }
2597
-
2598
- // [2] Whitespace between "=" and the value
2599
- $space[2] = $this->copy_skip($this->token_blank);
2600
-
2601
- switch ($this->char) {
2602
- case '"': // value is anything between double quotes
2603
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
2604
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2605
- $node->attr[$name] = $this->restore_noise($this->copy_until_char('"'));
2606
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2607
- break;
2608
- case '\'': // value is anything between single quotes
2609
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE;
2610
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2611
- $node->attr[$name] = $this->restore_noise($this->copy_until_char('\''));
2612
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2613
- break;
2614
- default: // value is anything until the first space or end tag
2615
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
2616
- $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr));
2617
- }
2618
- // PaperG: Attributes should not have \r or \n in them, that counts as
2619
- // html whitespace.
2620
- $node->attr[$name] = str_replace("\r", '', $node->attr[$name]);
2621
- $node->attr[$name] = str_replace("\n", '', $node->attr[$name]);
2622
- // PaperG: If this is a "class" selector, lets get rid of the preceeding
2623
- // and trailing space since some people leave it in the multi class case.
2624
- if ($name === 'class') {
2625
- $node->attr[$name] = trim($node->attr[$name]);
2626
- }
2627
- }
2628
-
2629
- /**
2630
- * Link node to parent node
2631
- *
2632
- * @param object $node Node to link to parent
2633
- * @param bool $is_child True if the node is a child of parent
2634
- * @return void
2635
- */
2636
- // link node's parent
2637
- protected function link_nodes(&$node, $is_child)
2638
- {
2639
- $node->parent = $this->parent;
2640
- $this->parent->nodes[] = $node;
2641
- if ($is_child) {
2642
- $this->parent->children[] = $node;
2643
- }
2644
- }
2645
-
2646
- /**
2647
- * Add tag as text node to current node
2648
- *
2649
- * @param string $tag Tag name
2650
- * @return bool True on success
2651
- */
2652
- protected function as_text_node($tag)
2653
- {
2654
- $node = new simple_html_dom_node($this);
2655
- ++$this->cursor;
2656
- $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
2657
- $this->link_nodes($node, false);
2658
- $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2659
- return true;
2660
- }
2661
-
2662
- /**
2663
- * Seek from the current document position to the first occurrence of a
2664
- * character not defined by the provided string. Update the current document
2665
- * position to the new position.
2666
- *
2667
- * @param string $chars A string containing every allowed character.
2668
- * @return void
2669
- */
2670
- protected function skip($chars)
2671
- {
2672
- $this->pos += strspn($this->doc, $chars, $this->pos);
2673
- $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2674
- }
2675
-
2676
- /**
2677
- * Copy substring from the current document position to the first occurrence
2678
- * of a character not defined by the provided string.
2679
- *
2680
- * @param string $chars A string containing every allowed character.
2681
- * @return string Substring from the current document position to the first
2682
- * occurrence of a character not defined by the provided string.
2683
- */
2684
- protected function copy_skip($chars)
2685
- {
2686
- $pos = $this->pos;
2687
- $len = strspn($this->doc, $chars, $pos);
2688
- $this->pos += $len;
2689
- $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2690
- if ($len === 0) {
2691
- return '';
2692
- }
2693
- return substr($this->doc, $pos, $len);
2694
- }
2695
-
2696
- /**
2697
- * Copy substring from the current document position to the first occurrence
2698
- * of any of the provided characters.
2699
- *
2700
- * @param string $chars A string containing every character to stop at.
2701
- * @return string Substring from the current document position to the first
2702
- * occurrence of any of the provided characters.
2703
- */
2704
- protected function copy_until($chars)
2705
- {
2706
- $pos = $this->pos;
2707
- $len = strcspn($this->doc, $chars, $pos);
2708
- $this->pos += $len;
2709
- $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2710
- return substr($this->doc, $pos, $len);
2711
- }
2712
-
2713
- /**
2714
- * Copy substring from the current document position to the first occurrence
2715
- * of the provided string.
2716
- *
2717
- * @param string $char The string to stop at.
2718
- * @return string Substring from the current document position to the first
2719
- * occurrence of the provided string.
2720
- */
2721
- protected function copy_until_char($char)
2722
- {
2723
- if ($this->char === null) {
2724
- return '';
2725
- }
2726
-
2727
- if (($pos = strpos($this->doc, $char, $this->pos)) === false) {
2728
- $ret = substr($this->doc, $this->pos, $this->size - $this->pos);
2729
- $this->char = null;
2730
- $this->pos = $this->size;
2731
- return $ret;
2732
- }
2733
-
2734
- if ($pos === $this->pos) {
2735
- return '';
2736
- }
2737
-
2738
- $pos_old = $this->pos;
2739
- $this->char = $this->doc[$pos];
2740
- $this->pos = $pos;
2741
- return substr($this->doc, $pos_old, $pos - $pos_old);
2742
- }
2743
-
2744
- /**
2745
- * Remove noise from HTML content
2746
- *
2747
- * Noise is stored to {@see simple_html_dom::$noise}
2748
- *
2749
- * @param string $pattern The regex pattern used for finding noise
2750
- * @param bool $remove_tag True to remove the entire match. Default is false
2751
- * to only remove the captured data.
2752
- */
2753
- protected function remove_noise($pattern, $remove_tag = false)
2754
- {
2755
- global $debug_object;
2756
- if (is_object($debug_object)) {
2757
- $debug_object->debug_log_entry(1);
2758
- }
2759
-
2760
- $count = preg_match_all(
2761
- $pattern,
2762
- $this->doc,
2763
- $matches,
2764
- PREG_SET_ORDER | PREG_OFFSET_CAPTURE
2765
- );
2766
-
2767
- for ($i = $count - 1; $i > -1; --$i) {
2768
- $key = '___noise___' . sprintf('% 5d', count($this->noise) + 1000);
2769
-
2770
- if (is_object($debug_object)) {
2771
- $debug_object->debug_log(2, 'key is: ' . $key);
2772
- }
2773
-
2774
- $idx = ($remove_tag) ? 0 : 1; // 0 = entire match, 1 = submatch
2775
- $this->noise[$key] = $matches[$i][$idx][0];
2776
- $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
2777
- }
2778
-
2779
- // reset the length of content
2780
- $this->size = strlen($this->doc);
2781
-
2782
- if ($this->size > 0) {
2783
- $this->char = $this->doc[0];
2784
- }
2785
- }
2786
-
2787
- /**
2788
- * Restore noise to HTML content
2789
- *
2790
- * Noise is restored from {@see simple_html_dom::$noise}
2791
- *
2792
- * @param string $text A subset of HTML containing noise
2793
- * @return string The same content with noise restored
2794
- */
2795
- function restore_noise($text)
2796
- {
2797
- global $debug_object;
2798
- if (is_object($debug_object)) {
2799
- $debug_object->debug_log_entry(1);
2800
- }
2801
-
2802
- while (($pos = strpos($text, '___noise___')) !== false) {
2803
- // Sometimes there is a broken piece of markup, and we don't GET the
2804
- // pos+11 etc... token which indicates a problem outside of us...
2805
-
2806
- // todo: "___noise___1000" (or any number with four or more digits)
2807
- // in the DOM causes an infinite loop which could be utilized by
2808
- // malicious software
2809
- if (strlen($text) > $pos + 15) {
2810
- $key = '___noise___'
2811
- . $text[$pos + 11]
2812
- . $text[$pos + 12]
2813
- . $text[$pos + 13]
2814
- . $text[$pos + 14]
2815
- . $text[$pos + 15];
2816
-
2817
- if (is_object($debug_object)) {
2818
- $debug_object->debug_log(2, 'located key of: ' . $key);
2819
- }
2820
-
2821
- if (isset($this->noise[$key])) {
2822
- $text = substr($text, 0, $pos)
2823
- . $this->noise[$key]
2824
- . substr($text, $pos + 16);
2825
- } else {
2826
- // do this to prevent an infinite loop.
2827
- $text = substr($text, 0, $pos)
2828
- . 'UNDEFINED NOISE FOR KEY: '
2829
- . $key
2830
- . substr($text, $pos + 16);
2831
- }
2832
- } else {
2833
- // There is no valid key being given back to us... We must get
2834
- // rid of the ___noise___ or we will have a problem.
2835
- $text = substr($text, 0, $pos)
2836
- . 'NO NUMERIC NOISE KEY'
2837
- . substr($text, $pos + 11);
2838
- }
2839
- }
2840
- return $text;
2841
- }
2842
-
2843
- // Sometimes we NEED one of the noise elements.
2844
- function search_noise($text)
2845
- {
2846
- global $debug_object;
2847
- if (is_object($debug_object)) {
2848
- $debug_object->debug_log_entry(1);
2849
- }
2850
-
2851
- foreach ($this->noise as $noiseElement) {
2852
- if (strpos($noiseElement, $text) !== false) {
2853
- return $noiseElement;
2854
- }
2855
- }
2856
- }
2857
-
2858
- function __toString()
2859
- {
2860
- return $this->root->innertext();
2861
- }
2862
-
2863
- function __get($name)
2864
- {
2865
- switch ($name) {
2866
- case 'outertext':
2867
- return $this->root->innertext();
2868
- case 'innertext':
2869
- return $this->root->innertext();
2870
- case 'plaintext':
2871
- return $this->root->text();
2872
- case 'charset':
2873
- return $this->_charset;
2874
- case 'target_charset':
2875
- return $this->_target_charset;
2876
- }
2877
- }
2878
-
2879
- // camel naming conventions
2880
- function childNodes($idx = -1)
2881
- {
2882
- return $this->root->childNodes($idx);
2883
- }
2884
-
2885
- function firstChild()
2886
- {
2887
- return $this->root->first_child();
2888
- }
2889
-
2890
- function lastChild()
2891
- {
2892
- return $this->root->last_child();
2893
- }
2894
-
2895
- function createElement($name, $value = null)
2896
- {
2897
- return @str_get_html("<$name>$value</$name>")->first_child();
2898
- }
2899
-
2900
- function createTextNode($value)
2901
- {
2902
- return @end(str_get_html($value)->nodes);
2903
- }
2904
-
2905
- function getElementById($id)
2906
- {
2907
- return $this->find("#$id", 0);
2908
- }
2909
-
2910
- function getElementsById($id, $idx = null)
2911
- {
2912
- return $this->find("#$id", $idx);
2913
- }
2914
-
2915
- function getElementByTagName($name)
2916
- {
2917
- return $this->find($name, 0);
2918
- }
2919
-
2920
- function getElementsByTagName($name, $idx = -1)
2921
- {
2922
- return $this->find($name, $idx);
2923
- }
2924
-
2925
- function loadFile()
2926
- {
2927
- $args = func_get_args();
2928
- $this->load_file($args);
2929
- }
2930
- }
1
+ <?php
2
+ /**
3
+ * Website: http://sourceforge.net/projects/simplehtmldom/
4
+ * Additional projects: http://sourceforge.net/projects/debugobject/
5
+ * Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
6
+ * Contributions by:
7
+ * Yousuke Kumakura (Attribute filters)
8
+ * Vadim Voituk (Negative indexes supports of "find" method)
9
+ * Antcs (Constructor with automatically load contents either text or file/url)
10
+ *
11
+ * all affected sections have comments starting with "PaperG"
12
+ *
13
+ * Paperg - Added case insensitive testing of the value of the selector.
14
+ *
15
+ * Paperg - Added tag_start for the starting index of tags - NOTE: This works
16
+ * but not accurately. This tag_start gets counted AFTER \r\n have been crushed
17
+ * out, and after the remove_noice calls so it will not reflect the REAL
18
+ * position of the tag in the source, it will almost always be smaller by some
19
+ * amount. We use this to determine how far into the file the tag in question
20
+ * is. This "percentage" will never be accurate as the $dom->size is the "real"
21
+ * number of bytes the dom was created from. But for most purposes, it's a
22
+ * really good estimation.
23
+ *
24
+ * Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags
25
+ * closed is great for malformed html, but it CAN lead to parsing errors.
26
+ *
27
+ * Allow the user to tell us how much they trust the html.
28
+ *
29
+ * Paperg add the text and plaintext to the selectors for the find syntax.
30
+ * plaintext implies text in the innertext of a node. text implies that the
31
+ * tag is a text node. This allows for us to find tags based on the text they
32
+ * contain.
33
+ *
34
+ * Create find_ancestor_tag to see if a tag is - at any level - inside of
35
+ * another specific tag.
36
+ *
37
+ * Paperg: added parse_charset so that we know about the character set of
38
+ * the source document. NOTE: If the user's system has a routine called
39
+ * get_last_retrieve_url_contents_content_type availalbe, we will assume it's
40
+ * returning the content-type header from the last transfer or curl_exec, and
41
+ * we will parse that and use it in preference to any other method of charset
42
+ * detection.
43
+ *
44
+ * Found infinite loop in the case of broken html in restore_noise. Rewrote to
45
+ * protect from that.
46
+ *
47
+ * PaperG (John Schlick) Added get_display_size for "IMG" tags.
48
+ *
49
+ * Licensed under The MIT License
50
+ * Redistributions of files must retain the above copyright notice.
51
+ *
52
+ * @author S.C. Chen <me578022@gmail.com>
53
+ * @author John Schlick
54
+ * @author Rus Carroll
55
+ * @version Rev. 1.8.1 (247)
56
+ * @package PlaceLocalInclude
57
+ * @subpackage simple_html_dom
58
+ */
59
+
60
+ /**
61
+ * All of the Defines for the classes below.
62
+ * @author S.C. Chen <me578022@gmail.com>
63
+ */
64
+ define('HDOM_TYPE_ELEMENT', 1);
65
+ define('HDOM_TYPE_COMMENT', 2);
66
+ define('HDOM_TYPE_TEXT', 3);
67
+ define('HDOM_TYPE_ENDTAG', 4);
68
+ define('HDOM_TYPE_ROOT', 5);
69
+ define('HDOM_TYPE_UNKNOWN', 6);
70
+ define('HDOM_QUOTE_DOUBLE', 0);
71
+ define('HDOM_QUOTE_SINGLE', 1);
72
+ define('HDOM_QUOTE_NO', 3);
73
+ define('HDOM_INFO_BEGIN', 0);
74
+ define('HDOM_INFO_END', 1);
75
+ define('HDOM_INFO_QUOTE', 2);
76
+ define('HDOM_INFO_SPACE', 3);
77
+ define('HDOM_INFO_TEXT', 4);
78
+ define('HDOM_INFO_INNER', 5);
79
+ define('HDOM_INFO_OUTER', 6);
80
+ define('HDOM_INFO_ENDSPACE', 7);
81
+
82
+ /** The default target charset */
83
+ defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
84
+
85
+ /** The default <br> text used instead of <br> tags when returning text */
86
+ defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
87
+
88
+ /** The default <span> text used instead of <span> tags when returning text */
89
+ defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
90
+
91
+ /** The maximum file size the parser should load */
92
+ defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
93
+
94
+ /** Contents between curly braces "{" and "}" are interpreted as text */
95
+ define('HDOM_SMARTY_AS_TEXT', 1);
96
+
97
+ // helper functions
98
+ // -----------------------------------------------------------------------------
99
+ // get html dom from file
100
+ // $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
101
+ function file_get_html(
102
+ $url,
103
+ $use_include_path = false,
104
+ $context = null,
105
+ $offset = 0,
106
+ $maxLen = -1,
107
+ $lowercase = true,
108
+ $forceTagsClosed = true,
109
+ $target_charset = DEFAULT_TARGET_CHARSET,
110
+ $stripRN = true,
111
+ $defaultBRText = DEFAULT_BR_TEXT,
112
+ $defaultSpanText = DEFAULT_SPAN_TEXT
113
+ ) {
114
+ // Ensure maximum length is greater than zero
115
+ if ($maxLen <= 0) {
116
+ $maxLen = MAX_FILE_SIZE;
117
+ }
118
+
119
+ // We DO force the tags to be terminated.
120
+ $dom = new simple_html_dom(
121
+ null,
122
+ $lowercase,
123
+ $forceTagsClosed,
124
+ $target_charset,
125
+ $stripRN,
126
+ $defaultBRText,
127
+ $defaultSpanText
128
+ );
129
+
130
+ /**
131
+ * For sourceforge users: uncomment the next line and comment the
132
+ * retrieve_url_contents line 2 lines down if it is not already done.
133
+ */
134
+ $contents = file_get_contents(
135
+ $url,
136
+ $use_include_path,
137
+ $context,
138
+ $offset,
139
+ $maxLen
140
+ );
141
+
142
+ // Paperg - use our own mechanism for getting the contents as we want to
143
+ // control the timeout.
144
+ // $contents = retrieve_url_contents($url);
145
+ if (empty($contents) || strlen($contents) > $maxLen) {
146
+ return false;
147
+ }
148
+
149
+ // The second parameter can force the selectors to all be lowercase.
150
+ $dom->load($contents, $lowercase, $stripRN);
151
+ return $dom;
152
+ }
153
+
154
+ // get html dom from string
155
+ function str_get_html(
156
+ $str,
157
+ $lowercase = true,
158
+ $forceTagsClosed = true,
159
+ $target_charset = DEFAULT_TARGET_CHARSET,
160
+ $stripRN = true,
161
+ $defaultBRText = DEFAULT_BR_TEXT,
162
+ $defaultSpanText = DEFAULT_SPAN_TEXT
163
+ ) {
164
+ $dom = new simple_html_dom(
165
+ null,
166
+ $lowercase,
167
+ $forceTagsClosed,
168
+ $target_charset,
169
+ $stripRN,
170
+ $defaultBRText,
171
+ $defaultSpanText
172
+ );
173
+
174
+ if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
175
+ $dom->clear();
176
+ return false;
177
+ }
178
+
179
+ $dom->load($str, $lowercase, $stripRN);
180
+ return $dom;
181
+ }
182
+
183
+ // dump html dom tree
184
+ function dump_html_tree($node, $show_attr = true, $deep = 0)
185
+ {
186
+ $node->dump($node);
187
+ }
188
+
189
+ /**
190
+ * simple html dom node
191
+ * PaperG - added ability for "find" routine to lowercase the value of the
192
+ * selector.
193
+ *
194
+ * PaperG - added $tag_start to track the start position of the tag in the total
195
+ * byte index
196
+ *
197
+ * @package PlaceLocalInclude
198
+ */
199
+ class simple_html_dom_node
200
+ {
201
+ /**
202
+ * Node type
203
+ *
204
+ * Default is {@see HDOM_TYPE_TEXT}
205
+ *
206
+ * @var int
207
+ */
208
+ public $nodetype = HDOM_TYPE_TEXT;
209
+
210
+ /**
211
+ * Tag name
212
+ *
213
+ * Default is 'text'
214
+ *
215
+ * @var string
216
+ */
217
+ public $tag = 'text';
218
+
219
+ /**
220
+ * List of attributes
221
+ *
222
+ * @var array
223
+ */
224
+ public $attr = array();
225
+
226
+ /**
227
+ * List of child node objects
228
+ *
229
+ * @var array
230
+ */
231
+ public $children = array();
232
+ public $nodes = array();
233
+
234
+ /**
235
+ * The parent node object
236
+ *
237
+ * @var object|null
238
+ */
239
+ public $parent = null;
240
+
241
+ // The "info" array - see HDOM_INFO_... for what each element contains.
242
+ public $_ = array();
243
+
244
+ /**
245
+ * Start position of the tag in the document
246
+ *
247
+ * @var int
248
+ */
249
+ public $tag_start = 0;
250
+
251
+ /**
252
+ * The DOM object
253
+ *
254
+ * @var object|null
255
+ */
256
+ private $dom = null;
257
+
258
+ /**
259
+ * Construct new node object
260
+ *
261
+ * Adds itself to the list of DOM Nodes {@see simple_html_dom::$nodes}
262
+ */
263
+ function __construct($dom)
264
+ {
265
+ $this->dom = $dom;
266
+ $dom->nodes[] = $this;
267
+ }
268
+
269
+ function __destruct()
270
+ {
271
+ $this->clear();
272
+ }
273
+
274
+ function __toString()
275
+ {
276
+ return $this->outertext();
277
+ }
278
+
279
+ // clean up memory due to php5 circular references memory leak...
280
+ function clear()
281
+ {
282
+ $this->dom = null;
283
+ $this->nodes = null;
284
+ $this->parent = null;
285
+ $this->children = null;
286
+ }
287
+
288
+ // dump node's tree
289
+ function dump($show_attr = true, $deep = 0)
290
+ {
291
+ $lead = str_repeat(' ', $deep);
292
+
293
+ echo $lead . $this->tag;
294
+
295
+ if ($show_attr && count($this->attr) > 0) {
296
+ echo '(';
297
+ foreach ($this->attr as $k => $v) {
298
+ echo "[$k]=>\"" . $this->$k . '", ';
299
+ }
300
+ echo ')';
301
+ }
302
+
303
+ echo "\n";
304
+
305
+ if ($this->nodes) {
306
+ foreach ($this->nodes as $c) {
307
+ $c->dump($show_attr, $deep + 1);
308
+ }
309
+ }
310
+ }
311
+
312
+
313
+ // Debugging function to dump a single dom node with a bunch of information about it.
314
+ function dump_node($echo = true)
315
+ {
316
+ $string = $this->tag;
317
+
318
+ if (count($this->attr) > 0) {
319
+ $string .= '(';
320
+ foreach ($this->attr as $k => $v) {
321
+ $string .= "[$k]=>\"" . $this->$k . '", ';
322
+ }
323
+ $string .= ')';
324
+ }
325
+
326
+ if (count($this->_) > 0) {
327
+ $string .= ' $_ (';
328
+ foreach ($this->_ as $k => $v) {
329
+ if (is_array($v)) {
330
+ $string .= "[$k]=>(";
331
+ foreach ($v as $k2 => $v2) {
332
+ $string .= "[$k2]=>\"" . $v2 . '", ';
333
+ }
334
+ $string .= ')';
335
+ } else {
336
+ $string .= "[$k]=>\"" . $v . '", ';
337
+ }
338
+ }
339
+ $string .= ')';
340
+ }
341
+
342
+ if (isset($this->text)) {
343
+ $string .= ' text: (' . $this->text . ')';
344
+ }
345
+
346
+ $string .= " HDOM_INNER_INFO: '";
347
+
348
+ if (isset($node->_[HDOM_INFO_INNER])) {
349
+ $string .= $node->_[HDOM_INFO_INNER] . "'";
350
+ } else {
351
+ $string .= ' NULL ';
352
+ }
353
+
354
+ $string .= ' children: ' . count($this->children);
355
+ $string .= ' nodes: ' . count($this->nodes);
356
+ $string .= ' tag_start: ' . $this->tag_start;
357
+ $string .= "\n";
358
+
359
+ if ($echo) {
360
+ echo $string;
361
+ return;
362
+ } else {
363
+ return $string;
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Return or set parent node
369
+ *
370
+ * @param object|null $parent (optional) The parent node, `null` to return
371
+ * the current parent node.
372
+ * @return object|null The parent node
373
+ */
374
+ function parent($parent = null)
375
+ {
376
+ // I am SURE that this doesn't work properly.
377
+ // It fails to unset the current node from it's current parents nodes or
378
+ // children list first.
379
+ if ($parent !== null) {
380
+ $this->parent = $parent;
381
+ $this->parent->nodes[] = $this;
382
+ $this->parent->children[] = $this;
383
+ }
384
+
385
+ return $this->parent;
386
+ }
387
+
388
+ /**
389
+ * @return bool True if the node has at least one child node
390
+ */
391
+ function has_child()
392
+ {
393
+ return !empty($this->children);
394
+ }
395
+
396
+ /**
397
+ * Get child node at specified index
398
+ *
399
+ * @param int $idx The index of the child node to return, `-1` to return all
400
+ * child nodes.
401
+ * @return object|array|null The child node at the specified index, all child
402
+ * nodes or null if the index is invalid.
403
+ */
404
+ function children($idx = -1)
405
+ {
406
+ if ($idx === -1) {
407
+ return $this->children;
408
+ }
409
+
410
+ if (isset($this->children[$idx])) {
411
+ return $this->children[$idx];
412
+ }
413
+
414
+ return null;
415
+ }
416
+
417
+ /**
418
+ * Get first child node
419
+ *
420
+ * @return object|null The first child node or null if the current node has
421
+ * no child nodes.
422
+ *
423
+ * @todo Use `empty()` instead of `count()` to improve performance on large
424
+ * arrays.
425
+ */
426
+ function first_child()
427
+ {
428
+ if (count($this->children) > 0) {
429
+ return $this->children[0];
430
+ }
431
+ return null;
432
+ }
433
+
434
+ /**
435
+ * Get last child node
436
+ *
437
+ * @return object|null The last child node or null if the current node has
438
+ * no child nodes.
439
+ *
440
+ * @todo Use `end()` to slightly improve performance on large arrays.
441
+ */
442
+ function last_child()
443
+ {
444
+ if (($count = count($this->children)) > 0) {
445
+ return $this->children[$count - 1];
446
+ }
447
+ return null;
448
+ }
449
+
450
+ /**
451
+ * Get next sibling node
452
+ *
453
+ * @return object|null The sibling node or null if the current node has no
454
+ * sibling nodes.
455
+ */
456
+ function next_sibling()
457
+ {
458
+ if ($this->parent === null) {
459
+ return null;
460
+ }
461
+
462
+ $idx = 0;
463
+ $count = count($this->parent->children);
464
+
465
+ while ($idx < $count && $this !== $this->parent->children[$idx]) {
466
+ ++$idx;
467
+ }
468
+
469
+ if (++$idx >= $count) {
470
+ return null;
471
+ }
472
+
473
+ return $this->parent->children[$idx];
474
+ }
475
+
476
+ /**
477
+ * Get previous sibling node
478
+ *
479
+ * @return object|null The sibling node or null if the current node has no
480
+ * sibling nodes.
481
+ */
482
+ function prev_sibling()
483
+ {
484
+ if ($this->parent === null) {
485
+ return null;
486
+ }
487
+
488
+ $idx = 0;
489
+ $count = count($this->parent->children);
490
+
491
+ while ($idx < $count && $this !== $this->parent->children[$idx]) {
492
+ ++$idx;
493
+ }
494
+
495
+ if (--$idx < 0) {
496
+ return null;
497
+ }
498
+
499
+ return $this->parent->children[$idx];
500
+ }
501
+
502
+ /**
503
+ * Traverse ancestors to the first matching tag.
504
+ *
505
+ * @param string $tag Tag to find
506
+ * @return object|null First matching node in the DOM tree or null if no
507
+ * match was found.
508
+ *
509
+ * @todo Null is returned implicitly by calling ->parent on the root node.
510
+ * This behaviour could change at any time, rendering this function invalid.
511
+ */
512
+ function find_ancestor_tag($tag)
513
+ {
514
+ global $debug_object;
515
+ if (is_object($debug_object)) {
516
+ $debug_object->debug_log_entry(1);
517
+ }
518
+
519
+ // Start by including ourselves in the comparison.
520
+ $returnDom = $this;
521
+
522
+ while (!is_null($returnDom)) {
523
+ if (is_object($debug_object)) {
524
+ $debug_object->debug_log(2, 'Current tag is: ' . $returnDom->tag);
525
+ }
526
+
527
+ if ($returnDom->tag == $tag) {
528
+ break;
529
+ }
530
+
531
+ $returnDom = $returnDom->parent;
532
+ }
533
+
534
+ return $returnDom;
535
+ }
536
+
537
+ /**
538
+ * Get node's inner text (everything inside the opening and closing tags)
539
+ *
540
+ * @return string
541
+ */
542
+ function innertext()
543
+ {
544
+ if (isset($this->_[HDOM_INFO_INNER])) {
545
+ return $this->_[HDOM_INFO_INNER];
546
+ }
547
+
548
+ if (isset($this->_[HDOM_INFO_TEXT])) {
549
+ return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
550
+ }
551
+
552
+ $ret = '';
553
+
554
+ foreach ($this->nodes as $n) {
555
+ $ret .= $n->outertext();
556
+ }
557
+
558
+ return $ret;
559
+ }
560
+
561
+ /**
562
+ * Get node's outer text (everything including the opening and closing tags)
563
+ *
564
+ * @return string
565
+ */
566
+ function outertext()
567
+ {
568
+ global $debug_object;
569
+
570
+ if (is_object($debug_object)) {
571
+ $text = '';
572
+
573
+ if ($this->tag === 'text') {
574
+ if (!empty($this->text)) {
575
+ $text = ' with text: ' . $this->text;
576
+ }
577
+ }
578
+
579
+ $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
580
+ }
581
+
582
+ if ($this->tag === 'root') {
583
+ return $this->innertext();
584
+ }
585
+
586
+ // trigger callback
587
+ if ($this->dom && $this->dom->callback !== null) {
588
+ call_user_func_array($this->dom->callback, array($this));
589
+ }
590
+
591
+ if (isset($this->_[HDOM_INFO_OUTER])) {
592
+ return $this->_[HDOM_INFO_OUTER];
593
+ }
594
+
595
+ if (isset($this->_[HDOM_INFO_TEXT])) {
596
+ return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
597
+ }
598
+
599
+ // render begin tag
600
+ if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
601
+ $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
602
+ } else {
603
+ $ret = '';
604
+ }
605
+
606
+ // render inner text
607
+ if (isset($this->_[HDOM_INFO_INNER])) {
608
+ // If it's a br tag... don't return the HDOM_INNER_INFO that we
609
+ // may or may not have added.
610
+ if ($this->tag !== 'br') {
611
+ $ret .= $this->_[HDOM_INFO_INNER];
612
+ }
613
+ } else {
614
+ if ($this->nodes) {
615
+ foreach ($this->nodes as $n) {
616
+ $ret .= $this->convert_text($n->outertext());
617
+ }
618
+ }
619
+ }
620
+
621
+ // render end tag
622
+ if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
623
+ $ret .= '</' . $this->tag . '>';
624
+ }
625
+
626
+ return $ret;
627
+ }
628
+
629
+ /**
630
+ * Get node's plain text (everything excluding all tags)
631
+ *
632
+ * @return string
633
+ */
634
+ function text()
635
+ {
636
+ if (isset($this->_[HDOM_INFO_INNER])) {
637
+ return $this->_[HDOM_INFO_INNER];
638
+ }
639
+
640
+ switch ($this->nodetype) {
641
+ case HDOM_TYPE_TEXT:
642
+ return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
643
+ case HDOM_TYPE_COMMENT:
644
+ return '';
645
+ case HDOM_TYPE_UNKNOWN:
646
+ return '';
647
+ }
648
+
649
+ if (strcasecmp($this->tag, 'script') === 0) {
650
+ return '';
651
+ }
652
+ if (strcasecmp($this->tag, 'style') === 0) {
653
+ return '';
654
+ }
655
+
656
+ $ret = '';
657
+
658
+ // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed
659
+ // for some span tags, and some p tags) $this->nodes is set to NULL.
660
+ // NOTE: This indicates that there is a problem where it's set to NULL
661
+ // without a clear happening.
662
+ // WHY is this happening?
663
+ if (!is_null($this->nodes)) {
664
+ foreach ($this->nodes as $n) {
665
+ // Start paragraph after a blank line
666
+ if ($n->tag === 'p') {
667
+ $ret .= "\n\n";
668
+ }
669
+
670
+ $ret .= $this->convert_text($n->text());
671
+
672
+ // If this node is a span... add a space at the end of it so
673
+ // multiple spans don't run into each other. This is plaintext
674
+ // after all.
675
+ if ($n->tag === 'span') {
676
+ $ret .= $this->dom->default_span_text;
677
+ }
678
+ }
679
+ }
680
+ return trim($ret);
681
+ }
682
+
683
+ /**
684
+ * Get node's xml text (inner text as a CDATA section)
685
+ *
686
+ * @return string
687
+ */
688
+ function xmltext()
689
+ {
690
+ $ret = $this->innertext();
691
+ $ret = str_ireplace('<![CDATA[', '', $ret);
692
+ $ret = str_replace(']]>', '', $ret);
693
+ return $ret;
694
+ }
695
+
696
+ // build node's text with tag
697
+ function makeup()
698
+ {
699
+ // text, comment, unknown
700
+ if (isset($this->_[HDOM_INFO_TEXT])) {
701
+ return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
702
+ }
703
+
704
+ $ret = '<' . $this->tag;
705
+ $i = -1;
706
+
707
+ foreach ($this->attr as $key => $val) {
708
+ ++$i;
709
+
710
+ // skip removed attribute
711
+ if ($val === null || $val === false) {
712
+ continue;
713
+ }
714
+
715
+ $ret .= $this->_[HDOM_INFO_SPACE][$i][0];
716
+
717
+ //no value attr: nowrap, checked selected...
718
+ if ($val === true) {
719
+ $ret .= $key;
720
+ } else {
721
+ switch ($this->_[HDOM_INFO_QUOTE][$i]) {
722
+ case HDOM_QUOTE_DOUBLE:
723
+ $quote = '"';
724
+ break;
725
+ case HDOM_QUOTE_SINGLE:
726
+ $quote = '\'';
727
+ break;
728
+ default:
729
+ $quote = '';
730
+ }
731
+
732
+ $ret .= $key
733
+ . $this->_[HDOM_INFO_SPACE][$i][1]
734
+ . '='
735
+ . $this->_[HDOM_INFO_SPACE][$i][2]
736
+ . $quote
737
+ . $val
738
+ . $quote;
739
+ }
740
+ }
741
+
742
+ $ret = $this->dom->restore_noise($ret);
743
+ return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
744
+ }
745
+
746
+ /**
747
+ * Find elements by CSS selector
748
+ *
749
+ * @param string $selector The CSS selector
750
+ * @param int|null $idx Index of element to return form the list of matching
751
+ * elements (default: `null` = disabled).
752
+ * @param bool $lowercase Matches tag names case insensitive (lowercase) if
753
+ * enabled (default: `false`)
754
+ * @return array|object|null A list of elements matching the specified CSS
755
+ * selector or a single element if $idx is specified or null if no element
756
+ * was found.
757
+ */
758
+ function find($selector, $idx = null, $lowercase = false)
759
+ {
760
+ $selectors = $this->parse_selector($selector);
761
+ if (($count = count($selectors)) === 0) {
762
+ return array();
763
+ }
764
+ $found_keys = array();
765
+
766
+ // find each selector
767
+ for ($c = 0; $c < $count; ++$c) {
768
+ // The change on the below line was documented on the sourceforge
769
+ // code tracker id 2788009
770
+ // used to be: if (($levle=count($selectors[0]))===0) return array();
771
+ if (($levle = count($selectors[$c])) === 0) {
772
+ return array();
773
+ }
774
+ if (!isset($this->_[HDOM_INFO_BEGIN])) {
775
+ return array();
776
+ }
777
+
778
+ $head = array($this->_[HDOM_INFO_BEGIN] => 1);
779
+ $cmd = ' '; // Combinator
780
+
781
+ // handle descendant selectors, no recursive!
782
+ for ($l = 0; $l < $levle; ++$l) {
783
+ $ret = array();
784
+
785
+ foreach ($head as $k => $v) {
786
+ $n = ($k === -1) ? $this->dom->root : $this->dom->nodes[$k];
787
+ //PaperG - Pass this optional parameter on to the seek function.
788
+ $n->seek($selectors[$c][$l], $ret, $cmd, $lowercase);
789
+ }
790
+
791
+ $head = $ret;
792
+ $cmd = $selectors[$c][$l][4]; // Next Combinator
793
+ }
794
+
795
+ foreach ($head as $k => $v) {
796
+ if (!isset($found_keys[$k])) {
797
+ $found_keys[$k] = 1;
798
+ }
799
+ }
800
+ }
801
+
802
+ // sort keys
803
+ ksort($found_keys);
804
+
805
+ $found = array();
806
+ foreach ($found_keys as $k => $v) {
807
+ $found[] = $this->dom->nodes[$k];
808
+ }
809
+
810
+ // return nth-element or array
811
+ if (is_null($idx)) {
812
+ return $found;
813
+ } elseif ($idx < 0) {
814
+ $idx = count($found) + $idx;
815
+ }
816
+ return (isset($found[$idx])) ? $found[$idx] : null;
817
+ }
818
+
819
+ /**
820
+ * Seek DOM elements by selector
821
+ *
822
+ * **Note**
823
+ * The selector element must be compatible to a selector from
824
+ * {@see simple_html_dom_node::parse_selector()}
825
+ *
826
+ * @param array $selector A selector element
827
+ * @param array $ret An array of matches
828
+ * @param bool $lowercase Matches tag names case insensitive (lowercase) if
829
+ * enabled (default: `false`)
830
+ * @return void
831
+ */
832
+ protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
833
+ {
834
+ global $debug_object;
835
+ if (is_object($debug_object)) {
836
+ $debug_object->debug_log_entry(1);
837
+ }
838
+
839
+ list($tag, $id, $class, $attributes, $cmb) = $selector;
840
+ $nodes = array();
841
+
842
+ if ($parent_cmd === ' ') { // Descendant Combinator
843
+ // Find parent closing tag if the current element doesn't have a closing
844
+ // tag (i.e. void element)
845
+ $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
846
+ if ($end == 0) {
847
+ $parent = $this->parent;
848
+ while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) {
849
+ $end -= 1;
850
+ $parent = $parent->parent;
851
+ }
852
+ $end += $parent->_[HDOM_INFO_END];
853
+ }
854
+
855
+ // Get list of target nodes
856
+ $nodes_start = $this->_[HDOM_INFO_BEGIN] + 1;
857
+ $nodes_count = $end - $nodes_start;
858
+ $nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true);
859
+ } elseif ($parent_cmd === '>') { // Child Combinator
860
+ $nodes = $this->children;
861
+ } elseif ($parent_cmd === '+'
862
+ && $this->parent
863
+ && in_array($this, $this->parent->children)) { // Next-Sibling Combinator
864
+ $index = array_search($this, $this->parent->children, true) + 1;
865
+ $nodes[] = $this->parent->children[$index];
866
+ } elseif ($parent_cmd === '~'
867
+ && $this->parent
868
+ && in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
869
+ $index = array_search($this, $this->parent->children, true);
870
+ $nodes = array_slice($this->parent->children, $index);
871
+ }
872
+
873
+ // Go throgh each element starting at this element until the end tag
874
+ // Note: If this element is a void tag, any previous void element is
875
+ // skipped.
876
+ foreach ($nodes as $node) {
877
+ $pass = true;
878
+
879
+ // Skip root nodes
880
+ if (!$node->parent) {
881
+ $pass = false;
882
+ }
883
+
884
+ // Skip if node isn't a child node (i.e. text nodes)
885
+ if ($pass && !in_array($node, $node->parent->children, true)) {
886
+ $pass = false;
887
+ }
888
+
889
+ // Skip if tag doesn't match
890
+ if ($pass && $tag !== '' && $tag !== $node->tag && $tag !== '*') {
891
+ $pass = false;
892
+ }
893
+
894
+ // Skip if ID doesn't exist
895
+ if ($pass && $id !== '' && !isset($node->attr['id'])) {
896
+ $pass = false;
897
+ }
898
+
899
+ // Check if ID matches
900
+ if ($pass && $id !== '' && isset($node->attr['id'])) {
901
+ // Note: Only consider the first ID (as browsers do)
902
+ $node_id = explode(' ', trim($node->attr['id']))[0];
903
+
904
+ if ($id !== $node_id) {
905
+ $pass = false;
906
+ }
907
+ }
908
+
909
+ // Check if all class(es) exist
910
+ if ($pass && $class !== '' && is_array($class) && !empty($class)) {
911
+ if (isset($node->attr['class'])) {
912
+ $node_classes = explode(' ', $node->attr['class']);
913
+
914
+ if ($lowercase) {
915
+ $node_classes = array_map('strtolower', $node_classes);
916
+ }
917
+
918
+ foreach ($class as $c) {
919
+ if (!in_array($c, $node_classes)) {
920
+ $pass = false;
921
+ break;
922
+ }
923
+ }
924
+ } else {
925
+ $pass = false;
926
+ }
927
+ }
928
+
929
+ // Check attributes
930
+ if ($pass
931
+ && $attributes !== ''
932
+ && is_array($attributes)
933
+ && !empty($attributes)) {
934
+ foreach ($attributes as $a) {
935
+ list (
936
+ $att_name,
937
+ $att_expr,
938
+ $att_val,
939
+ $att_inv,
940
+ $att_case_sensitivity
941
+ ) = $a;
942
+
943
+ // Handle indexing attributes (i.e. "[2]")
944
+ /**
945
+ * Note: This is not supported by the CSS Standard but adds
946
+ * the ability to select items compatible to XPath (i.e.
947
+ * the 3rd element within it's parent).
948
+ *
949
+ * Note: This doesn't conflict with the CSS Standard which
950
+ * doesn't work on numeric attributes anyway.
951
+ */
952
+ if (is_numeric($att_name)
953
+ && $att_expr === ''
954
+ && $att_val === '') {
955
+ $count = 0;
956
+
957
+ // Find index of current element in parent
958
+ foreach ($node->parent->children as $c) {
959
+ if ($c->tag === $node->tag) {
960
+ ++$count;
961
+ }
962
+ if ($c === $node) {
963
+ break;
964
+ }
965
+ }
966
+
967
+ // If this is the correct node, continue with next
968
+ // attribute
969
+ if ($count === (int)$att_name) {
970
+ continue;
971
+ }
972
+ }
973
+
974
+ // Check attribute availability
975
+ if ($att_inv) { // Attribute should NOT be set
976
+ if (isset($node->attr[$att_name])) {
977
+ $pass = false;
978
+ break;
979
+ }
980
+ } else { // Attribute should be set
981
+ // todo: "plaintext" is not a valid CSS selector!
982
+ if ($att_name !== 'plaintext'
983
+ && !isset($node->attr[$att_name])) {
984
+ $pass = false;
985
+ break;
986
+ }
987
+ }
988
+
989
+ // Continue with next attribute if expression isn't defined
990
+ if ($att_expr === '') {
991
+ continue;
992
+ }
993
+
994
+ // If they have told us that this is a "plaintext"
995
+ // search then we want the plaintext of the node - right?
996
+ // todo "plaintext" is not a valid CSS selector!
997
+ if ($att_name === 'plaintext') {
998
+ $nodeKeyValue = $node->text();
999
+ } else {
1000
+ $nodeKeyValue = $node->attr[$att_name];
1001
+ }
1002
+
1003
+ if (is_object($debug_object)) {
1004
+ $debug_object->debug_log(
1005
+ 2,
1006
+ 'testing node: '
1007
+ . $node->tag
1008
+ . ' for attribute: '
1009
+ . $att_name
1010
+ . $att_expr
1011
+ . $att_val
1012
+ . ' where nodes value is: '
1013
+ . $nodeKeyValue
1014
+ );
1015
+ }
1016
+
1017
+ // If lowercase is set, do a case insensitive test of
1018
+ // the value of the selector.
1019
+ if ($lowercase) {
1020
+ $check = $this->match(
1021
+ $att_expr,
1022
+ strtolower($att_val),
1023
+ strtolower($nodeKeyValue),
1024
+ $att_case_sensitivity
1025
+ );
1026
+ } else {
1027
+ $check = $this->match(
1028
+ $att_expr,
1029
+ $att_val,
1030
+ $nodeKeyValue,
1031
+ $att_case_sensitivity
1032
+ );
1033
+ }
1034
+
1035
+ if (is_object($debug_object)) {
1036
+ $debug_object->debug_log(
1037
+ 2,
1038
+ 'after match: '
1039
+ . ($check ? 'true' : 'false')
1040
+ );
1041
+ }
1042
+
1043
+ if (!$check) {
1044
+ $pass = false;
1045
+ break;
1046
+ }
1047
+ }
1048
+ }
1049
+
1050
+ // Found a match. Add to list and clear node
1051
+ if ($pass) {
1052
+ $ret[$node->_[HDOM_INFO_BEGIN]] = 1;
1053
+ }
1054
+ unset($node);
1055
+ }
1056
+ // It's passed by reference so this is actually what this function returns.
1057
+ if (is_object($debug_object)) {
1058
+ $debug_object->debug_log(1, 'EXIT - ret: ', $ret);
1059
+ }
1060
+ }
1061
+
1062
+ /**
1063
+ * Match value and pattern for a given CSS expression
1064
+ *
1065
+ * **Supported Expressions**
1066
+ *
1067
+ * | Expression | Description
1068
+ * | ---------- | -----------
1069
+ * | `=` | $value and $pattern must be equal
1070
+ * | `!=` | $value and $pattern must not be equal
1071
+ * | `^=` | $value must start with $pattern
1072
+ * | `$=` | $value must end with $pattern
1073
+ * | `*=` | $value must contain $pattern
1074
+ *
1075
+ * @param string $exp The expression.
1076
+ * @param string $pattern The pattern
1077
+ * @param string $value The value
1078
+ * @value bool True if $value matches $pattern
1079
+ */
1080
+ protected function match($exp, $pattern, $value, $case_sensitivity)
1081
+ {
1082
+ global $debug_object;
1083
+ if (is_object($debug_object)) {
1084
+ $debug_object->debug_log_entry(1);
1085
+ }
1086
+
1087
+ if ($case_sensitivity === 'i') {
1088
+ $pattern = strtolower($pattern);
1089
+ $value = strtolower($value);
1090
+ }
1091
+
1092
+ switch ($exp) {
1093
+ case '=':
1094
+ return ($value === $pattern);
1095
+ case '!=':
1096
+ return ($value !== $pattern);
1097
+ case '^=':
1098
+ return preg_match('/^' . preg_quote($pattern, '/') . '/', $value);
1099
+ case '$=':
1100
+ return preg_match('/' . preg_quote($pattern, '/') . '$/', $value);
1101
+ case '*=':
1102
+ return preg_match('/' . preg_quote($pattern, '/') . '/', $value);
1103
+ case '|=':
1104
+ /**
1105
+ * [att|=val]
1106
+ *
1107
+ * Represents an element with the att attribute, its value
1108
+ * either being exactly "val" or beginning with "val"
1109
+ * immediately followed by "-" (U+002D).
1110
+ */
1111
+ return strpos($value, $pattern) === 0;
1112
+ case '~=':
1113
+ /**
1114
+ * [att~=val]
1115
+ *
1116
+ * Represents an element with the att attribute whose value is a
1117
+ * whitespace-separated list of words, one of which is exactly
1118
+ * "val". If "val" contains whitespace, it will never represent
1119
+ * anything (since the words are separated by spaces). Also if
1120
+ * "val" is the empty string, it will never represent anything.
1121
+ */
1122
+ return in_array($pattern, explode(' ', trim($value)), true);
1123
+ }
1124
+ return false;
1125
+ }
1126
+
1127
+ /**
1128
+ * Parse CSS selector
1129
+ *
1130
+ * @param string $selector_string CSS selector string
1131
+ * @return array List of CSS selectors. The format depends on the type of
1132
+ * selector:
1133
+ *
1134
+ * ```php
1135
+ *
1136
+ * array( // list of selectors (each separated by a comma), i.e. 'img, p, div'
1137
+ * array( // list of combinator selectors, i.e. 'img > p > div'
1138
+ * array( // selector element
1139
+ * [0], // (string) The element tag
1140
+ * [1], // (string) The element id
1141
+ * [2], // (array<string>) The element classes
1142
+ * [3], // (array<array<string>>) The list of attributes, each
1143
+ * // with four elements: name, expression, value, inverted
1144
+ * [4] // (string) The selector combinator (' ' | '>' | '+' | '~')
1145
+ * )
1146
+ * )
1147
+ * )
1148
+ * ```
1149
+ *
1150
+ * @link https://www.w3.org/TR/selectors/#compound Compound selector
1151
+ */
1152
+ protected function parse_selector($selector_string)
1153
+ {
1154
+ global $debug_object;
1155
+ if (is_object($debug_object)) {
1156
+ $debug_object->debug_log_entry(1);
1157
+ }
1158
+
1159
+ /**
1160
+ * Pattern of CSS selectors, modified from mootools (https://mootools.net/)
1161
+ *
1162
+ * Paperg: Add the colon to the attribute, so that it properly finds
1163
+ * <tag attr:ibute="something" > like google does.
1164
+ *
1165
+ * Note: if you try to look at this attribute, you MUST use getAttribute
1166
+ * since $dom->x:y will fail the php syntax check.
1167
+ *
1168
+ * Notice the \[ starting the attribute? and the @? following? This
1169
+ * implies that an attribute can begin with an @ sign that is not
1170
+ * captured. This implies that an html attribute specifier may start
1171
+ * with an @ sign that is NOT captured by the expression. Farther study
1172
+ * is required to determine of this should be documented or removed.
1173
+ *
1174
+ * Matches selectors in this order:
1175
+ *
1176
+ * [0] - full match
1177
+ *
1178
+ * [1] - tag name
1179
+ * ([\w:\*-]*)
1180
+ * Matches the tag name consisting of zero or more words, colons,
1181
+ * asterisks and hyphens.
1182
+ *
1183
+ * [2] - id name
1184
+ * (?:\#([\w-]+))
1185
+ * Optionally matches a id name, consisting of an "#" followed by
1186
+ * the id name (one or more words and hyphens).
1187
+ *
1188
+ * [3] - class names (including dots)
1189
+ * (?:\.([\w\.-]+))?
1190
+ * Optionally matches a list of classs, consisting of an "."
1191
+ * followed by the class name (one or more words and hyphens)
1192
+ * where multiple classes can be chained (i.e. ".foo.bar.baz")
1193
+ *
1194
+ * [4] - attributes
1195
+ * ((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?
1196
+ * Optionally matches the attributes list
1197
+ *
1198
+ * [5] - separator
1199
+ * ([\/, >+~]+)
1200
+ * Matches the selector list separator
1201
+ */
1202
+ // phpcs:ignore Generic.Files.LineLength
1203
+ $pattern = "/([\w:\*-]*)(?:\#([\w-]+))?(?:|\.([\w\.-]+))?((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?([\/, >+~]+)/is";
1204
+
1205
+ preg_match_all(
1206
+ $pattern,
1207
+ trim($selector_string) . ' ', // Add final ' ' as pseudo separator
1208
+ $matches,
1209
+ PREG_SET_ORDER
1210
+ );
1211
+
1212
+ if (is_object($debug_object)) {
1213
+ $debug_object->debug_log(2, 'Matches Array: ', $matches);
1214
+ }
1215
+
1216
+ $selectors = array();
1217
+ $result = array();
1218
+
1219
+ foreach ($matches as $m) {
1220
+ $m[0] = trim($m[0]);
1221
+
1222
+ // Skip NoOps
1223
+ if ($m[0] === '' || $m[0] === '/' || $m[0] === '//') {
1224
+ continue;
1225
+ }
1226
+
1227
+ // Convert to lowercase
1228
+ if ($this->dom->lowercase) {
1229
+ $m[1] = strtolower($m[1]);
1230
+ }
1231
+
1232
+ // Extract classes
1233
+ if ($m[3] !== '') {
1234
+ $m[3] = explode('.', $m[3]);
1235
+ }
1236
+
1237
+ /* Extract attributes (pattern based on the pattern above!)
1238
+
1239
+ * [0] - full match
1240
+ * [1] - attribute name
1241
+ * [2] - attribute expression
1242
+ * [3] - attribute value
1243
+ * [4] - case sensitivity
1244
+ *
1245
+ * Note: Attributes can be negated with a "!" prefix to their name
1246
+ */
1247
+ if ($m[4] !== '') {
1248
+ preg_match_all(
1249
+ "/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s*?([iIsS])?)?\]/is",
1250
+ trim($m[4]),
1251
+ $attributes,
1252
+ PREG_SET_ORDER
1253
+ );
1254
+
1255
+ // Replace element by array
1256
+ $m[4] = array();
1257
+
1258
+ foreach ($attributes as $att) {
1259
+ // Skip empty matches
1260
+ if (trim($att[0]) === '') {
1261
+ continue;
1262
+ }
1263
+
1264
+ $inverted = (isset($att[1][0]) && $att[1][0] === '!');
1265
+ $m[4][] = array(
1266
+ $inverted ? substr($att[1], 1) : $att[1], // Name
1267
+ (isset($att[2])) ? $att[2] : '', // Expression
1268
+ (isset($att[3])) ? $att[3] : '', // Value
1269
+ $inverted, // Inverted Flag
1270
+ (isset($att[4])) ? strtolower($att[4]) : '', // Case-Sensitivity
1271
+ );
1272
+ }
1273
+ }
1274
+
1275
+ // Sanitize Separator
1276
+ if ($m[5] !== '' && trim($m[5]) === '') { // Descendant Separator
1277
+ $m[5] = ' ';
1278
+ } else { // Other Separator
1279
+ $m[5] = trim($m[5]);
1280
+ }
1281
+
1282
+ // Clear Separator if it's a Selector List
1283
+ if ($is_list = ($m[5] === ',')) {
1284
+ $m[5] = '';
1285
+ }
1286
+
1287
+ // Remove full match before adding to results
1288
+ array_shift($m);
1289
+ $result[] = $m;
1290
+
1291
+ if ($is_list) { // Selector List
1292
+ $selectors[] = $result;
1293
+ $result = array();
1294
+ }
1295
+ }
1296
+
1297
+ if (count($result) > 0) {
1298
+ $selectors[] = $result;
1299
+ }
1300
+ return $selectors;
1301
+ }
1302
+
1303
+ function __get($name)
1304
+ {
1305
+ if (isset($this->attr[$name])) {
1306
+ return $this->convert_text($this->attr[$name]);
1307
+ }
1308
+ switch ($name) {
1309
+ case 'outertext':
1310
+ return $this->outertext();
1311
+ case 'innertext':
1312
+ return $this->innertext();
1313
+ case 'plaintext':
1314
+ return $this->text();
1315
+ case 'xmltext':
1316
+ return $this->xmltext();
1317
+ default:
1318
+ return array_key_exists($name, $this->attr);
1319
+ }
1320
+ }
1321
+
1322
+ function __set($name, $value)
1323
+ {
1324
+ global $debug_object;
1325
+ if (is_object($debug_object)) {
1326
+ $debug_object->debug_log_entry(1);
1327
+ }
1328
+
1329
+ switch ($name) {
1330
+ case 'outertext':
1331
+ return $this->_[HDOM_INFO_OUTER] = $value;
1332
+ case 'innertext':
1333
+ if (isset($this->_[HDOM_INFO_TEXT])) {
1334
+ return $this->_[HDOM_INFO_TEXT] = $value;
1335
+ }
1336
+ return $this->_[HDOM_INFO_INNER] = $value;
1337
+ }
1338
+
1339
+ if (!isset($this->attr[$name])) {
1340
+ $this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
1341
+ $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
1342
+ }
1343
+
1344
+ $this->attr[$name] = $value;
1345
+ }
1346
+
1347
+ function __isset($name)
1348
+ {
1349
+ switch ($name) {
1350
+ case 'outertext':
1351
+ return true;
1352
+ case 'innertext':
1353
+ return true;
1354
+ case 'plaintext':
1355
+ return true;
1356
+ }
1357
+ //no value attr: nowrap, checked selected...
1358
+ return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
1359
+ }
1360
+
1361
+ function __unset($name)
1362
+ {
1363
+ if (isset($this->attr[$name])) {
1364
+ unset($this->attr[$name]);
1365
+ }
1366
+ }
1367
+
1368
+ // PaperG - Function to convert the text from one character set to another
1369
+ // if the two sets are not the same.
1370
+ function convert_text($text)
1371
+ {
1372
+ global $debug_object;
1373
+ if (is_object($debug_object)) {
1374
+ $debug_object->debug_log_entry(1);
1375
+ }
1376
+
1377
+ $converted_text = $text;
1378
+
1379
+ $sourceCharset = '';
1380
+ $targetCharset = '';
1381
+
1382
+ if ($this->dom) {
1383
+ $sourceCharset = strtoupper($this->dom->_charset);
1384
+ $targetCharset = strtoupper($this->dom->_target_charset);
1385
+ }
1386
+
1387
+ if (is_object($debug_object)) {
1388
+ $debug_object->debug_log(
1389
+ 3,
1390
+ 'source charset: '
1391
+ . $sourceCharset
1392
+ . ' target charaset: '
1393
+ . $targetCharset
1394
+ );
1395
+ }
1396
+
1397
+ if (!empty($sourceCharset)
1398
+ && !empty($targetCharset)
1399
+ && (strcasecmp($sourceCharset, $targetCharset) != 0)) {
1400
+ // Check if the reported encoding could have been incorrect and the text is actually already UTF-8
1401
+ if ((strcasecmp($targetCharset, 'UTF-8') == 0)
1402
+ && ($this->is_utf8($text))) {
1403
+ $converted_text = $text;
1404
+ } else {
1405
+ $converted_text = iconv($sourceCharset, $targetCharset, $text);
1406
+ }
1407
+ }
1408
+
1409
+ // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
1410
+ if ($targetCharset === 'UTF-8') {
1411
+ if (substr($converted_text, 0, 3) === "\xef\xbb\xbf") {
1412
+ $converted_text = substr($converted_text, 3);
1413
+ }
1414
+
1415
+ if (substr($converted_text, -3) === "\xef\xbb\xbf") {
1416
+ $converted_text = substr($converted_text, 0, -3);
1417
+ }
1418
+ }
1419
+
1420
+ return $converted_text;
1421
+ }
1422
+
1423
+ /**
1424
+ * Returns true if $string is valid UTF-8 and false otherwise.
1425
+ *
1426
+ * @param mixed $str String to be tested
1427
+ * @return boolean
1428
+ */
1429
+ static function is_utf8($str)
1430
+ {
1431
+ $c = 0;
1432
+ $b = 0;
1433
+ $bits = 0;
1434
+ $len = strlen($str);
1435
+ for ($i = 0; $i < $len; $i++) {
1436
+ $c = ord($str[$i]);
1437
+ if ($c > 128) {
1438
+ if (($c >= 254)) {
1439
+ return false;
1440
+ } elseif ($c >= 252) {
1441
+ $bits = 6;
1442
+ } elseif ($c >= 248) {
1443
+ $bits = 5;
1444
+ } elseif ($c >= 240) {
1445
+ $bits = 4;
1446
+ } elseif ($c >= 224) {
1447
+ $bits = 3;
1448
+ } elseif ($c >= 192) {
1449
+ $bits = 2;
1450
+ } else {
1451
+ return false;
1452
+ }
1453
+ if (($i + $bits) > $len) {
1454
+ return false;
1455
+ }
1456
+ while ($bits > 1) {
1457
+ $i++;
1458
+ $b = ord($str[$i]);
1459
+ if ($b < 128 || $b > 191) {
1460
+ return false;
1461
+ }
1462
+ $bits--;
1463
+ }
1464
+ }
1465
+ }
1466
+ return true;
1467
+ }
1468
+
1469
+ /**
1470
+ * Function to try a few tricks to determine the displayed size of an img on
1471
+ * the page. NOTE: This will ONLY work on an IMG tag. Returns FALSE on all
1472
+ * other tag types.
1473
+ *
1474
+ * @author John Schlick
1475
+ * @version April 19 2012
1476
+ * @return array an array containing the 'height' and 'width' of the image
1477
+ * on the page or -1 if we can't figure it out.
1478
+ */
1479
+ function get_display_size()
1480
+ {
1481
+ global $debug_object;
1482
+
1483
+ $width = -1;
1484
+ $height = -1;
1485
+
1486
+ if ($this->tag !== 'img') {
1487
+ return false;
1488
+ }
1489
+
1490
+ // See if there is aheight or width attribute in the tag itself.
1491
+ if (isset($this->attr['width'])) {
1492
+ $width = $this->attr['width'];
1493
+ }
1494
+
1495
+ if (isset($this->attr['height'])) {
1496
+ $height = $this->attr['height'];
1497
+ }
1498
+
1499
+ // Now look for an inline style.
1500
+ if (isset($this->attr['style'])) {
1501
+ // Thanks to user gnarf from stackoverflow for this regular expression.
1502
+ $attributes = array();
1503
+
1504
+ preg_match_all(
1505
+ '/([\w-]+)\s*:\s*([^;]+)\s*;?/',
1506
+ $this->attr['style'],
1507
+ $matches,
1508
+ PREG_SET_ORDER
1509
+ );
1510
+
1511
+ foreach ($matches as $match) {
1512
+ $attributes[$match[1]] = $match[2];
1513
+ }
1514
+
1515
+ // If there is a width in the style attributes:
1516
+ if (isset($attributes['width']) && $width == -1) {
1517
+ // check that the last two characters are px (pixels)
1518
+ if (strtolower(substr($attributes['width'], -2)) === 'px') {
1519
+ $proposed_width = substr($attributes['width'], 0, -2);
1520
+ // Now make sure that it's an integer and not something stupid.
1521
+ if (filter_var($proposed_width, FILTER_VALIDATE_INT)) {
1522
+ $width = $proposed_width;
1523
+ }
1524
+ }
1525
+ }
1526
+
1527
+ // If there is a width in the style attributes:
1528
+ if (isset($attributes['height']) && $height == -1) {
1529
+ // check that the last two characters are px (pixels)
1530
+ if (strtolower(substr($attributes['height'], -2)) == 'px') {
1531
+ $proposed_height = substr($attributes['height'], 0, -2);
1532
+ // Now make sure that it's an integer and not something stupid.
1533
+ if (filter_var($proposed_height, FILTER_VALIDATE_INT)) {
1534
+ $height = $proposed_height;
1535
+ }
1536
+ }
1537
+ }
1538
+ }
1539
+
1540
+ // Future enhancement:
1541
+ // Look in the tag to see if there is a class or id specified that has
1542
+ // a height or width attribute to it.
1543
+
1544
+ // Far future enhancement
1545
+ // Look at all the parent tags of this image to see if they specify a
1546
+ // class or id that has an img selector that specifies a height or width
1547
+ // Note that in this case, the class or id will have the img subselector
1548
+ // for it to apply to the image.
1549
+
1550
+ // ridiculously far future development
1551
+ // If the class or id is specified in a SEPARATE css file thats not on
1552
+ // the page, go get it and do what we were just doing for the ones on
1553
+ // the page.
1554
+
1555
+ $result = array(
1556
+ 'height' => $height,
1557
+ 'width' => $width
1558
+ );
1559
+
1560
+ return $result;
1561
+ }
1562
+
1563
+ // camel naming conventions
1564
+ function getAllAttributes()
1565
+ {
1566
+ return $this->attr;
1567
+ }
1568
+
1569
+ function getAttribute($name)
1570
+ {
1571
+ return $this->__get($name);
1572
+ }
1573
+
1574
+ function setAttribute($name, $value)
1575
+ {
1576
+ $this->__set($name, $value);
1577
+ }
1578
+
1579
+ function hasAttribute($name)
1580
+ {
1581
+ return $this->__isset($name);
1582
+ }
1583
+
1584
+ function removeAttribute($name)
1585
+ {
1586
+ $this->__set($name, null);
1587
+ }
1588
+
1589
+ function getElementById($id)
1590
+ {
1591
+ return $this->find("#$id", 0);
1592
+ }
1593
+
1594
+ function getElementsById($id, $idx = null)
1595
+ {
1596
+ return $this->find("#$id", $idx);
1597
+ }
1598
+
1599
+ function getElementByTagName($name)
1600
+ {
1601
+ return $this->find($name, 0);
1602
+ }
1603
+
1604
+ function getElementsByTagName($name, $idx = null)
1605
+ {
1606
+ return $this->find($name, $idx);
1607
+ }
1608
+
1609
+ function parentNode()
1610
+ {
1611
+ return $this->parent();
1612
+ }
1613
+
1614
+ function childNodes($idx = -1)
1615
+ {
1616
+ return $this->children($idx);
1617
+ }
1618
+
1619
+ function firstChild()
1620
+ {
1621
+ return $this->first_child();
1622
+ }
1623
+
1624
+ function lastChild()
1625
+ {
1626
+ return $this->last_child();
1627
+ }
1628
+
1629
+ function nextSibling()
1630
+ {
1631
+ return $this->next_sibling();
1632
+ }
1633
+
1634
+ function previousSibling()
1635
+ {
1636
+ return $this->prev_sibling();
1637
+ }
1638
+
1639
+ function hasChildNodes()
1640
+ {
1641
+ return $this->has_child();
1642
+ }
1643
+
1644
+ function nodeName()
1645
+ {
1646
+ return $this->tag;
1647
+ }
1648
+
1649
+ function appendChild($node)
1650
+ {
1651
+ $node->parent($this);
1652
+ return $node;
1653
+ }
1654
+ }
1655
+
1656
+ /**
1657
+ * simple html dom parser
1658
+ *
1659
+ * Paperg - in the find routine: allow us to specify that we want case
1660
+ * insensitive testing of the value of the selector.
1661
+ *
1662
+ * Paperg - change $size from protected to public so we can easily access it
1663
+ *
1664
+ * Paperg - added ForceTagsClosed in the constructor which tells us whether we
1665
+ * trust the html or not. Default is to NOT trust it.
1666
+ *
1667
+ * @package PlaceLocalInclude
1668
+ */
1669
+ class simple_html_dom
1670
+ {
1671
+ /**
1672
+ * The root node of the document
1673
+ *
1674
+ * @var object
1675
+ */
1676
+ public $root = null;
1677
+
1678
+ /**
1679
+ * List of nodes in the current DOM
1680
+ *
1681
+ * @var array
1682
+ */
1683
+ public $nodes = array();
1684
+
1685
+ /**
1686
+ * Callback function to run for each element in the DOM.
1687
+ *
1688
+ * @var callable|null
1689
+ */
1690
+ public $callback = null;
1691
+
1692
+ /**
1693
+ * Indicates how tags and attributes are matched
1694
+ *
1695
+ * @var bool When set to **true** tags and attributes will be converted to
1696
+ * lowercase before matching.
1697
+ */
1698
+ public $lowercase = false;
1699
+
1700
+ /**
1701
+ * Original document size
1702
+ *
1703
+ * Holds the original document size.
1704
+ *
1705
+ * @var int
1706
+ */
1707
+ public $original_size;
1708
+
1709
+ /**
1710
+ * Current document size
1711
+ *
1712
+ * Holds the current document size. The document size is determined by the
1713
+ * string length of ({@see simple_html_dom::$doc}).
1714
+ *
1715
+ * _Note_: Using this variable is more efficient than calling `strlen($doc)`
1716
+ *
1717
+ * @var int
1718
+ * */
1719
+ public $size;
1720
+
1721
+ /**
1722
+ * Current position in the document
1723
+ *
1724
+ * @var int
1725
+ */
1726
+ protected $pos;
1727
+
1728
+ /**
1729
+ * The document
1730
+ *
1731
+ * @var string
1732
+ */
1733
+ protected $doc;
1734
+
1735
+ /**
1736
+ * Current character
1737
+ *
1738
+ * Holds the current character at position {@see simple_html_dom::$pos} in
1739
+ * the document {@see simple_html_dom::$doc}
1740
+ *
1741
+ * _Note_: Using this variable is more efficient than calling
1742
+ * `substr($doc, $pos, 1)`
1743
+ *
1744
+ * @var string
1745
+ */
1746
+ protected $char;
1747
+
1748
+ protected $cursor;
1749
+
1750
+ /**
1751
+ * Parent node of the next node detected by the parser
1752
+ *
1753
+ * @var object
1754
+ */
1755
+ protected $parent;
1756
+ protected $noise = array();
1757
+
1758
+ /**
1759
+ * Tokens considered blank in HTML
1760
+ *
1761
+ * @var string
1762
+ */
1763
+ protected $token_blank = " \t\r\n";
1764
+
1765
+ /**
1766
+ * Tokens to identify the equal sign for attributes, stopping either at the
1767
+ * closing tag ("/" i.e. "<html />") or the end of an opening tag (">" i.e.
1768
+ * "<html>")
1769
+ *
1770
+ * @var string
1771
+ */
1772
+ protected $token_equal = ' =/>';
1773
+
1774
+ /**
1775
+ * Tokens to identify the end of a tag name. A tag name either ends on the
1776
+ * ending slash ("/" i.e. "<html/>") or whitespace ("\s\r\n\t")
1777
+ *
1778
+ * @var string
1779
+ */
1780
+ protected $token_slash = " />\r\n\t";
1781
+
1782
+ /**
1783
+ * Tokens to identify the end of an attribute
1784
+ *
1785
+ * @var string
1786
+ */
1787
+ protected $token_attr = ' >';
1788
+
1789
+ // Note that this is referenced by a child node, and so it needs to be
1790
+ // public for that node to see this information.
1791
+ public $_charset = '';
1792
+ public $_target_charset = '';
1793
+
1794
+ /**
1795
+ * Innertext for <br> elements
1796
+ *
1797
+ * @var string
1798
+ */
1799
+ protected $default_br_text = '';
1800
+
1801
+ /**
1802
+ * Suffix for <span> elements
1803
+ *
1804
+ * @var string
1805
+ */
1806
+ public $default_span_text = '';
1807
+
1808
+ /**
1809
+ * Defines a list of self-closing tags (Void elements) according to the HTML
1810
+ * Specification
1811
+ *
1812
+ * _Remarks_:
1813
+ * - Use `isset()` instead of `in_array()` on array elements to boost
1814
+ * performance about 30%
1815
+ * - Sort elements by name for better readability!
1816
+ *
1817
+ * @link https://www.w3.org/TR/html HTML Specification
1818
+ * @link https://www.w3.org/TR/html/syntax.html#void-elements Void elements
1819
+ */
1820
+ protected $self_closing_tags = array(
1821
+ 'area' => 1,
1822
+ 'base' => 1,
1823
+ 'br' => 1,
1824
+ 'col' => 1,
1825
+ 'embed' => 1,
1826
+ 'hr' => 1,
1827
+ 'img' => 1,
1828
+ 'input' => 1,
1829
+ 'link' => 1,
1830
+ 'meta' => 1,
1831
+ 'param' => 1,
1832
+ 'source' => 1,
1833
+ 'track' => 1,
1834
+ 'wbr' => 1
1835
+ );
1836
+
1837
+ /**
1838
+ * Defines a list of tags which - if closed - close all optional closing
1839
+ * elements within if they haven't been closed yet. (So, an element where
1840
+ * neither opening nor closing tag is omissible consistently closes every
1841
+ * optional closing element within)
1842
+ *
1843
+ * _Remarks_:
1844
+ * - Use `isset()` instead of `in_array()` on array elements to boost
1845
+ * performance about 30%
1846
+ * - Sort elements by name for better readability!
1847
+ */
1848
+ protected $block_tags = array(
1849
+ 'body' => 1,
1850
+ 'div' => 1,
1851
+ 'form' => 1,
1852
+ 'root' => 1,
1853
+ 'span' => 1,
1854
+ 'table' => 1
1855
+ );
1856
+
1857
+ /**
1858
+ * Defines elements whose end tag is omissible.
1859
+ *
1860
+ * * key = Name of an element whose end tag is omissible.
1861
+ * * value = Names of elements whose end tag is omissible, that are closed
1862
+ * by the current element.
1863
+ *
1864
+ * _Remarks_:
1865
+ * - Use `isset()` instead of `in_array()` on array elements to boost
1866
+ * performance about 30%
1867
+ * - Sort elements by name for better readability!
1868
+ *
1869
+ * **Example**
1870
+ *
1871
+ * An `li` element’s end tag may be omitted if the `li` element is immediately
1872
+ * followed by another `li` element. To do that, add following element to the
1873
+ * array:
1874
+ *
1875
+ * ```php
1876
+ * 'li' => array('li'),
1877
+ * ```
1878
+ *
1879
+ * With this, the following two examples are considered equal. Note that the
1880
+ * second example is missing the closing tags on `li` elements.
1881
+ *
1882
+ * ```html
1883
+ * <ul><li>First Item</li><li>Second Item</li></ul>
1884
+ * ```
1885
+ *
1886
+ * <ul><li>First Item</li><li>Second Item</li></ul>
1887
+ *
1888
+ * ```html
1889
+ * <ul><li>First Item<li>Second Item</ul>
1890
+ * ```
1891
+ *
1892
+ * <ul><li>First Item<li>Second Item</ul>
1893
+ *
1894
+ * @var array A two-dimensional array where the key is the name of an
1895
+ * element whose end tag is omissible and the value is an array of elements
1896
+ * whose end tag is omissible, that are closed by the current element.
1897
+ *
1898
+ * @link https://www.w3.org/TR/html/syntax.html#optional-tags Optional tags
1899
+ *
1900
+ * @todo The implementation of optional closing tags doesn't work in all cases
1901
+ * because it only consideres elements who close other optional closing
1902
+ * tags, not taking into account that some (non-blocking) tags should close
1903
+ * these optional closing tags. For example, the end tag for "p" is omissible
1904
+ * and can be closed by an "address" element, whose end tag is NOT omissible.
1905
+ * Currently a "p" element without closing tag stops at the next "p" element
1906
+ * or blocking tag, even if it contains other elements.
1907
+ *
1908
+ * @todo Known sourceforge issue #2977341
1909
+ * B tags that are not closed cause us to return everything to the end of
1910
+ * the document.
1911
+ */
1912
+ protected $optional_closing_tags = array(
1913
+ // Not optional, see
1914
+ // https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
1915
+ 'b' => array('b' => 1),
1916
+ 'dd' => array('dd' => 1, 'dt' => 1),
1917
+ // Not optional, see
1918
+ // https://www.w3.org/TR/html/grouping-content.html#the-dl-element
1919
+ 'dl' => array('dd' => 1, 'dt' => 1),
1920
+ 'dt' => array('dd' => 1, 'dt' => 1),
1921
+ 'li' => array('li' => 1),
1922
+ 'optgroup' => array('optgroup' => 1, 'option' => 1),
1923
+ 'option' => array('optgroup' => 1, 'option' => 1),
1924
+ 'p' => array('p' => 1),
1925
+ 'rp' => array('rp' => 1, 'rt' => 1),
1926
+ 'rt' => array('rp' => 1, 'rt' => 1),
1927
+ 'td' => array('td' => 1, 'th' => 1),
1928
+ 'th' => array('td' => 1, 'th' => 1),
1929
+ 'tr' => array('td' => 1, 'th' => 1, 'tr' => 1),
1930
+ );
1931
+
1932
+ function __construct(
1933
+ $str = null,
1934
+ $lowercase = true,
1935
+ $forceTagsClosed = true,
1936
+ $target_charset = DEFAULT_TARGET_CHARSET,
1937
+ $stripRN = true,
1938
+ $defaultBRText = DEFAULT_BR_TEXT,
1939
+ $defaultSpanText = DEFAULT_SPAN_TEXT,
1940
+ $options = 0
1941
+ ) {
1942
+ if ($str) {
1943
+ if (preg_match('/^http:\/\//i', $str) || is_file($str)) {
1944
+ $this->load_file($str);
1945
+ } else {
1946
+ $this->load(
1947
+ $str,
1948
+ $lowercase,
1949
+ $stripRN,
1950
+ $defaultBRText,
1951
+ $defaultSpanText,
1952
+ $options
1953
+ );
1954
+ }
1955
+ }
1956
+ // Forcing tags to be closed implies that we don't trust the html, but
1957
+ // it can lead to parsing errors if we SHOULD trust the html.
1958
+ if (!$forceTagsClosed) {
1959
+ $this->optional_closing_array = array();
1960
+ }
1961
+
1962
+ $this->_target_charset = $target_charset;
1963
+ }
1964
+
1965
+ function __destruct()
1966
+ {
1967
+ $this->clear();
1968
+ }
1969
+
1970
+ // load html from string
1971
+ function load(
1972
+ $str,
1973
+ $lowercase = true,
1974
+ $stripRN = true,
1975
+ $defaultBRText = DEFAULT_BR_TEXT,
1976
+ $defaultSpanText = DEFAULT_SPAN_TEXT,
1977
+ $options = 0
1978
+ ) {
1979
+ global $debug_object;
1980
+
1981
+ // prepare
1982
+ $this->prepare($str, $lowercase, $defaultBRText, $defaultSpanText);
1983
+
1984
+ // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
1985
+ // Script tags removal now preceeds style tag removal.
1986
+ // strip out <script> tags
1987
+ $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
1988
+ $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
1989
+
1990
+ // strip out the \r \n's if we are told to.
1991
+ if ($stripRN) {
1992
+ $this->doc = str_replace("\r", ' ', $this->doc);
1993
+ $this->doc = str_replace("\n", ' ', $this->doc);
1994
+
1995
+ // set the length of content since we have changed it.
1996
+ $this->size = strlen($this->doc);
1997
+ }
1998
+
1999
+ // strip out cdata
2000
+ $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
2001
+ // strip out comments
2002
+ $this->remove_noise("'<!--(.*?)-->'is");
2003
+ // strip out <style> tags
2004
+ $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
2005
+ $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
2006
+ // strip out preformatted tags
2007
+ $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
2008
+ // strip out server side scripts
2009
+ $this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
2010
+
2011
+ if ($options & HDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts
2012
+ $this->remove_noise("'(\{\w)(.*?)(\})'s", true);
2013
+ }
2014
+
2015
+ // parsing
2016
+ $this->parse();
2017
+ // end
2018
+ $this->root->_[HDOM_INFO_END] = $this->cursor;
2019
+ $this->parse_charset();
2020
+
2021
+ // make load function chainable
2022
+ return $this;
2023
+ }
2024
+
2025
+ // load html from file
2026
+ function load_file()
2027
+ {
2028
+ $args = func_get_args();
2029
+
2030
+ if (($doc = call_user_func_array('file_get_contents', $args)) !== false) {
2031
+ $this->load($doc, true);
2032
+ } else {
2033
+ return false;
2034
+ }
2035
+ }
2036
+
2037
+ /**
2038
+ * Set the callback function
2039
+ *
2040
+ * @param callable $function_name Callback function to run for each element
2041
+ * in the DOM.
2042
+ * @return void
2043
+ */
2044
+ function set_callback($function_name)
2045
+ {
2046
+ $this->callback = $function_name;
2047
+ }
2048
+
2049
+ /**
2050
+ * Remove callback function
2051
+ *
2052
+ * @return void
2053
+ */
2054
+ function remove_callback()
2055
+ {
2056
+ $this->callback = null;
2057
+ }
2058
+
2059
+ // save dom as string
2060
+ function save($filepath = '')
2061
+ {
2062
+ $ret = $this->root->innertext();
2063
+ if ($filepath !== '') {
2064
+ file_put_contents($filepath, $ret, LOCK_EX);
2065
+ }
2066
+ return $ret;
2067
+ }
2068
+
2069
+ // find dom node by css selector
2070
+ // Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
2071
+ function find($selector, $idx = null, $lowercase = false)
2072
+ {
2073
+ return $this->root->find($selector, $idx, $lowercase);
2074
+ }
2075
+
2076
+ // clean up memory due to php5 circular references memory leak...
2077
+ function clear()
2078
+ {
2079
+ foreach ($this->nodes as $n) {
2080
+ $n->clear();
2081
+ $n = null;
2082
+ }
2083
+
2084
+ // This add next line is documented in the sourceforge repository.
2085
+ // 2977248 as a fix for ongoing memory leaks that occur even with the
2086
+ // use of clear.
2087
+ if (isset($this->children)) {
2088
+ foreach ($this->children as $n) {
2089
+ $n->clear();
2090
+ $n = null;
2091
+ }
2092
+ }
2093
+
2094
+ if (isset($this->parent)) {
2095
+ $this->parent->clear();
2096
+ unset($this->parent);
2097
+ }
2098
+
2099
+ if (isset($this->root)) {
2100
+ $this->root->clear();
2101
+ unset($this->root);
2102
+ }
2103
+
2104
+ unset($this->doc);
2105
+ unset($this->noise);
2106
+ }
2107
+
2108
+ function dump($show_attr = true)
2109
+ {
2110
+ $this->root->dump($show_attr);
2111
+ }
2112
+
2113
+ // prepare HTML data and init everything
2114
+ protected function prepare(
2115
+ $str,
2116
+ $lowercase = true,
2117
+ $defaultBRText = DEFAULT_BR_TEXT,
2118
+ $defaultSpanText = DEFAULT_SPAN_TEXT
2119
+ ) {
2120
+ $this->clear();
2121
+
2122
+ $this->doc = trim($str);
2123
+ $this->size = strlen($this->doc);
2124
+ $this->original_size = $this->size; // original size of the html
2125
+ $this->pos = 0;
2126
+ $this->cursor = 1;
2127
+ $this->noise = array();
2128
+ $this->nodes = array();
2129
+ $this->lowercase = $lowercase;
2130
+ $this->default_br_text = $defaultBRText;
2131
+ $this->default_span_text = $defaultSpanText;
2132
+ $this->root = new simple_html_dom_node($this);
2133
+ $this->root->tag = 'root';
2134
+ $this->root->_[HDOM_INFO_BEGIN] = -1;
2135
+ $this->root->nodetype = HDOM_TYPE_ROOT;
2136
+ $this->parent = $this->root;
2137
+ if ($this->size > 0) {
2138
+ $this->char = $this->doc[0];
2139
+ }
2140
+ }
2141
+
2142
+ /**
2143
+ * Parse HTML content
2144
+ *
2145
+ * @return bool True on success
2146
+ */
2147
+ protected function parse()
2148
+ {
2149
+ while (true) {
2150
+ // Read next tag if there is no text between current position and the
2151
+ // next opening tag.
2152
+ if (($s = $this->copy_until_char('<')) === '') {
2153
+ if ($this->read_tag()) {
2154
+ continue;
2155
+ } else {
2156
+ return true;
2157
+ }
2158
+ }
2159
+
2160
+ // Add a text node for text between tags
2161
+ $node = new simple_html_dom_node($this);
2162
+ ++$this->cursor;
2163
+ $node->_[HDOM_INFO_TEXT] = $s;
2164
+ $this->link_nodes($node, false);
2165
+ }
2166
+ }
2167
+
2168
+ // PAPERG - dkchou - added this to try to identify the character set of the
2169
+ // page we have just parsed so we know better how to spit it out later.
2170
+ // NOTE: IF you provide a routine called
2171
+ // get_last_retrieve_url_contents_content_type which returns the
2172
+ // CURLINFO_CONTENT_TYPE from the last curl_exec
2173
+ // (or the content_type header from the last transfer), we will parse THAT,
2174
+ // and if a charset is specified, we will use it over any other mechanism.
2175
+ protected function parse_charset()
2176
+ {
2177
+ global $debug_object;
2178
+
2179
+ $charset = null;
2180
+
2181
+ if (function_exists('get_last_retrieve_url_contents_content_type')) {
2182
+ $contentTypeHeader = get_last_retrieve_url_contents_content_type();
2183
+ $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
2184
+ if ($success) {
2185
+ $charset = $matches[1];
2186
+ if (is_object($debug_object)) {
2187
+ $debug_object->debug_log(
2188
+ 2,
2189
+ 'header content-type found charset of: '
2190
+ . $charset
2191
+ );
2192
+ }
2193
+ }
2194
+ }
2195
+
2196
+ if (empty($charset)) {
2197
+ $el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
2198
+
2199
+ if (!empty($el)) {
2200
+ $fullvalue = $el->content;
2201
+ if (is_object($debug_object)) {
2202
+ $debug_object->debug_log(
2203
+ 2,
2204
+ 'meta content-type tag found'
2205
+ . $fullvalue
2206
+ );
2207
+ }
2208
+
2209
+ if (!empty($fullvalue)) {
2210
+ $success = preg_match(
2211
+ '/charset=(.+)/i',
2212
+ $fullvalue,
2213
+ $matches
2214
+ );
2215
+
2216
+ if ($success) {
2217
+ $charset = $matches[1];
2218
+ } else {
2219
+ // If there is a meta tag, and they don't specify the
2220
+ // character set, research says that it's typically
2221
+ // ISO-8859-1
2222
+ if (is_object($debug_object)) {
2223
+ $debug_object->debug_log(
2224
+ 2,
2225
+ 'meta content-type tag couldn\'t be parsed. using iso-8859 default.'
2226
+ );
2227
+ }
2228
+
2229
+ $charset = 'ISO-8859-1';
2230
+ }
2231
+ }
2232
+ }
2233
+ }
2234
+
2235
+ // If we couldn't find a charset above, then lets try to detect one
2236
+ // based on the text we got...
2237
+ if (empty($charset)) {
2238
+ // Use this in case mb_detect_charset isn't installed/loaded on
2239
+ // this machine.
2240
+ $charset = false;
2241
+ if (function_exists('mb_detect_encoding')) {
2242
+ // Have php try to detect the encoding from the text given to us.
2243
+ $charset = mb_detect_encoding(
2244
+ $this->doc . 'ascii',
2245
+ $encoding_list = array( 'UTF-8', 'CP1252' )
2246
+ );
2247
+
2248
+ if (is_object($debug_object)) {
2249
+ $debug_object->debug_log(2, 'mb_detect found: ' . $charset);
2250
+ }
2251
+ }
2252
+
2253
+ // and if this doesn't work... then we need to just wrongheadedly
2254
+ // assume it's UTF-8 so that we can move on - cause this will
2255
+ // usually give us most of what we need...
2256
+ if ($charset === false) {
2257
+ if (is_object($debug_object)) {
2258
+ $debug_object->debug_log(
2259
+ 2,
2260
+ 'since mb_detect failed - using default of utf-8'
2261
+ );
2262
+ }
2263
+
2264
+ $charset = 'UTF-8';
2265
+ }
2266
+ }
2267
+
2268
+ // Since CP1252 is a superset, if we get one of it's subsets, we want
2269
+ // it instead.
2270
+ if ((strtolower($charset) == strtolower('ISO-8859-1'))
2271
+ || (strtolower($charset) == strtolower('Latin1'))
2272
+ || (strtolower($charset) == strtolower('Latin-1'))) {
2273
+ if (is_object($debug_object)) {
2274
+ $debug_object->debug_log(
2275
+ 2,
2276
+ 'replacing ' . $charset . ' with CP1252 as its a superset'
2277
+ );
2278
+ }
2279
+
2280
+ $charset = 'CP1252';
2281
+ }
2282
+
2283
+ if (is_object($debug_object)) {
2284
+ $debug_object->debug_log(1, 'EXIT - ' . $charset);
2285
+ }
2286
+
2287
+ return $this->_charset = $charset;
2288
+ }
2289
+
2290
+ /**
2291
+ * Parse tag from current document position.
2292
+ *
2293
+ * @return bool True if a tag was found, false otherwise
2294
+ */
2295
+ protected function read_tag()
2296
+ {
2297
+ // Set end position if no further tags found
2298
+ if ($this->char !== '<') {
2299
+ $this->root->_[HDOM_INFO_END] = $this->cursor;
2300
+ return false;
2301
+ }
2302
+
2303
+ $begin_tag_pos = $this->pos;
2304
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2305
+
2306
+ // end tag
2307
+ if ($this->char === '/') {
2308
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2309
+
2310
+ // Skip whitespace in end tags (i.e. in "</ html>")
2311
+ $this->skip($this->token_blank);
2312
+ $tag = $this->copy_until_char('>');
2313
+
2314
+ // Skip attributes in end tags
2315
+ if (($pos = strpos($tag, ' ')) !== false) {
2316
+ $tag = substr($tag, 0, $pos);
2317
+ }
2318
+
2319
+ $parent_lower = strtolower($this->parent->tag);
2320
+ $tag_lower = strtolower($tag);
2321
+
2322
+ // The end tag is supposed to close the parent tag. Handle situations
2323
+ // when it doesn't
2324
+ if ($parent_lower !== $tag_lower) {
2325
+ // Parent tag does not have to be closed necessarily (optional closing tag)
2326
+ // Current tag is a block tag, so it may close an ancestor
2327
+ if (isset($this->optional_closing_tags[$parent_lower])
2328
+ && isset($this->block_tags[$tag_lower])) {
2329
+ $this->parent->_[HDOM_INFO_END] = 0;
2330
+ $org_parent = $this->parent;
2331
+
2332
+ // Traverse ancestors to find a matching opening tag
2333
+ // Stop at root node
2334
+ while (($this->parent->parent)
2335
+ && strtolower($this->parent->tag) !== $tag_lower
2336
+ ) {
2337
+ $this->parent = $this->parent->parent;
2338
+ }
2339
+
2340
+ // If we don't have a match add current tag as text node
2341
+ if (strtolower($this->parent->tag) !== $tag_lower) {
2342
+ $this->parent = $org_parent; // restore origonal parent
2343
+
2344
+ if ($this->parent->parent) {
2345
+ $this->parent = $this->parent->parent;
2346
+ }
2347
+
2348
+ $this->parent->_[HDOM_INFO_END] = $this->cursor;
2349
+ return $this->as_text_node($tag);
2350
+ }
2351
+ } elseif (($this->parent->parent)
2352
+ && isset($this->block_tags[$tag_lower])
2353
+ ) {
2354
+ // Grandparent exists and current tag is a block tag, so our
2355
+ // parent doesn't have an end tag
2356
+ $this->parent->_[HDOM_INFO_END] = 0; // No end tag
2357
+ $org_parent = $this->parent;
2358
+
2359
+ // Traverse ancestors to find a matching opening tag
2360
+ // Stop at root node
2361
+ while (($this->parent->parent)
2362
+ && strtolower($this->parent->tag) !== $tag_lower
2363
+ ) {
2364
+ $this->parent = $this->parent->parent;
2365
+ }
2366
+
2367
+ // If we don't have a match add current tag as text node
2368
+ if (strtolower($this->parent->tag) !== $tag_lower) {
2369
+ $this->parent = $org_parent; // restore origonal parent
2370
+ $this->parent->_[HDOM_INFO_END] = $this->cursor;
2371
+ return $this->as_text_node($tag);
2372
+ }
2373
+ } elseif (($this->parent->parent)
2374
+ && strtolower($this->parent->parent->tag) === $tag_lower
2375
+ ) { // Grandparent exists and current tag closes it
2376
+ $this->parent->_[HDOM_INFO_END] = 0;
2377
+ $this->parent = $this->parent->parent;
2378
+ } else { // Random tag, add as text node
2379
+ return $this->as_text_node($tag);
2380
+ }
2381
+ }
2382
+
2383
+ // Set end position of parent tag to current cursor position
2384
+ $this->parent->_[HDOM_INFO_END] = $this->cursor;
2385
+
2386
+ if ($this->parent->parent) {
2387
+ $this->parent = $this->parent->parent;
2388
+ }
2389
+
2390
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2391
+ return true;
2392
+ }
2393
+
2394
+ // start tag
2395
+ $node = new simple_html_dom_node($this);
2396
+ $node->_[HDOM_INFO_BEGIN] = $this->cursor;
2397
+ ++$this->cursor;
2398
+ $tag = $this->copy_until($this->token_slash); // Get tag name
2399
+ $node->tag_start = $begin_tag_pos;
2400
+
2401
+ // doctype, cdata & comments...
2402
+ // <!DOCTYPE html>
2403
+ // <![CDATA[ ... ]]>
2404
+ // <!-- Comment -->
2405
+ if (isset($tag[0]) && $tag[0] === '!') {
2406
+ $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
2407
+
2408
+ if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--")
2409
+ $node->nodetype = HDOM_TYPE_COMMENT;
2410
+ $node->tag = 'comment';
2411
+ } else { // Could be doctype or CDATA but we don't care
2412
+ $node->nodetype = HDOM_TYPE_UNKNOWN;
2413
+ $node->tag = 'unknown';
2414
+ }
2415
+
2416
+ if ($this->char === '>') {
2417
+ $node->_[HDOM_INFO_TEXT] .= '>';
2418
+ }
2419
+
2420
+ $this->link_nodes($node, true);
2421
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2422
+ return true;
2423
+ }
2424
+
2425
+ // The start tag cannot contain another start tag, if so add as text
2426
+ // i.e. "<<html>"
2427
+ if ($pos = strpos($tag, '<') !== false) {
2428
+ $tag = '<' . substr($tag, 0, -1);
2429
+ $node->_[HDOM_INFO_TEXT] = $tag;
2430
+ $this->link_nodes($node, false);
2431
+ $this->char = $this->doc[--$this->pos]; // prev
2432
+ return true;
2433
+ }
2434
+
2435
+ // Handle invalid tag names (i.e. "<html#doc>")
2436
+ if (!preg_match('/^\w[\w:-]*$/', $tag)) {
2437
+ $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
2438
+
2439
+ // Next char is the beginning of a new tag, don't touch it.
2440
+ if ($this->char === '<') {
2441
+ $this->link_nodes($node, false);
2442
+ return true;
2443
+ }
2444
+
2445
+ // Next char closes current tag, add and be done with it.
2446
+ if ($this->char === '>') {
2447
+ $node->_[HDOM_INFO_TEXT] .= '>';
2448
+ }
2449
+ $this->link_nodes($node, false);
2450
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2451
+ return true;
2452
+ }
2453
+
2454
+ // begin tag, add new node
2455
+ $node->nodetype = HDOM_TYPE_ELEMENT;
2456
+ $tag_lower = strtolower($tag);
2457
+ $node->tag = ($this->lowercase) ? $tag_lower : $tag;
2458
+
2459
+ // handle optional closing tags
2460
+ if (isset($this->optional_closing_tags[$tag_lower])) {
2461
+ // Traverse ancestors to close all optional closing tags
2462
+ while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
2463
+ $this->parent->_[HDOM_INFO_END] = 0;
2464
+ $this->parent = $this->parent->parent;
2465
+ }
2466
+ $node->parent = $this->parent;
2467
+ }
2468
+
2469
+ $guard = 0; // prevent infinity loop
2470
+
2471
+ // [0] Space between tag and first attribute
2472
+ $space = array($this->copy_skip($this->token_blank), '', '');
2473
+
2474
+ // attributes
2475
+ do {
2476
+ // Everything until the first equal sign should be the attribute name
2477
+ $name = $this->copy_until($this->token_equal);
2478
+
2479
+ if ($name === '' && $this->char !== null && $space[0] === '') {
2480
+ break;
2481
+ }
2482
+
2483
+ if ($guard === $this->pos) { // Escape infinite loop
2484
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2485
+ continue;
2486
+ }
2487
+
2488
+ $guard = $this->pos;
2489
+
2490
+ // handle endless '<'
2491
+ // Out of bounds before the tag ended
2492
+ if ($this->pos >= $this->size - 1 && $this->char !== '>') {
2493
+ $node->nodetype = HDOM_TYPE_TEXT;
2494
+ $node->_[HDOM_INFO_END] = 0;
2495
+ $node->_[HDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name;
2496
+ $node->tag = 'text';
2497
+ $this->link_nodes($node, false);
2498
+ return true;
2499
+ }
2500
+
2501
+ // handle mismatch '<'
2502
+ // Attributes cannot start after opening tag
2503
+ if ($this->doc[$this->pos - 1] == '<') {
2504
+ $node->nodetype = HDOM_TYPE_TEXT;
2505
+ $node->tag = 'text';
2506
+ $node->attr = array();
2507
+ $node->_[HDOM_INFO_END] = 0;
2508
+ $node->_[HDOM_INFO_TEXT] = substr(
2509
+ $this->doc,
2510
+ $begin_tag_pos,
2511
+ $this->pos - $begin_tag_pos - 1
2512
+ );
2513
+ $this->pos -= 2;
2514
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2515
+ $this->link_nodes($node, false);
2516
+ return true;
2517
+ }
2518
+
2519
+ if ($name !== '/' && $name !== '') { // this is a attribute name
2520
+ // [1] Whitespace after attribute name
2521
+ $space[1] = $this->copy_skip($this->token_blank);
2522
+
2523
+ $name = $this->restore_noise($name); // might be a noisy name
2524
+
2525
+ if ($this->lowercase) {
2526
+ $name = strtolower($name);
2527
+ }
2528
+
2529
+ if ($this->char === '=') { // attribute with value
2530
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2531
+ $this->parse_attr($node, $name, $space); // get attribute value
2532
+ } else {
2533
+ //no value attr: nowrap, checked selected...
2534
+ $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
2535
+ $node->attr[$name] = true;
2536
+ if ($this->char != '>') {
2537
+ $this->char = $this->doc[--$this->pos];
2538
+ } // prev
2539
+ }
2540
+
2541
+ $node->_[HDOM_INFO_SPACE][] = $space;
2542
+
2543
+ // prepare for next attribute
2544
+ $space = array(
2545
+ $this->copy_skip($this->token_blank),
2546
+ '',
2547
+ ''
2548
+ );
2549
+ } else { // no more attributes
2550
+ break;
2551
+ }
2552
+ } while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended
2553
+
2554
+ $this->link_nodes($node, true);
2555
+ $node->_[HDOM_INFO_ENDSPACE] = $space[0];
2556
+
2557
+ // handle empty tags (i.e. "<div/>")
2558
+ if ($this->copy_until_char('>') === '/') {
2559
+ $node->_[HDOM_INFO_ENDSPACE] .= '/';
2560
+ $node->_[HDOM_INFO_END] = 0;
2561
+ } else {
2562
+ // reset parent
2563
+ if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
2564
+ $this->parent = $node;
2565
+ }
2566
+ }
2567
+
2568
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2569
+
2570
+ // If it's a BR tag, we need to set it's text to the default text.
2571
+ // This way when we see it in plaintext, we can generate formatting that the user wants.
2572
+ // since a br tag never has sub nodes, this works well.
2573
+ if ($node->tag === 'br') {
2574
+ $node->_[HDOM_INFO_INNER] = $this->default_br_text;
2575
+ }
2576
+
2577
+ return true;
2578
+ }
2579
+
2580
+ /**
2581
+ * Parse attribute from current document position
2582
+ *
2583
+ * @param object $node Node for the attributes
2584
+ * @param string $name Name of the current attribute
2585
+ * @param array $space Array for spacing information
2586
+ * @return void
2587
+ */
2588
+ protected function parse_attr($node, $name, &$space)
2589
+ {
2590
+ // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
2591
+ // If the attribute is already defined inside a tag, only pay attention
2592
+ // to the first one as opposed to the last one.
2593
+ // https://stackoverflow.com/a/26341866
2594
+ if (isset($node->attr[$name])) {
2595
+ return;
2596
+ }
2597
+
2598
+ // [2] Whitespace between "=" and the value
2599
+ $space[2] = $this->copy_skip($this->token_blank);
2600
+
2601
+ switch ($this->char) {
2602
+ case '"': // value is anything between double quotes
2603
+ $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
2604
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2605
+ $node->attr[$name] = $this->restore_noise($this->copy_until_char('"'));
2606
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2607
+ break;
2608
+ case '\'': // value is anything between single quotes
2609
+ $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE;
2610
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2611
+ $node->attr[$name] = $this->restore_noise($this->copy_until_char('\''));
2612
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2613
+ break;
2614
+ default: // value is anything until the first space or end tag
2615
+ $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
2616
+ $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr));
2617
+ }
2618
+ // PaperG: Attributes should not have \r or \n in them, that counts as
2619
+ // html whitespace.
2620
+ $node->attr[$name] = str_replace("\r", '', $node->attr[$name]);
2621
+ $node->attr[$name] = str_replace("\n", '', $node->attr[$name]);
2622
+ // PaperG: If this is a "class" selector, lets get rid of the preceeding
2623
+ // and trailing space since some people leave it in the multi class case.
2624
+ if ($name === 'class') {
2625
+ $node->attr[$name] = trim($node->attr[$name]);
2626
+ }
2627
+ }
2628
+
2629
+ /**
2630
+ * Link node to parent node
2631
+ *
2632
+ * @param object $node Node to link to parent
2633
+ * @param bool $is_child True if the node is a child of parent
2634
+ * @return void
2635
+ */
2636
+ // link node's parent
2637
+ protected function link_nodes(&$node, $is_child)
2638
+ {
2639
+ $node->parent = $this->parent;
2640
+ $this->parent->nodes[] = $node;
2641
+ if ($is_child) {
2642
+ $this->parent->children[] = $node;
2643
+ }
2644
+ }
2645
+
2646
+ /**
2647
+ * Add tag as text node to current node
2648
+ *
2649
+ * @param string $tag Tag name
2650
+ * @return bool True on success
2651
+ */
2652
+ protected function as_text_node($tag)
2653
+ {
2654
+ $node = new simple_html_dom_node($this);
2655
+ ++$this->cursor;
2656
+ $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
2657
+ $this->link_nodes($node, false);
2658
+ $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2659
+ return true;
2660
+ }
2661
+
2662
+ /**
2663
+ * Seek from the current document position to the first occurrence of a
2664
+ * character not defined by the provided string. Update the current document
2665
+ * position to the new position.
2666
+ *
2667
+ * @param string $chars A string containing every allowed character.
2668
+ * @return void
2669
+ */
2670
+ protected function skip($chars)
2671
+ {
2672
+ $this->pos += strspn($this->doc, $chars, $this->pos);
2673
+ $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2674
+ }
2675
+
2676
+ /**
2677
+ * Copy substring from the current document position to the first occurrence
2678
+ * of a character not defined by the provided string.
2679
+ *
2680
+ * @param string $chars A string containing every allowed character.
2681
+ * @return string Substring from the current document position to the first
2682
+ * occurrence of a character not defined by the provided string.
2683
+ */
2684
+ protected function copy_skip($chars)
2685
+ {
2686
+ $pos = $this->pos;
2687
+ $len = strspn($this->doc, $chars, $pos);
2688
+ $this->pos += $len;
2689
+ $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2690
+ if ($len === 0) {
2691
+ return '';
2692
+ }
2693
+ return substr($this->doc, $pos, $len);
2694
+ }
2695
+
2696
+ /**
2697
+ * Copy substring from the current document position to the first occurrence
2698
+ * of any of the provided characters.
2699
+ *
2700
+ * @param string $chars A string containing every character to stop at.
2701
+ * @return string Substring from the current document position to the first
2702
+ * occurrence of any of the provided characters.
2703
+ */
2704
+ protected function copy_until($chars)
2705
+ {
2706
+ $pos = $this->pos;
2707
+ $len = strcspn($this->doc, $chars, $pos);
2708
+ $this->pos += $len;
2709
+ $this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2710
+ return substr($this->doc, $pos, $len);
2711
+ }
2712
+
2713
+ /**
2714
+ * Copy substring from the current document position to the first occurrence
2715
+ * of the provided string.
2716
+ *
2717
+ * @param string $char The string to stop at.
2718
+ * @return string Substring from the current document position to the first
2719
+ * occurrence of the provided string.
2720
+ */
2721
+ protected function copy_until_char($char)
2722
+ {
2723
+ if ($this->char === null) {
2724
+ return '';
2725
+ }
2726
+
2727
+ if (($pos = strpos($this->doc, $char, $this->pos)) === false) {
2728
+ $ret = substr($this->doc, $this->pos, $this->size - $this->pos);
2729
+ $this->char = null;
2730
+ $this->pos = $this->size;
2731
+ return $ret;
2732
+ }
2733
+
2734
+ if ($pos === $this->pos) {
2735
+ return '';
2736
+ }
2737
+
2738
+ $pos_old = $this->pos;
2739
+ $this->char = $this->doc[$pos];
2740
+ $this->pos = $pos;
2741
+ return substr($this->doc, $pos_old, $pos - $pos_old);
2742
+ }
2743
+
2744
+ /**
2745
+ * Remove noise from HTML content
2746
+ *
2747
+ * Noise is stored to {@see simple_html_dom::$noise}
2748
+ *
2749
+ * @param string $pattern The regex pattern used for finding noise
2750
+ * @param bool $remove_tag True to remove the entire match. Default is false
2751
+ * to only remove the captured data.
2752
+ */
2753
+ protected function remove_noise($pattern, $remove_tag = false)
2754
+ {
2755
+ global $debug_object;
2756
+ if (is_object($debug_object)) {
2757
+ $debug_object->debug_log_entry(1);
2758
+ }
2759
+
2760
+ $count = preg_match_all(
2761
+ $pattern,
2762
+ $this->doc,
2763
+ $matches,
2764
+ PREG_SET_ORDER | PREG_OFFSET_CAPTURE
2765
+ );
2766
+
2767
+ for ($i = $count - 1; $i > -1; --$i) {
2768
+ $key = '___noise___' . sprintf('% 5d', count($this->noise) + 1000);
2769
+
2770
+ if (is_object($debug_object)) {
2771
+ $debug_object->debug_log(2, 'key is: ' . $key);
2772
+ }
2773
+
2774
+ $idx = ($remove_tag) ? 0 : 1; // 0 = entire match, 1 = submatch
2775
+ $this->noise[$key] = $matches[$i][$idx][0];
2776
+ $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
2777
+ }
2778
+
2779
+ // reset the length of content
2780
+ $this->size = strlen($this->doc);
2781
+
2782
+ if ($this->size > 0) {
2783
+ $this->char = $this->doc[0];
2784
+ }
2785
+ }
2786
+
2787
+ /**
2788
+ * Restore noise to HTML content
2789
+ *
2790
+ * Noise is restored from {@see simple_html_dom::$noise}
2791
+ *
2792
+ * @param string $text A subset of HTML containing noise
2793
+ * @return string The same content with noise restored
2794
+ */
2795
+ function restore_noise($text)
2796
+ {
2797
+ global $debug_object;
2798
+ if (is_object($debug_object)) {
2799
+ $debug_object->debug_log_entry(1);
2800
+ }
2801
+
2802
+ while (($pos = strpos($text, '___noise___')) !== false) {
2803
+ // Sometimes there is a broken piece of markup, and we don't GET the
2804
+ // pos+11 etc... token which indicates a problem outside of us...
2805
+
2806
+ // todo: "___noise___1000" (or any number with four or more digits)
2807
+ // in the DOM causes an infinite loop which could be utilized by
2808
+ // malicious software
2809
+ if (strlen($text) > $pos + 15) {
2810
+ $key = '___noise___'
2811
+ . $text[$pos + 11]
2812
+ . $text[$pos + 12]
2813
+ . $text[$pos + 13]
2814
+ . $text[$pos + 14]
2815
+ . $text[$pos + 15];
2816
+
2817
+ if (is_object($debug_object)) {
2818
+ $debug_object->debug_log(2, 'located key of: ' . $key);
2819
+ }
2820
+
2821
+ if (isset($this->noise[$key])) {
2822
+ $text = substr($text, 0, $pos)
2823
+ . $this->noise[$key]
2824
+ . substr($text, $pos + 16);
2825
+ } else {
2826
+ // do this to prevent an infinite loop.
2827
+ $text = substr($text, 0, $pos)
2828
+ . 'UNDEFINED NOISE FOR KEY: '
2829
+ . $key
2830
+ . substr($text, $pos + 16);
2831
+ }
2832
+ } else {
2833
+ // There is no valid key being given back to us... We must get
2834
+ // rid of the ___noise___ or we will have a problem.
2835
+ $text = substr($text, 0, $pos)
2836
+ . 'NO NUMERIC NOISE KEY'
2837
+ . substr($text, $pos + 11);
2838
+ }
2839
+ }
2840
+ return $text;
2841
+ }
2842
+
2843
+ // Sometimes we NEED one of the noise elements.
2844
+ function search_noise($text)
2845
+ {
2846
+ global $debug_object;
2847
+ if (is_object($debug_object)) {
2848
+ $debug_object->debug_log_entry(1);
2849
+ }
2850
+
2851
+ foreach ($this->noise as $noiseElement) {
2852
+ if (strpos($noiseElement, $text) !== false) {
2853
+ return $noiseElement;
2854
+ }
2855
+ }
2856
+ }
2857
+
2858
+ function __toString()
2859
+ {
2860
+ return $this->root->innertext();
2861
+ }
2862
+
2863
+ function __get($name)
2864
+ {
2865
+ switch ($name) {
2866
+ case 'outertext':
2867
+ return $this->root->innertext();
2868
+ case 'innertext':
2869
+ return $this->root->innertext();
2870
+ case 'plaintext':
2871
+ return $this->root->text();
2872
+ case 'charset':
2873
+ return $this->_charset;
2874
+ case 'target_charset':
2875
+ return $this->_target_charset;
2876
+ }
2877
+ }
2878
+
2879
+ // camel naming conventions
2880
+ function childNodes($idx = -1)
2881
+ {
2882
+ return $this->root->childNodes($idx);
2883
+ }
2884
+
2885
+ function firstChild()
2886
+ {
2887
+ return $this->root->first_child();
2888
+ }
2889
+
2890
+ function lastChild()
2891
+ {
2892
+ return $this->root->last_child();
2893
+ }
2894
+
2895
+ function createElement($name, $value = null)
2896
+ {
2897
+ return @str_get_html("<$name>$value</$name>")->first_child();
2898
+ }
2899
+
2900
+ function createTextNode($value)
2901
+ {
2902
+ return @end(str_get_html($value)->nodes);
2903
+ }
2904
+
2905
+ function getElementById($id)
2906
+ {
2907
+ return $this->find("#$id", 0);
2908
+ }
2909
+
2910
+ function getElementsById($id, $idx = null)
2911
+ {
2912
+ return $this->find("#$id", $idx);
2913
+ }
2914
+
2915
+ function getElementByTagName($name)
2916
+ {
2917
+ return $this->find($name, 0);
2918
+ }
2919
+
2920
+ function getElementsByTagName($name, $idx = -1)
2921
+ {
2922
+ return $this->find($name, $idx);
2923
+ }
2924
+
2925
+ function loadFile()
2926
+ {
2927
+ $args = func_get_args();
2928
+ $this->load_file($args);
2929
+ }
2930
+ }
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php CHANGED
@@ -1,230 +1,230 @@
1
- <?php
2
-
3
- namespace DOMUtilForWebP;
4
-
5
- //use Sunra\PhpSimple\HtmlDomParser;
6
-
7
- /**
8
- * Highly configurable class for replacing image URLs in HTML (both src and srcset syntax)
9
- *
10
- * Based on http://simplehtmldom.sourceforge.net/ - a library for easily manipulating HTML by means of a DOM.
11
- * The great thing about this library is that it supports working on invalid HTML and it only applies the changes you
12
- * make - very gently.
13
- *
14
- * TODO: Check out how ewww does it
15
- *
16
- * Behaviour can be customized by overriding the public methods (replaceUrl, $searchInTags, etc)
17
- *
18
- * Default behaviour:
19
- * - The modified URL is the same as the original, with ".webp" appended (replaceUrl)
20
- * - Limits to these tags: <img>, <source>, <input> and <iframe> ($searchInTags)
21
- * - Limits to these attributes: "src", "src-set" and any attribute starting with "data-" (attributeFilter)
22
- * - Only replaces URLs that ends with "png", "jpg" or "jpeg" (no query strings either) (replaceUrl)
23
- *
24
- *
25
- */
26
- class ImageUrlReplacer
27
- {
28
-
29
- // define tags to be searched.
30
- // The div and li are on the list because these are often used with lazy loading
31
- // should we add <meta> ?
32
- // Probably not for open graph images or twitter
33
- // so not these:
34
- // - <meta property="og:image" content="[url]">
35
- // - <meta property="og:image:secure_url" content="[url]">
36
- // - <meta name="twitter:image" content="[url]">
37
- // Meta can also be used in schema.org micro-formatting, ie:
38
- // - <meta itemprop="image" content="[url]">
39
- //
40
- // How about preloaded images? - yes, suppose we should replace those
41
- // - <link rel="prefetch" href="[url]">
42
- // - <link rel="preload" as="image" href="[url]">
43
- public static $searchInTags = ['img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section'];
44
-
45
- /**
46
- *
47
- * @return string|null webp url or, if URL should not be changed, return nothing
48
- **/
49
- public function replaceUrl($url)
50
- {
51
- if (!preg_match('#(png|jpe?g)$#', $url)) {
52
- return null;
53
- }
54
- return $url . '.webp';
55
- }
56
-
57
- public function replaceUrlOr($url, $returnValueIfDenied)
58
- {
59
- $url = $this->replaceUrl($url);
60
- return (isset($url) ? $url : $returnValueIfDenied);
61
- }
62
-
63
- /*
64
- public function isValidUrl($url)
65
- {
66
- return preg_match('#(png|jpe?g)$#', $url);
67
- }*/
68
-
69
- public function handleSrc($attrValue)
70
- {
71
- return $this->replaceUrlOr($attrValue, $attrValue);
72
- }
73
-
74
- public function handleSrcSet($attrValue)
75
- {
76
- // $attrValue is ie: <img data-x="1.jpg 1000w, 2.jpg">
77
- $srcsetArr = explode(',', $attrValue);
78
- foreach ($srcsetArr as $i => $srcSetEntry) {
79
- // $srcSetEntry is ie "image.jpg 520w", but can also lack width, ie just "image.jpg"
80
- // it can also be ie "image.jpg 2x"
81
- $srcSetEntry = trim($srcSetEntry);
82
- $entryParts = preg_split('/\s+/', $srcSetEntry, 2);
83
- if (count($entryParts) == 2) {
84
- list($src, $descriptors) = $entryParts;
85
- } else {
86
- $src = $srcSetEntry;
87
- $descriptors = null;
88
- }
89
-
90
- $webpUrl = $this->replaceUrlOr($src, false);
91
- if ($webpUrl !== false) {
92
- $srcsetArr[$i] = $webpUrl . (isset($descriptors) ? ' ' . $descriptors : '');
93
- }
94
- }
95
- return implode(', ', $srcsetArr);
96
- }
97
-
98
- /**
99
- * Test if attribute value looks like it has srcset syntax.
100
- * "image.jpg 100w" does for example. And "image.jpg 1x". Also "image1.jpg, image2.jpg 1x"
101
- * Mixing x and w is invalid (according to
102
- * https://stackoverflow.com/questions/26928828/html5-srcset-mixing-x-and-w-syntax)
103
- * But we accept it anyway
104
- * It is not the job of this function to see if the first part is an image URL
105
- * That will be done in handleSrcSet.
106
- *
107
- */
108
- public function looksLikeSrcSet($value)
109
- {
110
- if (preg_match('#\s\d*(w|x)#', $value)) {
111
- return true;
112
- }
113
- return false;
114
- }
115
-
116
- public function handleAttribute($value)
117
- {
118
- if (self::looksLikeSrcSet($value)) {
119
- return self::handleSrcSet($value);
120
- }
121
- return self::handleSrc($value);
122
- }
123
-
124
- public function attributeFilter($attrName)
125
- {
126
- $attrName = strtolower($attrName);
127
- if (($attrName == 'src') || ($attrName == 'srcset') || (strpos($attrName, 'data-') === 0)) {
128
- return true;
129
- }
130
- return false;
131
- }
132
-
133
- public function processCSSRegExCallback($matches)
134
- {
135
- list($all, $pre, $quote, $url, $post) = $matches;
136
- return $pre . $this->replaceUrlOr($url, $url) . $post;
137
- }
138
-
139
- public function processCSS($css)
140
- {
141
- $declarations = explode(';', $css);
142
- foreach ($declarations as $i => &$declaration) {
143
- if (preg_match('#(background(-image)?)\\s*:#', $declaration)) {
144
- // https://regexr.com/46qdg
145
- //$regex = '#(url\s*\(([\"\']?))([^\'\";\)]*)(\2\s*\))#';
146
- $parts = explode(',', $declaration);
147
- //print_r($parts);
148
- foreach ($parts as &$part) {
149
- //echo 'part:' . $part . "\n";
150
- $regex = '#(url\\s*\\(([\\"\\\']?))([^\\\'\\";\\)]*)(\\2\\s*\\))#';
151
- $part = preg_replace_callback($regex, 'self::processCSSRegExCallback', $part);
152
- //echo 'result:' . $part . "\n";
153
- }
154
- $declarations[$i] = implode($parts, ',');
155
- }
156
- }
157
- return implode(';', $declarations);
158
- }
159
-
160
- public function replaceHtml($html)
161
- {
162
- if ($html == '') {
163
- return '';
164
- }
165
-
166
- // https://stackoverflow.com/questions/4812691/preserve-line-breaks-simple-html-dom-parser
167
-
168
- // function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET,
169
- // $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
170
-
171
- //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
172
- $dom = str_get_html($html, false, false, 'UTF-8', false);
173
-
174
- // MAX_FILE_SIZE is defined in simple_html_dom.
175
- // For safety sake, we make sure it is defined before using
176
- defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
177
-
178
- if ($dom === false) {
179
- if (strlen($html) > MAX_FILE_SIZE) {
180
- return '<!-- Alter HTML was skipped because the HTML is too big to process! ' .
181
- '(limit is set to ' . MAX_FILE_SIZE . ' bytes) -->' . "\n" . $html;
182
- }
183
- return '<!-- Alter HTML was skipped because the helper library refused to process the html -->' .
184
- "\n" . $html;
185
- }
186
-
187
- // Replace attributes (src, srcset, data-src, etc)
188
- foreach (self::$searchInTags as $tagName) {
189
- $elems = $dom->find($tagName);
190
- foreach ($elems as $index => $elem) {
191
- $attributes = $elem->getAllAttributes();
192
- foreach ($elem->getAllAttributes() as $attrName => $attrValue) {
193
- if ($this->attributeFilter($attrName)) {
194
- $elem->setAttribute($attrName, $this->handleAttribute($attrValue));
195
- }
196
- }
197
- }
198
- }
199
-
200
- // Replace <style> elements
201
- $elems = $dom->find('style');
202
- foreach ($elems as $index => $elem) {
203
- $css = $this->processCSS($elem->innertext);
204
- if ($css != $elem->innertext) {
205
- $elem->innertext = $css;
206
- }
207
- }
208
-
209
- // Replace "style attributes
210
- $elems = $dom->find('*[style]');
211
- foreach ($elems as $index => $elem) {
212
- $css = $this->processCSS($elem->style);
213
- if ($css != $elem->style) {
214
- $elem->style = $css;
215
- }
216
- }
217
-
218
- return $dom->save();
219
- }
220
-
221
- /* Main replacer function */
222
- public static function replace($html)
223
- {
224
- if (!function_exists('str_get_html')) {
225
- require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
226
- }
227
- $iur = new static();
228
- return $iur->replaceHtml($html);
229
- }
230
- }
1
+ <?php
2
+
3
+ namespace DOMUtilForWebP;
4
+
5
+ //use Sunra\PhpSimple\HtmlDomParser;
6
+
7
+ /**
8
+ * Highly configurable class for replacing image URLs in HTML (both src and srcset syntax)
9
+ *
10
+ * Based on http://simplehtmldom.sourceforge.net/ - a library for easily manipulating HTML by means of a DOM.
11
+ * The great thing about this library is that it supports working on invalid HTML and it only applies the changes you
12
+ * make - very gently.
13
+ *
14
+ * TODO: Check out how ewww does it
15
+ *
16
+ * Behaviour can be customized by overriding the public methods (replaceUrl, $searchInTags, etc)
17
+ *
18
+ * Default behaviour:
19
+ * - The modified URL is the same as the original, with ".webp" appended (replaceUrl)
20
+ * - Limits to these tags: <img>, <source>, <input> and <iframe> ($searchInTags)
21
+ * - Limits to these attributes: "src", "src-set" and any attribute starting with "data-" (attributeFilter)
22
+ * - Only replaces URLs that ends with "png", "jpg" or "jpeg" (no query strings either) (replaceUrl)
23
+ *
24
+ *
25
+ */
26
+ class ImageUrlReplacer
27
+ {
28
+
29
+ // define tags to be searched.
30
+ // The div and li are on the list because these are often used with lazy loading
31
+ // should we add <meta> ?
32
+ // Probably not for open graph images or twitter
33
+ // so not these:
34
+ // - <meta property="og:image" content="[url]">
35
+ // - <meta property="og:image:secure_url" content="[url]">
36
+ // - <meta name="twitter:image" content="[url]">
37
+ // Meta can also be used in schema.org micro-formatting, ie:
38
+ // - <meta itemprop="image" content="[url]">
39
+ //
40
+ // How about preloaded images? - yes, suppose we should replace those
41
+ // - <link rel="prefetch" href="[url]">
42
+ // - <link rel="preload" as="image" href="[url]">
43
+ public static $searchInTags = ['img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section'];
44
+
45
+ /**
46
+ *
47
+ * @return string|null webp url or, if URL should not be changed, return nothing
48
+ **/
49
+ public function replaceUrl($url)
50
+ {
51
+ if (!preg_match('#(png|jpe?g)$#', $url)) {
52
+ return null;
53
+ }
54
+ return $url . '.webp';
55
+ }
56
+
57
+ public function replaceUrlOr($url, $returnValueIfDenied)
58
+ {
59
+ $url = $this->replaceUrl($url);
60
+ return (isset($url) ? $url : $returnValueIfDenied);
61
+ }
62
+
63
+ /*
64
+ public function isValidUrl($url)
65
+ {
66
+ return preg_match('#(png|jpe?g)$#', $url);
67
+ }*/
68
+
69
+ public function handleSrc($attrValue)
70
+ {
71
+ return $this->replaceUrlOr($attrValue, $attrValue);
72
+ }
73
+
74
+ public function handleSrcSet($attrValue)
75
+ {
76
+ // $attrValue is ie: <img data-x="1.jpg 1000w, 2.jpg">
77
+ $srcsetArr = explode(',', $attrValue);
78
+ foreach ($srcsetArr as $i => $srcSetEntry) {
79
+ // $srcSetEntry is ie "image.jpg 520w", but can also lack width, ie just "image.jpg"
80
+ // it can also be ie "image.jpg 2x"
81
+ $srcSetEntry = trim($srcSetEntry);
82
+ $entryParts = preg_split('/\s+/', $srcSetEntry, 2);
83
+ if (count($entryParts) == 2) {
84
+ list($src, $descriptors) = $entryParts;
85
+ } else {
86
+ $src = $srcSetEntry;
87
+ $descriptors = null;
88
+ }
89
+
90
+ $webpUrl = $this->replaceUrlOr($src, false);
91
+ if ($webpUrl !== false) {
92
+ $srcsetArr[$i] = $webpUrl . (isset($descriptors) ? ' ' . $descriptors : '');
93
+ }
94
+ }
95
+ return implode(', ', $srcsetArr);
96
+ }
97
+
98
+ /**
99
+ * Test if attribute value looks like it has srcset syntax.
100
+ * "image.jpg 100w" does for example. And "image.jpg 1x". Also "image1.jpg, image2.jpg 1x"
101
+ * Mixing x and w is invalid (according to
102
+ * https://stackoverflow.com/questions/26928828/html5-srcset-mixing-x-and-w-syntax)
103
+ * But we accept it anyway
104
+ * It is not the job of this function to see if the first part is an image URL
105
+ * That will be done in handleSrcSet.
106
+ *
107
+ */
108
+ public function looksLikeSrcSet($value)
109
+ {
110
+ if (preg_match('#\s\d*(w|x)#', $value)) {
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+
116
+ public function handleAttribute($value)
117
+ {
118
+ if (self::looksLikeSrcSet($value)) {
119
+ return self::handleSrcSet($value);
120
+ }
121
+ return self::handleSrc($value);
122
+ }
123
+
124
+ public function attributeFilter($attrName)
125
+ {
126
+ $attrName = strtolower($attrName);
127
+ if (($attrName == 'src') || ($attrName == 'srcset') || (strpos($attrName, 'data-') === 0)) {
128
+ return true;
129
+ }
130
+ return false;
131
+ }
132
+
133
+ public function processCSSRegExCallback($matches)
134
+ {
135
+ list($all, $pre, $quote, $url, $post) = $matches;
136
+ return $pre . $this->replaceUrlOr($url, $url) . $post;
137
+ }
138
+
139
+ public function processCSS($css)
140
+ {
141
+ $declarations = explode(';', $css);
142
+ foreach ($declarations as $i => &$declaration) {
143
+ if (preg_match('#(background(-image)?)\\s*:#', $declaration)) {
144
+ // https://regexr.com/46qdg
145
+ //$regex = '#(url\s*\(([\"\']?))([^\'\";\)]*)(\2\s*\))#';
146
+ $parts = explode(',', $declaration);
147
+ //print_r($parts);
148
+ foreach ($parts as &$part) {
149
+ //echo 'part:' . $part . "\n";
150
+ $regex = '#(url\\s*\\(([\\"\\\']?))([^\\\'\\";\\)]*)(\\2\\s*\\))#';
151
+ $part = preg_replace_callback($regex, 'self::processCSSRegExCallback', $part);
152
+ //echo 'result:' . $part . "\n";
153
+ }
154
+ $declarations[$i] = implode($parts, ',');
155
+ }
156
+ }
157
+ return implode(';', $declarations);
158
+ }
159
+
160
+ public function replaceHtml($html)
161
+ {
162
+ if ($html == '') {
163
+ return '';
164
+ }
165
+
166
+ // https://stackoverflow.com/questions/4812691/preserve-line-breaks-simple-html-dom-parser
167
+
168
+ // function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET,
169
+ // $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
170
+
171
+ //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
172
+ $dom = str_get_html($html, false, false, 'UTF-8', false);
173
+
174
+ // MAX_FILE_SIZE is defined in simple_html_dom.
175
+ // For safety sake, we make sure it is defined before using
176
+ defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
177
+
178
+ if ($dom === false) {
179
+ if (strlen($html) > MAX_FILE_SIZE) {
180
+ return '<!-- Alter HTML was skipped because the HTML is too big to process! ' .
181
+ '(limit is set to ' . MAX_FILE_SIZE . ' bytes) -->' . "\n" . $html;
182
+ }
183
+ return '<!-- Alter HTML was skipped because the helper library refused to process the html -->' .
184
+ "\n" . $html;
185
+ }
186
+
187
+ // Replace attributes (src, srcset, data-src, etc)
188
+ foreach (self::$searchInTags as $tagName) {
189
+ $elems = $dom->find($tagName);
190
+ foreach ($elems as $index => $elem) {
191
+ $attributes = $elem->getAllAttributes();
192
+ foreach ($elem->getAllAttributes() as $attrName => $attrValue) {
193
+ if ($this->attributeFilter($attrName)) {
194
+ $elem->setAttribute($attrName, $this->handleAttribute($attrValue));
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ // Replace <style> elements
201
+ $elems = $dom->find('style');
202
+ foreach ($elems as $index => $elem) {
203
+ $css = $this->processCSS($elem->innertext);
204
+ if ($css != $elem->innertext) {
205
+ $elem->innertext = $css;
206
+ }
207
+ }
208
+
209
+ // Replace "style attributes
210
+ $elems = $dom->find('*[style]');
211
+ foreach ($elems as $index => $elem) {
212
+ $css = $this->processCSS($elem->style);
213
+ if ($css != $elem->style) {
214
+ $elem->style = $css;
215
+ }
216
+ }
217
+
218
+ return $dom->save();
219
+ }
220
+
221
+ /* Main replacer function */
222
+ public static function replace($html)
223
+ {
224
+ if (!function_exists('str_get_html')) {
225
+ require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
226
+ }
227
+ $iur = new static();
228
+ return $iur->replaceHtml($html);
229
+ }
230
+ }
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php CHANGED
@@ -1,202 +1,202 @@
1
- <?php
2
-
3
- namespace DOMUtilForWebP;
4
-
5
- //use Sunra\PhpSimple\HtmlDomParser;
6
- /**
7
- * Class PictureTags - convert an <img> tag to a <picture> tag and add the webp versions of the images
8
- * Based this code on code from the ShortPixel plugin, which used code from Responsify WP plugin
9
- */
10
-
11
- use \WebPExpress\AlterHtmlHelper;
12
-
13
- class PictureTags
14
- {
15
-
16
- public function replaceUrl($url)
17
- {
18
- if (!preg_match('#(png|jpe?g)$#', $url)) {
19
- return;
20
- }
21
- return $url . '.webp';
22
- }
23
-
24
- public function replaceUrlOr($url, $returnValueIfDenied)
25
- {
26
- $url = $this->replaceUrl($url);
27
- return (isset($url) ? $url : $returnValueIfDenied);
28
- }
29
-
30
- /**
31
- * Look for attributes such as "data-lazy-src" and "data-src" and prefer them over "src"
32
- *
33
- * @param array $attributes an array of attributes for the element
34
- * @param string $attrName ie "src", "srcset" or "sizes"
35
- *
36
- * @return array an array with "value" key and "attrName" key. ("value" is the value of the attribute and
37
- * "attrName" is the name of the attribute used)
38
- *
39
- */
40
- private static function lazyGet($attributes, $attrName)
41
- {
42
- return array(
43
- 'value' =>
44
- (isset($attributes['data-lazy-' . $attrName]) && strlen($attributes['data-lazy-' . $attrName])) ?
45
- trim($attributes['data-lazy-' . $attrName])
46
- : (isset($attributes['data-' . $attrName]) && strlen($attributes['data-' . $attrName]) ?
47
- trim($attributes['data-' . $attrName])
48
- : (isset($attributes[$attrName]) && strlen($attributes[$attrName]) ?
49
- trim($attributes[$attrName]) : false)),
50
- 'attrName' =>
51
- (isset($attributes['data-lazy-' . $attrName]) && strlen($attributes['data-lazy-' . $attrName])) ?
52
- 'data-lazy-' . $attrName
53
- : (isset($attributes['data-' . $attrName]) && strlen($attributes['data-' . $attrName]) ?
54
- 'data-' . $attrName
55
- : (isset($attributes[$attrName]) && strlen($attributes[$attrName]) ? $attrName : false))
56
- );
57
- }
58
-
59
- private static function getAttributes($html)
60
- {
61
- if (function_exists("mb_convert_encoding")) {
62
- $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
63
- }
64
- if (class_exists('\\DOMDocument')) {
65
- $dom = new \DOMDocument();
66
- @$dom->loadHTML($html);
67
- $image = $dom->getElementsByTagName('img')->item(0);
68
- $attributes = [];
69
- foreach ($image->attributes as $attr) {
70
- $attributes[$attr->nodeName] = $attr->nodeValue;
71
- }
72
- return $attributes;
73
- } else {
74
- //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
75
- $dom = str_get_html($html, false, false, 'UTF-8', false);
76
- if ($dom !== false) {
77
- $elems = $dom->find('img,IMG');
78
- foreach ($elems as $index => $elem) {
79
- $attributes = [];
80
- foreach ($elem->getAllAttributes() as $attrName => $attrValue) {
81
- $attributes[strtolower($attrName)] = $attrValue;
82
- }
83
- return $attributes;
84
- }
85
- }
86
- return [];
87
- }
88
- }
89
-
90
- /**
91
- * Makes a string with all attributes.
92
- *
93
- * @param array $attribute_array
94
- * @return string
95
- */
96
- private static function createAttributes($attribute_array)
97
- {
98
- $attributes = '';
99
- foreach ($attribute_array as $attribute => $value) {
100
- $attributes .= $attribute . '="' . $value . '" ';
101
- }
102
- if ($attributes == '') {
103
- return '';
104
- }
105
- // Removes the extra space after the last attribute. Add space before
106
- return ' ' . substr($attributes, 0, -1);
107
- }
108
-
109
- /**
110
- * Replace <image> tag with <picture> tag.
111
- */
112
- private function replaceCallback($match)
113
- {
114
- $imgTag = $match[0];
115
-
116
- // Do nothing with images that have the 'webpexpress-processed' class.
117
- if (strpos($imgTag, 'webpexpress-processed')) {
118
- return $imgTag;
119
- }
120
- $imgAttributes = self::getAttributes($imgTag);
121
-
122
- $srcInfo = self::lazyGet($imgAttributes, 'src');
123
- $srcsetInfo = self::lazyGet($imgAttributes, 'srcset');
124
- $sizesInfo = self::lazyGet($imgAttributes, 'sizes');
125
-
126
- // add the exclude class so if this content is processed again in other filter,
127
- // the img is not converted again in picture
128
- $imgAttributes['class'] = (isset($imgAttributes['class']) ? $imgAttributes['class'] . " " : "") .
129
- "webpexpress-processed";
130
-
131
- $srcsetWebP = '';
132
- if ($srcsetInfo['value']) {
133
- $srcsetArr = explode(', ', $srcsetInfo["value"]);
134
- $srcsetArrWebP = [];
135
- foreach ($srcsetArr as $i => $srcSetEntry) {
136
- // $srcSetEntry is ie "http://example.com/image.jpg 520w"
137
- $result = preg_split('/\s+/', trim($srcSetEntry));
138
- $src = trim($srcSetEntry);
139
- $width = null;
140
- if ($result && count($result) >= 2) {
141
- list($src, $width) = $result;
142
- }
143
-
144
- $webpUrl = $this->replaceUrlOr($src, false);
145
- if ($webpUrl !== false) {
146
- $srcsetArrWebP[] = $webpUrl . (isset($width) ? ' ' . $width : '');
147
- }
148
- }
149
- $srcsetWebP = implode(', ', $srcsetArrWebP);
150
- if (strlen($srcsetWebP) == 0) {
151
- // We have no webps for you, so no reason to create <picture> tag
152
- return $imgTag;
153
- }
154
- $sizesAttr = ($sizesInfo['value'] ? (' ' . $sizesInfo['attrName'] . '="' . $sizesInfo['value'] . '"') : '');
155
- $sourceSrcAttrName = $srcsetInfo['attrName'];
156
- if ($sourceSrcAttrName == 'src') {
157
- // "src" isn't allowed in <source> tag with <picture> tag as parent.
158
- $sourceSrcAttrName = 'srcset';
159
- }
160
- return '<picture>'
161
- . '<source ' . $sourceSrcAttrName . '="' . $srcsetWebP . '"' . $sizesAttr . ' type="image/webp">'
162
- . '<img' . self::createAttributes($imgAttributes) . '>'
163
- . '</picture>';
164
- } else {
165
- $srcWebP = $this->replaceUrlOr($srcInfo['value'], false);
166
- if ($srcWebP === false) {
167
- // No reason to create <picture> tag
168
- return $imgTag;
169
- }
170
-
171
- $sourceSrcAttrName = $srcInfo['attrName'];
172
- if ($sourceSrcAttrName == 'src') {
173
- // "src" isn't allowed in <source> tag with <picture> tag as parent.
174
- $sourceSrcAttrName = 'srcset';
175
- }
176
-
177
- return '<picture>'
178
- . '<source ' . $sourceSrcAttrName . '="' . $srcWebP . '" type="image/webp">'
179
- . '<img' . self::createAttributes($imgAttributes) . '>'
180
- . '</picture>';
181
- }
182
- }
183
-
184
- /*
185
- *
186
- */
187
- public function replaceHtml($content)
188
- {
189
- // TODO: We should not replace <img> tags that are inside <picture> tags already, now should we?
190
- return preg_replace_callback('/<img[^>]*>/i', array($this, 'replaceCallback'), $content);
191
- }
192
-
193
- /* Main replacer function */
194
- public static function replace($html)
195
- {
196
- if (!function_exists('str_get_html')) {
197
- require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
198
- }
199
- $pt = new static();
200
- return $pt->replaceHtml($html);
201
- }
202
- }
1
+ <?php
2
+
3
+ namespace DOMUtilForWebP;
4
+
5
+ //use Sunra\PhpSimple\HtmlDomParser;
6
+ /**
7
+ * Class PictureTags - convert an <img> tag to a <picture> tag and add the webp versions of the images
8
+ * Based this code on code from the ShortPixel plugin, which used code from Responsify WP plugin
9
+ */
10
+
11
+ use \WebPExpress\AlterHtmlHelper;
12
+
13
+ class PictureTags
14
+ {
15
+
16
+ public function replaceUrl($url)
17
+ {
18
+ if (!preg_match('#(png|jpe?g)$#', $url)) {
19
+ return;
20
+ }
21
+ return $url . '.webp';
22
+ }
23
+
24
+ public function replaceUrlOr($url, $returnValueIfDenied)
25
+ {
26
+ $url = $this->replaceUrl($url);
27
+ return (isset($url) ? $url : $returnValueIfDenied);
28
+ }
29
+
30
+ /**
31
+ * Look for attributes such as "data-lazy-src" and "data-src" and prefer them over "src"
32
+ *
33
+ * @param array $attributes an array of attributes for the element
34
+ * @param string $attrName ie "src", "srcset" or "sizes"
35
+ *
36
+ * @return array an array with "value" key and "attrName" key. ("value" is the value of the attribute and
37
+ * "attrName" is the name of the attribute used)
38
+ *
39
+ */
40
+ private static function lazyGet($attributes, $attrName)
41
+ {
42
+ return array(
43
+ 'value' =>
44
+ (isset($attributes['data-lazy-' . $attrName]) && strlen($attributes['data-lazy-' . $attrName])) ?
45
+ trim($attributes['data-lazy-' . $attrName])
46
+ : (isset($attributes['data-' . $attrName]) && strlen($attributes['data-' . $attrName]) ?
47
+ trim($attributes['data-' . $attrName])
48
+ : (isset($attributes[$attrName]) && strlen($attributes[$attrName]) ?
49
+ trim($attributes[$attrName]) : false)),
50
+ 'attrName' =>
51
+ (isset($attributes['data-lazy-' . $attrName]) && strlen($attributes['data-lazy-' . $attrName])) ?
52
+ 'data-lazy-' . $attrName
53
+ : (isset($attributes['data-' . $attrName]) && strlen($attributes['data-' . $attrName]) ?
54
+ 'data-' . $attrName
55
+ : (isset($attributes[$attrName]) && strlen($attributes[$attrName]) ? $attrName : false))
56
+ );
57
+ }
58
+
59
+ private static function getAttributes($html)
60
+ {
61
+ if (function_exists("mb_convert_encoding")) {
62
+ $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
63
+ }
64
+ if (class_exists('\\DOMDocument')) {
65
+ $dom = new \DOMDocument();
66
+ @$dom->loadHTML($html);
67
+ $image = $dom->getElementsByTagName('img')->item(0);
68
+ $attributes = [];
69
+ foreach ($image->attributes as $attr) {
70
+ $attributes[$attr->nodeName] = $attr->nodeValue;
71
+ }
72
+ return $attributes;
73
+ } else {
74
+ //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
75
+ $dom = str_get_html($html, false, false, 'UTF-8', false);
76
+ if ($dom !== false) {
77
+ $elems = $dom->find('img,IMG');
78
+ foreach ($elems as $index => $elem) {
79
+ $attributes = [];
80
+ foreach ($elem->getAllAttributes() as $attrName => $attrValue) {
81
+ $attributes[strtolower($attrName)] = $attrValue;
82
+ }
83
+ return $attributes;
84
+ }
85
+ }
86
+ return [];
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Makes a string with all attributes.
92
+ *
93
+ * @param array $attribute_array
94
+ * @return string
95
+ */
96
+ private static function createAttributes($attribute_array)
97
+ {
98
+ $attributes = '';
99
+ foreach ($attribute_array as $attribute => $value) {
100
+ $attributes .= $attribute . '="' . $value . '" ';
101
+ }
102
+ if ($attributes == '') {
103
+ return '';
104
+ }
105
+ // Removes the extra space after the last attribute. Add space before
106
+ return ' ' . substr($attributes, 0, -1);
107
+ }
108
+
109
+ /**
110
+ * Replace <image> tag with <picture> tag.
111
+ */
112
+ private function replaceCallback($match)
113
+ {
114
+ $imgTag = $match[0];
115
+
116
+ // Do nothing with images that have the 'webpexpress-processed' class.
117
+ if (strpos($imgTag, 'webpexpress-processed')) {
118
+ return $imgTag;
119
+ }
120
+ $imgAttributes = self::getAttributes($imgTag);
121
+
122
+ $srcInfo = self::lazyGet($imgAttributes, 'src');
123
+ $srcsetInfo = self::lazyGet($imgAttributes, 'srcset');
124
+ $sizesInfo = self::lazyGet($imgAttributes, 'sizes');
125
+
126
+ // add the exclude class so if this content is processed again in other filter,
127
+ // the img is not converted again in picture
128
+ $imgAttributes['class'] = (isset($imgAttributes['class']) ? $imgAttributes['class'] . " " : "") .
129
+ "webpexpress-processed";
130
+
131
+ $srcsetWebP = '';
132
+ if ($srcsetInfo['value']) {
133
+ $srcsetArr = explode(', ', $srcsetInfo["value"]);
134
+ $srcsetArrWebP = [];
135
+ foreach ($srcsetArr as $i => $srcSetEntry) {
136
+ // $srcSetEntry is ie "http://example.com/image.jpg 520w"
137
+ $result = preg_split('/\s+/', trim($srcSetEntry));
138
+ $src = trim($srcSetEntry);
139
+ $width = null;
140
+ if ($result && count($result) >= 2) {
141
+ list($src, $width) = $result;
142
+ }
143
+
144
+ $webpUrl = $this->replaceUrlOr($src, false);
145
+ if ($webpUrl !== false) {
146
+ $srcsetArrWebP[] = $webpUrl . (isset($width) ? ' ' . $width : '');
147
+ }
148
+ }
149
+ $srcsetWebP = implode(', ', $srcsetArrWebP);
150
+ if (strlen($srcsetWebP) == 0) {
151
+ // We have no webps for you, so no reason to create <picture> tag
152
+ return $imgTag;
153
+ }
154
+ $sizesAttr = ($sizesInfo['value'] ? (' ' . $sizesInfo['attrName'] . '="' . $sizesInfo['value'] . '"') : '');
155
+ $sourceSrcAttrName = $srcsetInfo['attrName'];
156
+ if ($sourceSrcAttrName == 'src') {
157
+ // "src" isn't allowed in <source> tag with <picture> tag as parent.
158
+ $sourceSrcAttrName = 'srcset';
159
+ }
160
+ return '<picture>'
161
+ . '<source ' . $sourceSrcAttrName . '="' . $srcsetWebP . '"' . $sizesAttr . ' type="image/webp">'
162
+ . '<img' . self::createAttributes($imgAttributes) . '>'
163
+ . '</picture>';
164
+ } else {
165
+ $srcWebP = $this->replaceUrlOr($srcInfo['value'], false);
166
+ if ($srcWebP === false) {
167
+ // No reason to create <picture> tag
168
+ return $imgTag;
169
+ }
170
+
171
+ $sourceSrcAttrName = $srcInfo['attrName'];
172
+ if ($sourceSrcAttrName == 'src') {
173
+ // "src" isn't allowed in <source> tag with <picture> tag as parent.
174
+ $sourceSrcAttrName = 'srcset';
175
+ }
176
+
177
+ return '<picture>'
178
+ . '<source ' . $sourceSrcAttrName . '="' . $srcWebP . '" type="image/webp">'
179
+ . '<img' . self::createAttributes($imgAttributes) . '>'
180
+ . '</picture>';
181
+ }
182
+ }
183
+
184
+ /*
185
+ *
186
+ */
187
+ public function replaceHtml($content)
188
+ {
189
+ // TODO: We should not replace <img> tags that are inside <picture> tags already, now should we?
190
+ return preg_replace_callback('/<img[^>]*>/i', array($this, 'replaceCallback'), $content);
191
+ }
192
+
193
+ /* Main replacer function */
194
+ public static function replace($html)
195
+ {
196
+ if (!function_exists('str_get_html')) {
197
+ require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
198
+ }
199
+ $pt = new static();
200
+ return $pt->replaceHtml($html);
201
+ }
202
+ }
libs/addons/readme.txt CHANGED
@@ -1,10 +1,9 @@
1
  === Webcraftic Plugin name ===
2
  Tags: clearfy, boilerplate, component
3
  Contributors: webcraftic
4
- Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VDX7JNTQPNPFW
5
  Requires at least: 4.2
6
- Tested up to: 4.9
7
- Requires PHP: 5.2
8
  Stable tag: trunk
9
  License: GPLv2
10
 
1
  === Webcraftic Plugin name ===
2
  Tags: clearfy, boilerplate, component
3
  Contributors: webcraftic
 
4
  Requires at least: 4.2
5
+ Tested up to: 5.5
6
+ Requires PHP: 5.6
7
  Stable tag: trunk
8
  License: GPLv2
9
 
libs/addons/robin-image-optimizer-premium.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin URI: https://robin-image-optimizer.webcraftic.com
5
  * Description: This is an extension for the plugin Robin image optimizer. Adds additional functions: Converting images to Webp, optimization of arbitrary directories, optimization of the Nextgen gallery.
6
  * Author: Webcraftic <wordpress.webraftic@gmail.com>
7
- * Version: 1.0.4
8
  * Text Domain: robin-image-optimizer
9
  * Domain Path: /languages/ Author
10
  * URI: https://robin-image-optimizer.webcraftic.com
4
  * Plugin URI: https://robin-image-optimizer.webcraftic.com
5
  * Description: This is an extension for the plugin Robin image optimizer. Adds additional functions: Converting images to Webp, optimization of arbitrary directories, optimization of the Nextgen gallery.
6
  * Author: Webcraftic <wordpress.webraftic@gmail.com>
7
+ * Version: 1.0.5
8
  * Text Domain: robin-image-optimizer
9
  * Domain Path: /languages/ Author
10
  * URI: https://robin-image-optimizer.webcraftic.com
libs/addons/views/modal-select-custom-folders.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
4
 
5
  /**
6
  * @var array $data
7
- * @var Wbcr_FactoryClearfy217_PageBase $page
8
  */
9
  ?>
10
  <p><?php _e( 'Select a directory for optimization. All nested images and folders will be optimized recursively.', 'robin-image-optimizer' ) ?></p>
4
 
5
  /**
6
  * @var array $data
7
+ * @var Wbcr_FactoryClearfy227_PageBase $page
8
  */
9
  ?>
10
  <p><?php _e( 'Select a directory for optimization. All nested images and folders will be optimized recursively.', 'robin-image-optimizer' ) ?></p>
libs/addons/views/part-bulk-optimization-table-folders.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
4
 
5
  /**
6
  * @var array $data
7
- * @var Wbcr_FactoryClearfy217_PageBase $page
8
  */
9
 
10
  $cf = WRIO_Custom_Folders::get_instance();
4
 
5
  /**
6
  * @var array $data
7
+ * @var Wbcr_FactoryClearfy227_PageBase $page
8
  */
9
 
10
  $cf = WRIO_Custom_Folders::get_instance();
libs/addons/views/part-settings-page-webp-options.php CHANGED
@@ -7,6 +7,20 @@ use WRIO\WEBP\HTML\Delivery as WEBP_Delivery;
7
  * @var array $data
8
  */
9
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  <div class="form-group">
11
  <label class="col-sm-4 control-label"></label>
12
  <div class="control-group col-sm-8">
@@ -45,7 +59,7 @@ use WRIO\WEBP\HTML\Delivery as WEBP_Delivery;
45
  <?php _e( 'Replace image URLs', 'robin-image-optimizer' ) ?>
46
  </label>
47
  <p class="wrio-webp-options-info">
48
- <?php _e( '"Image URLs" replaces the image URLs to point to the webp <i>rather than</i> the original. Handles src, srcset, common lazy-load attributes and even inline styles. Note that you will have to do something for the browsers that does not support webp. And that something is in most cases to enable the <i>Only do the replacements in webp enabled browsers</i> option, which will show up when you enable this option.', 'robin-image-optimizer' ) ?>
49
  </p>
50
  </li>
51
  <li>
7
  * @var array $data
8
  */
9
  ?>
10
+
11
+ <?php if($data['optimization_server'] !== 'server_5'): ?>
12
+ <div class="form-group">
13
+ <label class="col-sm-4 control-label"></label>
14
+ <div class="control-group col-sm-8">
15
+ <div class="factory-hints">
16
+ <div class="factory-hint factory-hint-normal" style="background-color: #fdd">
17
+ <?php _e( 'You can only use WebP conversion when using a premium server', 'robin-image-optimizer' ) ?>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <?php endif ?>
23
+
24
  <div class="form-group">
25
  <label class="col-sm-4 control-label"></label>
26
  <div class="control-group col-sm-8">
59
  <?php _e( 'Replace image URLs', 'robin-image-optimizer' ) ?>
60
  </label>
61
  <p class="wrio-webp-options-info">
62
+ <?php _e( '"Image URLs" replaces the image URLs to point to the webp <i>rather than</i> the original. Handles src, srcset, common lazy-load attributes and even inline styles.', 'robin-image-optimizer' ) ?>
63
  </p>
64
  </li>
65
  <li>
libs/factory/adverts/boot.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- use WBCR\Factory_Adverts_106\Base;
4
 
5
  /**
6
  * Factory Adverts
@@ -16,35 +16,35 @@ use WBCR\Factory_Adverts_106\Base;
16
  */
17
 
18
  // Exit if accessed directly
19
- if ( ! defined( 'ABSPATH' ) ) {
20
  exit;
21
  }
22
 
23
- if ( defined( 'FACTORY_ADVERTS_106_LOADED' ) || ( defined( 'FACTORY_ADVERTS_BLOCK' ) && FACTORY_ADVERTS_BLOCK ) ) {
24
  return;
25
  }
26
 
27
  # Устанавливаем константу, что модуль уже загружен
28
- define( 'FACTORY_ADVERTS_106_LOADED', true );
29
 
30
  # Устанавливаем версию модуля
31
- define( 'FACTORY_ADVERTS_106_VERSION', '1.0.6' );
32
 
33
  # Регистрируем тектовый домен, для интернализации интерфейса модуля
34
- load_plugin_textdomain( 'wbcr_factory_adverts_106', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
35
 
36
  # Устанавливаем директорию модуля
37
- define( 'FACTORY_ADVERTS_106_DIR', dirname( __FILE__ ) );
38
 
39
  # Устанавливаем url модуля
40
- define( 'FACTORY_ADVERTS_106_URL', plugins_url( null, __FILE__ ) );
41
 
42
- require_once( FACTORY_ADVERTS_106_DIR . '/includes/class-rest-request.php' );
43
- require_once( FACTORY_ADVERTS_106_DIR . '/includes/class-base.php' );
44
 
45
  /**
46
- * @param Wbcr_Factory425_Plugin $plugin
47
  */
48
- add_action( 'wbcr_factory_adverts_106_plugin_created', function ( $plugin ) {
49
- $plugin->set_adverts_manager( "WBCR\Factory_Adverts_106\Base" );
50
- } );
1
  <?php
2
 
3
+ use WBCR\Factory_Adverts_114\Base;
4
 
5
  /**
6
  * Factory Adverts
16
  */
17
 
18
  // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
  exit;
21
  }
22
 
23
+ if( defined('FACTORY_ADVERTS_114_LOADED') || (defined('FACTORY_ADVERTS_BLOCK') && FACTORY_ADVERTS_BLOCK) ) {
24
  return;
25
  }
26
 
27
  # Устанавливаем константу, что модуль уже загружен
28
+ define('FACTORY_ADVERTS_114_LOADED', true);
29
 
30
  # Устанавливаем версию модуля
31
+ define('FACTORY_ADVERTS_114_VERSION', '1.1.4');
32
 
33
  # Регистрируем тектовый домен, для интернализации интерфейса модуля
34
+ load_plugin_textdomain('wbcr_factory_adverts_114', false, dirname(plugin_basename(__FILE__)) . '/langs');
35
 
36
  # Устанавливаем директорию модуля
37
+ define('FACTORY_ADVERTS_114_DIR', dirname(__FILE__));
38
 
39
  # Устанавливаем url модуля
40
+ define('FACTORY_ADVERTS_114_URL', plugins_url(null, __FILE__));
41
 
42
+ require_once(FACTORY_ADVERTS_114_DIR . '/includes/class-rest-request.php');
43
+ require_once(FACTORY_ADVERTS_114_DIR . '/includes/class-base.php');
44
 
45
  /**
46
+ * @param Wbcr_Factory436_Plugin $plugin
47
  */
48
+ add_action('wbcr_factory_adverts_114_plugin_created', function ($plugin) {
49
+ $plugin->set_adverts_manager("WBCR\Factory_Adverts_114\Base");
50
+ });
libs/factory/adverts/includes/class-base.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Adverts_106;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
@@ -28,7 +28,7 @@ class Base {
28
  *
29
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
30
  * @since 1.0.1
31
- * @var \Wbcr_Factory425_Plugin
32
  */
33
  private $plugin;
34
 
@@ -53,7 +53,7 @@ class Base {
53
  *
54
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
55
  * @since 1.0.1
56
- * @var \WBCR\Factory_Adverts_106\Creative_Motion_API
57
  */
58
  private $api;
59
 
@@ -82,9 +82,9 @@ class Base {
82
  *
83
  * @since 1.0.0 Added
84
  *
85
- * @param \Wbcr_Factory425_Plugin $plugin
86
  */
87
- public function __construct( \Wbcr_Factory425_Plugin $plugin, $settings ) {
88
  $this->plugin = $plugin;
89
 
90
  $this->settings = wp_parse_args( $settings, [
@@ -257,7 +257,7 @@ class Base {
257
  $content = $this->get_debug_message( 'dashboard_widget' );
258
  }
259
 
260
- require_once FACTORY_ADVERTS_106_DIR . '/includes/class-dashboard-widget.php';
261
  new Dashboard_Widget( $this->plugin, $content );
262
  }
263
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_Adverts_114;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
28
  *
29
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
30
  * @since 1.0.1
31
+ * @var \Wbcr_Factory436_Plugin
32
  */
33
  private $plugin;
34
 
53
  *
54
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
55
  * @since 1.0.1
56
+ * @var \WBCR\Factory_Adverts_114\Creative_Motion_API
57
  */
58
  private $api;
59
 
82
  *
83
  * @since 1.0.0 Added
84
  *
85
+ * @param \Wbcr_Factory436_Plugin $plugin
86
  */
87
+ public function __construct( \Wbcr_Factory436_Plugin $plugin, $settings ) {
88
  $this->plugin = $plugin;
89
 
90
  $this->settings = wp_parse_args( $settings, [
257
  $content = $this->get_debug_message( 'dashboard_widget' );
258
  }
259
 
260
+ require_once FACTORY_ADVERTS_114_DIR . '/includes/class-dashboard-widget.php';
261
  new Dashboard_Widget( $this->plugin, $content );
262
  }
263
  }
libs/factory/adverts/includes/class-dashboard-widget.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Adverts_106;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
@@ -35,7 +35,7 @@ class Dashboard_Widget {
35
  *
36
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
37
  * @since 1.0.1
38
- * @var \Wbcr_Factory425_Plugin
39
  */
40
  private $plugin;
41
 
@@ -46,10 +46,10 @@ class Dashboard_Widget {
46
  *
47
  * @since 1.0.0 Added
48
  *
49
- * @param \Wbcr_Factory425_Plugin $plugin
50
  * @param string $content
51
  */
52
- public function __construct( \Wbcr_Factory425_Plugin $plugin, $content ) {
53
 
54
  $this->plugin = $plugin;
55
  $this->content = $content;
1
  <?php
2
 
3
+ namespace WBCR\Factory_Adverts_114;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
35
  *
36
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
37
  * @since 1.0.1
38
+ * @var \Wbcr_Factory436_Plugin
39
  */
40
  private $plugin;
41
 
46
  *
47
  * @since 1.0.0 Added
48
  *
49
+ * @param \Wbcr_Factory436_Plugin $plugin
50
  * @param string $content
51
  */
52
+ public function __construct( \Wbcr_Factory436_Plugin $plugin, $content ) {
53
 
54
  $this->plugin = $plugin;
55
  $this->content = $content;
libs/factory/adverts/includes/class-rest-request.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Adverts_106;
4
 
5
  // Exit if accessed directly
6
- if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
9
 
@@ -65,7 +65,7 @@ class Creative_Motion_API {
65
  *
66
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
67
  * @since 1.0.1
68
- * @var \Wbcr_Factory425_Plugin
69
  */
70
  private $plugin;
71
 
@@ -75,32 +75,34 @@ class Creative_Motion_API {
75
  *
76
  * Variable initialization.
77
  *
 
78
  * @since 1.0.0 Added
79
  *
80
- * @param \Wbcr_Factory425_Plugin $plugin_name
81
  */
82
- public function __construct( \Wbcr_Factory425_Plugin $plugin ) {
 
83
  $this->plugin = $plugin;
84
  }
85
 
86
  /**
87
  * Get adverts content.
88
  *
89
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
90
- * @since 1.0.1
91
- *
92
  * @param $position
93
  *
94
  * @return string|\WP_Error
 
 
 
95
  */
96
- public function get_content( $position ) {
97
- $data = $this->get_cache( $position );
 
98
 
99
- if ( is_wp_error( $data ) ) {
100
  return $data;
101
  }
102
 
103
- return strip_tags( $data['content'], '<b>,<a>,<i>,<strong>,<img>,<ul>,<ol>,<li>' );
104
  }
105
 
106
  /**
@@ -108,47 +110,52 @@ class Creative_Motion_API {
108
  *
109
  * If data in the cache, not empty and not expired, then get data from cache. Or get data from server.
110
  *
111
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
112
- *
113
- * @since 1.0.1 Полностью переписан, с перехватом api ошибок
114
- * @since 1.0.0 Added
115
- *
116
  * @return mixed array(
117
  * 'plugin' => 'wbcr_insert_php',
118
  * 'content' => '<p></p>',
119
  * 'expires' => 1563542199,
120
  * );
 
 
 
 
 
121
  */
122
- private function get_cache( $position ) {
 
123
 
124
- if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
125
- return $this->do_api_request( $position );
126
  }
127
 
128
- $key = $this->plugin->getPrefix() . md5( $position . 'adverts_transient_' );
 
 
 
 
129
 
130
- $cached = get_transient( $key );
131
 
132
- if ( $cached !== false ) {
133
- if ( isset( $cached['error_code'] ) && isset( $cached['error'] ) ) {
134
- return new \WP_Error( $cached['error_code'], $cached['error'] );
135
  }
136
-
137
  return $cached;
138
  }
139
 
140
- $data = $this->do_api_request( $position );
141
 
142
- if ( is_wp_error( $data ) ) {
143
- set_transient( $key, [
144
- 'error' => $data->get_error_message(),
145
  'error_code' => $data->get_error_code()
146
- ], self::SERVER_UNAVAILABLE_INTERVAL * HOUR_IN_SECONDS );
147
 
148
  return $data;
149
  }
150
-
151
- set_transient( $key, $data, self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS );
152
 
153
  return $data;
154
  }
@@ -159,39 +166,52 @@ class Creative_Motion_API {
159
  * In some case on the server (Apache) in the .htaccess must be set
160
  * RewriteRule ^wp-json/(.*)[?](.*) /?rest_route=/$1&$2 [L]
161
  *
162
- * @since 1.0.1 Добавлен перехват ошибок, рефакторинг кода.
163
- * @since 1.0.0 Added
164
- *
165
  * @return mixed array(
166
  * 'plugin' => 'wbcr_insert_php',
167
  * 'content' => '<p></p>',
168
  * 'expires' => 1563542199,
169
  * );
 
 
 
170
  */
171
- private function do_api_request( $position ) {
 
172
  $default_result = [
173
  'content' => '',
174
  'expires' => self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS,
175
  ];
176
 
177
- $url = untrailingslashit( self::SERVER_URL ) . '/wp-json' . self::REST_ROUTE;
178
- $url = add_query_arg( [ 'plugin' => $this->plugin->getPluginName(), 'position' => $position ], $url );
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
- $response = wp_remote_get( $url );
181
 
182
- $code = wp_remote_retrieve_response_code( $response );
183
- $body = wp_remote_retrieve_body( $response );
184
 
185
- $data = @json_decode( $body, true );
186
 
187
- if ( is_wp_error( $response ) ) {
188
  return $response;
189
  }
190
 
191
- if ( 200 !== $code ) {
192
- return new \WP_Error( 'http_request_error', 'Failed request to the remote server. Code: ' . $code );
193
  }
194
 
195
- return wp_parse_args( $data, $default_result );
196
  }
197
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_Adverts_114;
4
 
5
  // Exit if accessed directly
6
+ if( !defined('ABSPATH') ) {
7
  exit;
8
  }
9
 
65
  *
66
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
67
  * @since 1.0.1
68
+ * @var \Wbcr_Factory436_Plugin
69
  */
70
  private $plugin;
71
 
75
  *
76
  * Variable initialization.
77
  *
78
+ * @param \Wbcr_Factory436_Plugin $plugin_name
79
  * @since 1.0.0 Added
80
  *
 
81
  */
82
+ public function __construct(\Wbcr_Factory436_Plugin $plugin)
83
+ {
84
  $this->plugin = $plugin;
85
  }
86
 
87
  /**
88
  * Get adverts content.
89
  *
 
 
 
90
  * @param $position
91
  *
92
  * @return string|\WP_Error
93
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
94
+ * @since 1.0.1
95
+ *
96
  */
97
+ public function get_content($position)
98
+ {
99
+ $data = $this->get_cache($position);
100
 
101
+ if( is_wp_error($data) ) {
102
  return $data;
103
  }
104
 
105
+ return strip_tags($data['content'], '<b>,<a>,<i>,<strong>,<img>,<ul>,<ol>,<li>');
106
  }
107
 
108
  /**
110
  *
111
  * If data in the cache, not empty and not expired, then get data from cache. Or get data from server.
112
  *
 
 
 
 
 
113
  * @return mixed array(
114
  * 'plugin' => 'wbcr_insert_php',
115
  * 'content' => '<p></p>',
116
  * 'expires' => 1563542199,
117
  * );
118
+ * @since 1.0.1 Полностью переписан, с перехватом api ошибок
119
+ * @since 1.0.0 Added
120
+ *
121
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
122
+ *
123
  */
124
+ private function get_cache($position)
125
+ {
126
 
127
+ if( defined('FACTORY_ADVERTS_DEBUG') && FACTORY_ADVERTS_DEBUG ) {
128
+ return $this->do_api_request($position);
129
  }
130
 
131
+ $key = $this->plugin->getPrefix() . md5($position . 'adverts_transient_');
132
+
133
+ if( 'ru_RU' === get_locale() ) {
134
+ $key .= 'ru_';
135
+ }
136
 
137
+ $cached = get_transient($key);
138
 
139
+ if( $cached !== false ) {
140
+ if( isset($cached['error_code']) && isset($cached['error']) ) {
141
+ return new \WP_Error($cached['error_code'], $cached['error']);
142
  }
143
+
144
  return $cached;
145
  }
146
 
147
+ $data = $this->do_api_request($position);
148
 
149
+ if( is_wp_error($data) ) {
150
+ set_transient($key, [
151
+ 'error' => $data->get_error_message(),
152
  'error_code' => $data->get_error_code()
153
+ ], self::SERVER_UNAVAILABLE_INTERVAL * HOUR_IN_SECONDS);
154
 
155
  return $data;
156
  }
157
+
158
+ set_transient($key, $data, self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS);
159
 
160
  return $data;
161
  }
166
  * In some case on the server (Apache) in the .htaccess must be set
167
  * RewriteRule ^wp-json/(.*)[?](.*) /?rest_route=/$1&$2 [L]
168
  *
 
 
 
169
  * @return mixed array(
170
  * 'plugin' => 'wbcr_insert_php',
171
  * 'content' => '<p></p>',
172
  * 'expires' => 1563542199,
173
  * );
174
+ * @since 1.0.0 Added
175
+ *
176
+ * @since 1.0.1 Добавлен перехват ошибок, рефакторинг кода.
177
  */
178
+ private function do_api_request($position)
179
+ {
180
  $default_result = [
181
  'content' => '',
182
  'expires' => self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS,
183
  ];
184
 
185
+ $url = untrailingslashit(self::SERVER_URL) . '/wp-json' . self::REST_ROUTE;
186
+
187
+ $ads_ID = $this->plugin->getPluginName();
188
+
189
+ if( 'ru_RU' === get_locale() ) {
190
+ $ads_ID .= '-ru';
191
+ }
192
+
193
+ $url = add_query_arg([
194
+ 'plugin' => $ads_ID,
195
+ 'position' => $position,
196
+ 'plugin_title' => $this->plugin->getPluginTitle(),
197
+ 'lang' => get_locale()
198
+ ], $url);
199
 
200
+ $response = wp_remote_get($url);
201
 
202
+ $code = wp_remote_retrieve_response_code($response);
203
+ $body = wp_remote_retrieve_body($response);
204
 
205
+ $data = @json_decode($body, true);
206
 
207
+ if( is_wp_error($response) ) {
208
  return $response;
209
  }
210
 
211
+ if( 200 !== $code ) {
212
+ return new \WP_Error('http_request_error', 'Failed request to the remote server. Code: ' . $code);
213
  }
214
 
215
+ return wp_parse_args($data, $default_result);
216
  }
217
  }
libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.mo ADDED
Binary file
libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.po ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2018-10-16 22:44+0300\n"
5
+ "PO-Revision-Date: 2018-10-16 22:45+0300\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.1.1\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: includes/check-compatibility.php:80
21
+ msgid "warning"
22
+ msgstr "предупреждение"
23
+
24
+ #: includes/check-compatibility.php:82
25
+ #, php-format
26
+ msgid "The %s plugin has stopped."
27
+ msgstr "Работа плагина %s была остановлена."
28
+
29
+ #: includes/check-compatibility.php:83
30
+ msgid "Possible reasons:"
31
+ msgstr "Возможные причины:"
32
+
33
+ #: includes/check-compatibility.php:89
34
+ #, php-format
35
+ msgid "You need to update the PHP version to %s or higher!"
36
+ msgstr "Вам нужно обновить версию PHP до %s или выше!"
37
+
38
+ #: includes/check-compatibility.php:94
39
+ #, php-format
40
+ msgid "You need to update WordPress to %s or higher!"
41
+ msgstr "Вам нужно обновить WordPress до %s или выше!"
42
+
43
+ #: includes/functions.php:132
44
+ #, php-format
45
+ msgid ""
46
+ "%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead."
47
+ msgstr ""
48
+ "%1$s является <strong>устаревшим,</strong> начиная с версии %2$s в "
49
+ "Wordpress! Используйте %3$s."
50
+
51
+ #: includes/functions.php:134
52
+ #, php-format
53
+ msgid ""
54
+ "%1$s is <strong>deprecated</strong> since version %2$s with no alternative "
55
+ "available."
56
+ msgstr ""
57
+ "%1$s был вызван с параметром, который является <strong>устаревшими</strong> "
58
+ "начиная с версии %2$s , в настоящее время доступных альтернатив нет."
59
+
60
+ #: includes/plugin.class.php:202 includes/plugin.class.php:237
61
+ msgid ""
62
+ "You are trying to call this earlier than the plugin menu will be registered."
63
+ msgstr ""
64
+ "Вы пытаетесь вызвать это раньше, чем будет зарегистрировано меню плагина."
65
+
66
+ #: includes/plugin.class.php:220
67
+ msgid ""
68
+ "You are trying to get a link to a page that does not have multisite mode. "
69
+ "Clicking this link will lead the user to a non-existent page."
70
+ msgstr ""
71
+ "Вы пытаетесь получить ссылку на страницу, которая не имеет "
72
+ "многопользовательского режима. Щелчок по этой ссылке приведет пользователя "
73
+ "к несуществующей странице."
74
+
75
+ #: includes/plugin.class.php:222
76
+ msgid ""
77
+ "Trying to get a link to an unregistered page. You are trying to call this "
78
+ "earlier than the plugin menu will be registered."
79
+ msgstr ""
80
+ "Попытка получить ссылку на незарегистрированную страницу. Вы пытаетесь "
81
+ "вызвать это раньше, чем будет зарегистрировано меню плагина."
82
+
83
+
libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.mo ADDED
Binary file
libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.po ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2018-10-16 22:44+0300\n"
5
+ "PO-Revision-Date: 2018-10-16 22:45+0300\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.1.1\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: includes/check-compatibility.php:80
21
+ msgid "warning"
22
+ msgstr "предупреждение"
23
+
24
+ #: includes/check-compatibility.php:82
25
+ #, php-format
26
+ msgid "The %s plugin has stopped."
27
+ msgstr "Работа плагина %s была остановлена."
28
+
29
+ #: includes/check-compatibility.php:83
30
+ msgid "Possible reasons:"
31
+ msgstr "Возможные причины:"
32
+
33
+ #: includes/check-compatibility.php:89
34
+ #, php-format
35
+ msgid "You need to update the PHP version to %s or higher!"
36
+ msgstr "Вам нужно обновить версию PHP до %s или выше!"
37
+
38
+ #: includes/check-compatibility.php:94
39
+ #, php-format
40
+ msgid "You need to update WordPress to %s or higher!"
41
+ msgstr "Вам нужно обновить WordPress до %s или выше!"
42
+
43
+ #: includes/functions.php:132
44
+ #, php-format
45
+ msgid ""
46
+ "%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead."
47
+ msgstr ""
48
+ "%1$s является <strong>устаревшим,</strong> начиная с версии %2$s в "
49
+ "Wordpress! Используйте %3$s."
50
+
51
+ #: includes/functions.php:134
52
+ #, php-format
53
+ msgid ""
54
+ "%1$s is <strong>deprecated</strong> since version %2$s with no alternative "
55
+ "available."
56
+ msgstr ""
57
+ "%1$s был вызван с параметром, который является <strong>устаревшими</strong> "
58
+ "начиная с версии %2$s , в настоящее время доступных альтернатив нет."
59
+
60
+ #: includes/plugin.class.php:202 includes/plugin.class.php:237
61
+ msgid ""
62
+ "You are trying to call this earlier than the plugin menu will be registered."
63
+ msgstr ""
64
+ "Вы пытаетесь вызвать это раньше, чем будет зарегистрировано меню плагина."
65
+
66
+ #: includes/plugin.class.php:220
67
+ msgid ""
68
+ "You are trying to get a link to a page that does not have multisite mode. "
69
+ "Clicking this link will lead the user to a non-existent page."
70
+ msgstr ""
71
+ "Вы пытаетесь получить ссылку на страницу, которая не имеет "
72
+ "многопользовательского режима. Щелчок по этой ссылке приведет пользователя "
73
+ "к несуществующей странице."
74
+
75
+ #: includes/plugin.class.php:222
76
+ msgid ""
77
+ "Trying to get a link to an unregistered page. You are trying to call this "
78
+ "earlier than the plugin menu will be registered."
79
+ msgstr ""
80
+ "Попытка получить ссылку на незарегистрированную страницу. Вы пытаетесь "
81
+ "вызвать это раньше, чем будет зарегистрировано меню плагина."
82
+
83
+
libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.mo ADDED
Binary file
libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.po ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2018-10-16 22:44+0300\n"
5
+ "PO-Revision-Date: 2018-10-16 22:45+0300\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.1.1\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: includes/check-compatibility.php:80
21
+ msgid "warning"
22
+ msgstr "предупреждение"
23
+
24
+ #: includes/check-compatibility.php:82
25
+ #, php-format
26
+ msgid "The %s plugin has stopped."
27
+ msgstr "Работа плагина %s была остановлена."
28
+
29
+ #: includes/check-compatibility.php:83
30
+ msgid "Possible reasons:"
31
+ msgstr "Возможные причины:"
32
+
33
+ #: includes/check-compatibility.php:89
34
+ #, php-format
35
+ msgid "You need to update the PHP version to %s or higher!"
36
+ msgstr "Вам нужно обновить версию PHP до %s или выше!"
37
+
38
+ #: includes/check-compatibility.php:94
39
+ #, php-format
40
+ msgid "You need to update WordPress to %s or higher!"
41
+ msgstr "Вам нужно обновить WordPress до %s или выше!"
42
+
43
+ #: includes/functions.php:132
44
+ #, php-format
45
+ msgid ""
46
+ "%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead."
47
+ msgstr ""
48
+ "%1$s является <strong>устаревшим,</strong> начиная с версии %2$s в "
49
+ "Wordpress! Используйте %3$s."
50
+
51
+ #: includes/functions.php:134
52
+ #, php-format
53
+ msgid ""
54
+ "%1$s is <strong>deprecated</strong> since version %2$s with no alternative "
55
+ "available."
56
+ msgstr ""
57
+ "%1$s был вызван с параметром, который является <strong>устаревшими</strong> "
58
+ "начиная с версии %2$s , в настоящее время доступных альтернатив нет."
59
+
60
+ #: includes/plugin.class.php:202 includes/plugin.class.php:237
61
+ msgid ""
62
+ "You are trying to call this earlier than the plugin menu will be registered."
63
+ msgstr ""
64
+ "Вы пытаетесь вызвать это раньше, чем будет зарегистрировано меню плагина."
65
+
66
+ #: includes/plugin.class.php:220
67
+ msgid ""
68
+ "You are trying to get a link to a page that does not have multisite mode. "
69
+ "Clicking this link will lead the user to a non-existent page."
70
+ msgstr ""
71
+ "Вы пытаетесь получить ссылку на страницу, которая не имеет "
72
+ "многопользовательского режима. Щелчок по этой ссылке приведет пользователя "
73
+ "к несуществующей странице."
74
+
75
+ #: includes/plugin.class.php:222
76
+ msgid ""
77
+ "Trying to get a link to an unregistered page. You are trying to call this "
78
+ "earlier than the plugin menu will be registered."
79
+ msgstr ""
80
+ "Попытка получить ссылку на незарегистрированную страницу. Вы пытаетесь "
81
+ "вызвать это раньше, чем будет зарегистрировано меню плагина."
82
+
83
+
libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-426 .factory-accordion{margin:0 0 30px;border-top:1px solid #DDD;border-right:1px solid #DDD;border-left:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.factory-bootstrap-426 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-426 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-426 .factory-accordion-item{display:none}.factory-bootstrap-426 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-426 .factory-accordion>h3.active:hover{cursor:default}
8
  */
9
 
10
 
11
+ .factory-bootstrap-436 .factory-accordion{margin:0 0 30px;border-top:1px solid #DDD;border-right:1px solid #DDD;border-left:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.factory-bootstrap-436 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-436 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-436 .factory-accordion-item{display:none}.factory-bootstrap-436 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-436 .factory-accordion>h3.active:hover{cursor:default}
libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-426 .btn-primary{background:#e1a948;border-color:#d39323;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-426 .btn-primary:focus,.factory-bootstrap-426 .btn-primary:hover{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-426 .btn-primary:active{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-426 .btn-primary:disabled,.factory-bootstrap-426 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-426 .btn-group .btn.active.value{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.factory-bootstrap-426 .pagination>.active>a,.factory-bootstrap-426 .pagination>.active>a:focus,.factory-bootstrap-426 .pagination>.active>a:hover,.factory-bootstrap-426 .pagination>.active>span,.factory-bootstrap-426 .pagination>.active>span:focus,.factory-bootstrap-426 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
8
  */
9
 
10
 
11
+ .factory-bootstrap-436 .btn-primary{background:#e1a948;border-color:#d39323;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-436 .btn-primary:focus,.factory-bootstrap-436 .btn-primary:hover{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-436 .btn-primary:active{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-436 .btn-primary:disabled,.factory-bootstrap-436 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-436 .btn-group .btn.active.value{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.factory-bootstrap-436 .pagination>.active>a,.factory-bootstrap-436 .pagination>.active>a:focus,.factory-bootstrap-436 .pagination>.active>a:hover,.factory-bootstrap-436 .pagination>.active>span,.factory-bootstrap-436 .pagination>.active>span:focus,.factory-bootstrap-436 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-426 .btn-primary{background:#c7a589;border-color:#b78a66;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-426 .btn-primary:focus,.factory-bootstrap-426 .btn-primary:hover{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-426 .btn-primary:active{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-426 .btn-primary:disabled,.factory-bootstrap-426 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-426 .btn-group .btn.active.value{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.factory-bootstrap-426 .pagination>.active>a,.factory-bootstrap-426 .pagination>.active>a:focus,.factory-bootstrap-426 .pagination>.active>a:hover,.factory-bootstrap-426 .pagination>.active>span,.factory-bootstrap-426 .pagination>.active>span:focus,.factory-bootstrap-426 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
8
  */
9
 
10
 
11
+ .factory-bootstrap-436 .btn-primary{background:#c7a589;border-color:#b78a66;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-436 .btn-primary:focus,.factory-bootstrap-436 .btn-primary:hover{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-436 .btn-primary:active{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-436 .btn-primary:disabled,.factory-bootstrap-436 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-436 .btn-group .btn.active.value{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.factory-bootstrap-436 .pagination>.active>a,.factory-bootstrap-436 .pagination>.active>a:focus,.factory-bootstrap-436 .pagination>.active>a:hover,.factory-bootstrap-436 .pagination>.active>span,.factory-bootstrap-436 .pagination>.active>span:focus,.factory-bootstrap-436 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css CHANGED
@@ -8,7 +8,7 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-426 article,.factory-bootstrap-426 aside,.factory-bootstrap-426 details,.factory-bootstrap-426 figcaption,.factory-bootstrap-426 figure,.factory-bootstrap-426 footer,.factory-bootstrap-426 header,.factory-bootstrap-426 hgroup,.factory-bootstrap-426 main,.factory-bootstrap-426 nav,.factory-bootstrap-426 section,.factory-bootstrap-426 summary{display:block}.factory-bootstrap-426 audio,.factory-bootstrap-426 canvas,.factory-bootstrap-426 video{display:inline-block}.factory-bootstrap-426 audio:not([controls]){display:none;height:0}.factory-bootstrap-426 [hidden],.factory-bootstrap-426 template{display:none}.factory-bootstrap-426 body{margin:0}.factory-bootstrap-426 a{background:0 0}.factory-bootstrap-426 a:focus{outline:thin dotted}.factory-bootstrap-426 a:active,.factory-bootstrap-426 a:hover{outline:0}.factory-bootstrap-426 h1{margin:.67em 0}.factory-bootstrap-426 b,.factory-bootstrap-426 strong{font-weight:700}.factory-bootstrap-426 dfn{font-style:italic}.factory-bootstrap-426 hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-426 mark{color:#000;background:#ff0}.factory-bootstrap-426 code,.factory-bootstrap-426 kbd,.factory-bootstrap-426 pre,.factory-bootstrap-426 samp{font-size:1em}.factory-bootstrap-426 pre{white-space:pre-wrap}.factory-bootstrap-426 q{quotes:"\201C" "\201D" "\2018" "\2019"}.factory-bootstrap-426 sub,.factory-bootstrap-426 sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.factory-bootstrap-426 sup{top:-.5em}.factory-bootstrap-426 sub{bottom:-.25em}.factory-bootstrap-426 img{border:0}.factory-bootstrap-426 svg:not(:root){overflow:hidden}.factory-bootstrap-426 figure{margin:0}.factory-bootstrap-426 button,.factory-bootstrap-426 input,.factory-bootstrap-426 select,.factory-bootstrap-426 textarea{margin:0}.factory-bootstrap-426 button,.factory-bootstrap-426 select{text-transform:none}.factory-bootstrap-426 select{padding-right:4px!important}.factory-bootstrap-426 button,.factory-bootstrap-426 input[type=reset],.factory-bootstrap-426 input[type=submit],html .factory-bootstrap-426 input[type=button]{cursor:pointer;-webkit-appearance:button}.factory-bootstrap-426 button[disabled],html .factory-bootstrap-426 input[disabled]{cursor:default}.factory-bootstrap-426 input[type=checkbox],.factory-bootstrap-426 input[type=radio]{padding:0;box-sizing:border-box}.factory-bootstrap-426 input[type=search]{-webkit-appearance:textfield}.factory-bootstrap-426 input[type=search]::-webkit-search-cancel-button,.factory-bootstrap-426 input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.factory-bootstrap-426 button::-moz-focus-inner,.factory-bootstrap-426 input::-moz-focus-inner{padding:0;border:0}.factory-bootstrap-426 textarea{overflow:auto;vertical-align:top}.factory-bootstrap-426 table{border-collapse:collapse;border-spacing:0}@media print{.factory-bootstrap-426 *{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}.factory-bootstrap-426 a,.factory-bootstrap-426 a:visited{text-decoration:underline}.factory-bootstrap-426 a[href]:after{content:" (" attr(href) ")"}.factory-bootstrap-426 abbr[title]:after{content:" (" attr(title) ")"}.factory-bootstrap-426 a[href^="javascript:"]:after,.factory-bootstrap-426 a[href^="#"]:after{content:""}.factory-bootstrap-426 blockquote,.factory-bootstrap-426 pre{border:1px solid #999;page-break-inside:avoid}.factory-bootstrap-426 thead{display:table-header-group}.factory-bootstrap-426 img,.factory-bootstrap-426 tr{page-break-inside:avoid}.factory-bootstrap-426 img{max-width:100%!important}@page{margin:2cm .5cm}.factory-bootstrap-426 h2,.factory-bootstrap-426 h3,.factory-bootstrap-426 p{orphans:3;widows:3}.factory-bootstrap-426 h2,.factory-bootstrap-426 h3{page-break-after:avoid}.factory-bootstrap-426 select{background:#fff!important}.factory-bootstrap-426 .navbar{display:none}.factory-bootstrap-426 .table td,.factory-bootstrap-426 .table th{background-color:#fff!important}.factory-bootstrap-426 .btn>.caret,.factory-bootstrap-426 .dropup>.btn>.caret{border-top-color:#000!important}.factory-bootstrap-426 .label{border:1px solid #000}.factory-bootstrap-426 .table{border-collapse:collapse!important}.factory-bootstrap-426 .table-bordered td,.factory-bootstrap-426 .table-bordered th{border:1px solid #ddd!important}}.factory-bootstrap-426 *,.factory-bootstrap-426 :after,.factory-bootstrap-426 :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html .factory-bootstrap-426{-webkit-tap-highlight-color:rgba(0,0,0,0)}.factory-bootstrap-426 body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}.factory-bootstrap-426 button,.factory-bootstrap-426 input,.factory-bootstrap-426 select,.factory-bootstrap-426 textarea{font-family:inherit;font-size:inherit;line-height:inherit}.factory-bootstrap-426 img{vertical-align:middle}.factory-bootstrap-426 .img-responsive{display:block;height:auto;max-width:100%}.factory-bootstrap-426 .img-rounded{border-radius:6px}.factory-bootstrap-426 .img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-426 .img-circle{border-radius:50%}.factory-bootstrap-426 hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.factory-bootstrap-426 .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.factory-bootstrap-426 .h1,.factory-bootstrap-426 .h2,.factory-bootstrap-426 .h3,.factory-bootstrap-426 .h4,.factory-bootstrap-426 .h5,.factory-bootstrap-426 .h6,.factory-bootstrap-426 h1,.factory-bootstrap-426 h2,.factory-bootstrap-426 h3,.factory-bootstrap-426 h4,.factory-bootstrap-426 h5,.factory-bootstrap-426 h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}.factory-bootstrap-426 .h1 .small,.factory-bootstrap-426 .h1 small,.factory-bootstrap-426 .h2 .small,.factory-bootstrap-426 .h2 small,.factory-bootstrap-426 .h3 .small,.factory-bootstrap-426 .h3 small,.factory-bootstrap-426 .h4 .small,.factory-bootstrap-426 .h4 small,.factory-bootstrap-426 .h5 .small,.factory-bootstrap-426 .h5 small,.factory-bootstrap-426 .h6 .small,.factory-bootstrap-426 .h6 small,.factory-bootstrap-426 h1 .small,.factory-bootstrap-426 h1 small,.factory-bootstrap-426 h2 .small,.factory-bootstrap-426 h2 small,.factory-bootstrap-426 h3 .small,.factory-bootstrap-426 h3 small,.factory-bootstrap-426 h4 .small,.factory-bootstrap-426 h4 small,.factory-bootstrap-426 h5 .small,.factory-bootstrap-426 h5 small,.factory-bootstrap-426 h6 .small,.factory-bootstrap-426 h6 small{font-weight:400;line-height:1;color:#999}.factory-bootstrap-426 h1,.factory-bootstrap-426 h2,.factory-bootstrap-426 h3{margin-top:20px;margin-bottom:10px}.factory-bootstrap-426 h1 .small,.factory-bootstrap-426 h1 small,.factory-bootstrap-426 h2 .small,.factory-bootstrap-426 h2 small,.factory-bootstrap-426 h3 .small,.factory-bootstrap-426 h3 small{font-size:65%}.factory-bootstrap-426 h4,.factory-bootstrap-426 h5,.factory-bootstrap-426 h6{margin-top:10px;margin-bottom:10px}.factory-bootstrap-426 h4 .small,.factory-bootstrap-426 h4 small,.factory-bootstrap-426 h5 .small,.factory-bootstrap-426 h5 small,.factory-bootstrap-426 h6 .small,.factory-bootstrap-426 h6 small{font-size:75%}.factory-bootstrap-426 .h1,.factory-bootstrap-426 h1{font-size:36px}.factory-bootstrap-426 .h2,.factory-bootstrap-426 h2{font-size:30px}.factory-bootstrap-426 .h3,.factory-bootstrap-426 h3{font-size:24px}.factory-bootstrap-426 .h4,.factory-bootstrap-426 h4{font-size:18px}.factory-bootstrap-426 .h5,.factory-bootstrap-426 h5{font-size:14px}.factory-bootstrap-426 .h6,.factory-bootstrap-426 h6{font-size:12px}.factory-bootstrap-426 p{margin:0 0 10px}.factory-bootstrap-426 .lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.factory-bootstrap-426 .small,.factory-bootstrap-426 small{font-size:85%}.factory-bootstrap-426 cite{font-style:normal}.factory-bootstrap-426 .text-muted{color:#999}.factory-bootstrap-426 .text-primary{color:#428bca}.factory-bootstrap-426 .text-primary:hover{color:#3071a9}.factory-bootstrap-426 .text-warning{color:#8a6d3b}.factory-bootstrap-426 .text-warning:hover{color:#66512c}.factory-bootstrap-426 .text-danger{color:#a94442}.factory-bootstrap-426 .text-danger:hover{color:#843534}.factory-bootstrap-426 .text-success{color:#3c763d}.factory-bootstrap-426 .text-success:hover{color:#2b542c}.factory-bootstrap-426 .text-info{color:#31708f}.factory-bootstrap-426 .text-info:hover{color:#245269}.factory-bootstrap-426 .text-left{text-align:left}.factory-bootstrap-426 .text-right{text-align:right}.factory-bootstrap-426 .text-center{text-align:center}.factory-bootstrap-426 .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}.factory-bootstrap-426 ol,.factory-bootstrap-426 ul{margin-top:0;margin-bottom:10px}.factory-bootstrap-426 ol ol,.factory-bootstrap-426 ol ul,.factory-bootstrap-426 ul ol,.factory-bootstrap-426 ul ul{margin-bottom:0}.factory-bootstrap-426 .list-inline,.factory-bootstrap-426 .list-unstyled{padding-left:0;list-style:none}.factory-bootstrap-426 .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.factory-bootstrap-426 .list-inline>li:first-child{padding-left:0}.factory-bootstrap-426 dl{margin-top:0;margin-bottom:20px}.factory-bootstrap-426 dd,.factory-bootstrap-426 dt{line-height:1.428571429}.factory-bootstrap-426 dt{font-weight:700}.factory-bootstrap-426 dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{display:table;content:" "}.dl-horizontal dd:after{clear:both}}.factory-bootstrap-426 abbr[data-original-title],.factory-bootstrap-426 abbr[title]{cursor:help;border-bottom:1px dotted #999}.factory-bootstrap-426 .initialism{font-size:90%;text-transform:uppercase}.factory-bootstrap-426 blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}.factory-bootstrap-426 blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}.factory-bootstrap-426 blockquote p:last-child{margin-bottom:0}.factory-bootstrap-426 blockquote .small,.factory-bootstrap-426 blockquote small{display:block;line-height:1.428571429;color:#999}.factory-bootstrap-426 blockquote .small:before,.factory-bootstrap-426 blockquote small:before{content:'\2014 \00A0'}.factory-bootstrap-426 blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.factory-bootstrap-426 blockquote.pull-right .small,.factory-bootstrap-426 blockquote.pull-right p,.factory-bootstrap-426 blockquote.pull-right small{text-align:right}.factory-bootstrap-426 blockquote.pull-right .small:before,.factory-bootstrap-426 blockquote.pull-right small:before{content:''}.factory-bootstrap-426 blockquote.pull-right .small:after,.factory-bootstrap-426 blockquote.pull-right small:after{content:'\00A0 \2014'}.factory-bootstrap-426 blockquote:after,.factory-bootstrap-426 blockquote:before{content:""}.factory-bootstrap-426 address{margin-bottom:20px;font-style:normal;line-height:1.428571429}.factory-bootstrap-426 code,.factory-bootstrap-426 kbd,.factory-bootstrap-426 pre,.factory-bootstrap-426 samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}.factory-bootstrap-426 code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}.factory-bootstrap-426 pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-426 pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.factory-bootstrap-426 .pre-scrollable{max-height:340px;overflow-y:scroll}.factory-bootstrap-426 .container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.factory-bootstrap-426 .container:after,.factory-bootstrap-426 .container:before{display:table;content:" "}.factory-bootstrap-426 .container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.factory-bootstrap-426 .row{margin-right:-15px;margin-left:-15px}.factory-bootstrap-426 .row:after,.factory-bootstrap-426 .row:before{display:table;content:" "}.factory-bootstrap-426 .row:after{clear:both}.factory-bootstrap-426 .col-lg-1,.factory-bootstrap-426 .col-lg-10,.factory-bootstrap-426 .col-lg-11,.factory-bootstrap-426 .col-lg-12,.factory-bootstrap-426 .col-lg-2,.factory-bootstrap-426 .col-lg-3,.factory-bootstrap-426 .col-lg-4,.factory-bootstrap-426 .col-lg-5,.factory-bootstrap-426 .col-lg-6,.factory-bootstrap-426 .col-lg-7,.factory-bootstrap-426 .col-lg-8,.factory-bootstrap-426 .col-lg-9,.factory-bootstrap-426 .col-md-1,.factory-bootstrap-426 .col-md-10,.factory-bootstrap-426 .col-md-11,.factory-bootstrap-426 .col-md-12,.factory-bootstrap-426 .col-md-2,.factory-bootstrap-426 .col-md-3,.factory-bootstrap-426 .col-md-4,.factory-bootstrap-426 .col-md-5,.factory-bootstrap-426 .col-md-6,.factory-bootstrap-426 .col-md-7,.factory-bootstrap-426 .col-md-8,.factory-bootstrap-426 .col-md-9,.factory-bootstrap-426 .col-sm-1,.factory-bootstrap-426 .col-sm-10,.factory-bootstrap-426 .col-sm-11,.factory-bootstrap-426 .col-sm-12,.factory-bootstrap-426 .col-sm-2,.factory-bootstrap-426 .col-sm-3,.factory-bootstrap-426 .col-sm-4,.factory-bootstrap-426 .col-sm-5,.factory-bootstrap-426 .col-sm-6,.factory-bootstrap-426 .col-sm-7,.factory-bootstrap-426 .col-sm-8,.factory-bootstrap-426 .col-sm-9,.factory-bootstrap-426 .col-xs-1,.factory-bootstrap-426 .col-xs-10,.factory-bootstrap-426 .col-xs-11,.factory-bootstrap-426 .col-xs-12,.factory-bootstrap-426 .col-xs-2,.factory-bootstrap-426 .col-xs-3,.factory-bootstrap-426 .col-xs-4,.factory-bootstrap-426 .col-xs-5,.factory-bootstrap-426 .col-xs-6,.factory-bootstrap-426 .col-xs-7,.factory-bootstrap-426 .col-xs-8,.factory-bootstrap-426 .col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.factory-bootstrap-426 .col-xs-1,.factory-bootstrap-426 .col-xs-10,.factory-bootstrap-426 .col-xs-11,.factory-bootstrap-426 .col-xs-12,.factory-bootstrap-426 .col-xs-2,.factory-bootstrap-426 .col-xs-3,.factory-bootstrap-426 .col-xs-4,.factory-bootstrap-426 .col-xs-5,.factory-bootstrap-426 .col-xs-6,.factory-bootstrap-426 .col-xs-7,.factory-bootstrap-426 .col-xs-8,.factory-bootstrap-426 .col-xs-9{float:left}.factory-bootstrap-426 .col-xs-12{width:100%}.factory-bootstrap-426 .col-xs-11{width:91.66666666666666%}.factory-bootstrap-426 .col-xs-10{width:83.33333333333334%}.factory-bootstrap-426 .col-xs-9{width:75%}.factory-bootstrap-426 .col-xs-8{width:66.66666666666666%}.factory-bootstrap-426 .col-xs-7{width:58.333333333333336%}.factory-bootstrap-426 .col-xs-6{width:50%}.factory-bootstrap-426 .col-xs-5{width:41.66666666666667%}.factory-bootstrap-426 .col-xs-4{width:33.33333333333333%}.factory-bootstrap-426 .col-xs-3{width:25%}.factory-bootstrap-426 .col-xs-2{width:16.666666666666664%}.factory-bootstrap-426 .col-xs-1{width:8.333333333333332%}.factory-bootstrap-426 .col-xs-pull-12{right:100%}.factory-bootstrap-426 .col-xs-pull-11{right:91.66666666666666%}.factory-bootstrap-426 .col-xs-pull-10{right:83.33333333333334%}.factory-bootstrap-426 .col-xs-pull-9{right:75%}.factory-bootstrap-426 .col-xs-pull-8{right:66.66666666666666%}.factory-bootstrap-426 .col-xs-pull-7{right:58.333333333333336%}.factory-bootstrap-426 .col-xs-pull-6{right:50%}.factory-bootstrap-426 .col-xs-pull-5{right:41.66666666666667%}.factory-bootstrap-426 .col-xs-pull-4{right:33.33333333333333%}.factory-bootstrap-426 .col-xs-pull-3{right:25%}.factory-bootstrap-426 .col-xs-pull-2{right:16.666666666666664%}.factory-bootstrap-426 .col-xs-pull-1{right:8.333333333333332%}.factory-bootstrap-426 .col-xs-pull-0{right:0}.factory-bootstrap-426 .col-xs-push-12{left:100%}.factory-bootstrap-426 .col-xs-push-11{left:91.66666666666666%}.factory-bootstrap-426 .col-xs-push-10{left:83.33333333333334%}.factory-bootstrap-426 .col-xs-push-9{left:75%}.factory-bootstrap-426 .col-xs-push-8{left:66.66666666666666%}.factory-bootstrap-426 .col-xs-push-7{left:58.333333333333336%}.factory-bootstrap-426 .col-xs-push-6{left:50%}.factory-bootstrap-426 .col-xs-push-5{left:41.66666666666667%}.factory-bootstrap-426 .col-xs-push-4{left:33.33333333333333%}.factory-bootstrap-426 .col-xs-push-3{left:25%}.factory-bootstrap-426 .col-xs-push-2{left:16.666666666666664%}.factory-bootstrap-426 .col-xs-push-1{left:8.333333333333332%}.factory-bootstrap-426 .col-xs-push-0{left:0}.factory-bootstrap-426 .col-xs-offset-12{margin-left:100%}.factory-bootstrap-426 .col-xs-offset-11{margin-left:91.66666666666666%}.factory-bootstrap-426 .col-xs-offset-10{margin-left:83.33333333333334%}.factory-bootstrap-426 .col-xs-offset-9{margin-left:75%}.factory-bootstrap-426 .col-xs-offset-8{margin-left:66.66666666666666%}.factory-bootstrap-426 .col-xs-offset-7{margin-left:58.333333333333336%}.factory-bootstrap-426 .col-xs-offset-6{margin-left:50%}.factory-bootstrap-426 .col-xs-offset-5{margin-left:41.66666666666667%}.factory-bootstrap-426 .col-xs-offset-4{margin-left:33.33333333333333%}.factory-bootstrap-426 .col-xs-offset-3{margin-left:25%}.factory-bootstrap-426 .col-xs-offset-2{margin-left:16.666666666666664%}.factory-bootstrap-426 .col-xs-offset-1{margin-left:8.333333333333332%}.factory-bootstrap-426 .col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.factory-bootstrap-426 table{max-width:100%;background-color:transparent}.factory-bootstrap-426 th{text-align:left}.factory-bootstrap-426 .table{width:100%;margin-bottom:20px}.factory-bootstrap-426 .table>tbody>tr>td,.factory-bootstrap-426 .table>tbody>tr>th,.factory-bootstrap-426 .table>tfoot>tr>td,.factory-bootstrap-426 .table>tfoot>tr>th,.factory-bootstrap-426 .table>thead>tr>td,.factory-bootstrap-426 .table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.factory-bootstrap-426 .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.factory-bootstrap-426 .table>caption+thead>tr:first-child>td,.factory-bootstrap-426 .table>caption+thead>tr:first-child>th,.factory-bootstrap-426 .table>colgroup+thead>tr:first-child>td,.factory-bootstrap-426 .table>colgroup+thead>tr:first-child>th,.factory-bootstrap-426 .table>thead:first-child>tr:first-child>td,.factory-bootstrap-426 .table>thead:first-child>tr:first-child>th{border-top:0}.factory-bootstrap-426 .table>tbody+tbody{border-top:2px solid #ddd}.factory-bootstrap-426 .table .table{background-color:#fff}.factory-bootstrap-426 .table-condensed>tbody>tr>td,.factory-bootstrap-426 .table-condensed>tbody>tr>th,.factory-bootstrap-426 .table-condensed>tfoot>tr>td,.factory-bootstrap-426 .table-condensed>tfoot>tr>th,.factory-bootstrap-426 .table-condensed>thead>tr>td,.factory-bootstrap-426 .table-condensed>thead>tr>th{padding:5px}.factory-bootstrap-426 .table-bordered,.factory-bootstrap-426 .table-bordered>tbody>tr>td,.factory-bootstrap-426 .table-bordered>tbody>tr>th,.factory-bootstrap-426 .table-bordered>tfoot>tr>td,.factory-bootstrap-426 .table-bordered>tfoot>tr>th,.factory-bootstrap-426 .table-bordered>thead>tr>td,.factory-bootstrap-426 .table-bordered>thead>tr>th{border:1px solid #ddd}.factory-bootstrap-426 .table-bordered>thead>tr>td,.factory-bootstrap-426 .table-bordered>thead>tr>th{border-bottom-width:2px}.factory-bootstrap-426 .table-striped>tbody>tr:nth-child(odd)>td,.factory-bootstrap-426 .table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.factory-bootstrap-426 .table-hover>tbody>tr:hover>td,.factory-bootstrap-426 .table-hover>tbody>tr:hover>th{background-color:#f5f5f5}.factory-bootstrap-426 table col[class*=col-]{position:static;display:table-column;float:none}.factory-bootstrap-426 table td[class*=col-],.factory-bootstrap-426 table th[class*=col-]{display:table-cell;float:none}.factory-bootstrap-426 .table>tbody>.active>td,.factory-bootstrap-426 .table>tbody>.active>th,.factory-bootstrap-426 .table>tbody>tr>.active,.factory-bootstrap-426 .table>tfoot>.active>td,.factory-bootstrap-426 .table>tfoot>.active>th,.factory-bootstrap-426 .table>tfoot>tr>.active,.factory-bootstrap-426 .table>thead>.active>td,.factory-bootstrap-426 .table>thead>.active>th,.factory-bootstrap-426 .table>thead>tr>.active{background-color:#f5f5f5}.factory-bootstrap-426 .table-hover>tbody>.active:hover>td,.factory-bootstrap-426 .table-hover>tbody>.active:hover>th,.factory-bootstrap-426 .table-hover>tbody>tr>.active:hover{background-color:#e8e8e8}.factory-bootstrap-426 .table>tbody>.success>td,.factory-bootstrap-426 .table>tbody>.success>th,.factory-bootstrap-426 .table>tbody>tr>.success,.factory-bootstrap-426 .table>tfoot>.success>td,.factory-bootstrap-426 .table>tfoot>.success>th,.factory-bootstrap-426 .table>tfoot>tr>.success,.factory-bootstrap-426 .table>thead>.success>td,.factory-bootstrap-426 .table>thead>.success>th,.factory-bootstrap-426 .table>thead>tr>.success{background-color:#dff0d8}.factory-bootstrap-426 .table-hover>tbody>.success:hover>td,.factory-bootstrap-426 .table-hover>tbody>.success:hover>th,.factory-bootstrap-426 .table-hover>tbody>tr>.success:hover{background-color:#d0e9c6}.factory-bootstrap-426 .table>tbody>.danger>td,.factory-bootstrap-426 .table>tbody>.danger>th,.factory-bootstrap-426 .table>tbody>tr>.danger,.factory-bootstrap-426 .table>tfoot>.danger>td,.factory-bootstrap-426 .table>tfoot>.danger>th,.factory-bootstrap-426 .table>tfoot>tr>.danger,.factory-bootstrap-426 .table>thead>.danger>td,.factory-bootstrap-426 .table>thead>.danger>th,.factory-bootstrap-426 .table>thead>tr>.danger{background-color:#f2dede}.factory-bootstrap-426 .table-hover>tbody>.danger:hover>td,.factory-bootstrap-426 .table-hover>tbody>.danger:hover>th,.factory-bootstrap-426 .table-hover>tbody>tr>.danger:hover{background-color:#ebcccc}.factory-bootstrap-426 .table>tbody>.warning>td,.factory-bootstrap-426 .table>tbody>.warning>th,.factory-bootstrap-426 .table>tbody>tr>.warning,.factory-bootstrap-426 .table>tfoot>.warning>td,.factory-bootstrap-426 .table>tfoot>.warning>th,.factory-bootstrap-426 .table>tfoot>tr>.warning,.factory-bootstrap-426 .table>thead>.warning>td,.factory-bootstrap-426 .table>thead>.warning>th,.factory-bootstrap-426 .table>thead>tr>.warning{background-color:#fcf8e3}.factory-bootstrap-426 .table-hover>tbody>.warning:hover>td,.factory-bootstrap-426 .table-hover>tbody>.warning:hover>th,.factory-bootstrap-426 .table-hover>tbody>tr>.warning:hover{background-color:#faf2cc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}.factory-bootstrap-426 fieldset{padding:0;margin:0;border:0}.factory-bootstrap-426 legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-426 label{display:inline-block;margin-bottom:5px;font-weight:700}.factory-bootstrap-426 input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.factory-bootstrap-426 input[type=checkbox],.factory-bootstrap-426 input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}.factory-bootstrap-426 input[type=file]{display:block}.factory-bootstrap-426 select[multiple],.factory-bootstrap-426 select[size]{height:auto}.factory-bootstrap-426 select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}.factory-bootstrap-426 input[type=checkbox]:focus,.factory-bootstrap-426 input[type=file]:focus,.factory-bootstrap-426 input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-426 input[type=number]::-webkit-inner-spin-button,.factory-bootstrap-426 input[type=number]::-webkit-outer-spin-button{height:auto}.factory-bootstrap-426 output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.factory-bootstrap-426 .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.factory-bootstrap-426 .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-426 .form-control:-moz-placeholder{color:#999}.factory-bootstrap-426 .form-control::-moz-placeholder{color:#999;opacity:1}.factory-bootstrap-426 .form-control:-ms-input-placeholder{color:#999}.factory-bootstrap-426 .form-control::-webkit-input-placeholder{color:#999}.factory-bootstrap-426 .form-control[disabled],.factory-bootstrap-426 .form-control[readonly],.factory-bootstrap-426 fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}.factory-bootstrap-426 textarea.form-control{height:auto}.factory-bootstrap-426 .form-group{margin-bottom:15px}.factory-bootstrap-426 .checkbox,.factory-bootstrap-426 .radio{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.factory-bootstrap-426 .checkbox label,.factory-bootstrap-426 .radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.factory-bootstrap-426 .checkbox input[type=checkbox],.factory-bootstrap-426 .checkbox-inline input[type=checkbox],.factory-bootstrap-426 .radio input[type=radio],.factory-bootstrap-426 .radio-inline input[type=radio]{float:left;margin-left:-20px}.factory-bootstrap-426 .checkbox+.checkbox,.factory-bootstrap-426 .radio+.radio{margin-top:-5px}.factory-bootstrap-426 .checkbox-inline,.factory-bootstrap-426 .radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.factory-bootstrap-426 .checkbox-inline+.checkbox-inline,.factory-bootstrap-426 .radio-inline+.radio-inline{margin-top:0;margin-left:10px}.factory-bootstrap-426 .checkbox-inline[disabled],.factory-bootstrap-426 .checkbox[disabled],.factory-bootstrap-426 .radio-inline[disabled],.factory-bootstrap-426 .radio[disabled],.factory-bootstrap-426 fieldset[disabled] .checkbox,.factory-bootstrap-426 fieldset[disabled] .checkbox-inline,.factory-bootstrap-426 fieldset[disabled] .radio,.factory-bootstrap-426 fieldset[disabled] .radio-inline,.factory-bootstrap-426 fieldset[disabled] input[type=checkbox],.factory-bootstrap-426 fieldset[disabled] input[type=radio],.factory-bootstrap-426 input[type=checkbox][disabled],.factory-bootstrap-426 input[type=radio][disabled]{cursor:not-allowed}.factory-bootstrap-426 .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 select.input-sm{height:30px;line-height:30px}.factory-bootstrap-426 textarea.input-sm{height:auto}.factory-bootstrap-426 .input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-426 select.input-lg{height:46px;line-height:46px}.factory-bootstrap-426 textarea.input-lg{height:auto}.factory-bootstrap-426 .has-warning .checkbox,.factory-bootstrap-426 .has-warning .checkbox-inline,.factory-bootstrap-426 .has-warning .control-label,.factory-bootstrap-426 .has-warning .help-block,.factory-bootstrap-426 .has-warning .radio,.factory-bootstrap-426 .has-warning .radio-inline{color:#8a6d3b}.factory-bootstrap-426 .has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-426 .has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.factory-bootstrap-426 .has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.factory-bootstrap-426 .has-error .checkbox,.factory-bootstrap-426 .has-error .checkbox-inline,.factory-bootstrap-426 .has-error .control-label,.factory-bootstrap-426 .has-error .help-block,.factory-bootstrap-426 .has-error .radio,.factory-bootstrap-426 .has-error .radio-inline{color:#a94442}.factory-bootstrap-426 .controls{display:block}.factory-bootstrap-426 .has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-426 .has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.factory-bootstrap-426 .has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.factory-bootstrap-426 .has-success .checkbox,.factory-bootstrap-426 .has-success .checkbox-inline,.factory-bootstrap-426 .has-success .control-label,.factory-bootstrap-426 .has-success .help-block,.factory-bootstrap-426 .has-success .radio,.factory-bootstrap-426 .has-success .radio-inline{color:#3c763d}.factory-bootstrap-426 .has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-426 .has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.factory-bootstrap-426 .has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.factory-bootstrap-426 .form-control-static{margin-bottom:0}.factory-bootstrap-426 .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;font-weight:400}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.factory-bootstrap-426 .form-horizontal .checkbox,.factory-bootstrap-426 .form-horizontal .checkbox-inline,.factory-bootstrap-426 .form-horizontal .control-label,.factory-bootstrap-426 .form-horizontal .radio,.factory-bootstrap-426 .form-horizontal .radio-inline{position:relative;padding-top:7px;margin-top:0;margin-bottom:0}.factory-bootstrap-426 .form-horizontal .control-label{max-width:200px}.factory-bootstrap-426 .form-horizontal .checkbox,.factory-bootstrap-426 .form-horizontal .radio{min-height:27px}.factory-bootstrap-426 .form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.factory-bootstrap-426 .form-horizontal .form-group:after,.factory-bootstrap-426 .form-horizontal .form-group:before{display:table;content:" "}.factory-bootstrap-426 .form-horizontal .form-group:after{clear:both}.factory-bootstrap-426 .form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.factory-bootstrap-426 .btn{display:inline-block;padding:5px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.factory-bootstrap-426 .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-426 .btn{text-decoration:none}.factory-bootstrap-426 .btn:focus,.factory-bootstrap-426 .btn:hover{color:#333;text-decoration:none}.factory-bootstrap-426 .btn.disabled,.factory-bootstrap-426 .btn[disabled],.factory-bootstrap-426 fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-426 .btn-default.active,.factory-bootstrap-426 .btn-default:active,.factory-bootstrap-426 .btn-default:focus,.factory-bootstrap-426 .btn-default:hover,.factory-bootstrap-426 .open .dropdown-toggle.btn-default{background:#fafafa;border-color:#999;color:#222}.factory-bootstrap-426 .btn-default.active,.factory-bootstrap-426 .btn-default:active,.factory-bootstrap-426 .open .dropdown-toggle.btn-default{background-image:none}.factory-bootstrap-426 .btn-default.disabled,.factory-bootstrap-426 .btn-default.disabled.active,.factory-bootstrap-426 .btn-default.disabled:active,.factory-bootstrap-426 .btn-default.disabled:focus,.factory-bootstrap-426 .btn-default.disabled:hover,.factory-bootstrap-426 .btn-default[disabled],.factory-bootstrap-426 .btn-default[disabled].active,.factory-bootstrap-426 .btn-default[disabled]:active,.factory-bootstrap-426 .btn-default[disabled]:focus,.factory-bootstrap-426 .btn-default[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-default,.factory-bootstrap-426 fieldset[disabled] .btn-default.active,.factory-bootstrap-426 fieldset[disabled] .btn-default:active,.factory-bootstrap-426 fieldset[disabled] .btn-default:focus,.factory-bootstrap-426 fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.factory-bootstrap-426 .btn-default .badge{color:#fff;background-color:#fff}.factory-bootstrap-426 .btn-primary.active,.factory-bootstrap-426 .btn-primary:active,.factory-bootstrap-426 .btn-primary:focus,.factory-bootstrap-426 .btn-primary:hover,.factory-bootstrap-426 .open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.factory-bootstrap-426 .btn-primary.active,.factory-bootstrap-426 .btn-primary:active,.factory-bootstrap-426 .open .dropdown-toggle.btn-primary{background-image:none}.factory-bootstrap-426 .btn-primary.disabled,.factory-bootstrap-426 .btn-primary.disabled.active,.factory-bootstrap-426 .btn-primary.disabled:active,.factory-bootstrap-426 .btn-primary.disabled:focus,.factory-bootstrap-426 .btn-primary.disabled:hover,.factory-bootstrap-426 .btn-primary[disabled],.factory-bootstrap-426 .btn-primary[disabled].active,.factory-bootstrap-426 .btn-primary[disabled]:active,.factory-bootstrap-426 .btn-primary[disabled]:focus,.factory-bootstrap-426 .btn-primary[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-primary,.factory-bootstrap-426 fieldset[disabled] .btn-primary.active,.factory-bootstrap-426 fieldset[disabled] .btn-primary:active,.factory-bootstrap-426 fieldset[disabled] .btn-primary:focus,.factory-bootstrap-426 fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.factory-bootstrap-426 .btn-primary .badge{color:#428bca;background-color:#fff}.factory-bootstrap-426 .btn-warning{color:#fff;background-color:#f0ad4e}.factory-bootstrap-426 .btn-warning.active,.factory-bootstrap-426 .btn-warning:active,.factory-bootstrap-426 .btn-warning:focus,.factory-bootstrap-426 .btn-warning:hover,.factory-bootstrap-426 .open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.factory-bootstrap-426 .btn-warning.active,.factory-bootstrap-426 .btn-warning:active,.factory-bootstrap-426 .open .dropdown-toggle.btn-warning{background-image:none}.factory-bootstrap-426 .btn-warning.disabled,.factory-bootstrap-426 .btn-warning.disabled.active,.factory-bootstrap-426 .btn-warning.disabled:active,.factory-bootstrap-426 .btn-warning.disabled:focus,.factory-bootstrap-426 .btn-warning.disabled:hover,.factory-bootstrap-426 .btn-warning[disabled],.factory-bootstrap-426 .btn-warning[disabled].active,.factory-bootstrap-426 .btn-warning[disabled]:active,.factory-bootstrap-426 .btn-warning[disabled]:focus,.factory-bootstrap-426 .btn-warning[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-warning,.factory-bootstrap-426 fieldset[disabled] .btn-warning.active,.factory-bootstrap-426 fieldset[disabled] .btn-warning:active,.factory-bootstrap-426 fieldset[disabled] .btn-warning:focus,.factory-bootstrap-426 fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.factory-bootstrap-426 .btn-warning .badge{color:#f0ad4e;background-color:#fff}.factory-bootstrap-426 .btn-success{color:#fff;background-color:#5cb85c}.factory-bootstrap-426 .btn-success.active,.factory-bootstrap-426 .btn-success:active,.factory-bootstrap-426 .btn-success:focus,.factory-bootstrap-426 .btn-success:hover,.factory-bootstrap-426 .open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.factory-bootstrap-426 .btn-success.active,.factory-bootstrap-426 .btn-success:active,.factory-bootstrap-426 .open .dropdown-toggle.btn-success{background-image:none}.factory-bootstrap-426 .btn-success.disabled,.factory-bootstrap-426 .btn-success.disabled.active,.factory-bootstrap-426 .btn-success.disabled:active,.factory-bootstrap-426 .btn-success.disabled:focus,.factory-bootstrap-426 .btn-success.disabled:hover,.factory-bootstrap-426 .btn-success[disabled],.factory-bootstrap-426 .btn-success[disabled].active,.factory-bootstrap-426 .btn-success[disabled]:active,.factory-bootstrap-426 .btn-success[disabled]:focus,.factory-bootstrap-426 .btn-success[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-success,.factory-bootstrap-426 fieldset[disabled] .btn-success.active,.factory-bootstrap-426 fieldset[disabled] .btn-success:active,.factory-bootstrap-426 fieldset[disabled] .btn-success:focus,.factory-bootstrap-426 fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.factory-bootstrap-426 .btn-success .badge{color:#5cb85c;background-color:#fff}.factory-bootstrap-426 .btn-info{color:#fff;background-color:#5bc0de}.factory-bootstrap-426 .btn-info.active,.factory-bootstrap-426 .btn-info:active,.factory-bootstrap-426 .btn-info:focus,.factory-bootstrap-426 .btn-info:hover,.factory-bootstrap-426 .open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.factory-bootstrap-426 .btn-info.active,.factory-bootstrap-426 .btn-info:active,.factory-bootstrap-426 .open .dropdown-toggle.btn-info{background-image:none}.factory-bootstrap-426 .btn-info.disabled,.factory-bootstrap-426 .btn-info.disabled.active,.factory-bootstrap-426 .btn-info.disabled:active,.factory-bootstrap-426 .btn-info.disabled:focus,.factory-bootstrap-426 .btn-info.disabled:hover,.factory-bootstrap-426 .btn-info[disabled],.factory-bootstrap-426 .btn-info[disabled].active,.factory-bootstrap-426 .btn-info[disabled]:active,.factory-bootstrap-426 .btn-info[disabled]:focus,.factory-bootstrap-426 .btn-info[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-info,.factory-bootstrap-426 fieldset[disabled] .btn-info.active,.factory-bootstrap-426 fieldset[disabled] .btn-info:active,.factory-bootstrap-426 fieldset[disabled] .btn-info:focus,.factory-bootstrap-426 fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.factory-bootstrap-426 .btn-info .badge{color:#5bc0de;background-color:#fff}.factory-bootstrap-426 .btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.factory-bootstrap-426 .btn-link,.factory-bootstrap-426 .btn-link:active,.factory-bootstrap-426 .btn-link[disabled],.factory-bootstrap-426 fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-426 .btn-link,.factory-bootstrap-426 .btn-link:active,.factory-bootstrap-426 .btn-link:focus,.factory-bootstrap-426 .btn-link:hover{border-color:transparent}.factory-bootstrap-426 .btn-link:focus,.factory-bootstrap-426 .btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.factory-bootstrap-426 .btn-link[disabled]:focus,.factory-bootstrap-426 .btn-link[disabled]:hover,.factory-bootstrap-426 fieldset[disabled] .btn-link:focus,.factory-bootstrap-426 fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.factory-bootstrap-426 .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-426 .btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 .btn-block{display:block;width:100%;padding-right:0;padding-left:0}.factory-bootstrap-426 .btn-block+.btn-block{margin-top:5px}.factory-bootstrap-426 input[type=button].btn-block,.factory-bootstrap-426 input[type=reset].btn-block,.factory-bootstrap-426 input[type=submit].btn-block{width:100%}.factory-bootstrap-426 .fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.factory-bootstrap-426 .fade.in{opacity:1}.factory-bootstrap-426 .collapse{display:none}.factory-bootstrap-426 .collapse.in{display:block}.factory-bootstrap-426 .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.factory-bootstrap-426 .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.factory-bootstrap-426 .glyphicon:empty{width:1em}.factory-bootstrap-426 .glyphicon-asterisk:before{content:"\2a"}.factory-bootstrap-426 .glyphicon-plus:before{content:"\2b"}.factory-bootstrap-426 .glyphicon-euro:before{content:"\20ac"}.factory-bootstrap-426 .glyphicon-minus:before{content:"\2212"}.factory-bootstrap-426 .glyphicon-cloud:before{content:"\2601"}.factory-bootstrap-426 .glyphicon-envelope:before{content:"\2709"}.factory-bootstrap-426 .glyphicon-pencil:before{content:"\270f"}.factory-bootstrap-426 .glyphicon-glass:before{content:"\e001"}.factory-bootstrap-426 .glyphicon-music:before{content:"\e002"}.factory-bootstrap-426 .glyphicon-search:before{content:"\e003"}.factory-bootstrap-426 .glyphicon-heart:before{content:"\e005"}.factory-bootstrap-426 .glyphicon-star:before{content:"\e006"}.factory-bootstrap-426 .glyphicon-star-empty:before{content:"\e007"}.factory-bootstrap-426 .glyphicon-user:before{content:"\e008"}.factory-bootstrap-426 .glyphicon-film:before{content:"\e009"}.factory-bootstrap-426 .glyphicon-th-large:before{content:"\e010"}.factory-bootstrap-426 .glyphicon-th:before{content:"\e011"}.factory-bootstrap-426 .glyphicon-th-list:before{content:"\e012"}.factory-bootstrap-426 .glyphicon-ok:before{content:"\e013"}.factory-bootstrap-426 .glyphicon-remove:before{content:"\e014"}.factory-bootstrap-426 .glyphicon-zoom-in:before{content:"\e015"}.factory-bootstrap-426 .glyphicon-zoom-out:before{content:"\e016"}.factory-bootstrap-426 .glyphicon-off:before{content:"\e017"}.factory-bootstrap-426 .glyphicon-signal:before{content:"\e018"}.factory-bootstrap-426 .glyphicon-cog:before{content:"\e019"}.factory-bootstrap-426 .glyphicon-trash:before{content:"\e020"}.factory-bootstrap-426 .glyphicon-home:before{content:"\e021"}.factory-bootstrap-426 .glyphicon-file:before{content:"\e022"}.factory-bootstrap-426 .glyphicon-time:before{content:"\e023"}.factory-bootstrap-426 .glyphicon-road:before{content:"\e024"}.factory-bootstrap-426 .glyphicon-download-alt:before{content:"\e025"}.factory-bootstrap-426 .glyphicon-download:before{content:"\e026"}.factory-bootstrap-426 .glyphicon-upload:before{content:"\e027"}.factory-bootstrap-426 .glyphicon-inbox:before{content:"\e028"}.factory-bootstrap-426 .glyphicon-play-circle:before{content:"\e029"}.factory-bootstrap-426 .glyphicon-repeat:before{content:"\e030"}.factory-bootstrap-426 .glyphicon-refresh:before{content:"\e031"}.factory-bootstrap-426 .glyphicon-list-alt:before{content:"\e032"}.factory-bootstrap-426 .glyphicon-lock:before{content:"\e033"}.factory-bootstrap-426 .glyphicon-flag:before{content:"\e034"}.factory-bootstrap-426 .glyphicon-headphones:before{content:"\e035"}.factory-bootstrap-426 .glyphicon-volume-off:before{content:"\e036"}.factory-bootstrap-426 .glyphicon-volume-down:before{content:"\e037"}.factory-bootstrap-426 .glyphicon-volume-up:before{content:"\e038"}.factory-bootstrap-426 .glyphicon-qrcode:before{content:"\e039"}.factory-bootstrap-426 .glyphicon-barcode:before{content:"\e040"}.factory-bootstrap-426 .glyphicon-tag:before{content:"\e041"}.factory-bootstrap-426 .glyphicon-tags:before{content:"\e042"}.factory-bootstrap-426 .glyphicon-book:before{content:"\e043"}.factory-bootstrap-426 .glyphicon-bookmark:before{content:"\e044"}.factory-bootstrap-426 .glyphicon-print:before{content:"\e045"}.factory-bootstrap-426 .glyphicon-camera:before{content:"\e046"}.factory-bootstrap-426 .glyphicon-font:before{content:"\e047"}.factory-bootstrap-426 .glyphicon-bold:before{content:"\e048"}.factory-bootstrap-426 .glyphicon-italic:before{content:"\e049"}.factory-bootstrap-426 .glyphicon-text-height:before{content:"\e050"}.factory-bootstrap-426 .glyphicon-text-width:before{content:"\e051"}.factory-bootstrap-426 .glyphicon-align-left:before{content:"\e052"}.factory-bootstrap-426 .glyphicon-align-center:before{content:"\e053"}.factory-bootstrap-426 .glyphicon-align-right:before{content:"\e054"}.factory-bootstrap-426 .glyphicon-align-justify:before{content:"\e055"}.factory-bootstrap-426 .glyphicon-list:before{content:"\e056"}.factory-bootstrap-426 .glyphicon-indent-left:before{content:"\e057"}.factory-bootstrap-426 .glyphicon-indent-right:before{content:"\e058"}.factory-bootstrap-426 .glyphicon-facetime-video:before{content:"\e059"}.factory-bootstrap-426 .glyphicon-picture:before{content:"\e060"}.factory-bootstrap-426 .glyphicon-map-marker:before{content:"\e062"}.factory-bootstrap-426 .glyphicon-adjust:before{content:"\e063"}.factory-bootstrap-426 .glyphicon-tint:before{content:"\e064"}.factory-bootstrap-426 .glyphicon-edit:before{content:"\e065"}.factory-bootstrap-426 .glyphicon-share:before{content:"\e066"}.factory-bootstrap-426 .glyphicon-check:before{content:"\e067"}.factory-bootstrap-426 .glyphicon-move:before{content:"\e068"}.factory-bootstrap-426 .glyphicon-step-backward:before{content:"\e069"}.factory-bootstrap-426 .glyphicon-fast-backward:before{content:"\e070"}.factory-bootstrap-426 .glyphicon-backward:before{content:"\e071"}.factory-bootstrap-426 .glyphicon-play:before{content:"\e072"}.factory-bootstrap-426 .glyphicon-pause:before{content:"\e073"}.factory-bootstrap-426 .glyphicon-stop:before{content:"\e074"}.factory-bootstrap-426 .glyphicon-forward:before{content:"\e075"}.factory-bootstrap-426 .glyphicon-fast-forward:before{content:"\e076"}.factory-bootstrap-426 .glyphicon-step-forward:before{content:"\e077"}.factory-bootstrap-426 .glyphicon-eject:before{content:"\e078"}.factory-bootstrap-426 .glyphicon-chevron-left:before{content:"\e079"}.factory-bootstrap-426 .glyphicon-chevron-right:before{content:"\e080"}.factory-bootstrap-426 .glyphicon-plus-sign:before{content:"\e081"}.factory-bootstrap-426 .glyphicon-minus-sign:before{content:"\e082"}.factory-bootstrap-426 .glyphicon-remove-sign:before{content:"\e083"}.factory-bootstrap-426 .glyphicon-ok-sign:before{content:"\e084"}.factory-bootstrap-426 .glyphicon-question-sign:before{content:"\e085"}.factory-bootstrap-426 .glyphicon-info-sign:before{content:"\e086"}.factory-bootstrap-426 .glyphicon-screenshot:before{content:"\e087"}.factory-bootstrap-426 .glyphicon-remove-circle:before{content:"\e088"}.factory-bootstrap-426 .glyphicon-ok-circle:before{content:"\e089"}.factory-bootstrap-426 .glyphicon-ban-circle:before{content:"\e090"}.factory-bootstrap-426 .glyphicon-arrow-left:before{content:"\e091"}.factory-bootstrap-426 .glyphicon-arrow-right:before{content:"\e092"}.factory-bootstrap-426 .glyphicon-arrow-up:before{content:"\e093"}.factory-bootstrap-426 .glyphicon-arrow-down:before{content:"\e094"}.factory-bootstrap-426 .glyphicon-share-alt:before{content:"\e095"}.factory-bootstrap-426 .glyphicon-resize-full:before{content:"\e096"}.factory-bootstrap-426 .glyphicon-resize-small:before{content:"\e097"}.factory-bootstrap-426 .glyphicon-exclamation-sign:before{content:"\e101"}.factory-bootstrap-426 .glyphicon-gift:before{content:"\e102"}.factory-bootstrap-426 .glyphicon-leaf:before{content:"\e103"}.factory-bootstrap-426 .glyphicon-fire:before{content:"\e104"}.factory-bootstrap-426 .glyphicon-eye-open:before{content:"\e105"}.factory-bootstrap-426 .glyphicon-eye-close:before{content:"\e106"}.factory-bootstrap-426 .glyphicon-warning-sign:before{content:"\e107"}.factory-bootstrap-426 .glyphicon-plane:before{content:"\e108"}.factory-bootstrap-426 .glyphicon-calendar:before{content:"\e109"}.factory-bootstrap-426 .glyphicon-random:before{content:"\e110"}.factory-bootstrap-426 .glyphicon-comment:before{content:"\e111"}.factory-bootstrap-426 .glyphicon-magnet:before{content:"\e112"}.factory-bootstrap-426 .glyphicon-chevron-up:before{content:"\e113"}.factory-bootstrap-426 .glyphicon-chevron-down:before{content:"\e114"}.factory-bootstrap-426 .glyphicon-retweet:before{content:"\e115"}.factory-bootstrap-426 .glyphicon-shopping-cart:before{content:"\e116"}.factory-bootstrap-426 .glyphicon-folder-close:before{content:"\e117"}.factory-bootstrap-426 .glyphicon-folder-open:before{content:"\e118"}.factory-bootstrap-426 .glyphicon-resize-vertical:before{content:"\e119"}.factory-bootstrap-426 .glyphicon-resize-horizontal:before{content:"\e120"}.factory-bootstrap-426 .glyphicon-hdd:before{content:"\e121"}.factory-bootstrap-426 .glyphicon-bullhorn:before{content:"\e122"}.factory-bootstrap-426 .glyphicon-bell:before{content:"\e123"}.factory-bootstrap-426 .glyphicon-certificate:before{content:"\e124"}.factory-bootstrap-426 .glyphicon-thumbs-up:before{content:"\e125"}.factory-bootstrap-426 .glyphicon-thumbs-down:before{content:"\e126"}.factory-bootstrap-426 .glyphicon-hand-right:before{content:"\e127"}.factory-bootstrap-426 .glyphicon-hand-left:before{content:"\e128"}.factory-bootstrap-426 .glyphicon-hand-up:before{content:"\e129"}.factory-bootstrap-426 .glyphicon-hand-down:before{content:"\e130"}.factory-bootstrap-426 .glyphicon-circle-arrow-right:before{content:"\e131"}.factory-bootstrap-426 .glyphicon-circle-arrow-left:before{content:"\e132"}.factory-bootstrap-426 .glyphicon-circle-arrow-up:before{content:"\e133"}.factory-bootstrap-426 .glyphicon-circle-arrow-down:before{content:"\e134"}.factory-bootstrap-426 .glyphicon-globe:before{content:"\e135"}.factory-bootstrap-426 .glyphicon-wrench:before{content:"\e136"}.factory-bootstrap-426 .glyphicon-tasks:before{content:"\e137"}.factory-bootstrap-426 .glyphicon-filter:before{content:"\e138"}.factory-bootstrap-426 .glyphicon-briefcase:before{content:"\e139"}.factory-bootstrap-426 .glyphicon-fullscreen:before{content:"\e140"}.factory-bootstrap-426 .glyphicon-dashboard:before{content:"\e141"}.factory-bootstrap-426 .glyphicon-paperclip:before{content:"\e142"}.factory-bootstrap-426 .glyphicon-heart-empty:before{content:"\e143"}.factory-bootstrap-426 .glyphicon-link:before{content:"\e144"}.factory-bootstrap-426 .glyphicon-phone:before{content:"\e145"}.factory-bootstrap-426 .glyphicon-pushpin:before{content:"\e146"}.factory-bootstrap-426 .glyphicon-usd:before{content:"\e148"}.factory-bootstrap-426 .glyphicon-gbp:before{content:"\e149"}.factory-bootstrap-426 .glyphicon-sort:before{content:"\e150"}.factory-bootstrap-426 .glyphicon-sort-by-alphabet:before{content:"\e151"}.factory-bootstrap-426 .glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.factory-bootstrap-426 .glyphicon-sort-by-order:before{content:"\e153"}.factory-bootstrap-426 .glyphicon-sort-by-order-alt:before{content:"\e154"}.factory-bootstrap-426 .glyphicon-sort-by-attributes:before{content:"\e155"}.factory-bootstrap-426 .glyphicon-sort-by-attributes-alt:before{content:"\e156"}.factory-bootstrap-426 .glyphicon-unchecked:before{content:"\e157"}.factory-bootstrap-426 .glyphicon-expand:before{content:"\e158"}.factory-bootstrap-426 .glyphicon-collapse-down:before{content:"\e159"}.factory-bootstrap-426 .glyphicon-collapse-up:before{content:"\e160"}.factory-bootstrap-426 .glyphicon-log-in:before{content:"\e161"}.factory-bootstrap-426 .glyphicon-flash:before{content:"\e162"}.factory-bootstrap-426 .glyphicon-log-out:before{content:"\e163"}.factory-bootstrap-426 .glyphicon-new-window:before{content:"\e164"}.factory-bootstrap-426 .glyphicon-record:before{content:"\e165"}.factory-bootstrap-426 .glyphicon-save:before{content:"\e166"}.factory-bootstrap-426 .glyphicon-open:before{content:"\e167"}.factory-bootstrap-426 .glyphicon-saved:before{content:"\e168"}.factory-bootstrap-426 .glyphicon-import:before{content:"\e169"}.factory-bootstrap-426 .glyphicon-export:before{content:"\e170"}.factory-bootstrap-426 .glyphicon-send:before{content:"\e171"}.factory-bootstrap-426 .glyphicon-floppy-disk:before{content:"\e172"}.factory-bootstrap-426 .glyphicon-floppy-saved:before{content:"\e173"}.factory-bootstrap-426 .glyphicon-floppy-remove:before{content:"\e174"}.factory-bootstrap-426 .glyphicon-floppy-save:before{content:"\e175"}.factory-bootstrap-426 .glyphicon-floppy-open:before{content:"\e176"}.factory-bootstrap-426 .glyphicon-credit-card:before{content:"\e177"}.factory-bootstrap-426 .glyphicon-transfer:before{content:"\e178"}.factory-bootstrap-426 .glyphicon-cutlery:before{content:"\e179"}.factory-bootstrap-426 .glyphicon-header:before{content:"\e180"}.factory-bootstrap-426 .glyphicon-compressed:before{content:"\e181"}.factory-bootstrap-426 .glyphicon-earphone:before{content:"\e182"}.factory-bootstrap-426 .glyphicon-phone-alt:before{content:"\e183"}.factory-bootstrap-426 .glyphicon-tower:before{content:"\e184"}.factory-bootstrap-426 .glyphicon-stats:before{content:"\e185"}.factory-bootstrap-426 .glyphicon-sd-video:before{content:"\e186"}.factory-bootstrap-426 .glyphicon-hd-video:before{content:"\e187"}.factory-bootstrap-426 .glyphicon-subtitles:before{content:"\e188"}.factory-bootstrap-426 .glyphicon-sound-stereo:before{content:"\e189"}.factory-bootstrap-426 .glyphicon-sound-dolby:before{content:"\e190"}.factory-bootstrap-426 .glyphicon-sound-5-1:before{content:"\e191"}.factory-bootstrap-426 .glyphicon-sound-6-1:before{content:"\e192"}.factory-bootstrap-426 .glyphicon-sound-7-1:before{content:"\e193"}.factory-bootstrap-426 .glyphicon-copyright-mark:before{content:"\e194"}.factory-bootstrap-426 .glyphicon-registration-mark:before{content:"\e195"}.factory-bootstrap-426 .glyphicon-cloud-download:before{content:"\e197"}.factory-bootstrap-426 .glyphicon-cloud-upload:before{content:"\e198"}.factory-bootstrap-426 .glyphicon-tree-conifer:before{content:"\e199"}.factory-bootstrap-426 .glyphicon-tree-deciduous:before{content:"\e200"}.factory-bootstrap-426 .caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.factory-bootstrap-426 .dropdown{position:relative}.factory-bootstrap-426 .dropdown-toggle:focus{outline:0}.factory-bootstrap-426 .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.factory-bootstrap-426 .dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-426 .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-426 .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.factory-bootstrap-426 .dropdown-menu>li>a:focus,.factory-bootstrap-426 .dropdown-menu>li>a:hover{color:#262626;text-decoration:none}.factory-bootstrap-426 .dropdown-menu>.active>a,.factory-bootstrap-426 .dropdown-menu>.active>a:focus,.factory-bootstrap-426 .dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.factory-bootstrap-426 .dropdown-menu>.disabled>a,.factory-bootstrap-426 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-426 .dropdown-menu>.disabled>a:hover{color:#999}.factory-bootstrap-426 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-426 .dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-426 .open>.dropdown-menu{display:block}.factory-bootstrap-426 .open>a{outline:0}.factory-bootstrap-426 .dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.factory-bootstrap-426 .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.factory-bootstrap-426 .pull-right>.dropdown-menu{right:0;left:auto}.factory-bootstrap-426 .dropup .caret,.factory-bootstrap-426 .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.factory-bootstrap-426 .dropup .dropdown-menu,.factory-bootstrap-426 .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.factory-bootstrap-426 .btn-group,.factory-bootstrap-426 .btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.factory-bootstrap-426 .btn-group-vertical>.btn,.factory-bootstrap-426 .btn-group>.btn{position:relative;float:left}.factory-bootstrap-426 .btn-group-vertical>.btn.active,.factory-bootstrap-426 .btn-group-vertical>.btn:active,.factory-bootstrap-426 .btn-group-vertical>.btn:focus,.factory-bootstrap-426 .btn-group-vertical>.btn:hover,.factory-bootstrap-426 .btn-group>.btn.active,.factory-bootstrap-426 .btn-group>.btn:active,.factory-bootstrap-426 .btn-group>.btn:focus,.factory-bootstrap-426 .btn-group>.btn:hover{z-index:2}.factory-bootstrap-426 .btn-group-vertical>.btn:focus,.factory-bootstrap-426 .btn-group>.btn:focus{outline:0}.factory-bootstrap-426 .btn-group .btn+.btn,.factory-bootstrap-426 .btn-group .btn+.btn-group,.factory-bootstrap-426 .btn-group .btn-group+.btn,.factory-bootstrap-426 .btn-group .btn-group+.btn-group{margin-left:-1px}.factory-bootstrap-426 .btn-toolbar:after,.factory-bootstrap-426 .btn-toolbar:before{display:table;content:" "}.factory-bootstrap-426 .btn-toolbar:after{clear:both}.factory-bootstrap-426 .btn-toolbar .btn-group{float:left}.factory-bootstrap-426 .btn-toolbar>.btn+.btn,.factory-bootstrap-426 .btn-toolbar>.btn+.btn-group,.factory-bootstrap-426 .btn-toolbar>.btn-group+.btn,.factory-bootstrap-426 .btn-toolbar>.btn-group+.btn-group{margin-left:5px}.factory-bootstrap-426 .btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.factory-bootstrap-426 .btn-group>.btn:first-child{margin-left:0}.factory-bootstrap-426 .btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-426 .btn-group>.btn:last-child:not(:first-child),.factory-bootstrap-426 .btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-426 .btn-group>.btn-group{float:left}.factory-bootstrap-426 .btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-426 .btn-group>.btn-group:first-child>.btn:last-child,.factory-bootstrap-426 .btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-426 .btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-426 .btn-group .dropdown-toggle:active,.factory-bootstrap-426 .btn-group.open .dropdown-toggle{outline:0}.factory-bootstrap-426 .btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 .btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 .btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-426 .btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.factory-bootstrap-426 .btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.factory-bootstrap-426 .btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.factory-bootstrap-426 .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-426 .btn-group{border:4px solid #f9f9f9;border-radius:4px}.factory-bootstrap-426 .btn-group .btn.active.value{text-shadow:none;color:#fff;background-color:#33aad5;-webkit-box-shadow:inset 0 1px 1px #0074a2;box-shadow:inset 0 1px 3px #0074a2;border-top:1px solid #0074a2;border-bottom:1px solid #0074a2;border-left:1px solid #0074a2}.factory-bootstrap-426 .btn .caret{margin-left:0}.factory-bootstrap-426 .btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.factory-bootstrap-426 .dropup .btn-lg .caret{border-width:0 5px 5px}.factory-bootstrap-426 .btn-group-vertical>.btn,.factory-bootstrap-426 .btn-group-vertical>.btn-group,.factory-bootstrap-426 .btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.factory-bootstrap-426 .btn-group-vertical>.btn-group:after,.factory-bootstrap-426 .btn-group-vertical>.btn-group:before{display:table;content:" "}.factory-bootstrap-426 .btn-group-vertical>.btn-group:after{clear:both}.factory-bootstrap-426 .btn-group-vertical>.btn-group>.btn{float:none}.factory-bootstrap-426 .btn-group-vertical>.btn+.btn,.factory-bootstrap-426 .btn-group-vertical>.btn+.btn-group,.factory-bootstrap-426 .btn-group-vertical>.btn-group+.btn,.factory-bootstrap-426 .btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.factory-bootstrap-426 .btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-426 .btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-426 .btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.factory-bootstrap-426 .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-426 .btn-group-vertical>.btn-group:first-child>.btn:last-child,.factory-bootstrap-426 .btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-426 .btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-426 .btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.factory-bootstrap-426 .btn-group-justified>.btn,.factory-bootstrap-426 .btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.factory-bootstrap-426 .btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.factory-bootstrap-426 .input-group{position:relative;display:table;border-collapse:separate}.factory-bootstrap-426 .input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.factory-bootstrap-426 .input-group .form-control{width:100%;margin-bottom:0}.factory-bootstrap-426 .input-group-lg>.form-control,.factory-bootstrap-426 .input-group-lg>.input-group-addon,.factory-bootstrap-426 .input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-426 select.input-group-lg>.form-control,.factory-bootstrap-426 select.input-group-lg>.input-group-addon,.factory-bootstrap-426 select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}.factory-bootstrap-426 textarea.input-group-lg>.form-control,.factory-bootstrap-426 textarea.input-group-lg>.input-group-addon,.factory-bootstrap-426 textarea.input-group-lg>.input-group-btn>.btn{height:auto}.factory-bootstrap-426 .input-group-sm>.form-control,.factory-bootstrap-426 .input-group-sm>.input-group-addon,.factory-bootstrap-426 .input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-426 select.input-group-sm>.form-control,.factory-bootstrap-426 select.input-group-sm>.input-group-addon,.factory-bootstrap-426 select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}.factory-bootstrap-426 textarea.input-group-sm>.form-control,.factory-bootstrap-426 textarea.input-group-sm>.input-group-addon,.factory-bootstrap-426 textarea.input-group-sm>.input-group-btn>.btn{height:auto}.factory-bootstrap-426 .input-group .form-control,.factory-bootstrap-426 .input-group-addon,.factory-bootstrap-426 .input-group-btn{display:table-cell}.factory-bootstrap-426 .input-group .form-control:not(:first-child):not(:last-child),.factory-bootstrap-426 .input-group-addon:not(:first-child):not(:last-child),.factory-bootstrap-426 .input-group-btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-426 .input-group-addon,.factory-bootstrap-426 .input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.factory-bootstrap-426 .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4
8
  */
9
 
10