Version Description
- Added: Lazy Load option for images
Download this release
Release Info
Developer | alexkovalevv |
Plugin | 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
- admin/activation.php +3 -3
- admin/ajax/bulk-optimization.php +98 -88
- admin/assets/css/base-statistic.css +675 -676
- admin/assets/css/base-statistic.less +1 -1
- admin/assets/css/settings-premium.css +17 -0
- admin/assets/css/sweetalert-custom.css +155 -156
- admin/assets/js/Chart.min.js +3 -3
- admin/assets/js/bulk-optimization.js +566 -553
- admin/assets/js/settings-premium.js +1 -0
- admin/assets/js/statistic.js +23 -21
- admin/boot.php +9 -9
- admin/includes/classes/class-rio-optimize-template.php +18 -18
- admin/pages/class-rio-license.php +3 -3
- admin/pages/class-rio-log.php +2 -2
- admin/pages/class-rio-page.php +1 -1
- admin/pages/class-rio-settings.php +113 -60
- admin/pages/class-rio-statistic.php +261 -241
- assets/js/jquery.lazy.js +872 -0
- assets/js/jquery.lazy.min.js +2 -0
- assets/js/lazy-load.js +8 -0
- includes/class-rio-plugin.php +177 -170
- includes/classes/class-rio-attachment.php +16 -14
- includes/classes/class-rio-backup.php +1 -3
- includes/classes/class-rio-image-statistic.php +33 -24
- includes/classes/class-rio-lazy-load.php +76 -0
- includes/classes/class-rio-media-library.php +34 -23
- includes/classes/class-rio-optimization-tools.php +2 -10
- includes/classes/class-rio-views.php +4 -4
- includes/classes/processors/class-rio-server-abstract.php +81 -20
- includes/classes/processors/class-rio-server-premium.php +26 -11
- includes/classes/processors/class-rio-server-resmush.php +37 -31
- includes/classes/processors/class-rio-server-robin.php +184 -0
- includes/functions.php +17 -4
- languages/robin-image-optimizer-ru_RU.mo +0 -0
- languages/robin-image-optimizer-ru_RU.po +1234 -800
- libs/addons/admin/assets/js/custom-folders.js +4 -4
- libs/addons/admin/boot.php +1 -1
- libs/addons/admin/filters/settings-page.php +4 -2
- libs/addons/includes/classes/class.folder.php +11 -1
- libs/addons/includes/classes/webp/class-webp-api.php +85 -80
- libs/addons/includes/classes/webp/vendor/autoload.php +7 -7
- libs/addons/includes/classes/webp/vendor/composer/ClassLoader.php +445 -445
- libs/addons/includes/classes/webp/vendor/composer/InstalledVersions.php +220 -0
- libs/addons/includes/classes/webp/vendor/composer/LICENSE +21 -21
- libs/addons/includes/classes/webp/vendor/composer/autoload_classmap.php +10 -9
- libs/addons/includes/classes/webp/vendor/composer/autoload_namespaces.php +9 -9
- libs/addons/includes/classes/webp/vendor/composer/autoload_psr4.php +10 -10
- libs/addons/includes/classes/webp/vendor/composer/autoload_real.php +55 -52
- libs/addons/includes/classes/webp/vendor/composer/autoload_static.php +36 -31
- libs/addons/includes/classes/webp/vendor/composer/installed.json +63 -59
- libs/addons/includes/classes/webp/vendor/composer/installed.php +35 -0
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/.php_cs.dist +19 -19
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/README.md +161 -161
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/composer.json +60 -60
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpstan.neon +3 -3
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src-vendor/simple_html_dom/simple_html_dom.inc +2930 -2930
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php +230 -230
- libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php +202 -202
- libs/addons/readme.txt +2 -3
- libs/addons/robin-image-optimizer-premium.php +1 -1
- libs/addons/views/modal-select-custom-folders.php +1 -1
- libs/addons/views/part-bulk-optimization-table-folders.php +1 -1
- libs/addons/views/part-settings-page-webp-options.php +15 -1
- libs/factory/adverts/boot.php +14 -14
- libs/factory/adverts/includes/class-base.php +6 -6
- libs/factory/adverts/includes/class-dashboard-widget.php +4 -4
- libs/factory/adverts/includes/class-rest-request.php +67 -47
- libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.mo +0 -0
- libs/factory/adverts/langs/wbcr_factory_adverts_109-ru_RU.po +83 -0
- libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.mo +0 -0
- libs/factory/adverts/langs/wbcr_factory_adverts_112-ru_RU.po +83 -0
- libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.mo +0 -0
- libs/factory/adverts/langs/wbcr_factory_adverts_114-ru_RU.po +83 -0
- libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css +1 -1
- libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css +1 -1
- libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css +1 -1
- 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
|
9 |
* @version 1.0
|
10 |
*/
|
11 |
|
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
14 |
exit;
|
15 |
}
|
16 |
|
17 |
-
class WIO_Activation extends
|
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 |
-
|
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 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
$
|
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 |
-
$
|
295 |
-
$
|
296 |
-
$
|
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:
|
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:
|
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.
|
5 |
*
|
6 |
-
* Copyright
|
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 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
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(
|
5 |
|
6 |
-
window.wio_chart = new Chart(
|
7 |
-
type:
|
8 |
data: {
|
9 |
-
datasets: [
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
23 |
},
|
24 |
options: {
|
25 |
legend: {
|
26 |
display: false
|
27 |
},
|
28 |
-
events:
|
29 |
animation: {
|
30 |
easing: 'easeOutBounce'
|
31 |
},
|
32 |
-
responsive:
|
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-
|
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
|
127 |
-
* @param
|
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
|
150 |
*
|
151 |
* @return bool
|
152 |
*/
|
153 |
-
/*add_action('
|
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( '
|
178 |
|
179 |
/**
|
180 |
* Widget with the offer to buy Clearfy Business
|
181 |
*
|
182 |
* @param array $widgets
|
183 |
* @param string $position
|
184 |
-
* @param
|
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
|
324 |
-
* @param
|
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
|
30 |
*
|
31 |
* @throws Exception
|
32 |
*/
|
33 |
|
34 |
-
/*public function showPageContent(
|
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
|
76 |
-
* @type bool
|
77 |
-
* @type string $attach_dimensions
|
78 |
-
* @type int
|
79 |
-
* @type bool
|
80 |
* оптимизации
|
81 |
-
* @type int
|
82 |
-
* @type int
|
83 |
-
* @type int
|
84 |
-
* @type int
|
85 |
-
* @type string $optimization_level
|
86 |
-
* @type string $error_msg
|
87 |
-
* @type bool
|
88 |
-
* @type float
|
89 |
-
* @type float
|
90 |
* }
|
91 |
*
|
92 |
* @return string
|
@@ -209,7 +209,7 @@ class WIO_OptimizePageTemplate {
|
|
209 |
</div>
|
210 |
<!-- .wio-datas-actions-links -->
|
211 |
<?php
|
212 |
-
}
|
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
|
13 |
|
14 |
/**
|
15 |
* {@inheritdoc}
|
@@ -43,9 +43,9 @@ class WRIO_License_Page extends Wbcr_FactoryClearfy217_LicensePage {
|
|
43 |
|
44 |
/**
|
45 |
* {@inheritdoc}
|
46 |
-
* @param
|
47 |
*/
|
48 |
-
public function __construct(
|
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.
|
110 |
},
|
111 |
error: function(jqXHR, textStatus, errorThrown) {
|
112 |
-
jQuery.
|
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
|
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
|
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
|
108 |
-
|
109 |
],
|
110 |
[
|
111 |
'server_2',
|
112 |
-
__( 'Server 2
|
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
|
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-
|
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-
|
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 |
-
|
3 |
-
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
}
|
6 |
-
|
7 |
/**
|
8 |
-
*
|
9 |
-
*
|
10 |
*
|
11 |
-
* @
|
12 |
-
|
13 |
-
|
14 |
-
|
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 |
-
|
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 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
}
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
}
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
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 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
<?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
|
207 |
-
</script>
|
208 |
<?php
|
209 |
-
//
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
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 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
/**
|
8 |
-
*
|
9 |
*
|
10 |
-
*
|
11 |
-
*
|
12 |
-
*
|
|
|
|
|
|
|
|
|
13 |
*/
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
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 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
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 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
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
|
52 |
-
* @param array|false $attachment_meta
|
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
|
686 |
*
|
687 |
* @return string
|
688 |
*/
|
@@ -700,8 +702,8 @@ class WIO_Attachment {
|
|
700 |
/**
|
701 |
* Заменяет оригинальный файл на оптимизированный.
|
702 |
*
|
703 |
-
* @param array
|
704 |
-
* @param string $image_size
|
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
|
807 |
*
|
808 |
* @return string|null
|
809 |
*/
|
@@ -821,7 +823,7 @@ class WIO_Attachment {
|
|
821 |
/**
|
822 |
* Возвращает путь к изображению по указанному размеру.
|
823 |
*
|
824 |
-
* @param string $size
|
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 |
-
* @
|
43 |
* @since 1.3.0
|
44 |
*
|
45 |
-
* @
|
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
|
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
|
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
|
195 |
*
|
196 |
* @return array {
|
197 |
* Параметры
|
198 |
-
* @type string $id
|
199 |
-
* @type string $file_name
|
200 |
-
* @type string $url
|
201 |
-
* @type string $thumbnail_url
|
202 |
-
* @type string $original_size
|
203 |
-
* @type string $optimized_size
|
204 |
-
* @type string $webp_size
|
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 |
-
* @
|
|
|
233 |
* @since 1.3.9
|
234 |
*
|
235 |
-
* @
|
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 |
-
* @
|
33 |
* @since 1.3.0
|
34 |
*
|
35 |
-
* @
|
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
|
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
|
105 |
* @param mixed $attachment_meta
|
106 |
*
|
107 |
* @return WIO_Attachment
|
@@ -117,8 +118,8 @@ class WRIO_Media_Library {
|
|
117 |
/**
|
118 |
* Оптимизирует аттачмент и сохраняет статистику
|
119 |
*
|
120 |
-
* @param int
|
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
|
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 (
|
|
|
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
|
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
|
433 |
-
* @param object $post
|
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
|
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
|
472 |
-
* @param int
|
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
|
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
|
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-
|
40 |
-
self::$image_processor = new
|
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
|
67 |
*
|
68 |
* @return bool|string The page contents. False if the template doesn't exist.
|
69 |
*/
|
70 |
-
public function get_template( $template, $data = [],
|
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
|
96 |
*/
|
97 |
-
public function print_template( $template, $data = [],
|
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
|
56 |
-
* @param string
|
57 |
-
* @param array|string|null $body
|
58 |
-
* @param array
|
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
|
103 |
-
* @param array|false $post_fields
|
104 |
-
* @param array|false $headers
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
|
|
|
|
|
|
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 |
-
'
|
|
|
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:
|
9 |
-
"PO-Revision-Date:
|
10 |
-
"Last-Translator:
|
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.
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
#: admin/
|
37 |
-
msgid "
|
38 |
-
msgstr "
|
39 |
-
|
40 |
-
#: admin/
|
41 |
-
msgid "
|
42 |
-
msgstr ""
|
43 |
-
|
44 |
-
#: admin/
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
"
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
"
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
msgstr "
|
70 |
-
|
71 |
-
#: admin/
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
msgstr "
|
78 |
-
|
79 |
-
#:
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
msgstr ""
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
"
|
114 |
-
"
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
"
|
126 |
-
|
127 |
-
|
128 |
-
#:
|
129 |
-
msgid "
|
130 |
-
msgstr "
|
131 |
-
|
132 |
-
#:
|
133 |
-
msgid "
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
"
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
"
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
"
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
"
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
"
|
164 |
-
|
165 |
-
|
166 |
-
#:
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
#:
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
"
|
183 |
-
|
184 |
-
|
185 |
-
#:
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
#: admin/pages/settings.php:
|
195 |
-
msgid "
|
196 |
-
msgstr ""
|
197 |
-
|
198 |
-
#:
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
"
|
223 |
-
msgstr ""
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
#:
|
237 |
-
msgid ""
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
msgstr ""
|
243 |
-
|
244 |
-
|
245 |
-
"
|
246 |
-
"
|
247 |
-
|
248 |
-
#:
|
249 |
-
msgid "
|
250 |
-
msgstr "
|
251 |
-
|
252 |
-
#:
|
253 |
-
msgid "
|
254 |
-
msgstr ""
|
255 |
-
"
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
"
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
"
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
"
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
"
|
283 |
-
"
|
284 |
-
"
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
msgstr "
|
293 |
-
|
294 |
-
#: admin/
|
295 |
-
msgid ""
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
"
|
300 |
-
|
301 |
-
|
302 |
-
#: admin/
|
303 |
-
msgid "
|
304 |
-
msgstr "
|
305 |
-
|
306 |
-
#: admin/
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
#: admin/
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
#: admin/pages/
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
"
|
359 |
-
msgstr ""
|
360 |
-
|
361 |
-
#: admin/pages/statistic.php:
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
#: admin/
|
376 |
-
msgid "
|
377 |
-
msgstr "
|
378 |
-
|
379 |
-
#: admin/pages/
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
#: admin/
|
401 |
-
msgid "
|
402 |
-
msgstr "
|
403 |
-
|
404 |
-
#: admin/pages/
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
"
|
447 |
-
msgstr ""
|
448 |
-
|
449 |
-
#:
|
450 |
-
msgid "
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
msgstr "
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
#:
|
486 |
-
msgid "
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
"
|
518 |
-
msgstr ""
|
519 |
-
|
520 |
-
#: admin/
|
521 |
-
msgid "
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
"
|
527 |
-
"
|
528 |
-
|
529 |
-
|
530 |
-
"
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
"
|
539 |
-
"
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
#: admin/
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
"
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
msgstr ""
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
msgstr "
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
#:
|
677 |
-
msgid ""
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
#: admin/
|
699 |
-
msgid "
|
700 |
-
msgstr "
|
701 |
-
|
702 |
-
#: admin/
|
703 |
-
msgid "
|
704 |
-
msgstr "
|
705 |
-
|
706 |
-
#: admin/
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
#: admin/
|
723 |
-
msgid "
|
724 |
-
msgstr "
|
725 |
-
|
726 |
-
#: admin/
|
727 |
-
#: admin/
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
msgstr "
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
#: admin/
|
736 |
-
msgid "
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
msgstr "
|
783 |
-
|
784 |
-
|
785 |
-
msgid ""
|
786 |
-
"
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 <img> tags with <picture> 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 <img> will be replaced with a <picture> 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 <picture> 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 <img> 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 = $.
|
90 |
|
91 |
setTimeout(function() {
|
92 |
-
$.
|
93 |
}, 5000);
|
94 |
}
|
95 |
return;
|
@@ -150,10 +150,10 @@
|
|
150 |
if( response.data && response.data.error_message ) {
|
151 |
// todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
|
152 |
// может быть скомпилирован.
|
153 |
-
var noticeId = $.
|
154 |
|
155 |
setTimeout(function() {
|
156 |
-
$.
|
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
|
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 = '
|
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 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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
|
41 |
-
* @see
|
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
|
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 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
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
|
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
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
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 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
"
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
"
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
"
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
"
|
26 |
-
"
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
"
|
37 |
-
"
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
"
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
"
|
54 |
-
|
55 |
-
|
56 |
-
|
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 *<img>* tags with *<picture>* 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: *<img>*, *<source>*, *<input>* and *<iframe>* (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 *<img>* tags with *<picture>* tags
|
124 |
-
|
125 |
-
The *PictureTags::replace($html)* method accepts a piece of HTML and returns HTML where where all <img> tags have been replaced with <picture> 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 *<img>* tags with *<picture>* 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: *<img>*, *<source>*, *<input>* and *<iframe>* (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 *<img>* tags with *<picture>* tags
|
124 |
+
|
125 |
+
The *PictureTags::replace($html)* method accepts a piece of HTML and returns HTML where where all <img> tags have been replaced with <picture> 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:
|
7 |
-
Requires PHP: 5.
|
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.
|
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
|
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
|
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.
|
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\
|
4 |
|
5 |
/**
|
6 |
* Factory Adverts
|
@@ -16,35 +16,35 @@ use WBCR\Factory_Adverts_106\Base;
|
|
16 |
*/
|
17 |
|
18 |
// Exit if accessed directly
|
19 |
-
if
|
20 |
exit;
|
21 |
}
|
22 |
|
23 |
-
if
|
24 |
return;
|
25 |
}
|
26 |
|
27 |
# Устанавливаем константу, что модуль уже загружен
|
28 |
-
define(
|
29 |
|
30 |
# Устанавливаем версию модуля
|
31 |
-
define(
|
32 |
|
33 |
# Регистрируем тектовый домен, для интернализации интерфейса модуля
|
34 |
-
load_plugin_textdomain(
|
35 |
|
36 |
# Устанавливаем директорию модуля
|
37 |
-
define(
|
38 |
|
39 |
# Устанавливаем url модуля
|
40 |
-
define(
|
41 |
|
42 |
-
require_once(
|
43 |
-
require_once(
|
44 |
|
45 |
/**
|
46 |
-
* @param
|
47 |
*/
|
48 |
-
add_action(
|
49 |
-
$plugin->set_adverts_manager(
|
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\
|
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 \
|
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\
|
57 |
*/
|
58 |
private $api;
|
59 |
|
@@ -82,9 +82,9 @@ class Base {
|
|
82 |
*
|
83 |
* @since 1.0.0 Added
|
84 |
*
|
85 |
-
* @param \
|
86 |
*/
|
87 |
-
public function __construct( \
|
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
|
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\
|
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 \
|
39 |
*/
|
40 |
private $plugin;
|
41 |
|
@@ -46,10 +46,10 @@ class Dashboard_Widget {
|
|
46 |
*
|
47 |
* @since 1.0.0 Added
|
48 |
*
|
49 |
-
* @param \
|
50 |
* @param string $content
|
51 |
*/
|
52 |
-
public function __construct( \
|
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\
|
4 |
|
5 |
// Exit if accessed directly
|
6 |
-
if
|
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 \
|
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(
|
|
|
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(
|
97 |
-
|
|
|
98 |
|
99 |
-
if
|
100 |
return $data;
|
101 |
}
|
102 |
|
103 |
-
return strip_tags(
|
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(
|
|
|
123 |
|
124 |
-
if
|
125 |
-
return $this->do_api_request(
|
126 |
}
|
127 |
|
128 |
-
$key = $this->plugin->getPrefix() . md5(
|
|
|
|
|
|
|
|
|
129 |
|
130 |
-
$cached = get_transient(
|
131 |
|
132 |
-
if
|
133 |
-
if
|
134 |
-
return new \WP_Error(
|
135 |
}
|
136 |
-
|
137 |
return $cached;
|
138 |
}
|
139 |
|
140 |
-
$data = $this->do_api_request(
|
141 |
|
142 |
-
if
|
143 |
-
set_transient(
|
144 |
-
'error'
|
145 |
'error_code' => $data->get_error_code()
|
146 |
-
], self::SERVER_UNAVAILABLE_INTERVAL * HOUR_IN_SECONDS
|
147 |
|
148 |
return $data;
|
149 |
}
|
150 |
-
|
151 |
-
set_transient(
|
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(
|
|
|
172 |
$default_result = [
|
173 |
'content' => '',
|
174 |
'expires' => self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS,
|
175 |
];
|
176 |
|
177 |
-
$url = untrailingslashit(
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
-
$response = wp_remote_get(
|
181 |
|
182 |
-
$code = wp_remote_retrieve_response_code(
|
183 |
-
$body = wp_remote_retrieve_body(
|
184 |
|
185 |
-
$data = @json_decode(
|
186 |
|
187 |
-
if
|
188 |
return $response;
|
189 |
}
|
190 |
|
191 |
-
if
|
192 |
-
return new \WP_Error(
|
193 |
}
|
194 |
|
195 |
-
return wp_parse_args(
|
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-
|
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-
|
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-
|
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 |
|
|