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

Version Description

  • Errors fixes
Download this release

Release Info

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

Code changes from version 1.5.3 to 1.5.6

Files changed (53) hide show
  1. admin/activation.php +93 -93
  2. admin/ajax/backup.php +103 -103
  3. admin/ajax/bulk-optimization.php +0 -356
  4. admin/ajax/index.php +2 -2
  5. admin/ajax/logs.php +23 -23
  6. admin/ajax/meta-migrations.php +174 -174
  7. admin/ajax/multisite-update-current-blog.php +29 -29
  8. admin/ajax/settings.php +37 -37
  9. admin/assets/css/base-statistic.css +33 -14
  10. admin/assets/css/base-statistic.less +913 -888
  11. admin/assets/css/index.php +2 -2
  12. admin/assets/css/media.css +215 -215
  13. admin/assets/css/settings-premium.css +17 -17
  14. admin/assets/css/statistic.css +410 -410
  15. admin/assets/css/sweetalert-custom.css +155 -155
  16. admin/assets/css/sweetalert-custom.less +185 -185
  17. admin/assets/css/sweetalert2.css +716 -716
  18. admin/assets/img/index.php +2 -2
  19. admin/assets/index.php +2 -2
  20. admin/assets/js/Chart.min.js +10 -10
  21. admin/assets/js/bulk-conversion.js +393 -0
  22. admin/assets/js/bulk-optimization.js +639 -633
  23. admin/assets/js/index.php +2 -2
  24. admin/assets/js/meta-migrations.js +52 -52
  25. admin/assets/js/modals.js +59 -59
  26. admin/assets/js/restore-backup.js +162 -162
  27. admin/assets/js/settings-premium.js +2 -2
  28. admin/assets/js/single-optimization.js +101 -64
  29. admin/assets/js/statistic.js +76 -38
  30. admin/assets/js/sweetalert2.js +1641 -1641
  31. admin/boot.php +347 -347
  32. admin/includes/classes/class-rio-nextgen-landing.php +61 -61
  33. admin/includes/classes/class-rio-optimize-template.php +263 -226
  34. admin/includes/classes/index.php +2 -2
  35. admin/includes/index.php +2 -2
  36. admin/includes/sidebar-widgets.php +83 -83
  37. admin/index.php +2 -2
  38. admin/pages/class-rio-license.php +125 -125
  39. admin/pages/class-rio-log.php +100 -100
  40. admin/pages/class-rio-page.php +83 -83
  41. admin/pages/class-rio-settings.php +625 -620
  42. admin/pages/class-rio-statistic.php +306 -279
  43. admin/pages/index.php +2 -2
  44. assets/js/jquery.lazy.js +0 -872
  45. assets/js/jquery.lazy.min.js +0 -2
  46. assets/js/lazy-load.js +11 -11
  47. assets/js/lozad.min.js +9 -9
  48. includes/class-rio-plugin.php +212 -209
  49. includes/classes/class-rio-attachment.php +1009 -992
  50. includes/classes/class-rio-backup.php +535 -535
  51. includes/classes/class-rio-bulk-optimization.php +664 -461
  52. includes/classes/class-rio-cron.php +190 -148
  53. includes/classes/class-rio-image-statistic.php +78 -411
admin/activation.php CHANGED
@@ -1,93 +1,93 @@
1
- <?php
2
-
3
- /**
4
- * Activator for the Robin image optimizer
5
- *
6
- * @author Webcraftic <wordpress.webraftic@gmail.com>
7
- * @copyright (c) 09.09.2017, Webcraftic
8
- * @see Factory446_Activator
9
- * @version 1.0
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- class WIO_Activation extends Wbcr_Factory446_Activator {
18
-
19
- /**
20
- * Runs activation actions.
21
- *
22
- * @since 1.0.0
23
- * @throws \Exception
24
- */
25
- public function activate() {
26
- WRIO_Plugin::app()->logger->info( 'Parent plugin start installation!' );
27
-
28
- WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', 'server_1' );
29
- WRIO_Plugin::app()->updatePopulateOption( 'backup_origin_images', 1 );
30
- WRIO_Plugin::app()->updatePopulateOption( 'save_exif_data', 1 );
31
-
32
- if ( function_exists( 'wrio_is_license_activate' ) && wrio_is_license_activate() ) {
33
- WRIO_Plugin::app()->logger->info( 'Premium plugin start installation!' );
34
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
35
- wrio_premium_activate();
36
- WRIO_Plugin::app()->logger->info( 'Premium plugin installation complete!' );
37
- }
38
-
39
- $db_version = RIO_Process_Queue::get_db_version();
40
- $plugin_version_in_db = $this->get_plugin_version_in_db();
41
- $current_plugin_version = $this->plugin->getPluginVersion();
42
-
43
- $create_table_log_message = "Plugin installation: try create plugin tables.\r\n";
44
- $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-DB Version: {$db_version}\r\n";
45
- $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Plugin Version in DB: {$plugin_version_in_db}\r\n";
46
- $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Current Plugin Version: {$current_plugin_version}";
47
-
48
- WRIO_Plugin::app()->logger->info( $create_table_log_message );
49
-
50
- RIO_Process_Queue::try_create_plugin_tables();
51
-
52
- WbcrFactoryClearfy237_Helpers::flushPageCache();
53
-
54
- WRIO_Plugin::app()->logger->info( 'Parent plugin installation complete!' );
55
- }
56
-
57
- /**
58
- * Get previous plugin version
59
- *
60
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
61
- * @since 1.3.8
62
- * @return number
63
- */
64
- public function get_plugin_version_in_db() {
65
- if ( WRIO_Plugin::app()->isNetworkActive() ) {
66
- return get_site_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
67
- }
68
-
69
- return get_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
70
- }
71
-
72
- /**
73
- * Runs activation actions.
74
- *
75
- * @since 1.0.0
76
- */
77
- public function deactivate() {
78
- WRIO_Plugin::app()->logger->info( 'Parent plugin start deactivation!' );
79
-
80
- if ( class_exists( 'WRIO_Cron' ) ) {
81
- WRIO_Cron::stop();
82
- }
83
-
84
- if ( function_exists( 'wrio_is_license_activate' ) && wrio_is_license_activate() ) {
85
- WRIO_Plugin::app()->logger->info( 'Premium plugin start deactivation!' );
86
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
87
- wrio_premium_deactivate();
88
- WRIO_Plugin::app()->logger->info( 'Premium plugin deactivation complete!' );
89
- }
90
-
91
- WRIO_Plugin::app()->logger->info( 'Parent plugin deactivation complete!' );
92
- }
93
- }
1
+ <?php
2
+
3
+ /**
4
+ * Activator for the Robin image optimizer
5
+ *
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
7
+ * @copyright (c) 09.09.2017, Webcraftic
8
+ * @see Factory450_Activator
9
+ * @version 1.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ class WIO_Activation extends Wbcr_Factory450_Activator {
18
+
19
+ /**
20
+ * Runs activation actions.
21
+ *
22
+ * @since 1.0.0
23
+ * @throws \Exception
24
+ */
25
+ public function activate() {
26
+ WRIO_Plugin::app()->logger->info( 'Parent plugin start installation!' );
27
+
28
+ WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', 'server_1' );
29
+ WRIO_Plugin::app()->updatePopulateOption( 'backup_origin_images', 1 );
30
+ WRIO_Plugin::app()->updatePopulateOption( 'save_exif_data', 1 );
31
+
32
+ if ( function_exists( 'wrio_is_license_activate' ) && wrio_is_license_activate() ) {
33
+ WRIO_Plugin::app()->logger->info( 'Premium plugin start installation!' );
34
+ require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
35
+ wrio_premium_activate();
36
+ WRIO_Plugin::app()->logger->info( 'Premium plugin installation complete!' );
37
+ }
38
+
39
+ $db_version = RIO_Process_Queue::get_db_version();
40
+ $plugin_version_in_db = $this->get_plugin_version_in_db();
41
+ $current_plugin_version = $this->plugin->getPluginVersion();
42
+
43
+ $create_table_log_message = "Plugin installation: try create plugin tables.\r\n";
44
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-DB Version: {$db_version}\r\n";
45
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Plugin Version in DB: {$plugin_version_in_db}\r\n";
46
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Current Plugin Version: {$current_plugin_version}";
47
+
48
+ WRIO_Plugin::app()->logger->info( $create_table_log_message );
49
+
50
+ RIO_Process_Queue::try_create_plugin_tables();
51
+
52
+ WBCR\Factory_Templates_102\Helpers::flushPageCache();
53
+
54
+ WRIO_Plugin::app()->logger->info( 'Parent plugin installation complete!' );
55
+ }
56
+
57
+ /**
58
+ * Get previous plugin version
59
+ *
60
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
61
+ * @since 1.3.8
62
+ * @return number
63
+ */
64
+ public function get_plugin_version_in_db() {
65
+ if ( WRIO_Plugin::app()->isNetworkActive() ) {
66
+ return get_site_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
67
+ }
68
+
69
+ return get_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
70
+ }
71
+
72
+ /**
73
+ * Runs activation actions.
74
+ *
75
+ * @since 1.0.0
76
+ */
77
+ public function deactivate() {
78
+ WRIO_Plugin::app()->logger->info( 'Parent plugin start deactivation!' );
79
+
80
+ if ( class_exists( 'WRIO_Cron' ) ) {
81
+ WRIO_Cron::stop();
82
+ }
83
+
84
+ if ( function_exists( 'wrio_is_license_activate' ) && wrio_is_license_activate() ) {
85
+ WRIO_Plugin::app()->logger->info( 'Premium plugin start deactivation!' );
86
+ require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
87
+ wrio_premium_deactivate();
88
+ WRIO_Plugin::app()->logger->info( 'Premium plugin deactivation complete!' );
89
+ }
90
+
91
+ WRIO_Plugin::app()->logger->info( 'Parent plugin deactivation complete!' );
92
+ }
93
+ }
admin/ajax/backup.php CHANGED
@@ -1,103 +1,103 @@
1
- <?php
2
- /**
3
- * Back-up related filters.
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright (c) 2018 Webraftic Ltd
7
- * @version 1.0
8
- */
9
-
10
- // Exit if accessed directly
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
-
15
- /**
16
- * AJAX обработчик восстановления из резервной копии
17
- */
18
- add_action( 'wp_ajax_wio_restore_backup', function () {
19
- check_admin_referer( 'wio-iph' );
20
-
21
- if ( ! current_user_can( 'manage_options' ) ) {
22
- wp_die( - 1 );
23
- }
24
-
25
- $max_process_per_request = 25;
26
-
27
- //$blog_id = WRIO_Plugin::app()->request->post( 'blog_id', null, true );
28
-
29
- /*if ( $blog_id !== null ) {
30
- switch_to_blog( $blog_id );
31
- }*/
32
-
33
- // Total number of remained images to restore
34
- $remane_count = 0;
35
-
36
- $total = 0;
37
-
38
- $filter_results = apply_filters( 'wbcr/rio/backup/restore_filter', $max_process_per_request );
39
-
40
- if ( isset( $filter_results['remane'] ) ) {
41
- $remane_count += $filter_results['remane'];
42
- }
43
-
44
- if ( isset( $filter_results['total'] ) ) {
45
- $total += $filter_results['total'];
46
- }
47
-
48
- $media_library = WRIO_Media_Library::get_instance();
49
-
50
- $total += $media_library->getOptimizedCount();
51
-
52
- $restored_data = $media_library->restoreAllFromBackup( $max_process_per_request );
53
-
54
- if ( isset( $restored_data['remain'] ) ) {
55
- $remane_count += $restored_data['remain'];
56
- }
57
-
58
- /*if ( $blog_id !== null ) {
59
- restore_current_blog();
60
- }*/
61
-
62
- $restored_data['total'] = $total;
63
-
64
- if ( $total > 0 ) {
65
- $restored_data['percent'] = 100 - ( $remane_count * 100 / $total );
66
- } else {
67
- $restored_data['percent'] = 0;
68
- }
69
-
70
- // если изображения закончились - посылаем команду завершения
71
- if ( $remane_count <= 0 ) {
72
- $restored_data['end'] = true;
73
- }
74
-
75
- wp_send_json( $restored_data );
76
- } );
77
-
78
- /**
79
- * AJAX обработчик очистки папки с бекапами
80
- */
81
- add_action( 'wp_ajax_wio_clear_backup', function () {
82
- check_admin_referer( 'wio-iph' );
83
-
84
- if ( ! current_user_can( 'manage_options' ) ) {
85
- wp_die( - 1 );
86
- }
87
-
88
- $backup = WIO_Backup::get_instance();
89
- $blogs = WRIO_Plugin::app()->request->post( 'blogs', [], true );
90
-
91
- if ( ! empty( $blogs ) ) {
92
- foreach ( $blogs as $blog_id ) {
93
- switch_to_blog( intval( $blog_id ) );
94
- $backup->removeBlogBackupDir();
95
- restore_current_blog();
96
- }
97
- } else {
98
- $backup->removeBackupDir();
99
- }
100
-
101
- wp_send_json( true );
102
- } );
103
-
1
+ <?php
2
+ /**
3
+ * Back-up related filters.
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright (c) 2018 Webraftic Ltd
7
+ * @version 1.0
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * AJAX обработчик восстановления из резервной копии
17
+ */
18
+ add_action( 'wp_ajax_wio_restore_backup', function () {
19
+ check_admin_referer( 'wio-iph' );
20
+
21
+ if ( ! current_user_can( 'manage_options' ) ) {
22
+ wp_die( - 1 );
23
+ }
24
+
25
+ $max_process_per_request = 25;
26
+
27
+ //$blog_id = WRIO_Plugin::app()->request->post( 'blog_id', null, true );
28
+
29
+ /*if ( $blog_id !== null ) {
30
+ switch_to_blog( $blog_id );
31
+ }*/
32
+
33
+ // Total number of remained images to restore
34
+ $remane_count = 0;
35
+
36
+ $total = 0;
37
+
38
+ $filter_results = apply_filters( 'wbcr/rio/backup/restore_filter', $max_process_per_request );
39
+
40
+ if ( isset( $filter_results['remane'] ) ) {
41
+ $remane_count += $filter_results['remane'];
42
+ }
43
+
44
+ if ( isset( $filter_results['total'] ) ) {
45
+ $total += $filter_results['total'];
46
+ }
47
+
48
+ $media_library = WRIO_Media_Library::get_instance();
49
+
50
+ $total += $media_library->getOptimizedCount();
51
+
52
+ $restored_data = $media_library->restoreAllFromBackup( $max_process_per_request );
53
+
54
+ if ( isset( $restored_data['remain'] ) ) {
55
+ $remane_count += $restored_data['remain'];
56
+ }
57
+
58
+ /*if ( $blog_id !== null ) {
59
+ restore_current_blog();
60
+ }*/
61
+
62
+ $restored_data['total'] = $total;
63
+
64
+ if ( $total > 0 ) {
65
+ $restored_data['percent'] = 100 - ( $remane_count * 100 / $total );
66
+ } else {
67
+ $restored_data['percent'] = 0;
68
+ }
69
+
70
+ // если изображения закончились - посылаем команду завершения
71
+ if ( $remane_count <= 0 ) {
72
+ $restored_data['end'] = true;
73
+ }
74
+
75
+ wp_send_json( $restored_data );
76
+ } );
77
+
78
+ /**
79
+ * AJAX обработчик очистки папки с бекапами
80
+ */
81
+ add_action( 'wp_ajax_wio_clear_backup', function () {
82
+ check_admin_referer( 'wio-iph' );
83
+
84
+ if ( ! current_user_can( 'manage_options' ) ) {
85
+ wp_die( - 1 );
86
+ }
87
+
88
+ $backup = WIO_Backup::get_instance();
89
+ $blogs = WRIO_Plugin::app()->request->post( 'blogs', [], true );
90
+
91
+ if ( ! empty( $blogs ) ) {
92
+ foreach ( $blogs as $blog_id ) {
93
+ switch_to_blog( intval( $blog_id ) );
94
+ $backup->removeBlogBackupDir();
95
+ restore_current_blog();
96
+ }
97
+ } else {
98
+ $backup->removeBackupDir();
99
+ }
100
+
101
+ wp_send_json( true );
102
+ } );
103
+
admin/ajax/bulk-optimization.php DELETED
@@ -1,356 +0,0 @@
1
- <?php
2
- /**
3
- * @author Webcraftic <wordpress.webraftic@gmail.com>
4
- * @copyright (c) 2018 Webraftic Ltd
5
- * @version 1.0
6
- */
7
-
8
- // Exit if accessed directly
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Cron start
15
- */
16
- add_action( 'wp_ajax_wrio-cron-start', function () {
17
- check_ajax_referer( 'bulk_optimization' );
18
-
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
-
42
- /**
43
- * Cron stop
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
-
58
- /**
59
- * AJAX обработчик массовой оптимизации изображений со страницы статистики
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';
86
- } else if ( 'custom-folders' === $scope ) {
87
- $class_name = 'WRIO_Custom_Folders';
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.
100
- *
101
- * @see WRIO_Media_Library
102
- * @see WRIO_Custom_Folders
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
-
141
- /**
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
- } );
174
-
175
- /**
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
- } );
196
-
197
- /**
198
- * На странице массовой оптмизации есть поле для выбора сервера. Когда пользователь
199
- * выберет какой-то сервер, выполняется этот ajax обработчик. Обработчик пингует выбранный
200
- * пользователем сервер и возвращает статус пинга (если пинг успешен, то сервер переход в
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';
241
- $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
242
- $headers['PluginId'] = wrio_get_freemius_plugin_id();
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
-
269
- /**
270
- * На странице массовой оптмизации есть поле для выбора сервера. Когда пользователь
271
- * выберет какой-то сервер, выполняется этот ajax обработчик. Обработчик пингует выбранный
272
- * пользователем сервер и возвращает статус пинга (если пинг успешен, то сервер переход в
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 ) {
326
- $error_data = @json_decode( $response_body );
327
- $return_data['error'] = $error_data->message;
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
- $output = ['balance' => $current_quota];
348
-
349
- if ( $optimization_server == 'server_5') {
350
- $reset_at = (int) $data->response->reset_at;
351
- $reset_at += (int) get_option('gmt_offset', 0);
352
- $output['reset_at'] = date('d-m-Y H:i', $reset_at);
353
- }
354
-
355
- wp_send_json_success( $output );
356
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/ajax/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/ajax/logs.php CHANGED
@@ -1,24 +1,24 @@
1
- <?php
2
-
3
- /**
4
- * Used to clean-up logs.
5
- */
6
- add_action( 'wp_ajax_wrio_logs_cleanup', function () {
7
- check_admin_referer( 'wrio_clean_logs', 'nonce' );
8
-
9
- if ( ! current_user_can( 'manage_options' ) ) {
10
- wp_die( - 1 );
11
- }
12
-
13
- if ( ! WRIO_Plugin::app()->logger->clean_up() ) {
14
- wp_send_json_error( [
15
- 'message' => esc_html__( 'Failed to clean-up logs. Please try again later.', 'robin-image-optimizer' ),
16
- 'type' => 'danger',
17
- ] );
18
- }
19
-
20
- wp_send_json( [
21
- 'message' => esc_html__( 'Logs clean-up successfully', 'robin-image-optimizer' ),
22
- 'type' => 'success',
23
- ] );
24
  } );
1
+ <?php
2
+
3
+ /**
4
+ * Used to clean-up logs.
5
+ */
6
+ add_action( 'wp_ajax_wrio_logs_cleanup', function () {
7
+ check_admin_referer( 'wrio_clean_logs', 'nonce' );
8
+
9
+ if ( ! current_user_can( 'manage_options' ) ) {
10
+ wp_die( - 1 );
11
+ }
12
+
13
+ if ( ! WRIO_Plugin::app()->logger->clean_up() ) {
14
+ wp_send_json_error( [
15
+ 'message' => esc_html__( 'Failed to clean-up logs. Please try again later.', 'robin-image-optimizer' ),
16
+ 'type' => 'danger',
17
+ ] );
18
+ }
19
+
20
+ wp_send_json( [
21
+ 'message' => esc_html__( 'Logs clean-up successfully', 'robin-image-optimizer' ),
22
+ 'type' => 'success',
23
+ ] );
24
  } );
admin/ajax/meta-migrations.php CHANGED
@@ -1,174 +1,174 @@
1
- <?php
2
- /**
3
- * Ajax action to migrate old architecture based on post meta into new table.
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @author Alexander Teshabaev <sasha.tesh@gmail.com>
7
- * @see RIO_Process_Queue for further information.
8
- *
9
- * @copyright (c) 2018 Webraftic Ltd
10
- * @version 1.0
11
- */
12
-
13
- // Exit if accessed directly
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- exit;
16
- }
17
-
18
- add_action( 'wp_ajax_wrio_meta_migrations', 'wbcr_rio_migrate_postmeta_to_process_queue' );
19
-
20
- /**
21
- * Migrating postmeta to newly created table.
22
- *
23
- * @author Alexander Teshabaev <sasha.tesh@gmail.com>
24
- * @since 1.3.0
25
- * @see RIO_Process_Queue as referce for new table.
26
- */
27
- function wbcr_rio_migrate_postmeta_to_process_queue() {
28
- global $wpdb;
29
-
30
- check_admin_referer( 'wrio-meta-migrations' );
31
-
32
- if ( ! current_user_can( 'manage_options' ) ) {
33
- wp_die( - 1 );
34
- }
35
-
36
- $error = (int) WRIO_Plugin::app()->request->post( 'error', 0 );
37
-
38
- if ( $error ) {
39
- WRIO_Plugin::app()->logger->error( 'Previous migration was not completed due to an error.' );
40
- }
41
-
42
- $limit = (int) WRIO_Plugin::app()->request->post( 'limit', 150 );
43
-
44
- $processed_items = 0;
45
-
46
- WRIO_Plugin::app()->logger->info( 'Start meta migration. Limit ' . $limit );
47
- WRIO_Plugin::app()->logger->memory_usage();
48
-
49
- $attachments = wbcr_rio_get_meta_to_migrate();
50
-
51
- if ( isset( $attachments->posts ) && ( $attachments_total = count( $attachments->posts ) ) > 0 ) {
52
-
53
- if ( $attachments_total < $limit ) {
54
- $limit = $attachments_total;
55
- }
56
-
57
- WRIO_Plugin::app()->logger->info( 'Finded ' . $attachments_total . ' attachments for migration.' );
58
-
59
- if ( function_exists( 'wp_raise_memory_limit' ) ) {
60
- wp_raise_memory_limit( 'image' );
61
- }
62
-
63
- WRIO_Plugin::app()->logger->memory_usage();
64
-
65
- /**
66
- * @var WP_Post $attachment
67
- */
68
- for ( $i = 0; $i < $limit; $i ++ ) {
69
- $attachment = $attachments->posts[ $i ];
70
- $post_meta = get_post_custom( $attachment->ID );
71
-
72
- $extra_data = new RIO_Attachment_Extra_Data();
73
-
74
- $is_backed_up = false;
75
- $original_size = 0;
76
- $final_size = 0;
77
-
78
- if ( isset( $post_meta['wio_backuped'][0] ) && $post_meta['wio_backuped'][0] ) {
79
- $is_backed_up = true;
80
- }
81
-
82
- if ( isset( $post_meta['wio_thumbnails_count'][0] ) ) {
83
- $extra_data->set_thumbnails_count( intval( $post_meta['wio_thumbnails_count'][0] ) );
84
- }
85
-
86
- if ( isset( $post_meta['wio_original_size'][0] ) ) {
87
- $original_size = intval( $post_meta['wio_original_size'][0] );
88
- }
89
-
90
- if ( isset( $post_meta['wio_optimized_size'][0] ) ) {
91
- $final_size = intval( $post_meta['wio_optimized_size'][0] );
92
- }
93
-
94
- if ( isset( $post_meta['wio_original_main_size'][0] ) ) {
95
- $extra_data->set_original_main_size( intval( $post_meta['wio_original_main_size'][0] ) );
96
- }
97
-
98
- if ( isset( $post_meta['wio_error'][0] ) ) {
99
- $extra_data->set_error( 'optimization' );
100
- $extra_data->set_error_msg( $post_meta['wio_error'][0] );
101
- }
102
-
103
- $level = 'normal';
104
-
105
- if ( isset( $post_meta['wio_optimization_level'][0] ) && ! empty( $post_meta['wio_optimization_level'][0] ) ) {
106
- $level = $post_meta['wio_optimization_level'][0];
107
- }
108
-
109
- $data = [
110
- 'server_id' => null,
111
- 'object_id' => $attachment->ID,
112
- 'object_name' => $wpdb->posts,
113
- 'item_type' => 'attachment',
114
- 'result_status' => ! $final_size ? 'error' : 'success',
115
- 'processing_level' => $level,
116
- 'is_backed_up' => $is_backed_up,
117
- 'original_size' => $original_size,
118
- 'final_size' => $final_size,
119
- 'original_mime_type' => $attachment->post_mime_type,
120
- 'final_mime_type' => $attachment->post_mime_type,
121
- 'extra_data' => (string) $extra_data,
122
- 'created_at' => time(),
123
- ];
124
-
125
- $format = [
126
- '%s',
127
- '%d',
128
- '%s',
129
- '%s',
130
- '%s',
131
- '%s',
132
- '%d',
133
- '%d',
134
- '%d',
135
- '%s',
136
- '%s',
137
- '%s',
138
- '%d',
139
- ];
140
-
141
- $rows_inserted = $wpdb->insert( RIO_Process_Queue::table_name(), $data, $format );
142
-
143
- if ( $rows_inserted > 0 ) {
144
- $processed_items ++;
145
-
146
- $attachment_id = absint( $attachment->ID );
147
- $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE post_id='{$attachment_id}' AND meta_key LIKE 'wio_%'" );
148
- }
149
- }
150
-
151
- $left_items = $attachments_total - $processed_items;
152
- $message = sprintf( __( 'left to migrate: %s items', 'robin-image-optimizer' ), $left_items );
153
- $need_more_time = true;
154
-
155
- WRIO_Plugin::app()->logger->info( 'Succefull migrated ' . $processed_items . ' items.' );
156
- } else {
157
- WRIO_Plugin::app()->logger->info( 'Succefull migrated all items. Finishing-up...' );
158
-
159
- // Assumed to be 2 after 010105.php migration
160
- RIO_Process_Queue::update_db_version( 2 );
161
-
162
- $need_more_time = false;
163
- $message = __( 'Finishing-up...', 'robin-image-optimizer' );
164
- }
165
-
166
- WRIO_Plugin::app()->logger->memory_usage();
167
-
168
- wp_send_json_success( [
169
- 'need_more_time' => $need_more_time,
170
- 'message' => $message,
171
- ] );
172
- }
173
-
174
-
1
+ <?php
2
+ /**
3
+ * Ajax action to migrate old architecture based on post meta into new table.
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @author Alexander Teshabaev <sasha.tesh@gmail.com>
7
+ * @see RIO_Process_Queue for further information.
8
+ *
9
+ * @copyright (c) 2018 Webraftic Ltd
10
+ * @version 1.0
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit;
16
+ }
17
+
18
+ add_action( 'wp_ajax_wrio_meta_migrations', 'wbcr_rio_migrate_postmeta_to_process_queue' );
19
+
20
+ /**
21
+ * Migrating postmeta to newly created table.
22
+ *
23
+ * @author Alexander Teshabaev <sasha.tesh@gmail.com>
24
+ * @since 1.3.0
25
+ * @see RIO_Process_Queue as referce for new table.
26
+ */
27
+ function wbcr_rio_migrate_postmeta_to_process_queue() {
28
+ global $wpdb;
29
+
30
+ check_admin_referer( 'wrio-meta-migrations' );
31
+
32
+ if ( ! current_user_can( 'manage_options' ) ) {
33
+ wp_die( - 1 );
34
+ }
35
+
36
+ $error = (int) WRIO_Plugin::app()->request->post( 'error', 0 );
37
+
38
+ if ( $error ) {
39
+ WRIO_Plugin::app()->logger->error( 'Previous migration was not completed due to an error.' );
40
+ }
41
+
42
+ $limit = (int) WRIO_Plugin::app()->request->post( 'limit', 150 );
43
+
44
+ $processed_items = 0;
45
+
46
+ WRIO_Plugin::app()->logger->info( 'Start meta migration. Limit ' . $limit );
47
+ WRIO_Plugin::app()->logger->memory_usage();
48
+
49
+ $attachments = wbcr_rio_get_meta_to_migrate();
50
+
51
+ if ( isset( $attachments->posts ) && ( $attachments_total = count( $attachments->posts ) ) > 0 ) {
52
+
53
+ if ( $attachments_total < $limit ) {
54
+ $limit = $attachments_total;
55
+ }
56
+
57
+ WRIO_Plugin::app()->logger->info( 'Finded ' . $attachments_total . ' attachments for migration.' );
58
+
59
+ if ( function_exists( 'wp_raise_memory_limit' ) ) {
60
+ wp_raise_memory_limit( 'image' );
61
+ }
62
+
63
+ WRIO_Plugin::app()->logger->memory_usage();
64
+
65
+ /**
66
+ * @var WP_Post $attachment
67
+ */
68
+ for ( $i = 0; $i < $limit; $i ++ ) {
69
+ $attachment = $attachments->posts[ $i ];
70
+ $post_meta = get_post_custom( $attachment->ID );
71
+
72
+ $extra_data = new RIO_Attachment_Extra_Data();
73
+
74
+ $is_backed_up = false;
75
+ $original_size = 0;
76
+ $final_size = 0;
77
+
78
+ if ( isset( $post_meta['wio_backuped'][0] ) && $post_meta['wio_backuped'][0] ) {
79
+ $is_backed_up = true;
80
+ }
81
+
82
+ if ( isset( $post_meta['wio_thumbnails_count'][0] ) ) {
83
+ $extra_data->set_thumbnails_count( intval( $post_meta['wio_thumbnails_count'][0] ) );
84
+ }
85
+
86
+ if ( isset( $post_meta['wio_original_size'][0] ) ) {
87
+ $original_size = intval( $post_meta['wio_original_size'][0] );
88
+ }
89
+
90
+ if ( isset( $post_meta['wio_optimized_size'][0] ) ) {
91
+ $final_size = intval( $post_meta['wio_optimized_size'][0] );
92
+ }
93
+
94
+ if ( isset( $post_meta['wio_original_main_size'][0] ) ) {
95
+ $extra_data->set_original_main_size( intval( $post_meta['wio_original_main_size'][0] ) );
96
+ }
97
+
98
+ if ( isset( $post_meta['wio_error'][0] ) ) {
99
+ $extra_data->set_error( 'optimization' );
100
+ $extra_data->set_error_msg( $post_meta['wio_error'][0] );
101
+ }
102
+
103
+ $level = 'normal';
104
+
105
+ if ( isset( $post_meta['wio_optimization_level'][0] ) && ! empty( $post_meta['wio_optimization_level'][0] ) ) {
106
+ $level = $post_meta['wio_optimization_level'][0];
107
+ }
108
+
109
+ $data = [
110
+ 'server_id' => null,
111
+ 'object_id' => $attachment->ID,
112
+ 'object_name' => $wpdb->posts,
113
+ 'item_type' => 'attachment',
114
+ 'result_status' => ! $final_size ? 'error' : 'success',
115
+ 'processing_level' => $level,
116
+ 'is_backed_up' => $is_backed_up,
117
+ 'original_size' => $original_size,
118
+ 'final_size' => $final_size,
119
+ 'original_mime_type' => $attachment->post_mime_type,
120
+ 'final_mime_type' => $attachment->post_mime_type,
121
+ 'extra_data' => (string) $extra_data,
122
+ 'created_at' => time(),
123
+ ];
124
+
125
+ $format = [
126
+ '%s',
127
+ '%d',
128
+ '%s',
129
+ '%s',
130
+ '%s',
131
+ '%s',
132
+ '%d',
133
+ '%d',
134
+ '%d',
135
+ '%s',
136
+ '%s',
137
+ '%s',
138
+ '%d',
139
+ ];
140
+
141
+ $rows_inserted = $wpdb->insert( RIO_Process_Queue::table_name(), $data, $format );
142
+
143
+ if ( $rows_inserted > 0 ) {
144
+ $processed_items ++;
145
+
146
+ $attachment_id = absint( $attachment->ID );
147
+ $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE post_id='{$attachment_id}' AND meta_key LIKE 'wio_%'" );
148
+ }
149
+ }
150
+
151
+ $left_items = $attachments_total - $processed_items;
152
+ $message = sprintf( __( 'left to migrate: %s items', 'robin-image-optimizer' ), $left_items );
153
+ $need_more_time = true;
154
+
155
+ WRIO_Plugin::app()->logger->info( 'Succefull migrated ' . $processed_items . ' items.' );
156
+ } else {
157
+ WRIO_Plugin::app()->logger->info( 'Succefull migrated all items. Finishing-up...' );
158
+
159
+ // Assumed to be 2 after 010105.php migration
160
+ RIO_Process_Queue::update_db_version( 2 );
161
+
162
+ $need_more_time = false;
163
+ $message = __( 'Finishing-up...', 'robin-image-optimizer' );
164
+ }
165
+
166
+ WRIO_Plugin::app()->logger->memory_usage();
167
+
168
+ wp_send_json_success( [
169
+ 'need_more_time' => $need_more_time,
170
+ 'message' => $message,
171
+ ] );
172
+ }
173
+
174
+
admin/ajax/multisite-update-current-blog.php CHANGED
@@ -1,29 +1,29 @@
1
- <?php
2
- /**
3
- * Ajax действие, которое выполняется для смены текущего multisite блога
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright (c) 2018 Webraftic Ltd
7
- * @version 1.0
8
- */
9
-
10
- // Exit if accessed directly
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
-
15
- /*add_action( 'wp_ajax_wbcr_rio_update_current_blog', function () {
16
- check_ajax_referer( 'update_blog_id', 'wpnonce' );
17
- $blog_id = (int) WRIO_Plugin::app()->request->post( 'current_blog_id' );
18
- $context = sanitize_text_field( WRIO_Plugin::app()->request->post( 'context' ) );
19
- WRIO_Plugin::app()->updatePopulateOption( 'current_blog', $blog_id );
20
- $image_statistics = WIO_OptimizationTools::getImageStatistics( $context );
21
-
22
- switch_to_blog( $blog_id );
23
- $statistic_data = $image_statistics->load();
24
- restore_current_blog();
25
-
26
- wp_send_json_success( array(
27
- 'statistic' => $statistic_data,
28
- ) );
29
- } );*/
1
+ <?php
2
+ /**
3
+ * Ajax действие, которое выполняется для смены текущего multisite блога
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright (c) 2018 Webraftic Ltd
7
+ * @version 1.0
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /*add_action( 'wp_ajax_wbcr_rio_update_current_blog', function () {
16
+ check_ajax_referer( 'update_blog_id', 'wpnonce' );
17
+ $blog_id = (int) WRIO_Plugin::app()->request->post( 'current_blog_id' );
18
+ $context = sanitize_text_field( WRIO_Plugin::app()->request->post( 'context' ) );
19
+ WRIO_Plugin::app()->updatePopulateOption( 'current_blog', $blog_id );
20
+ $image_statistics = WIO_OptimizationTools::getImageStatistics( $context );
21
+
22
+ switch_to_blog( $blog_id );
23
+ $statistic_data = $image_statistics->load();
24
+ restore_current_blog();
25
+
26
+ wp_send_json_success( array(
27
+ 'statistic' => $statistic_data,
28
+ ) );
29
+ } );*/
admin/ajax/settings.php CHANGED
@@ -1,37 +1,37 @@
1
- <?php
2
- /**
3
- * Ajax действие, которое выполняется при сохранении настроек
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright (c) 2018 Webraftic Ltd
7
- * @version 1.0
8
- */
9
-
10
- // Exit if accessed directly
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
-
15
- /**
16
- * AJAX обработчик массовой сохранения уровня сжатия
17
- */
18
- add_action( 'wp_ajax_wio_settings_update_level', function () {
19
- check_admin_referer( 'wio-iph' );
20
-
21
- if ( ! current_user_can( 'manage_options' ) ) {
22
- wp_die( - 1 );
23
- }
24
-
25
- $level = sanitize_text_field( $_POST['level'] );
26
-
27
- if ( ! $level ) {
28
- die();
29
- }
30
-
31
- if ( ! in_array( $level, [ 'normal', 'aggresive', 'ultra' ] ) ) {
32
- die();
33
- }
34
-
35
- WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_level', $level );
36
- die();
37
- } );
1
+ <?php
2
+ /**
3
+ * Ajax действие, которое выполняется при сохранении настроек
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright (c) 2018 Webraftic Ltd
7
+ * @version 1.0
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * AJAX обработчик массовой сохранения уровня сжатия
17
+ */
18
+ add_action( 'wp_ajax_wio_settings_update_level', function () {
19
+ check_admin_referer( 'wio-iph' );
20
+
21
+ if ( ! current_user_can( 'manage_options' ) ) {
22
+ wp_die( - 1 );
23
+ }
24
+
25
+ $level = sanitize_text_field( $_POST['level'] );
26
+
27
+ if ( ! $level ) {
28
+ die();
29
+ }
30
+
31
+ if ( ! in_array( $level, [ 'normal', 'aggresive', 'ultra' ] ) ) {
32
+ die();
33
+ }
34
+
35
+ WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_level', $level );
36
+ die();
37
+ } );
admin/assets/css/base-statistic.css CHANGED
@@ -29,11 +29,11 @@
29
  }
30
  }*/
31
  }
32
- #WBCR .factory-bootstrap-446 select.form-control {
33
  background: #efefef url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat right 5px top 55% !important;
34
  }
35
- #WBCR .factory-bootstrap-446 .btn-default.active,
36
- #WBCR .factory-bootstrap-446 .factory-bootstrap-446 .btn-default:active {
37
  text-shadow: none;
38
  color: #fff;
39
  background-color: #33aad5;
@@ -43,7 +43,7 @@
43
  border-bottom: 1px solid #0074a2;
44
  border-left: 1px solid #0074a2;
45
  }
46
- #WBCR .factory-bootstrap-446 .btn-group > .btn:last-of-type {
47
  border-top-right-radius: 3px;
48
  border-bottom-right-radius: 3px;
49
  }
@@ -178,7 +178,7 @@
178
  background: #f3f3f3;
179
  }
180
  #WBCR .wrio-table .wbcr-rio-server-success {
181
- color: #8CC152;
182
  }
183
  #WBCR .wrio-table .wbcr-rio-server-error {
184
  color: #fb5d49;
@@ -365,7 +365,7 @@
365
  padding-top: 0.85em;
366
  }
367
  #WBCR .wio-bars + .wio-number-you-optimized p {
368
- color: #72a53b;
369
  }
370
  #WBCR .wio-bar-negative .wio-progress {
371
  background: #D2D3D6;
@@ -381,15 +381,21 @@
381
  }*/
382
  }
383
  #WBCR .wio-bar-positive .wio-progress {
384
- background: #8CC152;
385
  }
386
  #WBCR .wio-bar-positive .wio-barnb {
387
- color: #72a53b;
388
  }
389
  #WBCR .wio-bar-primary .wio-progress {
390
- background: #8CC152;
391
  }
392
  #WBCR .wio-bar-primary .wio-barnb {
 
 
 
 
 
 
393
  color: #72a53b;
394
  }
395
  #WBCR .wio-right-outside-number .wio-barnb {
@@ -417,6 +423,10 @@
417
  float: left;
418
  margin-right: 20px;
419
  }
 
 
 
 
420
  #WBCR .wio-chart-percent {
421
  position: absolute;
422
  left: 0;
@@ -425,7 +435,7 @@
425
  margin-top: -0.5em;
426
  line-height: 0.8;
427
  text-align: center;
428
- font-size: 54px;
429
  font-weight: bold;
430
  color: #afafaf;
431
  }
@@ -489,8 +499,9 @@
489
  font-size: 14px;
490
  text-align: center;
491
  }
492
- #WBCR .wio-total-percent {
493
- color: #587f2e;
 
494
  }
495
  #WBCR #wio-start-msg-top,
496
  #WBCR #wio-start-msg-right,
@@ -508,10 +519,18 @@
508
  padding-bottom: 0 !important;
509
  }
510
  #WBCR .wio-page-statistic {
511
- padding-left: 40px;
512
  }
513
  #WBCR .wio-page-statistic .wio-chart-percent {
514
- margin-top: -1.1em;
 
 
 
 
 
 
 
 
515
  }
516
  #WBCR .wio-page-total {
517
  padding: 20px 20px;
29
  }
30
  }*/
31
  }
32
+ #WBCR .factory-bootstrap-450 select.form-control {
33
  background: #efefef url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat right 5px top 55% !important;
34
  }
35
+ #WBCR .factory-bootstrap-450 .btn-default.active,
36
+ #WBCR .factory-bootstrap-450 .factory-bootstrap-450 .btn-default:active {
37
  text-shadow: none;
38
  color: #fff;
39
  background-color: #33aad5;
43
  border-bottom: 1px solid #0074a2;
44
  border-left: 1px solid #0074a2;
45
  }
46
+ #WBCR .factory-bootstrap-450 .btn-group > .btn:last-of-type {
47
  border-top-right-radius: 3px;
48
  border-bottom-right-radius: 3px;
49
  }
178
  background: #f3f3f3;
179
  }
180
  #WBCR .wrio-table .wbcr-rio-server-success {
181
+ color: #bbd2a1;
182
  }
183
  #WBCR .wrio-table .wbcr-rio-server-error {
184
  color: #fb5d49;
365
  padding-top: 0.85em;
366
  }
367
  #WBCR .wio-bars + .wio-number-you-optimized p {
368
+ color: #a2c17f;
369
  }
370
  #WBCR .wio-bar-negative .wio-progress {
371
  background: #D2D3D6;
381
  }*/
382
  }
383
  #WBCR .wio-bar-positive .wio-progress {
384
+ background: #bbd2a1;
385
  }
386
  #WBCR .wio-bar-positive .wio-barnb {
387
+ color: #a2c17f;
388
  }
389
  #WBCR .wio-bar-primary .wio-progress {
390
+ background: #bbd2a1;
391
  }
392
  #WBCR .wio-bar-primary .wio-barnb {
393
+ color: #a2c17f;
394
+ }
395
+ #WBCR .wio-bar-webp .wio-progress {
396
+ background: #8CC152;
397
+ }
398
+ #WBCR .wio-bar-webp .wio-barnb {
399
  color: #72a53b;
400
  }
401
  #WBCR .wio-right-outside-number .wio-barnb {
423
  float: left;
424
  margin-right: 20px;
425
  }
426
+ #WBCR .wio-overview-chart-container-webp {
427
+ float: right;
428
+ margin-left: 20px;
429
+ }
430
  #WBCR .wio-chart-percent {
431
  position: absolute;
432
  left: 0;
435
  margin-top: -0.5em;
436
  line-height: 0.8;
437
  text-align: center;
438
+ font-size: 45px;
439
  font-weight: bold;
440
  color: #afafaf;
441
  }
499
  font-size: 14px;
500
  text-align: center;
501
  }
502
+ #WBCR .wio-total-percent,
503
+ #WBCR .wio-total-percent-webp {
504
+ color: #89b15c;
505
  }
506
  #WBCR #wio-start-msg-top,
507
  #WBCR #wio-start-msg-right,
519
  padding-bottom: 0 !important;
520
  }
521
  #WBCR .wio-page-statistic {
522
+ padding: 20px;
523
  }
524
  #WBCR .wio-page-statistic .wio-chart-percent {
525
+ margin-top: -1.2em;
526
+ }
527
+ #WBCR .wio-page-statistic .wio-optimize-statistic {
528
+ display: flex;
529
+ justify-content: space-between;
530
+ }
531
+ #WBCR .wio-page-statistic .wrio-statistic-buttons-wrap {
532
+ display: flex;
533
+ justify-content: space-between;
534
  }
535
  #WBCR .wio-page-total {
536
  padding: 20px 20px;
admin/assets/css/base-statistic.less CHANGED
@@ -1,888 +1,913 @@
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
-
8
- @positiveColor: #8CC152;
9
- @negativeColor: #D2D3D6;
10
- @neutralColor: #828282;
11
-
12
- @errorColor: #fb5d49;
13
- @waringColor: #ffb635;
14
-
15
- @greyButtonBg: #f3f3f3;
16
- @greyButtonColor: #656565;
17
-
18
- @greenButtonBg: #c9deb2;
19
- @greenButtonColor: #586549;
20
-
21
- @orangeButtonBg: #fdd599;
22
- @orangeButtonColor: #a57b3c;
23
-
24
- #WBCR {
25
- .premium-label(@position: relative, @positionTop:-8px, @positionLeft:-10px, @positionRight:auto) {
26
- display: inline-block;
27
- position: @position;
28
- content: 'PRO';
29
- background: #ff5722;
30
- border-radius: 4px;
31
- color: #fff;
32
- font-size: 10px;
33
- line-height: 1;
34
- font-style: normal;
35
- padding: 4px 6px;
36
- margin-left: 4px;
37
- vertical-align: top;
38
- top: @positionTop;
39
- left: @positionLeft;
40
- right: @positionRight;
41
- z-index: 11;
42
- }
43
-
44
- .factory-bootstrap-000 {
45
- select.form-control {
46
- background: #efefef url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat right 5px top 55% !important;
47
- }
48
-
49
- .btn-default.active, .factory-bootstrap-000 .btn-default:active {
50
- text-shadow: none;
51
- color: #fff;
52
- background-color: #33aad5;
53
- -webkit-box-shadow: inset 0 1px 1px #0074a2;
54
- box-shadow: inset 0 1px 3px #0074a2;
55
- border-top: 1px solid #0074a2;
56
- border-bottom: 1px solid #0074a2;
57
- border-left: 1px solid #0074a2;
58
- }
59
-
60
- .btn-group > .btn:last-of-type {
61
- border-top-right-radius: 3px;
62
- border-bottom-right-radius: 3px;
63
- }
64
- }
65
-
66
-
67
- .wio-clear {
68
- clear: both;
69
- }
70
-
71
- // Fix for Clearfy
72
- // This code hides tabs custom folders and nextgen gallery
73
- // -----------------------------------------------
74
- #io_folders_statistic-wbcr_clearfy-tab, #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
75
- display: none !important;
76
- }
77
-
78
- // Styling tabs on statistics pages
79
- // -----------------------------------------------
80
- .wrio-statistic-nav {
81
- margin: 0;
82
- //box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
83
- background: #efefef;
84
-
85
- ul {
86
- margin: 0 0 0 10px;
87
-
88
- li {
89
- position: relative;
90
- display: inline-block;
91
- //width: 300px;
92
- margin: 0 5px 0 0;
93
- background: #ffffff;
94
- box-shadow: 0 -2px 0 #eaeaea;
95
-
96
- &:hover {
97
- background: #f7f7f7;
98
- }
99
-
100
- &.active {
101
- //box-shadow: 0 -2px 0 #c9deb2;
102
- background: #f7f7f7;
103
- border-top: 1px solid #d4d4d4;
104
- border-left: 1px solid #d4d4d4;
105
- border-right: 1px solid #d4d4d4;
106
- border-bottom: 1px solid #f7f7f7;
107
- margin-bottom: -1px;
108
-
109
- a {
110
- color: #222;
111
-
112
- .wrio-statistic-tab-percent {
113
- border: 2px dashed #8bc34a;
114
- color: #5e8237;
115
- }
116
- }
117
-
118
- .dashicons, .dashicons-before:before {
119
- color: #ff8b66;
120
- }
121
- }
122
-
123
- .wrio-statistic-tab {
124
- display: block;
125
- padding: 10px 20px 10px 20px;
126
- text-decoration: none;
127
- color: #d4d4d4;
128
- font-size: 22px;
129
- line-height: 2;
130
-
131
- &:active, &:focus {
132
- background: 0;
133
- box-shadow: none;
134
- outline: none;
135
- }
136
-
137
- .dashicons, .dashicons-before:before {
138
- display: inline-block;
139
- width: 30px;
140
- height: 30px;
141
- font-size: 30px;
142
- line-height: 1.5;
143
- margin-right: 15px;
144
- color: #d4d4d4;
145
- }
146
-
147
-
148
- .wrio-statistic-tab-percent {
149
- display: inline-block;
150
- width: 42px;
151
- height: 42px;
152
- border-radius: 100px;
153
- border: 2px dashed #e4e4e4;
154
- padding: 5px;
155
- margin-left: 30px;
156
- font-size: 14px;
157
- font-weight: 600;
158
- text-align: center;
159
- color: #bdbdbd;
160
- }
161
- }
162
-
163
- .wrio-statistic-tab-premium-label:after {
164
- .premium-label(absolute, 10px, auto, 10px);
165
- }
166
- }
167
- }
168
- }
169
-
170
- // Table style. The table is used for optimization log
171
- .wrio-table {
172
- width: 100%;
173
- table-layout: fixed;
174
- box-sizing: border-box;
175
- border-spacing: 3px;
176
- background: #fff;
177
- border-top: 2px dashed #cac9c9;
178
-
179
- th, td {
180
- padding: 16px 10px;
181
- text-align: center;
182
- }
183
-
184
- th {
185
- background: #f3f3f3;
186
- color: #777777;
187
- box-shadow: 0 1px 0 rgb(216, 216, 216);
188
-
189
- &:nth-child(2n+1) {
190
- background: #f9f9f9
191
- }
192
- }
193
-
194
- tr.wrio-error {
195
- background-color: #ffe9e9 !important;
196
- }
197
-
198
- .wrio-table-spinner {
199
- background: url("../img/quick-start-loader.gif") center center no-repeat;
200
- }
201
-
202
- .wrio-table-highlighter {
203
- display: inline-block;
204
- padding: 3px 7px;
205
- background: @greyButtonBg;
206
- }
207
-
208
- .wbcr-rio-server-success {
209
- color: @positiveColor;
210
- }
211
-
212
- .wbcr-rio-server-error {
213
- color: @errorColor;
214
- }
215
-
216
- .wbcr-rio-server-warning {
217
- color: @waringColor;
218
- }
219
-
220
- &.wbcr-rio-folders-table {
221
- td:nth-child(3) {
222
- text-align: left;
223
- }
224
- }
225
- }
226
-
227
- .wrio-servers {
228
- padding: 20px 20px;
229
-
230
- label {
231
- span {
232
- display: block;
233
- font-weight: normal;
234
- font-size: 12px;
235
- color: #b7b2b2;
236
- }
237
- }
238
-
239
- #wrio-change-optimization-server {
240
- position: relative;
241
- display: inline-block;
242
- max-width: 400px;
243
- margin-right: 15px;
244
- margin-bottom: 0;
245
- border: 1px solid #d2d0d0;
246
- background-color: #efefef;
247
- }
248
-
249
- .wrio-servers-info {
250
- margin: 0 0 0;
251
- padding: 20px;
252
- background: #fff;
253
- }
254
-
255
- .wrio-server-status-wrap {
256
- display: inline-block;
257
- margin-top: 8px;
258
-
259
- .wrio-server-status {
260
- background: transparent;
261
- color: #fff;
262
- padding: 3px 5px;
263
- border-radius: 4px;
264
-
265
- &.wrio-down {
266
- background: #ff5722;
267
- }
268
-
269
- &.wrio-stable {
270
- background: #8bc34a;
271
- }
272
-
273
- &.wrio-server-check-proccess {
274
- display: inline-block;
275
- height: 10px;
276
- width: 30px;
277
- background: url("../img/quick-start-loader.gif") center no-repeat;
278
- }
279
- }
280
- }
281
-
282
-
283
- .wrio-premium-user-balance-wrap {
284
- display: inline-block;
285
- margin-top: 8px;
286
- margin-left: 10px;
287
-
288
- .wrio-premium-user-balance {
289
- color: #fff;
290
- padding: 3px 5px;
291
- border-radius: 4px;
292
- background: #ffc107;
293
- }
294
-
295
- .wrio-premium-user-balance-check-proccess {
296
- display: inline-block;
297
- height: 10px;
298
- width: 30px;
299
- background: url("../img/quick-start-loader.gif") center no-repeat;
300
- }
301
- }
302
-
303
- .wrio-premium-user-update-wrap {
304
- display: inline-block;
305
- margin-top: 8px;
306
- margin-left: 10px;
307
-
308
- .wrio-premium-user-update {
309
- color: #fff;
310
- padding: 3px 5px;
311
- border-radius: 4px;
312
- background: #ffc107;
313
- }
314
-
315
- .wrio-premium-user-update-check-proccess {
316
- display: inline-block;
317
- height: 10px;
318
- width: 30px;
319
- background: url("../img/quick-start-loader.gif") center no-repeat;
320
- }
321
- }
322
- }
323
-
324
- .wio-columns {
325
- overflow: hidden;
326
- padding: 15px 0;
327
- counter-reset: cols;
328
-
329
- [class^="col-"] {
330
- float: left;
331
- -webkit-box-sizing: border-box;
332
- -moz-box-sizing: border-box;
333
- box-sizing: border-box;
334
- }
335
-
336
- .col-1-3 {
337
- width: 33.333%;
338
- padding-left: 28px;
339
- }
340
-
341
- .col-2-3 {
342
- width: 66.666%;
343
- padding-left: 28px
344
- }
345
-
346
- .col-1-2 {
347
- width: 50%;
348
- padding: 0 20px;
349
- }
350
-
351
- .col-statistics.col-statistics {
352
- width: 60%;
353
- }
354
-
355
- .col-chart.col-chart {
356
- width: 40%;
357
- position: relative;
358
- padding: 20px;
359
- font-size: 12px;
360
- text-transform: uppercase;
361
- background: #f1f1f1b3;
362
- color: #abacaf;
363
- font-weight: bold;
364
- border-radius: 5px;
365
- margin-top: 10px;
366
- text-align: left;
367
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
368
- }
369
- }
370
-
371
- .wio-col {
372
- float: left;
373
- width: 50%;
374
- box-sizing: border-box;
375
- -webkit-flex-basis: 50%;
376
- -ms-flex-preferred-size: 50%;
377
- flex-basis: 50%;
378
- }
379
-
380
- .wio-col {
381
- padding-right: 20px;
382
- }
383
-
384
- .wio-col + .wio-col {
385
- padding-right: 0;
386
- padding-left: 50px;
387
- }
388
-
389
- .wio-col:target {
390
- animation: wiohello 1s 3 linear backwards;
391
- }
392
-
393
- .wio-number-you-optimized {
394
- margin-bottom: 1.35em;
395
- overflow: hidden;
396
-
397
- #wio-total-optimized-attachments-pct {
398
- color: @neutralColor;
399
- }
400
-
401
- .wio-number {
402
- display: table-cell;
403
- padding-right: 15px;
404
- font-size: 48px;
405
- font-weight: bold;
406
- line-height: 1;
407
- vertical-align: middle;
408
- white-space: nowrap;
409
- color: @neutralColor;
410
- }
411
-
412
- .wio-text {
413
- display: table-cell;
414
- vertical-align: middle;
415
- overflow: hidden;
416
- font-size: 12px;
417
- color: @neutralColor;
418
- }
419
-
420
- & > p {
421
- display: table;
422
- }
423
- }
424
-
425
- .wio-bars {
426
- padding-right: 15px;
427
- }
428
-
429
- .wio-bars p {
430
- font-size: 12px;
431
- margin-bottom: 5px;
432
- }
433
-
434
- .wio-bars + .wio-number-you-optimized {
435
- border-bottom: 0;
436
- padding-top: 0.85em;
437
- }
438
-
439
- .wio-bars + .wio-number-you-optimized p {
440
- color: darken(@positiveColor, 10);
441
- }
442
-
443
- .wio-bar-negative {
444
- .wio-progress {
445
- background: @negativeColor;
446
- }
447
-
448
- .wio-barnb {
449
- color: darken(@negativeColor, 20);
450
- }
451
- }
452
-
453
- .wio-progress {
454
- height: 8px;
455
- transition: width .3s;
456
-
457
- /*.wio-bar-negative {
458
- width: 92% !important;
459
- }*/
460
- }
461
-
462
- .wio-bar-positive {
463
- .wio-progress {
464
- background: @positiveColor;
465
- }
466
-
467
- .wio-barnb {
468
- color: darken(@positiveColor, 10);
469
- }
470
- }
471
-
472
- .wio-bar-primary {
473
- .wio-progress {
474
- background: @positiveColor;
475
- }
476
-
477
- .wio-barnb {
478
- color: darken(@positiveColor, 10);
479
- }
480
- }
481
-
482
- .wio-right-outside-number .wio-barnb {
483
- display: block;
484
- margin-right: -5.25em;
485
- text-align: right;
486
- font-weight: bold;
487
- line-height: .8;
488
- }
489
-
490
- /* Doughnut */
491
-
492
- .wio-chart {
493
- position: relative;
494
- top: 1px;
495
- display: inline-block;
496
- vertical-align: middle;
497
- }
498
-
499
- .wio-chart-container {
500
- position: relative;
501
- display: inline-block;
502
- margin-right: 5px;
503
- }
504
-
505
- .wio-chart-container canvas {
506
- display: block;
507
- }
508
-
509
- .wio-overview-chart-container {
510
- float: left;
511
- margin-right: 20px;
512
- }
513
-
514
- .wio-chart-percent {
515
- position: absolute;
516
- left: 0;
517
- right: 0;
518
- top: 50%;
519
- margin-top: -.5em;
520
- line-height: 0.8;
521
- text-align: center;
522
- font-size: 54px;
523
- font-weight: bold;
524
- color: #afafaf;
525
- }
526
-
527
- .wio-chart-percent span {
528
- font-size: 20px;
529
- vertical-align: super;
530
- }
531
-
532
- #wio-overview-chart-legend {
533
- overflow: hidden;
534
- }
535
-
536
- .wio-doughnut-legend li {
537
- display: inline-block;
538
- position: relative;
539
- margin-bottom: 15px;
540
- border-radius: 5px;
541
- padding: 3px 8px 2px 31px;
542
- font-size: 9px;
543
- cursor: default;
544
- -webkit-transition: background-color 200ms ease-in-out;
545
- -moz-transition: background-color 200ms ease-in-out;
546
- -o-transition: background-color 200ms ease-in-out;
547
- transition: background-color 200ms ease-in-out;
548
- }
549
-
550
- .wio-doughnut-legend li span {
551
- display: block;
552
- position: absolute;
553
- left: 0;
554
- top: 0;
555
- width: 25px;
556
- height: 25px;
557
- border-radius: 50%;
558
- }
559
-
560
- .wio-optimize-button {
561
- min-width: 180px;
562
- padding: 12px 30px;
563
- background: @greenButtonBg;
564
- color: @greenButtonColor;
565
- border: 0;
566
- box-shadow: none;
567
- font-size: 14px;
568
- text-transform: uppercase !important;
569
- font-weight: bold;
570
- border-radius: 4px;
571
- outline: none;
572
-
573
- &:active {
574
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
575
- }
576
-
577
- &:disabled {
578
- background: lighten(@greenButtonBg, 10%);
579
- color: lighten(@greenButtonColor, 30%);
580
- }
581
-
582
- &.wio-running {
583
- color: @orangeButtonColor;
584
- background: @orangeButtonBg url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
585
- padding-left: 50px;
586
- }
587
- }
588
-
589
- .wio-global-optim-phrase {
590
- width: 180px;
591
- padding-top: 20px;
592
- font-size: 14px;
593
- text-align: center;
594
- }
595
-
596
- .wio-total-percent {
597
- color: darken(@positiveColor, 20);
598
- }
599
-
600
- #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
601
- display: none;
602
- }
603
-
604
- .wio-text-left {
605
- text-align: left;
606
- }
607
-
608
- span.wio-num {
609
- display: inline !important;
610
- position: inherit !important;
611
- }
612
-
613
-
614
- // WIDGETS SPACE
615
- // -----------------------------------------------
616
- .wio-image-optimize-board {
617
- padding-bottom: 0 !important;
618
- }
619
-
620
- .wio-page-statistic {
621
- padding-left: 40px;
622
-
623
- .wio-chart-percent {
624
- margin-top: -1.1em;
625
- }
626
- }
627
-
628
- .wio-page-total {
629
- padding: 20px 20px;
630
- background: #efefef;
631
-
632
- .wrio-calculate-process {
633
- display: inline-block !important;
634
- height: 10px;
635
- width: 30px;
636
- background: transparent url("../img/quick-start-loader.gif") center no-repeat !important;
637
- }
638
-
639
- .wrio-total-images {
640
- font-weight: bold;
641
- color: #fff;
642
- padding: 3px 5px;
643
- border-radius: 4px;
644
- background: #ffc107;
645
- }
646
-
647
- span.wrio-total-images-desc {
648
- display: block;
649
- font-weight: normal;
650
- font-size: 12px;
651
- color: #b7b2b2;
652
- }
653
- }
654
-
655
- .wrio-optimization-progress {
656
- //margin-top: 30px;
657
- background: none;
658
- padding: 0;
659
-
660
- h4 {
661
- font-size: 15px;
662
- font-weight: 700;
663
- }
664
-
665
- /*button {
666
- padding: 5px 10px;
667
- border: 0;
668
- font-size: 11px;
669
- text-transform: uppercase !important;
670
- font-weight: bold;
671
- border-radius: 4px;
672
- outline: none;
673
- background: @greyButtonBg;
674
- color: @greyButtonColor;
675
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
676
-
677
- &:active {
678
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
679
- }
680
-
681
- &.wbcr-rio-loading {
682
- width: 56px;
683
- font-size: 0;
684
- background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
685
- }
686
-
687
- &.wbcr-rio-selected {
688
- background: #f3efe2;
689
- color: #d8d8d8;
690
-
691
- &:active {
692
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
693
- }
694
- }
695
- }*/
696
-
697
- .wbcr-rio-warning-message {
698
- padding: 20px;
699
- background: #efefef;
700
- font-size: 15px;
701
- color: #b7b7b7;
702
- font-style: italic;
703
- }
704
- }
705
-
706
- .wio-widget {
707
- padding: 0 !important;
708
-
709
- .wio-chart-percent {
710
- font-size: 44px;
711
- line-height: 1;
712
- }
713
-
714
- .wio-bars {
715
- width: 60%;
716
- margin-left: 155px;
717
- }
718
-
719
- .col-chart.col-chart {
720
- width: 100%;
721
- }
722
-
723
- .col-controls {
724
- width: 45%;
725
- padding-left: 5px;
726
- padding-top: 110px
727
- }
728
-
729
- .wio-doughnut-legend {
730
- /*padding-top:30px;*/
731
- text-align: left;
732
- }
733
-
734
- .wio-widget-bottom {
735
- display: table;
736
- padding-top: 20px !important;
737
- width: 100%;
738
- text-align: right;
739
- }
740
-
741
- .wio-widget-bottom li {
742
- display: table-cell;
743
- }
744
-
745
- .wio-widget-bottom li:first-child {
746
- text-align: left;
747
- }
748
- }
749
-
750
- // FORMS SPACE
751
- // -----------------------------------------------
752
- .factory-checkbox {
753
- &.wrio-checkbox-premium-label:after {
754
- .premium-label();
755
- }
756
- }
757
-
758
- .factory-checkbox-disabled {
759
- input, button {
760
- pointer-events: none;
761
- cursor: not-allowed;
762
- opacity: .65;
763
- filter: alpha(opacity=65);
764
- -webkit-box-shadow: none;
765
- box-shadow: none;
766
- }
767
- }
768
-
769
- #wrio-webp-options, #wrio-error-log-options {
770
- h3 {
771
- font-size: 14px;
772
- margin: 0 0 10px 0;
773
- font-weight: 600;
774
- color: #565656;
775
- }
776
-
777
- .wrio-webp-options-info {
778
- color: #8a8787;
779
- font-size: 12px;
780
- }
781
-
782
- ul {
783
- padding-left: 0;
784
-
785
- li {
786
- &:after {
787
- content: '';
788
- display: block;
789
- clear: both;;
790
- }
791
-
792
- label {
793
- font-weight: 600;
794
- }
795
-
796
- .wrio-webp-options-radio, .wrio-error-log-options-checkbox {
797
- display: block;
798
- float: left;
799
- margin-top: 2px;
800
- margin-right: 8px;
801
-
802
- &:focus {
803
- outline: none;
804
- box-shadow: none;
805
- }
806
- }
807
-
808
- .wrio-webp-options-info, .wrio-error-log-options-info {
809
- padding-left: 25px;
810
- }
811
- }
812
- }
813
-
814
-
815
- }
816
-
817
- // MEDIA SPACE
818
- // -----------------------------------------------
819
-
820
- @media (max-width: 830px) {
821
- .wio [class^="col-"] {
822
- float: none;
823
- margin-bottom: 1.5em;
824
- }
825
-
826
- .wio .col-1-3,
827
- .wio .col-1-2 {
828
- width: auto;
829
- padding: 0 28px;
830
- clear: both;
831
- padding-top: 1em;
832
- }
833
- }
834
-
835
- @keyframes wiohello {
836
- 0%, 100% {
837
- background: #FFF;
838
- }
839
- 50% {
840
- background: #F4F7F9;
841
- }
842
- }
843
-
844
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
845
- .wio-columns {
846
- .col-statistics.col-statistics, .col-chart.col-chart {
847
- width: 50%;
848
- }
849
- }
850
-
851
- }
852
-
853
- @media (max-width: 808px) {
854
- .wio-columns {
855
- .col-statistics.col-statistics, .col-chart.col-chart {
856
- width: auto;
857
- float: none;
858
- padding: 0;
859
- }
860
-
861
- .col-chart.col-chart {
862
- margin-top: 3em;
863
- }
864
- }
865
- }
866
- /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
867
- .wio-overview-chart-container {
868
- float: none;
869
- margin-right: 0;
870
- }
871
- }
872
-
873
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
874
- .wio-overview-chart-container {
875
- float: none;
876
- margin-right: 0;
877
- }
878
-
879
- .wio-doughnut-legend {
880
- margin-top: 18px;
881
- }
882
-
883
- .wio-global-optim-phrase {
884
- padding-top: 0;
885
- width: auto;
886
- }
887
- }*/
888
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
8
+ @positiveColor: #bbd2a1;
9
+ @webpPositiveColor: #8CC152;
10
+ @negativeColor: #D2D3D6;
11
+ @neutralColor: #828282;
12
+
13
+ @errorColor: #fb5d49;
14
+ @waringColor: #ffb635;
15
+
16
+ @greyButtonBg: #f3f3f3;
17
+ @greyButtonColor: #656565;
18
+
19
+ @greenButtonBg: #c9deb2;
20
+ @greenButtonColor: #586549;
21
+
22
+ @orangeButtonBg: #fdd599;
23
+ @orangeButtonColor: #a57b3c;
24
+
25
+ #WBCR {
26
+ .premium-label(@position: relative, @positionTop:-8px, @positionLeft:-10px, @positionRight:auto) {
27
+ display: inline-block;
28
+ position: @position;
29
+ content: 'PRO';
30
+ background: #ff5722;
31
+ border-radius: 4px;
32
+ color: #fff;
33
+ font-size: 10px;
34
+ line-height: 1;
35
+ font-style: normal;
36
+ padding: 4px 6px;
37
+ margin-left: 4px;
38
+ vertical-align: top;
39
+ top: @positionTop;
40
+ left: @positionLeft;
41
+ right: @positionRight;
42
+ z-index: 11;
43
+ }
44
+
45
+ .factory-bootstrap-000 {
46
+ select.form-control {
47
+ background: #efefef url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat right 5px top 55% !important;
48
+ }
49
+
50
+ .btn-default.active, .factory-bootstrap-000 .btn-default:active {
51
+ text-shadow: none;
52
+ color: #fff;
53
+ background-color: #33aad5;
54
+ -webkit-box-shadow: inset 0 1px 1px #0074a2;
55
+ box-shadow: inset 0 1px 3px #0074a2;
56
+ border-top: 1px solid #0074a2;
57
+ border-bottom: 1px solid #0074a2;
58
+ border-left: 1px solid #0074a2;
59
+ }
60
+
61
+ .btn-group > .btn:last-of-type {
62
+ border-top-right-radius: 3px;
63
+ border-bottom-right-radius: 3px;
64
+ }
65
+ }
66
+
67
+
68
+ .wio-clear {
69
+ clear: both;
70
+ }
71
+
72
+ // Fix for Clearfy
73
+ // This code hides tabs custom folders and nextgen gallery
74
+ // -----------------------------------------------
75
+ #io_folders_statistic-wbcr_clearfy-tab, #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
76
+ display: none !important;
77
+ }
78
+
79
+ // Styling tabs on statistics pages
80
+ // -----------------------------------------------
81
+ .wrio-statistic-nav {
82
+ margin: 0;
83
+ //box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
84
+ background: #efefef;
85
+
86
+ ul {
87
+ margin: 0 0 0 10px;
88
+
89
+ li {
90
+ position: relative;
91
+ display: inline-block;
92
+ //width: 300px;
93
+ margin: 0 5px 0 0;
94
+ background: #ffffff;
95
+ box-shadow: 0 -2px 0 #eaeaea;
96
+
97
+ &:hover {
98
+ background: #f7f7f7;
99
+ }
100
+
101
+ &.active {
102
+ //box-shadow: 0 -2px 0 #c9deb2;
103
+ background: #f7f7f7;
104
+ border-top: 1px solid #d4d4d4;
105
+ border-left: 1px solid #d4d4d4;
106
+ border-right: 1px solid #d4d4d4;
107
+ border-bottom: 1px solid #f7f7f7;
108
+ margin-bottom: -1px;
109
+
110
+ a {
111
+ color: #222;
112
+
113
+ .wrio-statistic-tab-percent {
114
+ border: 2px dashed #8bc34a;
115
+ color: #5e8237;
116
+ }
117
+ }
118
+
119
+ .dashicons, .dashicons-before:before {
120
+ color: #ff8b66;
121
+ }
122
+ }
123
+
124
+ .wrio-statistic-tab {
125
+ display: block;
126
+ padding: 10px 20px 10px 20px;
127
+ text-decoration: none;
128
+ color: #d4d4d4;
129
+ font-size: 22px;
130
+ line-height: 2;
131
+
132
+ &:active, &:focus {
133
+ background: 0;
134
+ box-shadow: none;
135
+ outline: none;
136
+ }
137
+
138
+ .dashicons, .dashicons-before:before {
139
+ display: inline-block;
140
+ width: 30px;
141
+ height: 30px;
142
+ font-size: 30px;
143
+ line-height: 1.5;
144
+ margin-right: 15px;
145
+ color: #d4d4d4;
146
+ }
147
+
148
+
149
+ .wrio-statistic-tab-percent {
150
+ display: inline-block;
151
+ width: 42px;
152
+ height: 42px;
153
+ border-radius: 100px;
154
+ border: 2px dashed #e4e4e4;
155
+ padding: 5px;
156
+ margin-left: 30px;
157
+ font-size: 14px;
158
+ font-weight: 600;
159
+ text-align: center;
160
+ color: #bdbdbd;
161
+ }
162
+ }
163
+
164
+ .wrio-statistic-tab-premium-label:after {
165
+ .premium-label(absolute, 10px, auto, 10px);
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ // Table style. The table is used for optimization log
172
+ .wrio-table {
173
+ width: 100%;
174
+ table-layout: fixed;
175
+ box-sizing: border-box;
176
+ border-spacing: 3px;
177
+ background: #fff;
178
+ border-top: 2px dashed #cac9c9;
179
+
180
+ th, td {
181
+ padding: 16px 10px;
182
+ text-align: center;
183
+ }
184
+
185
+ th {
186
+ background: #f3f3f3;
187
+ color: #777777;
188
+ box-shadow: 0 1px 0 rgb(216, 216, 216);
189
+
190
+ &:nth-child(2n+1) {
191
+ background: #f9f9f9
192
+ }
193
+ }
194
+
195
+ tr.wrio-error {
196
+ background-color: #ffe9e9 !important;
197
+ }
198
+
199
+ .wrio-table-spinner {
200
+ background: url("../img/quick-start-loader.gif") center center no-repeat;
201
+ }
202
+
203
+ .wrio-table-highlighter {
204
+ display: inline-block;
205
+ padding: 3px 7px;
206
+ background: @greyButtonBg;
207
+ }
208
+
209
+ .wbcr-rio-server-success {
210
+ color: @positiveColor;
211
+ }
212
+
213
+ .wbcr-rio-server-error {
214
+ color: @errorColor;
215
+ }
216
+
217
+ .wbcr-rio-server-warning {
218
+ color: @waringColor;
219
+ }
220
+
221
+ &.wbcr-rio-folders-table {
222
+ td:nth-child(3) {
223
+ text-align: left;
224
+ }
225
+ }
226
+ }
227
+
228
+ .wrio-servers {
229
+ padding: 20px 20px;
230
+
231
+ label {
232
+ span {
233
+ display: block;
234
+ font-weight: normal;
235
+ font-size: 12px;
236
+ color: #b7b2b2;
237
+ }
238
+ }
239
+
240
+ #wrio-change-optimization-server {
241
+ position: relative;
242
+ display: inline-block;
243
+ max-width: 400px;
244
+ margin-right: 15px;
245
+ margin-bottom: 0;
246
+ border: 1px solid #d2d0d0;
247
+ background-color: #efefef;
248
+ }
249
+
250
+ .wrio-servers-info {
251
+ margin: 0 0 0;
252
+ padding: 20px;
253
+ background: #fff;
254
+ }
255
+
256
+ .wrio-server-status-wrap {
257
+ display: inline-block;
258
+ margin-top: 8px;
259
+
260
+ .wrio-server-status {
261
+ background: transparent;
262
+ color: #fff;
263
+ padding: 3px 5px;
264
+ border-radius: 4px;
265
+
266
+ &.wrio-down {
267
+ background: #ff5722;
268
+ }
269
+
270
+ &.wrio-stable {
271
+ background: #8bc34a;
272
+ }
273
+
274
+ &.wrio-server-check-proccess {
275
+ display: inline-block;
276
+ height: 10px;
277
+ width: 30px;
278
+ background: url("../img/quick-start-loader.gif") center no-repeat;
279
+ }
280
+ }
281
+ }
282
+
283
+
284
+ .wrio-premium-user-balance-wrap {
285
+ display: inline-block;
286
+ margin-top: 8px;
287
+ margin-left: 10px;
288
+
289
+ .wrio-premium-user-balance {
290
+ color: #fff;
291
+ padding: 3px 5px;
292
+ border-radius: 4px;
293
+ background: #ffc107;
294
+ }
295
+
296
+ .wrio-premium-user-balance-check-proccess {
297
+ display: inline-block;
298
+ height: 10px;
299
+ width: 30px;
300
+ background: url("../img/quick-start-loader.gif") center no-repeat;
301
+ }
302
+ }
303
+
304
+ .wrio-premium-user-update-wrap {
305
+ display: inline-block;
306
+ margin-top: 8px;
307
+ margin-left: 10px;
308
+
309
+ .wrio-premium-user-update {
310
+ color: #fff;
311
+ padding: 3px 5px;
312
+ border-radius: 4px;
313
+ background: #ffc107;
314
+ }
315
+
316
+ .wrio-premium-user-update-check-proccess {
317
+ display: inline-block;
318
+ height: 10px;
319
+ width: 30px;
320
+ background: url("../img/quick-start-loader.gif") center no-repeat;
321
+ }
322
+ }
323
+ }
324
+
325
+ .wio-columns {
326
+ overflow: hidden;
327
+ padding: 15px 0;
328
+ counter-reset: cols;
329
+
330
+ [class^="col-"] {
331
+ float: left;
332
+ -webkit-box-sizing: border-box;
333
+ -moz-box-sizing: border-box;
334
+ box-sizing: border-box;
335
+ }
336
+
337
+ .col-1-3 {
338
+ width: 33.333%;
339
+ padding-left: 28px;
340
+ }
341
+
342
+ .col-2-3 {
343
+ width: 66.666%;
344
+ padding-left: 28px
345
+ }
346
+
347
+ .col-1-2 {
348
+ width: 50%;
349
+ padding: 0 20px;
350
+ }
351
+
352
+ .col-statistics.col-statistics {
353
+ width: 60%;
354
+ }
355
+
356
+ .col-chart.col-chart {
357
+ width: 40%;
358
+ position: relative;
359
+ padding: 20px;
360
+ font-size: 12px;
361
+ text-transform: uppercase;
362
+ background: #f1f1f1b3;
363
+ color: #abacaf;
364
+ font-weight: bold;
365
+ border-radius: 5px;
366
+ margin-top: 10px;
367
+ text-align: left;
368
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
369
+ }
370
+ }
371
+
372
+ .wio-col {
373
+ float: left;
374
+ width: 50%;
375
+ box-sizing: border-box;
376
+ -webkit-flex-basis: 50%;
377
+ -ms-flex-preferred-size: 50%;
378
+ flex-basis: 50%;
379
+ }
380
+
381
+ .wio-col {
382
+ padding-right: 20px;
383
+ }
384
+
385
+ .wio-col + .wio-col {
386
+ padding-right: 0;
387
+ padding-left: 50px;
388
+ }
389
+
390
+ .wio-col:target {
391
+ animation: wiohello 1s 3 linear backwards;
392
+ }
393
+
394
+ .wio-number-you-optimized {
395
+ margin-bottom: 1.35em;
396
+ overflow: hidden;
397
+
398
+ #wio-total-optimized-attachments-pct {
399
+ color: @neutralColor;
400
+ }
401
+
402
+ .wio-number {
403
+ display: table-cell;
404
+ padding-right: 15px;
405
+ font-size: 48px;
406
+ font-weight: bold;
407
+ line-height: 1;
408
+ vertical-align: middle;
409
+ white-space: nowrap;
410
+ color: @neutralColor;
411
+ }
412
+
413
+ .wio-text {
414
+ display: table-cell;
415
+ vertical-align: middle;
416
+ overflow: hidden;
417
+ font-size: 12px;
418
+ color: @neutralColor;
419
+ }
420
+
421
+ & > p {
422
+ display: table;
423
+ }
424
+ }
425
+
426
+ .wio-bars {
427
+ padding-right: 15px;
428
+ }
429
+
430
+ .wio-bars p {
431
+ font-size: 12px;
432
+ margin-bottom: 5px;
433
+ }
434
+
435
+ .wio-bars + .wio-number-you-optimized {
436
+ border-bottom: 0;
437
+ padding-top: 0.85em;
438
+ }
439
+
440
+ .wio-bars + .wio-number-you-optimized p {
441
+ color: darken(@positiveColor, 10);
442
+ }
443
+
444
+ .wio-bar-negative {
445
+ .wio-progress {
446
+ background: @negativeColor;
447
+ }
448
+
449
+ .wio-barnb {
450
+ color: darken(@negativeColor, 20);
451
+ }
452
+ }
453
+
454
+ .wio-progress {
455
+ height: 8px;
456
+ transition: width .3s;
457
+
458
+ /*.wio-bar-negative {
459
+ width: 92% !important;
460
+ }*/
461
+ }
462
+
463
+ .wio-bar-positive {
464
+ .wio-progress {
465
+ background: @positiveColor;
466
+ }
467
+
468
+ .wio-barnb {
469
+ color: darken(@positiveColor, 10);
470
+ }
471
+ }
472
+
473
+ .wio-bar-primary {
474
+ .wio-progress {
475
+ background: @positiveColor;
476
+ }
477
+
478
+ .wio-barnb {
479
+ color: darken(@positiveColor, 10);
480
+ }
481
+ }
482
+
483
+ .wio-bar-webp {
484
+ .wio-progress {
485
+ background: @webpPositiveColor;
486
+ }
487
+
488
+ .wio-barnb {
489
+ color: darken(@webpPositiveColor, 10);
490
+ }
491
+ }
492
+
493
+ .wio-right-outside-number .wio-barnb {
494
+ display: block;
495
+ margin-right: -5.25em;
496
+ text-align: right;
497
+ font-weight: bold;
498
+ line-height: .8;
499
+ }
500
+
501
+ /* Doughnut */
502
+
503
+ .wio-chart {
504
+ position: relative;
505
+ top: 1px;
506
+ display: inline-block;
507
+ vertical-align: middle;
508
+ }
509
+
510
+ .wio-chart-container {
511
+ position: relative;
512
+ display: inline-block;
513
+ margin-right: 5px;
514
+ }
515
+
516
+ .wio-chart-container canvas {
517
+ display: block;
518
+ }
519
+
520
+ .wio-overview-chart-container {
521
+ float: left;
522
+ margin-right: 20px;
523
+ }
524
+
525
+ .wio-overview-chart-container-webp {
526
+ float: right;
527
+ margin-left: 20px;
528
+ }
529
+
530
+ .wio-chart-percent {
531
+ position: absolute;
532
+ left: 0;
533
+ right: 0;
534
+ top: 50%;
535
+ margin-top: -.5em;
536
+ line-height: 0.8;
537
+ text-align: center;
538
+ font-size: 45px;
539
+ font-weight: bold;
540
+ color: #afafaf;
541
+ }
542
+
543
+ .wio-chart-percent span {
544
+ font-size: 20px;
545
+ vertical-align: super;
546
+ }
547
+
548
+ #wio-overview-chart-legend {
549
+ overflow: hidden;
550
+ }
551
+
552
+ .wio-doughnut-legend li {
553
+ display: inline-block;
554
+ position: relative;
555
+ margin-bottom: 15px;
556
+ border-radius: 5px;
557
+ padding: 3px 8px 2px 31px;
558
+ font-size: 9px;
559
+ cursor: default;
560
+ -webkit-transition: background-color 200ms ease-in-out;
561
+ -moz-transition: background-color 200ms ease-in-out;
562
+ -o-transition: background-color 200ms ease-in-out;
563
+ transition: background-color 200ms ease-in-out;
564
+ }
565
+
566
+ .wio-doughnut-legend li span {
567
+ display: block;
568
+ position: absolute;
569
+ left: 0;
570
+ top: 0;
571
+ width: 25px;
572
+ height: 25px;
573
+ border-radius: 50%;
574
+ }
575
+
576
+ .wio-optimize-button {
577
+ min-width: 180px;
578
+ padding: 12px 30px;
579
+ background: @greenButtonBg;
580
+ color: @greenButtonColor;
581
+ border: 0;
582
+ box-shadow: none;
583
+ font-size: 14px;
584
+ text-transform: uppercase !important;
585
+ font-weight: bold;
586
+ border-radius: 4px;
587
+ outline: none;
588
+
589
+ &:active {
590
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
591
+ }
592
+
593
+ &:disabled {
594
+ background: lighten(@greenButtonBg, 10%);
595
+ color: lighten(@greenButtonColor, 30%);
596
+ }
597
+
598
+ &.wio-running {
599
+ color: @orangeButtonColor;
600
+ background: @orangeButtonBg url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
601
+ padding-left: 50px;
602
+ }
603
+ }
604
+
605
+ .wio-global-optim-phrase {
606
+ width: 180px;
607
+ padding-top: 20px;
608
+ font-size: 14px;
609
+ text-align: center;
610
+ }
611
+
612
+ .wio-total-percent, .wio-total-percent-webp {
613
+ color: darken(@positiveColor, 20);
614
+ }
615
+
616
+ #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
617
+ display: none;
618
+ }
619
+
620
+ .wio-text-left {
621
+ text-align: left;
622
+ }
623
+
624
+ span.wio-num {
625
+ display: inline !important;
626
+ position: inherit !important;
627
+ }
628
+
629
+
630
+ // WIDGETS SPACE
631
+ // -----------------------------------------------
632
+ .wio-image-optimize-board {
633
+ padding-bottom: 0 !important;
634
+ }
635
+
636
+ .wio-page-statistic {
637
+ padding: 20px;
638
+
639
+ .wio-chart-percent {
640
+ margin-top: -1.2em;
641
+ }
642
+
643
+ .wio-optimize-statistic {
644
+ display: flex;
645
+ justify-content: space-between;
646
+ }
647
+ .wrio-statistic-buttons-wrap {
648
+ display: flex;
649
+ justify-content: space-between;
650
+ }
651
+ }
652
+
653
+ .wio-page-total {
654
+ padding: 20px 20px;
655
+ background: #efefef;
656
+
657
+ .wrio-calculate-process {
658
+ display: inline-block !important;
659
+ height: 10px;
660
+ width: 30px;
661
+ background: transparent url("../img/quick-start-loader.gif") center no-repeat !important;
662
+ }
663
+
664
+ .wrio-total-images {
665
+ font-weight: bold;
666
+ color: #fff;
667
+ padding: 3px 5px;
668
+ border-radius: 4px;
669
+ background: #ffc107;
670
+ }
671
+
672
+ span.wrio-total-images-desc {
673
+ display: block;
674
+ font-weight: normal;
675
+ font-size: 12px;
676
+ color: #b7b2b2;
677
+ }
678
+ }
679
+
680
+ .wrio-optimization-progress {
681
+ //margin-top: 30px;
682
+ background: none;
683
+ padding: 0;
684
+
685
+ h4 {
686
+ font-size: 15px;
687
+ font-weight: 700;
688
+ }
689
+
690
+ /*button {
691
+ padding: 5px 10px;
692
+ border: 0;
693
+ font-size: 11px;
694
+ text-transform: uppercase !important;
695
+ font-weight: bold;
696
+ border-radius: 4px;
697
+ outline: none;
698
+ background: @greyButtonBg;
699
+ color: @greyButtonColor;
700
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
701
+
702
+ &:active {
703
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
704
+ }
705
+
706
+ &.wbcr-rio-loading {
707
+ width: 56px;
708
+ font-size: 0;
709
+ background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
710
+ }
711
+
712
+ &.wbcr-rio-selected {
713
+ background: #f3efe2;
714
+ color: #d8d8d8;
715
+
716
+ &:active {
717
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
718
+ }
719
+ }
720
+ }*/
721
+
722
+ .wbcr-rio-warning-message {
723
+ padding: 20px;
724
+ background: #efefef;
725
+ font-size: 15px;
726
+ color: #b7b7b7;
727
+ font-style: italic;
728
+ }
729
+ }
730
+
731
+ .wio-widget {
732
+ padding: 0 !important;
733
+
734
+ .wio-chart-percent {
735
+ font-size: 44px;
736
+ line-height: 1;
737
+ }
738
+
739
+ .wio-bars {
740
+ width: 60%;
741
+ margin-left: 155px;
742
+ }
743
+
744
+ .col-chart.col-chart {
745
+ width: 100%;
746
+ }
747
+
748
+ .col-controls {
749
+ width: 45%;
750
+ padding-left: 5px;
751
+ padding-top: 110px
752
+ }
753
+
754
+ .wio-doughnut-legend {
755
+ /*padding-top:30px;*/
756
+ text-align: left;
757
+ }
758
+
759
+ .wio-widget-bottom {
760
+ display: table;
761
+ padding-top: 20px !important;
762
+ width: 100%;
763
+ text-align: right;
764
+ }
765
+
766
+ .wio-widget-bottom li {
767
+ display: table-cell;
768
+ }
769
+
770
+ .wio-widget-bottom li:first-child {
771
+ text-align: left;
772
+ }
773
+ }
774
+
775
+ // FORMS SPACE
776
+ // -----------------------------------------------
777
+ .factory-checkbox {
778
+ &.wrio-checkbox-premium-label:after {
779
+ .premium-label();
780
+ }
781
+ }
782
+
783
+ .factory-checkbox-disabled {
784
+ input, button {
785
+ pointer-events: none;
786
+ cursor: not-allowed;
787
+ opacity: .65;
788
+ filter: alpha(opacity=65);
789
+ -webkit-box-shadow: none;
790
+ box-shadow: none;
791
+ }
792
+ }
793
+
794
+ #wrio-webp-options, #wrio-error-log-options {
795
+ h3 {
796
+ font-size: 14px;
797
+ margin: 0 0 10px 0;
798
+ font-weight: 600;
799
+ color: #565656;
800
+ }
801
+
802
+ .wrio-webp-options-info {
803
+ color: #8a8787;
804
+ font-size: 12px;
805
+ }
806
+
807
+ ul {
808
+ padding-left: 0;
809
+
810
+ li {
811
+ &:after {
812
+ content: '';
813
+ display: block;
814
+ clear: both;;
815
+ }
816
+
817
+ label {
818
+ font-weight: 600;
819
+ }
820
+
821
+ .wrio-webp-options-radio, .wrio-error-log-options-checkbox {
822
+ display: block;
823
+ float: left;
824
+ margin-top: 2px;
825
+ margin-right: 8px;
826
+
827
+ &:focus {
828
+ outline: none;
829
+ box-shadow: none;
830
+ }
831
+ }
832
+
833
+ .wrio-webp-options-info, .wrio-error-log-options-info {
834
+ padding-left: 25px;
835
+ }
836
+ }
837
+ }
838
+
839
+
840
+ }
841
+
842
+ // MEDIA SPACE
843
+ // -----------------------------------------------
844
+
845
+ @media (max-width: 830px) {
846
+ .wio [class^="col-"] {
847
+ float: none;
848
+ margin-bottom: 1.5em;
849
+ }
850
+
851
+ .wio .col-1-3,
852
+ .wio .col-1-2 {
853
+ width: auto;
854
+ padding: 0 28px;
855
+ clear: both;
856
+ padding-top: 1em;
857
+ }
858
+ }
859
+
860
+ @keyframes wiohello {
861
+ 0%, 100% {
862
+ background: #FFF;
863
+ }
864
+ 50% {
865
+ background: #F4F7F9;
866
+ }
867
+ }
868
+
869
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
870
+ .wio-columns {
871
+ .col-statistics.col-statistics, .col-chart.col-chart {
872
+ width: 50%;
873
+ }
874
+ }
875
+
876
+ }
877
+
878
+ @media (max-width: 808px) {
879
+ .wio-columns {
880
+ .col-statistics.col-statistics, .col-chart.col-chart {
881
+ width: auto;
882
+ float: none;
883
+ padding: 0;
884
+ }
885
+
886
+ .col-chart.col-chart {
887
+ margin-top: 3em;
888
+ }
889
+ }
890
+ }
891
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
892
+ .wio-overview-chart-container {
893
+ float: none;
894
+ margin-right: 0;
895
+ }
896
+ }
897
+
898
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
899
+ .wio-overview-chart-container {
900
+ float: none;
901
+ margin-right: 0;
902
+ }
903
+
904
+ .wio-doughnut-legend {
905
+ margin-top: 18px;
906
+ }
907
+
908
+ .wio-global-optim-phrase {
909
+ padding-top: 0;
910
+ width: auto;
911
+ }
912
+ }*/
913
+ }
admin/assets/css/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/assets/css/media.css CHANGED
@@ -1,215 +1,215 @@
1
- /**
2
- * == Custom column & Metabox
3
- */
4
- .column-wio_optimized_file.column-wio_optimized_file {
5
- width: 300px;
6
- text-align: center;
7
- vertical-align: middle;
8
- }
9
- .column-wio_optimized_file > * {
10
- max-width: 235px;
11
- margin: 0 auto;
12
- }
13
- @media (min-width: 1151px) and (max-width: 1800px) {
14
- .column-wio_optimized_file.column-wio_optimized_file {
15
- width: 235px;
16
- }
17
- }
18
- @media (min-width: 783px) and (max-width: 1150px) {
19
- .column-wio_optimized_file.column-wio_optimized_file {
20
- width: 13em;
21
- }
22
- table.media .column-title .has-media-icon ~ .row-actions.row-actions {
23
- margin-left: 0;
24
- }
25
- }
26
- @media (max-width: 782px) {
27
- table.media .column-wio_optimized_file.column-wio_optimized_file {
28
- text-align: left;
29
- }
30
- table.media .wio-datas-more-action,
31
- table.media .wio-datas-actions-links {
32
- text-align: center;
33
- }
34
- table.media .column-wio_optimized_file > *,
35
- table.media .column-wio_optimized_file .wio-datas-actions-links a {
36
- max-width: 100%;
37
- margin-left: 0;
38
- }
39
- }
40
- @media (min-width: 783px) and (max-width: 1150px), (max-width: 360px) {
41
- table.media .wio-hide-if-small {
42
- position: absolute;
43
- margin: -1px;
44
- padding: 0;
45
- height: 1px;
46
- width: 1px;
47
- overflow: hidden;
48
- clip: rect(0 0 0 0);
49
- border: 0;
50
- word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */
51
- }
52
- }
53
- .compat-field-wio .label {
54
- vertical-align: top;
55
- }
56
- .compat-field-wio ul.wio-datas-list {
57
- margin-top: 7px;
58
- font-size: 11px;
59
- }
60
- ul.wio-datas-list.wio-datas-list {
61
- margin: 0 auto;
62
- color: #555;
63
- font-size: 10px;
64
- }
65
- ul.wio-datas-list .big {
66
- font-size: 12px;
67
- color: #40B1D0;
68
- }
69
- .wio-data-item {
70
- overflow: hidden;
71
- }
72
- li.wio-data-item {
73
- clear: both;
74
- margin-bottom: 2px;
75
- }
76
- ul.wio-datas-list .wio-data-item span.data,
77
- ul.wio-datas-list .wio-data-item strong {
78
- float: left;
79
- width: 50%;
80
- -webkit-box-sizing: border-box;
81
- -moz-box-sizing: border-box;
82
- box-sizing: border-box;
83
- }
84
- ul.wio-datas-list .wio-data-item span.data {
85
- text-align: left;
86
- padding-right: 5px;
87
- }
88
- .compat-field-wio .wio-datas-list .wio-data-item .data {
89
- width: 130px;
90
- text-align: left;
91
- font-weight: bold;
92
- }
93
- ul.wio-datas-list .wio-data-item strong {
94
- text-align: left;
95
- padding-left: 5px;
96
- }
97
- .media-sidebar .wio-datas-list .wio-data-item .data {
98
- width: auto;
99
- float: none;
100
- }
101
- .media-sidebar .wio-datas-list .wio-data-item strong {
102
- display: inline-block;
103
- width: auto;
104
- float: none;
105
- }
106
- .media-sidebar .wio-datas-list .wio-data-item .wio-chart {
107
- float: left;
108
- }
109
- .wio-datas-more-action.wio-datas-more-action {
110
- margin: .4em auto;
111
- background: linear-gradient(to bottom, transparent, transparent 49%, rgba(0,0,0,.075) 50%, rgba(0,0,0,.075) 58%, transparent 58%, transparent);
112
- }
113
- .wio-datas-more-action a {
114
- display: inline-block;
115
- padding: 0 5px;
116
- background: #40B1D0;
117
- color: #FFF;
118
- text-transform: uppercase;
119
- font-size: 9px;
120
- font-weight: bold;
121
- line-height: 1.9;
122
- text-decoration: none;
123
- }
124
- .wio-datas-more-action a.is-open {
125
- background: #555;
126
- }
127
- .wio-datas-more-action a.is-open .dashicons {
128
- transform: rotate(180deg);
129
- }
130
- .wio-datas-more-action a .dashicons {
131
- font-size: 14px;
132
- vertical-align: middle;
133
- line-height: .8;
134
- }
135
- .wio-datas-more-action a .dashicons:before {
136
- vertical-align: middle;
137
- line-height: 20px;
138
- }
139
- .wio-datas-more-action .the-text {
140
- display: inline-block;
141
- vertical-align: middle;
142
- height: auto;
143
- line-height: inherit;
144
- }
145
-
146
- ul.wio-datas-details.wio-datas-details {
147
- margin: .7em auto;
148
- }
149
- .wio-datas-details strong {
150
- color: #40B1D0;
151
- }
152
- .wio-datas-details .original {
153
- color: #555;
154
- }
155
-
156
- .wio-datas-actions-links {
157
- overflow: hidden;
158
- border-top: 2px solid transparent;
159
- padding-top: 5px;
160
- font-size: 8px;
161
- }
162
- .nggform .wio-datas-actions-links {
163
- position: relative;
164
- z-index: 2;
165
- }
166
- .nggform .row-actions {
167
- z-index: 1;
168
- }
169
- .wio-datas-actions-links a {
170
- position: relative;
171
- display: inline-block;
172
- padding-left: 17px;
173
- text-decoration: none;
174
- font-weight: 600;
175
- }
176
- .compat-field-wio .wio-datas-actions-links {
177
- max-width: 300px;
178
- }
179
- .misc-pub-wio .wio-datas-actions-links {
180
- border-top: 2px solid #f2f2f2;
181
- padding-bottom: 5px;
182
- }
183
- /* Library */
184
- .column-wio_optimized_file .wio-datas-actions-links a {
185
- margin: 0 .7em;
186
- padding-left: 15px;
187
- }
188
-
189
- /* Media edition */
190
- .compat-field-wio .wio-datas-actions-links a,
191
- .misc-pub-wio .wio-datas-actions-links a {
192
- font-size: 10px;
193
- float: left;
194
- width: 50%;
195
- }
196
- .media-sidebar .compat-field-wio .wio-datas-actions-links a,
197
- .submitbox .misc-pub-wio .wio-datas-actions-links a {
198
- display: block;
199
- width: auto;
200
- float: none;
201
- }
202
- .wio-datas-actions-links a:only-child {
203
- float: none;
204
- width: auto;
205
- }
206
- .wio-datas-details.is-open + .wio-datas-actions-links {
207
- border-top-color: rgba(0,0,0,.075);
208
- }
209
- .wio-datas-actions-links .dashicons {
210
- position: absolute;
211
- left: 0; top: 4px;
212
- width: 12px;
213
- margin-right: 2px;
214
- font-size: 11px;
215
- }
1
+ /**
2
+ * == Custom column & Metabox
3
+ */
4
+ .column-wio_optimized_file.column-wio_optimized_file {
5
+ width: 300px;
6
+ text-align: center;
7
+ vertical-align: middle;
8
+ }
9
+ .column-wio_optimized_file > * {
10
+ max-width: 235px;
11
+ margin: 0 auto;
12
+ }
13
+ @media (min-width: 1151px) and (max-width: 1800px) {
14
+ .column-wio_optimized_file.column-wio_optimized_file {
15
+ width: 235px;
16
+ }
17
+ }
18
+ @media (min-width: 783px) and (max-width: 1150px) {
19
+ .column-wio_optimized_file.column-wio_optimized_file {
20
+ width: 13em;
21
+ }
22
+ table.media .column-title .has-media-icon ~ .row-actions.row-actions {
23
+ margin-left: 0;
24
+ }
25
+ }
26
+ @media (max-width: 782px) {
27
+ table.media .column-wio_optimized_file.column-wio_optimized_file {
28
+ text-align: left;
29
+ }
30
+ table.media .wio-datas-more-action,
31
+ table.media .wio-datas-actions-links {
32
+ text-align: center;
33
+ }
34
+ table.media .column-wio_optimized_file > *,
35
+ table.media .column-wio_optimized_file .wio-datas-actions-links a {
36
+ max-width: 100%;
37
+ margin-left: 0;
38
+ }
39
+ }
40
+ @media (min-width: 783px) and (max-width: 1150px), (max-width: 360px) {
41
+ table.media .wio-hide-if-small {
42
+ position: absolute;
43
+ margin: -1px;
44
+ padding: 0;
45
+ height: 1px;
46
+ width: 1px;
47
+ overflow: hidden;
48
+ clip: rect(0 0 0 0);
49
+ border: 0;
50
+ word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */
51
+ }
52
+ }
53
+ .compat-field-wio .label {
54
+ vertical-align: top;
55
+ }
56
+ .compat-field-wio ul.wio-datas-list {
57
+ margin-top: 7px;
58
+ font-size: 11px;
59
+ }
60
+ ul.wio-datas-list.wio-datas-list {
61
+ margin: 0 auto;
62
+ color: #555;
63
+ font-size: 10px;
64
+ }
65
+ ul.wio-datas-list .big {
66
+ font-size: 12px;
67
+ color: #40B1D0;
68
+ }
69
+ .wio-data-item {
70
+ overflow: hidden;
71
+ }
72
+ li.wio-data-item {
73
+ clear: both;
74
+ margin-bottom: 2px;
75
+ }
76
+ ul.wio-datas-list .wio-data-item span.data,
77
+ ul.wio-datas-list .wio-data-item strong {
78
+ float: left;
79
+ width: 50%;
80
+ -webkit-box-sizing: border-box;
81
+ -moz-box-sizing: border-box;
82
+ box-sizing: border-box;
83
+ }
84
+ ul.wio-datas-list .wio-data-item span.data {
85
+ text-align: left;
86
+ padding-right: 5px;
87
+ }
88
+ .compat-field-wio .wio-datas-list .wio-data-item .data {
89
+ width: 130px;
90
+ text-align: left;
91
+ font-weight: bold;
92
+ }
93
+ ul.wio-datas-list .wio-data-item strong {
94
+ text-align: left;
95
+ padding-left: 5px;
96
+ }
97
+ .media-sidebar .wio-datas-list .wio-data-item .data {
98
+ width: auto;
99
+ float: none;
100
+ }
101
+ .media-sidebar .wio-datas-list .wio-data-item strong {
102
+ display: inline-block;
103
+ width: auto;
104
+ float: none;
105
+ }
106
+ .media-sidebar .wio-datas-list .wio-data-item .wio-chart {
107
+ float: left;
108
+ }
109
+ .wio-datas-more-action.wio-datas-more-action {
110
+ margin: .4em auto;
111
+ background: linear-gradient(to bottom, transparent, transparent 49%, rgba(0,0,0,.075) 50%, rgba(0,0,0,.075) 58%, transparent 58%, transparent);
112
+ }
113
+ .wio-datas-more-action a {
114
+ display: inline-block;
115
+ padding: 0 5px;
116
+ background: #40B1D0;
117
+ color: #FFF;
118
+ text-transform: uppercase;
119
+ font-size: 9px;
120
+ font-weight: bold;
121
+ line-height: 1.9;
122
+ text-decoration: none;
123
+ }
124
+ .wio-datas-more-action a.is-open {
125
+ background: #555;
126
+ }
127
+ .wio-datas-more-action a.is-open .dashicons {
128
+ transform: rotate(180deg);
129
+ }
130
+ .wio-datas-more-action a .dashicons {
131
+ font-size: 14px;
132
+ vertical-align: middle;
133
+ line-height: .8;
134
+ }
135
+ .wio-datas-more-action a .dashicons:before {
136
+ vertical-align: middle;
137
+ line-height: 20px;
138
+ }
139
+ .wio-datas-more-action .the-text {
140
+ display: inline-block;
141
+ vertical-align: middle;
142
+ height: auto;
143
+ line-height: inherit;
144
+ }
145
+
146
+ ul.wio-datas-details.wio-datas-details {
147
+ margin: .7em auto;
148
+ }
149
+ .wio-datas-details strong {
150
+ color: #40B1D0;
151
+ }
152
+ .wio-datas-details .original {
153
+ color: #555;
154
+ }
155
+
156
+ .wio-datas-actions-links {
157
+ overflow: hidden;
158
+ border-top: 2px solid transparent;
159
+ padding-top: 5px;
160
+ font-size: 8px;
161
+ }
162
+ .nggform .wio-datas-actions-links {
163
+ position: relative;
164
+ z-index: 2;
165
+ }
166
+ .nggform .row-actions {
167
+ z-index: 1;
168
+ }
169
+ .wio-datas-actions-links a {
170
+ position: relative;
171
+ display: inline-block;
172
+ padding-left: 17px;
173
+ text-decoration: none;
174
+ font-weight: 600;
175
+ }
176
+ .compat-field-wio .wio-datas-actions-links {
177
+ max-width: 300px;
178
+ }
179
+ .misc-pub-wio .wio-datas-actions-links {
180
+ border-top: 2px solid #f2f2f2;
181
+ padding-bottom: 5px;
182
+ }
183
+ /* Library */
184
+ .column-wio_optimized_file .wio-datas-actions-links a {
185
+ margin: 0 .7em;
186
+ padding-left: 15px;
187
+ }
188
+
189
+ /* Media edition */
190
+ .compat-field-wio .wio-datas-actions-links a,
191
+ .misc-pub-wio .wio-datas-actions-links a {
192
+ font-size: 10px;
193
+ float: left;
194
+ width: 50%;
195
+ }
196
+ .media-sidebar .compat-field-wio .wio-datas-actions-links a,
197
+ .submitbox .misc-pub-wio .wio-datas-actions-links a {
198
+ display: block;
199
+ width: auto;
200
+ float: none;
201
+ }
202
+ .wio-datas-actions-links a:only-child {
203
+ float: none;
204
+ width: auto;
205
+ }
206
+ .wio-datas-details.is-open + .wio-datas-actions-links {
207
+ border-top-color: rgba(0,0,0,.075);
208
+ }
209
+ .wio-datas-actions-links .dashicons {
210
+ position: absolute;
211
+ left: 0; top: 4px;
212
+ width: 12px;
213
+ margin-right: 2px;
214
+ font-size: 11px;
215
+ }
admin/assets/css/settings-premium.css CHANGED
@@ -1,17 +1,17 @@
1
- button[data-value="googlepage"]:after, button[data-value="background"]: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
- }
1
+ button[data-value="googlepage"]:after, button[data-value="background"]: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/statistic.css CHANGED
@@ -1,410 +1,410 @@
1
-
2
- /**
3
- * == Columns
4
- */
5
- .wio-columns {
6
- overflow: hidden;
7
- padding: 15px 0;
8
- counter-reset: cols;
9
- }
10
-
11
- .wio-columns [class^="col-"] {
12
- float: left;
13
- -webkit-box-sizing: border-box;
14
- -moz-box-sizing: border-box;
15
- box-sizing: border-box;
16
- }
17
-
18
- .wio-columns .col-1-3 {
19
- width: 33.333%;
20
- padding-left: 28px;
21
- }
22
-
23
- .wio .col-2-3 {
24
- width: 66.666%;
25
- padding-left: 28px
26
- }
27
-
28
- .wio .col-1-2 {
29
- width: 50%;
30
- padding: 0 20px;
31
- }
32
-
33
- @media (max-width: 830px) {
34
- .wio [class^="col-"] {
35
- float: none;
36
- margin-bottom: 1.5em;
37
- }
38
-
39
- .wio .col-1-3,
40
- .wio .col-1-2 {
41
- width: auto;
42
- padding: 0 28px;
43
- clear: both;
44
- padding-top: 1em;
45
- }
46
- }
47
-
48
- /* Col, behavior depending on parent */
49
- .wio-col {
50
- float: left;
51
- width: 50%;
52
- box-sizing: border-box;
53
- -webkit-flex-basis: 50%;
54
- -ms-flex-preferred-size: 50%;
55
- flex-basis: 50%;
56
- }
57
-
58
- .wio-col {
59
- padding-right: 20px;
60
- }
61
-
62
- .wio-col + .wio-col {
63
- padding-right: 0;
64
- padding-left: 50px;
65
- }
66
-
67
- .wio-col:target {
68
- animation: wiohello 1s 3 linear backwards;
69
- }
70
-
71
- @keyframes wiohello {
72
- 0%, 100% {
73
- background: #FFF;
74
- }
75
- 50% {
76
- background: #F4F7F9;
77
- }
78
- }
79
-
80
- .wio-columns .col-statistics.col-statistics {
81
- width: 60%;
82
- }
83
-
84
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
85
- .wio-columns .col-statistics.col-statistics,
86
- .wio-columns .col-chart.col-chart {
87
- width: 50%;
88
- }
89
- }
90
-
91
- @media (max-width: 808px) {
92
- .wio-columns .col-statistics.col-statistics,
93
- .wio-columns .col-chart.col-chart {
94
- width: auto;
95
- float: none;
96
- padding: 0;
97
- }
98
-
99
- .wio-columns .col-chart.col-chart {
100
- margin-top: 3em;
101
- }
102
- }
103
-
104
- /* Number display */
105
- .wio-number-you-optimized {
106
- margin-bottom: 1.35em;
107
- overflow: hidden;
108
- }
109
-
110
- .wio-number-you-optimized .number {
111
- display: table-cell;
112
- padding-right: 15px;
113
- font-size: 48px;
114
- font-weight: bold;
115
- line-height: 1;
116
- vertical-align: middle;
117
- white-space: nowrap;
118
- color: #000;
119
- }
120
-
121
- .wio-number-you-optimized [id="wio-total-optimized-attachments-pct"] {
122
- color: #40B1D0;
123
- }
124
-
125
- .wio-number-you-optimized .text {
126
- display: table-cell;
127
- vertical-align: middle;
128
- overflow: hidden;
129
- font-size: 12px;
130
- color: #626E7B;
131
- }
132
-
133
- .wio-number-you-optimized > p {
134
- display: table;
135
- }
136
-
137
- /* Number and bars */
138
- .wio-bars {
139
- padding-right: 15px;
140
- }
141
-
142
- .wio-bars p {
143
- font-size: 12px;
144
- margin-bottom: 5px;
145
- }
146
-
147
- .wio-bars + .wio-number-you-optimized {
148
- border-bottom: 0;
149
- padding-top: 0.85em;
150
- }
151
-
152
- .wio-bars + .wio-number-you-optimized p {
153
- color: #46b1ce;
154
- }
155
-
156
- .wio-bar-negative .wio-progress {
157
- background: #D2D3D6;
158
- }
159
-
160
- .wio-bar-negative .wio-barnb {
161
- color: #7A8996;
162
- }
163
-
164
- .wio-bar-neutral .wio-progress {
165
- background: #F5A623;
166
- }
167
-
168
- .wio-space-left .wio-bar-negative .wio-progress {
169
- background: #C51162;
170
- }
171
-
172
- .wio-progress {
173
- height: 8px;
174
- }
175
-
176
- .wio-progress {
177
- transition: width .3s;
178
- }
179
-
180
- .wio-bar-positive .wio-progress {
181
- background: #8CC152;
182
- }
183
-
184
- .wio-bar-positive .wio-barnb {
185
- color: #8CC152;
186
- }
187
-
188
- .wio-bar-primary .wio-progress {
189
- background: #8bc34a;
190
- }
191
-
192
- .wio-bar-primary .wio-barnb {
193
- color: #8bc34a;
194
- }
195
-
196
- .right-outside-number .wio-barnb {
197
- display: block;
198
- margin-right: -5.25em;
199
- text-align: right;
200
- font-weight: bold;
201
- line-height: .8;
202
- }
203
-
204
-
205
- /* Doughnut */
206
- .wio-chart {
207
- position: relative;
208
- top: 1px;
209
- display: inline-block;
210
- vertical-align: middle;
211
- }
212
-
213
- .wio-chart-container {
214
- position: relative;
215
- display: inline-block;
216
- margin-right: 5px;
217
- }
218
-
219
- .wio-chart-container canvas {
220
- display: block;
221
- }
222
-
223
- .wio-overview-chart-container {
224
- float: left;
225
- margin-right: 20px;
226
- }
227
-
228
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
229
- .wio-overview-chart-container {
230
- float: none;
231
- margin-right: 0;
232
- }
233
- }
234
-
235
- .wio-chart-percent {
236
- position: absolute;
237
- left: 0;
238
- right: 0;
239
- top: 50%;
240
- margin-top: -.5em;
241
- line-height: 1;
242
- text-align: center;
243
- font-size: 55px;
244
- font-weight: bold;
245
- color: #afafaf;
246
- }
247
-
248
- .wio-chart-percent span {
249
- font-size: 20px;
250
- vertical-align: super;
251
- }
252
-
253
- #wio-overview-chart-legend {
254
- overflow: hidden;
255
- }
256
-
257
- .imagify-doughnut-legend {
258
- margin-top: 38px;
259
- list-style: none;
260
- }
261
-
262
- .wio-doughnut-legend li {
263
- display: inline-block;
264
- padding-left: 30px;
265
- position: relative;
266
- margin-bottom: 15px;
267
- border-radius: 5px;
268
- padding: 3px 8px 2px 31px;
269
- font-size: 13px;
270
- cursor: default;
271
- -webkit-transition: background-color 200ms ease-in-out;
272
- -moz-transition: background-color 200ms ease-in-out;
273
- -o-transition: background-color 200ms ease-in-out;
274
- transition: background-color 200ms ease-in-out;
275
- }
276
-
277
- .wio-doughnut-legend li span {
278
- display: block;
279
- position: absolute;
280
- left: 0;
281
- top: 0;
282
- width: 25px;
283
- height: 25px;
284
- border-radius: 50%;
285
- }
286
-
287
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
288
- .wio-overview-chart-container {
289
- float: none;
290
- margin-right: 0;
291
- }
292
-
293
- .wio-doughnut-legend {
294
- margin-top: 18px;
295
- }
296
-
297
- .wio-global-optim-phrase {
298
- padding-top: 0;
299
- width: auto;
300
- }
301
- }
302
-
303
- .wio-global-optim-phrase {
304
- width: 180px;
305
- padding-top: 20px;
306
- font-size: 14px;
307
- text-align: center;
308
- }
309
-
310
- .wio-clear {
311
- clear: both;
312
- }
313
-
314
- .wio-total-percent {
315
- color: #46b1ce;
316
- }
317
-
318
- .wio-columns .col-chart.col-chart {
319
- width: 40%;
320
- position: relative;
321
- padding: 20px;
322
- font-size: 12px;
323
- text-transform: uppercase;
324
- background: #f1f1f1b3;
325
- color: #abacaf;
326
- font-weight: bold;
327
- border-radius: 5px;
328
- margin-top: 10px;
329
- text-align: left;
330
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
331
- }
332
-
333
- .wio-image-optimize-board {
334
- padding-bottom: 0 !important;
335
- }
336
-
337
- .wio-optimize-button {
338
- width: 180px;
339
- padding: 12px 30px;
340
- background: #c9deb2;
341
- color: #586549;
342
- border: 0;
343
- box-shadow: none;
344
- font-size: 16px;
345
- text-transform: uppercase !important;
346
- font-weight: bold;
347
- border-radius: 4px;
348
- outline: none;
349
- }
350
-
351
- .wio-optimize-button:active {
352
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
353
- }
354
-
355
- .wio-optimize-button.running {
356
- color: #a57b3c;
357
- background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
358
- }
359
-
360
- .wio-widget-bottom {
361
- display: table;
362
- padding-top: 20px !important;
363
- width: 100%;
364
- text-align: right;
365
- }
366
-
367
- .wio-widget-bottom li {
368
- display: table-cell;
369
- }
370
-
371
- .wio-widget-bottom li:first-child {
372
- text-align: left;
373
- }
374
-
375
- .wio-imagify-widget {
376
- padding: 0 !important;
377
- }
378
-
379
- .wio-imagify-widget .wio-bars {
380
- width: 60%;
381
- margin-left: 155px;
382
- }
383
-
384
- .wio-imagify-widget .col-chart.col-chart {
385
- width: 100%;
386
- }
387
-
388
- .wio-imagify-widget .col-controls {
389
- width: 45%;
390
- padding-left: 5px;
391
- padding-top: 110px
392
- }
393
-
394
- .wio-imagify-widget .wio-doughnut-legend {
395
- /*padding-top:30px;*/
396
- text-align: left;
397
- }
398
-
399
- #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
400
- display: none;
401
- }
402
-
403
- .wio-text-left {
404
- text-align: left;
405
- }
406
-
407
- span.wio-num {
408
- display: inline !important;
409
- position: inherit !important;
410
- }
1
+
2
+ /**
3
+ * == Columns
4
+ */
5
+ .wio-columns {
6
+ overflow: hidden;
7
+ padding: 15px 0;
8
+ counter-reset: cols;
9
+ }
10
+
11
+ .wio-columns [class^="col-"] {
12
+ float: left;
13
+ -webkit-box-sizing: border-box;
14
+ -moz-box-sizing: border-box;
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ .wio-columns .col-1-3 {
19
+ width: 33.333%;
20
+ padding-left: 28px;
21
+ }
22
+
23
+ .wio .col-2-3 {
24
+ width: 66.666%;
25
+ padding-left: 28px
26
+ }
27
+
28
+ .wio .col-1-2 {
29
+ width: 50%;
30
+ padding: 0 20px;
31
+ }
32
+
33
+ @media (max-width: 830px) {
34
+ .wio [class^="col-"] {
35
+ float: none;
36
+ margin-bottom: 1.5em;
37
+ }
38
+
39
+ .wio .col-1-3,
40
+ .wio .col-1-2 {
41
+ width: auto;
42
+ padding: 0 28px;
43
+ clear: both;
44
+ padding-top: 1em;
45
+ }
46
+ }
47
+
48
+ /* Col, behavior depending on parent */
49
+ .wio-col {
50
+ float: left;
51
+ width: 50%;
52
+ box-sizing: border-box;
53
+ -webkit-flex-basis: 50%;
54
+ -ms-flex-preferred-size: 50%;
55
+ flex-basis: 50%;
56
+ }
57
+
58
+ .wio-col {
59
+ padding-right: 20px;
60
+ }
61
+
62
+ .wio-col + .wio-col {
63
+ padding-right: 0;
64
+ padding-left: 50px;
65
+ }
66
+
67
+ .wio-col:target {
68
+ animation: wiohello 1s 3 linear backwards;
69
+ }
70
+
71
+ @keyframes wiohello {
72
+ 0%, 100% {
73
+ background: #FFF;
74
+ }
75
+ 50% {
76
+ background: #F4F7F9;
77
+ }
78
+ }
79
+
80
+ .wio-columns .col-statistics.col-statistics {
81
+ width: 60%;
82
+ }
83
+
84
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
85
+ .wio-columns .col-statistics.col-statistics,
86
+ .wio-columns .col-chart.col-chart {
87
+ width: 50%;
88
+ }
89
+ }
90
+
91
+ @media (max-width: 808px) {
92
+ .wio-columns .col-statistics.col-statistics,
93
+ .wio-columns .col-chart.col-chart {
94
+ width: auto;
95
+ float: none;
96
+ padding: 0;
97
+ }
98
+
99
+ .wio-columns .col-chart.col-chart {
100
+ margin-top: 3em;
101
+ }
102
+ }
103
+
104
+ /* Number display */
105
+ .wio-number-you-optimized {
106
+ margin-bottom: 1.35em;
107
+ overflow: hidden;
108
+ }
109
+
110
+ .wio-number-you-optimized .number {
111
+ display: table-cell;
112
+ padding-right: 15px;
113
+ font-size: 48px;
114
+ font-weight: bold;
115
+ line-height: 1;
116
+ vertical-align: middle;
117
+ white-space: nowrap;
118
+ color: #000;
119
+ }
120
+
121
+ .wio-number-you-optimized [id="wio-total-optimized-attachments-pct"] {
122
+ color: #40B1D0;
123
+ }
124
+
125
+ .wio-number-you-optimized .text {
126
+ display: table-cell;
127
+ vertical-align: middle;
128
+ overflow: hidden;
129
+ font-size: 12px;
130
+ color: #626E7B;
131
+ }
132
+
133
+ .wio-number-you-optimized > p {
134
+ display: table;
135
+ }
136
+
137
+ /* Number and bars */
138
+ .wio-bars {
139
+ padding-right: 15px;
140
+ }
141
+
142
+ .wio-bars p {
143
+ font-size: 12px;
144
+ margin-bottom: 5px;
145
+ }
146
+
147
+ .wio-bars + .wio-number-you-optimized {
148
+ border-bottom: 0;
149
+ padding-top: 0.85em;
150
+ }
151
+
152
+ .wio-bars + .wio-number-you-optimized p {
153
+ color: #46b1ce;
154
+ }
155
+
156
+ .wio-bar-negative .wio-progress {
157
+ background: #D2D3D6;
158
+ }
159
+
160
+ .wio-bar-negative .wio-barnb {
161
+ color: #7A8996;
162
+ }
163
+
164
+ .wio-bar-neutral .wio-progress {
165
+ background: #F5A623;
166
+ }
167
+
168
+ .wio-space-left .wio-bar-negative .wio-progress {
169
+ background: #C51162;
170
+ }
171
+
172
+ .wio-progress {
173
+ height: 8px;
174
+ }
175
+
176
+ .wio-progress {
177
+ transition: width .3s;
178
+ }
179
+
180
+ .wio-bar-positive .wio-progress {
181
+ background: #8CC152;
182
+ }
183
+
184
+ .wio-bar-positive .wio-barnb {
185
+ color: #8CC152;
186
+ }
187
+
188
+ .wio-bar-primary .wio-progress {
189
+ background: #8bc34a;
190
+ }
191
+
192
+ .wio-bar-primary .wio-barnb {
193
+ color: #8bc34a;
194
+ }
195
+
196
+ .right-outside-number .wio-barnb {
197
+ display: block;
198
+ margin-right: -5.25em;
199
+ text-align: right;
200
+ font-weight: bold;
201
+ line-height: .8;
202
+ }
203
+
204
+
205
+ /* Doughnut */
206
+ .wio-chart {
207
+ position: relative;
208
+ top: 1px;
209
+ display: inline-block;
210
+ vertical-align: middle;
211
+ }
212
+
213
+ .wio-chart-container {
214
+ position: relative;
215
+ display: inline-block;
216
+ margin-right: 5px;
217
+ }
218
+
219
+ .wio-chart-container canvas {
220
+ display: block;
221
+ }
222
+
223
+ .wio-overview-chart-container {
224
+ float: left;
225
+ margin-right: 20px;
226
+ }
227
+
228
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
229
+ .wio-overview-chart-container {
230
+ float: none;
231
+ margin-right: 0;
232
+ }
233
+ }
234
+
235
+ .wio-chart-percent {
236
+ position: absolute;
237
+ left: 0;
238
+ right: 0;
239
+ top: 50%;
240
+ margin-top: -.5em;
241
+ line-height: 1;
242
+ text-align: center;
243
+ font-size: 55px;
244
+ font-weight: bold;
245
+ color: #afafaf;
246
+ }
247
+
248
+ .wio-chart-percent span {
249
+ font-size: 20px;
250
+ vertical-align: super;
251
+ }
252
+
253
+ #wio-overview-chart-legend {
254
+ overflow: hidden;
255
+ }
256
+
257
+ .imagify-doughnut-legend {
258
+ margin-top: 38px;
259
+ list-style: none;
260
+ }
261
+
262
+ .wio-doughnut-legend li {
263
+ display: inline-block;
264
+ padding-left: 30px;
265
+ position: relative;
266
+ margin-bottom: 15px;
267
+ border-radius: 5px;
268
+ padding: 3px 8px 2px 31px;
269
+ font-size: 13px;
270
+ cursor: default;
271
+ -webkit-transition: background-color 200ms ease-in-out;
272
+ -moz-transition: background-color 200ms ease-in-out;
273
+ -o-transition: background-color 200ms ease-in-out;
274
+ transition: background-color 200ms ease-in-out;
275
+ }
276
+
277
+ .wio-doughnut-legend li span {
278
+ display: block;
279
+ position: absolute;
280
+ left: 0;
281
+ top: 0;
282
+ width: 25px;
283
+ height: 25px;
284
+ border-radius: 50%;
285
+ }
286
+
287
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
288
+ .wio-overview-chart-container {
289
+ float: none;
290
+ margin-right: 0;
291
+ }
292
+
293
+ .wio-doughnut-legend {
294
+ margin-top: 18px;
295
+ }
296
+
297
+ .wio-global-optim-phrase {
298
+ padding-top: 0;
299
+ width: auto;
300
+ }
301
+ }
302
+
303
+ .wio-global-optim-phrase {
304
+ width: 180px;
305
+ padding-top: 20px;
306
+ font-size: 14px;
307
+ text-align: center;
308
+ }
309
+
310
+ .wio-clear {
311
+ clear: both;
312
+ }
313
+
314
+ .wio-total-percent {
315
+ color: #46b1ce;
316
+ }
317
+
318
+ .wio-columns .col-chart.col-chart {
319
+ width: 40%;
320
+ position: relative;
321
+ padding: 20px;
322
+ font-size: 12px;
323
+ text-transform: uppercase;
324
+ background: #f1f1f1b3;
325
+ color: #abacaf;
326
+ font-weight: bold;
327
+ border-radius: 5px;
328
+ margin-top: 10px;
329
+ text-align: left;
330
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
331
+ }
332
+
333
+ .wio-image-optimize-board {
334
+ padding-bottom: 0 !important;
335
+ }
336
+
337
+ .wio-optimize-button {
338
+ width: 180px;
339
+ padding: 12px 30px;
340
+ background: #c9deb2;
341
+ color: #586549;
342
+ border: 0;
343
+ box-shadow: none;
344
+ font-size: 16px;
345
+ text-transform: uppercase !important;
346
+ font-weight: bold;
347
+ border-radius: 4px;
348
+ outline: none;
349
+ }
350
+
351
+ .wio-optimize-button:active {
352
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
353
+ }
354
+
355
+ .wio-optimize-button.running {
356
+ color: #a57b3c;
357
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
358
+ }
359
+
360
+ .wio-widget-bottom {
361
+ display: table;
362
+ padding-top: 20px !important;
363
+ width: 100%;
364
+ text-align: right;
365
+ }
366
+
367
+ .wio-widget-bottom li {
368
+ display: table-cell;
369
+ }
370
+
371
+ .wio-widget-bottom li:first-child {
372
+ text-align: left;
373
+ }
374
+
375
+ .wio-imagify-widget {
376
+ padding: 0 !important;
377
+ }
378
+
379
+ .wio-imagify-widget .wio-bars {
380
+ width: 60%;
381
+ margin-left: 155px;
382
+ }
383
+
384
+ .wio-imagify-widget .col-chart.col-chart {
385
+ width: 100%;
386
+ }
387
+
388
+ .wio-imagify-widget .col-controls {
389
+ width: 45%;
390
+ padding-left: 5px;
391
+ padding-top: 110px
392
+ }
393
+
394
+ .wio-imagify-widget .wio-doughnut-legend {
395
+ /*padding-top:30px;*/
396
+ text-align: left;
397
+ }
398
+
399
+ #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
400
+ display: none;
401
+ }
402
+
403
+ .wio-text-left {
404
+ text-align: left;
405
+ }
406
+
407
+ span.wio-num {
408
+ display: inline !important;
409
+ position: inherit !important;
410
+ }
admin/assets/css/sweetalert-custom.css CHANGED
@@ -1,155 +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: 5px 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
- }
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: 5px 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/css/sweetalert-custom.less CHANGED
@@ -1,185 +1,185 @@
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
-
7
- .wrio-modal {
8
- padding: 0 !important;
9
-
10
- .swal2-close {
11
- color: rgba(0, 0, 0, .8);
12
- }
13
-
14
- .swal2-modal {
15
- border-radius: 2px;
16
- }
17
-
18
- .swal2-icon {
19
- margin-bottom: 25px;
20
- }
21
-
22
- .swal2-title {
23
- margin: 0;
24
- padding: 28px 32px;
25
- font-size: 24px;
26
- text-align: left;
27
- color: #fff !important;
28
- background: #3e3e3e !important;
29
- }
30
-
31
- .swal2-content {
32
- font-size: 14px;
33
- padding: 28px 32px;
34
- background: #efefef;
35
- }
36
-
37
- .swal2-buttonswrapper {
38
- margin-top: 0;
39
- padding: 22px;
40
- background: #F4F7F9;
41
-
42
- a.button svg {
43
- margin-right: 12px;
44
- vertical-align: -2px;
45
- }
46
-
47
- button.loading {
48
- border-radius: 100% !important;
49
- height: 40px !important;
50
- padding: 0 !important;
51
- box-shadow: none !important;
52
- }
53
-
54
- button.swal2-styled {
55
- height: auto;
56
- padding: 12px 32px;
57
- margin: 10px;
58
- font-size: 14px;
59
- letter-spacing: 1px;
60
- text-transform: uppercase;
61
- border-radius: 3px;
62
- font-weight: bold;
63
- outline: none;
64
-
65
- &.swal2-confirm {
66
- background-color: #fdd599 !important;
67
- text-shadow: none !important;
68
- box-shadow: 0 3px 0 #ceac7a !important;
69
- color: #a57b3c !important;
70
- }
71
-
72
- &.swal2-cancel {
73
- background-color: #d2d2d2 !important;
74
- color: #656464 !important;
75
- text-shadow: none !important;
76
- box-shadow: 0 3px 0 #a9a9a9;
77
- /*background-color: #c9deb2 !important;
78
- color: #606956 !important;
79
- text-shadow: none !important;
80
- box-shadow: 0 3px 0 #a7b994;*/
81
- }
82
-
83
- &:focus, &:hover {
84
- outline: none;
85
- text-shadow: none;
86
- color: #FFF;
87
- }
88
- }
89
- }
90
- }
91
-
92
- .wrio-modal-warning {
93
- background: #FF5722 !important;
94
-
95
- .swal2-title {
96
- text-align: center;
97
- color: #222 !important;
98
- background: #efefef !important;
99
- }
100
-
101
- .swal2-content {
102
- font-size: 16px;
103
- padding: 10px 20px 32px;
104
- background: #efefef;
105
- }
106
-
107
- .swal2-buttonswrapper {
108
- background: #efefef;
109
- }
110
- }
111
-
112
- .wrio-modal-error {
113
- background: #dec2c0 !important;
114
-
115
- .swal2-title {
116
- text-align: center;
117
- color: #222 !important;
118
- background: #efefef !important;
119
- }
120
-
121
- .swal2-content {
122
- font-size: 16px;
123
- padding: 10px 20px 32px;
124
- background: #efefef;
125
- }
126
-
127
- .swal2-buttonswrapper {
128
- background: #efefef;
129
- }
130
- }
131
-
132
- .wrio-modal-optimization-way {
133
- background: #1F2332 !important;
134
-
135
- .wrio-swal-subtitle {
136
- padding: 0 0 28px;
137
- margin-top: 0px;
138
- font-weight: 500;
139
- font-size: 18px;
140
- text-align: left;
141
- color: #8c8888;
142
- background: #efefef;
143
- }
144
-
145
- .wrio-list-infos {
146
- margin: 0;
147
- padding: 0;
148
-
149
- li {
150
- display: flex;
151
- align-items: center;
152
- padding: 15px 5px;
153
- text-align: left;
154
- font-size: 14px;
155
- line-height: 1.5;
156
- color: #8c8888;
157
- }
158
-
159
- li:first-child {
160
- padding-top: 5px;
161
- }
162
-
163
- li:last-child {
164
- padding-bottom: 5px;
165
- }
166
-
167
- li + li {
168
- border-top: 1px solid #E9EFF2;
169
- }
170
-
171
- a:before {
172
- content: '';
173
- display: block;
174
- }
175
- }
176
-
177
- .wrio-info-icon {
178
- flex-grow: 0;
179
- flex-basis: 50px;
180
- }
181
-
182
- .wrio-info-icon + span {
183
- padding-left: 20px;
184
- }
185
- }
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
+
7
+ .wrio-modal {
8
+ padding: 0 !important;
9
+
10
+ .swal2-close {
11
+ color: rgba(0, 0, 0, .8);
12
+ }
13
+
14
+ .swal2-modal {
15
+ border-radius: 2px;
16
+ }
17
+
18
+ .swal2-icon {
19
+ margin-bottom: 25px;
20
+ }
21
+
22
+ .swal2-title {
23
+ margin: 0;
24
+ padding: 28px 32px;
25
+ font-size: 24px;
26
+ text-align: left;
27
+ color: #fff !important;
28
+ background: #3e3e3e !important;
29
+ }
30
+
31
+ .swal2-content {
32
+ font-size: 14px;
33
+ padding: 28px 32px;
34
+ background: #efefef;
35
+ }
36
+
37
+ .swal2-buttonswrapper {
38
+ margin-top: 0;
39
+ padding: 22px;
40
+ background: #F4F7F9;
41
+
42
+ a.button svg {
43
+ margin-right: 12px;
44
+ vertical-align: -2px;
45
+ }
46
+
47
+ button.loading {
48
+ border-radius: 100% !important;
49
+ height: 40px !important;
50
+ padding: 0 !important;
51
+ box-shadow: none !important;
52
+ }
53
+
54
+ button.swal2-styled {
55
+ height: auto;
56
+ padding: 12px 32px;
57
+ margin: 10px;
58
+ font-size: 14px;
59
+ letter-spacing: 1px;
60
+ text-transform: uppercase;
61
+ border-radius: 3px;
62
+ font-weight: bold;
63
+ outline: none;
64
+
65
+ &.swal2-confirm {
66
+ background-color: #fdd599 !important;
67
+ text-shadow: none !important;
68
+ box-shadow: 0 3px 0 #ceac7a !important;
69
+ color: #a57b3c !important;
70
+ }
71
+
72
+ &.swal2-cancel {
73
+ background-color: #d2d2d2 !important;
74
+ color: #656464 !important;
75
+ text-shadow: none !important;
76
+ box-shadow: 0 3px 0 #a9a9a9;
77
+ /*background-color: #c9deb2 !important;
78
+ color: #606956 !important;
79
+ text-shadow: none !important;
80
+ box-shadow: 0 3px 0 #a7b994;*/
81
+ }
82
+
83
+ &:focus, &:hover {
84
+ outline: none;
85
+ text-shadow: none;
86
+ color: #FFF;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ .wrio-modal-warning {
93
+ background: #FF5722 !important;
94
+
95
+ .swal2-title {
96
+ text-align: center;
97
+ color: #222 !important;
98
+ background: #efefef !important;
99
+ }
100
+
101
+ .swal2-content {
102
+ font-size: 16px;
103
+ padding: 10px 20px 32px;
104
+ background: #efefef;
105
+ }
106
+
107
+ .swal2-buttonswrapper {
108
+ background: #efefef;
109
+ }
110
+ }
111
+
112
+ .wrio-modal-error {
113
+ background: #dec2c0 !important;
114
+
115
+ .swal2-title {
116
+ text-align: center;
117
+ color: #222 !important;
118
+ background: #efefef !important;
119
+ }
120
+
121
+ .swal2-content {
122
+ font-size: 16px;
123
+ padding: 10px 20px 32px;
124
+ background: #efefef;
125
+ }
126
+
127
+ .swal2-buttonswrapper {
128
+ background: #efefef;
129
+ }
130
+ }
131
+
132
+ .wrio-modal-optimization-way {
133
+ background: #1F2332 !important;
134
+
135
+ .wrio-swal-subtitle {
136
+ padding: 0 0 28px;
137
+ margin-top: 0px;
138
+ font-weight: 500;
139
+ font-size: 18px;
140
+ text-align: left;
141
+ color: #8c8888;
142
+ background: #efefef;
143
+ }
144
+
145
+ .wrio-list-infos {
146
+ margin: 0;
147
+ padding: 0;
148
+
149
+ li {
150
+ display: flex;
151
+ align-items: center;
152
+ padding: 15px 5px;
153
+ text-align: left;
154
+ font-size: 14px;
155
+ line-height: 1.5;
156
+ color: #8c8888;
157
+ }
158
+
159
+ li:first-child {
160
+ padding-top: 5px;
161
+ }
162
+
163
+ li:last-child {
164
+ padding-bottom: 5px;
165
+ }
166
+
167
+ li + li {
168
+ border-top: 1px solid #E9EFF2;
169
+ }
170
+
171
+ a:before {
172
+ content: '';
173
+ display: block;
174
+ }
175
+ }
176
+
177
+ .wrio-info-icon {
178
+ flex-grow: 0;
179
+ flex-basis: 50px;
180
+ }
181
+
182
+ .wrio-info-icon + span {
183
+ padding-left: 20px;
184
+ }
185
+ }
admin/assets/css/sweetalert2.css CHANGED
@@ -1,716 +1,716 @@
1
- body.swal2-shown {
2
- overflow-y: hidden; }
3
-
4
- body.swal2-iosfix {
5
- position: fixed;
6
- left: 0;
7
- right: 0; }
8
-
9
- .swal2-container {
10
- display: -webkit-box;
11
- display: -ms-flexbox;
12
- display: flex;
13
- -webkit-box-align: center;
14
- -ms-flex-align: center;
15
- align-items: center;
16
- position: fixed;
17
- top: 0;
18
- left: 0;
19
- bottom: 0;
20
- right: 0;
21
- padding: 10px;
22
- background-color: transparent;
23
- z-index: 1060; }
24
- .swal2-container.swal2-fade {
25
- -webkit-transition: background-color .1s;
26
- transition: background-color .1s; }
27
- .swal2-container.swal2-shown {
28
- background-color: rgba(0, 0, 0, 0.4); }
29
-
30
- .swal2-modal {
31
- background-color: #fff;
32
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
33
- border-radius: 5px;
34
- -webkit-box-sizing: border-box;
35
- box-sizing: border-box;
36
- text-align: center;
37
- margin: auto;
38
- overflow-x: hidden;
39
- overflow-y: auto;
40
- display: none;
41
- position: relative;
42
- max-width: 100%; }
43
- .swal2-modal:focus {
44
- outline: none; }
45
- .swal2-modal.swal2-loading {
46
- overflow-y: hidden; }
47
- .swal2-modal .swal2-title {
48
- color: #595959;
49
- font-size: 30px;
50
- text-align: center;
51
- font-weight: 600;
52
- text-transform: none;
53
- position: relative;
54
- margin: 0 0 .4em;
55
- padding: 0;
56
- display: block;
57
- word-wrap: break-word; }
58
- .swal2-modal .swal2-buttonswrapper {
59
- margin-top: 15px; }
60
- .swal2-modal .swal2-buttonswrapper:not(.swal2-loading) .swal2-styled[disabled] {
61
- opacity: .4;
62
- cursor: no-drop; }
63
- .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-confirm {
64
- -webkit-box-sizing: border-box;
65
- box-sizing: border-box;
66
- border: 4px solid transparent;
67
- border-color: transparent;
68
- width: 40px;
69
- height: 40px;
70
- padding: 0;
71
- margin: 7.5px;
72
- vertical-align: top;
73
- background-color: transparent !important;
74
- color: transparent;
75
- cursor: default;
76
- border-radius: 100%;
77
- -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
78
- animation: rotate-loading 1.5s linear 0s infinite normal;
79
- -webkit-user-select: none;
80
- -moz-user-select: none;
81
- -ms-user-select: none;
82
- user-select: none; }
83
- .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-cancel {
84
- margin-left: 30px;
85
- margin-right: 30px; }
86
- .swal2-modal .swal2-buttonswrapper.swal2-loading :not(.swal2-styled).swal2-confirm::after {
87
- display: inline-block;
88
- content: '';
89
- margin-left: 5px 0 15px;
90
- vertical-align: -1px;
91
- height: 15px;
92
- width: 15px;
93
- border: 3px solid #999999;
94
- -webkit-box-shadow: 1px 1px 1px #fff;
95
- box-shadow: 1px 1px 1px #fff;
96
- border-right-color: transparent;
97
- border-radius: 50%;
98
- -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
99
- animation: rotate-loading 1.5s linear 0s infinite normal; }
100
- .swal2-modal .swal2-styled {
101
- border: 0;
102
- border-radius: 3px;
103
- -webkit-box-shadow: none;
104
- box-shadow: none;
105
- color: #fff;
106
- cursor: pointer;
107
- font-size: 17px;
108
- font-weight: 500;
109
- margin: 15px 5px 0;
110
- padding: 10px 32px; }
111
- .swal2-modal .swal2-image {
112
- margin: 20px auto;
113
- max-width: 100%; }
114
- .swal2-modal .swal2-close {
115
- background: transparent;
116
- border: 0;
117
- margin: 0;
118
- padding: 0;
119
- width: 38px;
120
- height: 40px;
121
- font-size: 36px;
122
- line-height: 40px;
123
- font-family: serif;
124
- position: absolute;
125
- top: 5px;
126
- right: 8px;
127
- cursor: pointer;
128
- color: #cccccc;
129
- -webkit-transition: color .1s ease;
130
- transition: color .1s ease; }
131
- .swal2-modal .swal2-close:hover {
132
- color: #d55; }
133
- .swal2-modal > .swal2-input,
134
- .swal2-modal > .swal2-file,
135
- .swal2-modal > .swal2-textarea,
136
- .swal2-modal > .swal2-select,
137
- .swal2-modal > .swal2-radio,
138
- .swal2-modal > .swal2-checkbox {
139
- display: none; }
140
- .swal2-modal .swal2-content {
141
- font-size: 18px;
142
- text-align: center;
143
- font-weight: 300;
144
- position: relative;
145
- float: none;
146
- margin: 0;
147
- padding: 0;
148
- line-height: normal;
149
- color: #545454;
150
- word-wrap: break-word; }
151
- .swal2-modal .swal2-input,
152
- .swal2-modal .swal2-file,
153
- .swal2-modal .swal2-textarea,
154
- .swal2-modal .swal2-select,
155
- .swal2-modal .swal2-radio,
156
- .swal2-modal .swal2-checkbox {
157
- margin: 20px auto; }
158
- .swal2-modal .swal2-input,
159
- .swal2-modal .swal2-file,
160
- .swal2-modal .swal2-textarea {
161
- width: 100%;
162
- -webkit-box-sizing: border-box;
163
- box-sizing: border-box;
164
- font-size: 18px;
165
- border-radius: 3px;
166
- border: 1px solid #d9d9d9;
167
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
168
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
169
- -webkit-transition: border-color box-shadow .3s;
170
- transition: border-color box-shadow .3s; }
171
- .swal2-modal .swal2-input.swal2-inputerror,
172
- .swal2-modal .swal2-file.swal2-inputerror,
173
- .swal2-modal .swal2-textarea.swal2-inputerror {
174
- border-color: #f27474 !important;
175
- -webkit-box-shadow: 0 0 2px #f27474 !important;
176
- box-shadow: 0 0 2px #f27474 !important; }
177
- .swal2-modal .swal2-input:focus,
178
- .swal2-modal .swal2-file:focus,
179
- .swal2-modal .swal2-textarea:focus {
180
- outline: none;
181
- border: 1px solid #b4dbed;
182
- -webkit-box-shadow: 0 0 3px #c4e6f5;
183
- box-shadow: 0 0 3px #c4e6f5; }
184
- .swal2-modal .swal2-input:focus::-webkit-input-placeholder,
185
- .swal2-modal .swal2-file:focus::-webkit-input-placeholder,
186
- .swal2-modal .swal2-textarea:focus::-webkit-input-placeholder {
187
- -webkit-transition: opacity .3s .03s ease;
188
- transition: opacity .3s .03s ease;
189
- opacity: .8; }
190
- .swal2-modal .swal2-input:focus:-ms-input-placeholder,
191
- .swal2-modal .swal2-file:focus:-ms-input-placeholder,
192
- .swal2-modal .swal2-textarea:focus:-ms-input-placeholder {
193
- -webkit-transition: opacity .3s .03s ease;
194
- transition: opacity .3s .03s ease;
195
- opacity: .8; }
196
- .swal2-modal .swal2-input:focus::placeholder,
197
- .swal2-modal .swal2-file:focus::placeholder,
198
- .swal2-modal .swal2-textarea:focus::placeholder {
199
- -webkit-transition: opacity .3s .03s ease;
200
- transition: opacity .3s .03s ease;
201
- opacity: .8; }
202
- .swal2-modal .swal2-input::-webkit-input-placeholder,
203
- .swal2-modal .swal2-file::-webkit-input-placeholder,
204
- .swal2-modal .swal2-textarea::-webkit-input-placeholder {
205
- color: #e6e6e6; }
206
- .swal2-modal .swal2-input:-ms-input-placeholder,
207
- .swal2-modal .swal2-file:-ms-input-placeholder,
208
- .swal2-modal .swal2-textarea:-ms-input-placeholder {
209
- color: #e6e6e6; }
210
- .swal2-modal .swal2-input::placeholder,
211
- .swal2-modal .swal2-file::placeholder,
212
- .swal2-modal .swal2-textarea::placeholder {
213
- color: #e6e6e6; }
214
- .swal2-modal .swal2-range input {
215
- float: left;
216
- width: 80%; }
217
- .swal2-modal .swal2-range output {
218
- float: right;
219
- width: 20%;
220
- font-size: 20px;
221
- font-weight: 600;
222
- text-align: center; }
223
- .swal2-modal .swal2-range input,
224
- .swal2-modal .swal2-range output {
225
- height: 43px;
226
- line-height: 43px;
227
- vertical-align: middle;
228
- margin: 20px auto;
229
- padding: 0; }
230
- .swal2-modal .swal2-input {
231
- height: 43px;
232
- padding: 0 12px; }
233
- .swal2-modal .swal2-input[type='number'] {
234
- max-width: 150px; }
235
- .swal2-modal .swal2-file {
236
- font-size: 20px; }
237
- .swal2-modal .swal2-textarea {
238
- height: 108px;
239
- padding: 12px; }
240
- .swal2-modal .swal2-select {
241
- color: #545454;
242
- font-size: inherit;
243
- padding: 5px 10px;
244
- min-width: 40%;
245
- max-width: 100%; }
246
- .swal2-modal .swal2-radio {
247
- border: 0; }
248
- .swal2-modal .swal2-radio label:not(:first-child) {
249
- margin-left: 20px; }
250
- .swal2-modal .swal2-radio input,
251
- .swal2-modal .swal2-radio span {
252
- vertical-align: middle; }
253
- .swal2-modal .swal2-radio input {
254
- margin: 0 3px 0 0; }
255
- .swal2-modal .swal2-checkbox {
256
- color: #545454; }
257
- .swal2-modal .swal2-checkbox input,
258
- .swal2-modal .swal2-checkbox span {
259
- vertical-align: middle; }
260
- .swal2-modal .swal2-validationerror {
261
- background-color: #f0f0f0;
262
- margin: 0 -20px;
263
- overflow: hidden;
264
- padding: 10px;
265
- color: gray;
266
- font-size: 16px;
267
- font-weight: 300;
268
- display: none; }
269
- .swal2-modal .swal2-validationerror::before {
270
- content: '!';
271
- display: inline-block;
272
- width: 24px;
273
- height: 24px;
274
- border-radius: 50%;
275
- background-color: #ea7d7d;
276
- color: #fff;
277
- line-height: 24px;
278
- text-align: center;
279
- margin-right: 10px; }
280
-
281
- @supports (-ms-accelerator: true) {
282
- .swal2-range input {
283
- width: 100% !important; }
284
- .swal2-range output {
285
- display: none; } }
286
-
287
- @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
288
- .swal2-range input {
289
- width: 100% !important; }
290
- .swal2-range output {
291
- display: none; } }
292
-
293
- .swal2-icon {
294
- width: 80px;
295
- height: 80px;
296
- border: 4px solid transparent;
297
- border-radius: 50%;
298
- margin: 20px auto 30px;
299
- padding: 0;
300
- position: relative;
301
- -webkit-box-sizing: content-box;
302
- box-sizing: content-box;
303
- cursor: default;
304
- -webkit-user-select: none;
305
- -moz-user-select: none;
306
- -ms-user-select: none;
307
- user-select: none; }
308
- .swal2-icon.swal2-error {
309
- border-color: #f27474; }
310
- .swal2-icon.swal2-error .swal2-x-mark {
311
- position: relative;
312
- display: block; }
313
- .swal2-icon.swal2-error [class^='swal2-x-mark-line'] {
314
- position: absolute;
315
- height: 5px;
316
- width: 47px;
317
- background-color: #f27474;
318
- display: block;
319
- top: 37px;
320
- border-radius: 2px; }
321
- .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='left'] {
322
- -webkit-transform: rotate(45deg);
323
- transform: rotate(45deg);
324
- left: 17px; }
325
- .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='right'] {
326
- -webkit-transform: rotate(-45deg);
327
- transform: rotate(-45deg);
328
- right: 16px; }
329
- .swal2-icon.swal2-warning {
330
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
331
- color: #f8bb86;
332
- border-color: #facea8;
333
- font-size: 60px;
334
- line-height: 80px;
335
- text-align: center; }
336
- .swal2-icon.swal2-info {
337
- font-family: 'Open Sans', sans-serif;
338
- color: #3fc3ee;
339
- border-color: #9de0f6;
340
- font-size: 60px;
341
- line-height: 80px;
342
- text-align: center; }
343
- .swal2-icon.swal2-question {
344
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
345
- color: #87adbd;
346
- border-color: #c9dae1;
347
- font-size: 60px;
348
- line-height: 80px;
349
- text-align: center; }
350
- .swal2-icon.swal2-success {
351
- border-color: #a5dc86; }
352
- .swal2-icon.swal2-success [class^='swal2-success-circular-line'] {
353
- border-radius: 50%;
354
- position: absolute;
355
- width: 60px;
356
- height: 120px;
357
- -webkit-transform: rotate(45deg);
358
- transform: rotate(45deg); }
359
- .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='left'] {
360
- border-radius: 120px 0 0 120px;
361
- top: -7px;
362
- left: -33px;
363
- -webkit-transform: rotate(-45deg);
364
- transform: rotate(-45deg);
365
- -webkit-transform-origin: 60px 60px;
366
- transform-origin: 60px 60px; }
367
- .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='right'] {
368
- border-radius: 0 120px 120px 0;
369
- top: -11px;
370
- left: 30px;
371
- -webkit-transform: rotate(-45deg);
372
- transform: rotate(-45deg);
373
- -webkit-transform-origin: 0 60px;
374
- transform-origin: 0 60px; }
375
- .swal2-icon.swal2-success .swal2-success-ring {
376
- width: 80px;
377
- height: 80px;
378
- border: 4px solid rgba(165, 220, 134, 0.2);
379
- border-radius: 50%;
380
- -webkit-box-sizing: content-box;
381
- box-sizing: content-box;
382
- position: absolute;
383
- left: -4px;
384
- top: -4px;
385
- z-index: 2; }
386
- .swal2-icon.swal2-success .swal2-success-fix {
387
- width: 7px;
388
- height: 90px;
389
- position: absolute;
390
- left: 28px;
391
- top: 8px;
392
- z-index: 1;
393
- -webkit-transform: rotate(-45deg);
394
- transform: rotate(-45deg); }
395
- .swal2-icon.swal2-success [class^='swal2-success-line'] {
396
- height: 5px;
397
- background-color: #a5dc86;
398
- display: block;
399
- border-radius: 2px;
400
- position: absolute;
401
- z-index: 2; }
402
- .swal2-icon.swal2-success [class^='swal2-success-line'][class$='tip'] {
403
- width: 25px;
404
- left: 14px;
405
- top: 46px;
406
- -webkit-transform: rotate(45deg);
407
- transform: rotate(45deg); }
408
- .swal2-icon.swal2-success [class^='swal2-success-line'][class$='long'] {
409
- width: 47px;
410
- right: 8px;
411
- top: 38px;
412
- -webkit-transform: rotate(-45deg);
413
- transform: rotate(-45deg); }
414
-
415
- .swal2-progresssteps {
416
- font-weight: 600;
417
- margin: 0 0 20px;
418
- padding: 0; }
419
- .swal2-progresssteps li {
420
- display: inline-block;
421
- position: relative; }
422
- .swal2-progresssteps .swal2-progresscircle {
423
- background: #3085d6;
424
- border-radius: 2em;
425
- color: #fff;
426
- height: 2em;
427
- line-height: 2em;
428
- text-align: center;
429
- width: 2em;
430
- z-index: 20; }
431
- .swal2-progresssteps .swal2-progresscircle:first-child {
432
- margin-left: 0; }
433
- .swal2-progresssteps .swal2-progresscircle:last-child {
434
- margin-right: 0; }
435
- .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep {
436
- background: #3085d6; }
437
- .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progresscircle {
438
- background: #add8e6; }
439
- .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progressline {
440
- background: #add8e6; }
441
- .swal2-progresssteps .swal2-progressline {
442
- background: #3085d6;
443
- height: .4em;
444
- margin: 0 -1px;
445
- z-index: 10; }
446
-
447
- [class^='swal2'] {
448
- -webkit-tap-highlight-color: transparent; }
449
-
450
- @-webkit-keyframes showSweetAlert {
451
- 0% {
452
- -webkit-transform: scale(0.7);
453
- transform: scale(0.7); }
454
- 45% {
455
- -webkit-transform: scale(1.05);
456
- transform: scale(1.05); }
457
- 80% {
458
- -webkit-transform: scale(0.95);
459
- transform: scale(0.95); }
460
- 100% {
461
- -webkit-transform: scale(1);
462
- transform: scale(1); } }
463
-
464
- @keyframes showSweetAlert {
465
- 0% {
466
- -webkit-transform: scale(0.7);
467
- transform: scale(0.7); }
468
- 45% {
469
- -webkit-transform: scale(1.05);
470
- transform: scale(1.05); }
471
- 80% {
472
- -webkit-transform: scale(0.95);
473
- transform: scale(0.95); }
474
- 100% {
475
- -webkit-transform: scale(1);
476
- transform: scale(1); } }
477
-
478
- @-webkit-keyframes hideSweetAlert {
479
- 0% {
480
- -webkit-transform: scale(1);
481
- transform: scale(1);
482
- opacity: 1; }
483
- 100% {
484
- -webkit-transform: scale(0.5);
485
- transform: scale(0.5);
486
- opacity: 0; } }
487
-
488
- @keyframes hideSweetAlert {
489
- 0% {
490
- -webkit-transform: scale(1);
491
- transform: scale(1);
492
- opacity: 1; }
493
- 100% {
494
- -webkit-transform: scale(0.5);
495
- transform: scale(0.5);
496
- opacity: 0; } }
497
-
498
- .swal2-show {
499
- -webkit-animation: showSweetAlert 0.3s;
500
- animation: showSweetAlert 0.3s; }
501
- .swal2-show.swal2-noanimation {
502
- -webkit-animation: none;
503
- animation: none; }
504
-
505
- .swal2-hide {
506
- -webkit-animation: hideSweetAlert 0.15s forwards;
507
- animation: hideSweetAlert 0.15s forwards; }
508
- .swal2-hide.swal2-noanimation {
509
- -webkit-animation: none;
510
- animation: none; }
511
-
512
- @-webkit-keyframes animate-success-tip {
513
- 0% {
514
- width: 0;
515
- left: 1px;
516
- top: 19px; }
517
- 54% {
518
- width: 0;
519
- left: 1px;
520
- top: 19px; }
521
- 70% {
522
- width: 50px;
523
- left: -8px;
524
- top: 37px; }
525
- 84% {
526
- width: 17px;
527
- left: 21px;
528
- top: 48px; }
529
- 100% {
530
- width: 25px;
531
- left: 14px;
532
- top: 45px; } }
533
-
534
- @keyframes animate-success-tip {
535
- 0% {
536
- width: 0;
537
- left: 1px;
538
- top: 19px; }
539
- 54% {
540
- width: 0;
541
- left: 1px;
542
- top: 19px; }
543
- 70% {
544
- width: 50px;
545
- left: -8px;
546
- top: 37px; }
547
- 84% {
548
- width: 17px;
549
- left: 21px;
550
- top: 48px; }
551
- 100% {
552
- width: 25px;
553
- left: 14px;
554
- top: 45px; } }
555
-
556
- @-webkit-keyframes animate-success-long {
557
- 0% {
558
- width: 0;
559
- right: 46px;
560
- top: 54px; }
561
- 65% {
562
- width: 0;
563
- right: 46px;
564
- top: 54px; }
565
- 84% {
566
- width: 55px;
567
- right: 0;
568
- top: 35px; }
569
- 100% {
570
- width: 47px;
571
- right: 8px;
572
- top: 38px; } }
573
-
574
- @keyframes animate-success-long {
575
- 0% {
576
- width: 0;
577
- right: 46px;
578
- top: 54px; }
579
- 65% {
580
- width: 0;
581
- right: 46px;
582
- top: 54px; }
583
- 84% {
584
- width: 55px;
585
- right: 0;
586
- top: 35px; }
587
- 100% {
588
- width: 47px;
589
- right: 8px;
590
- top: 38px; } }
591
-
592
- @-webkit-keyframes rotatePlaceholder {
593
- 0% {
594
- -webkit-transform: rotate(-45deg);
595
- transform: rotate(-45deg); }
596
- 5% {
597
- -webkit-transform: rotate(-45deg);
598
- transform: rotate(-45deg); }
599
- 12% {
600
- -webkit-transform: rotate(-405deg);
601
- transform: rotate(-405deg); }
602
- 100% {
603
- -webkit-transform: rotate(-405deg);
604
- transform: rotate(-405deg); } }
605
-
606
- @keyframes rotatePlaceholder {
607
- 0% {
608
- -webkit-transform: rotate(-45deg);
609
- transform: rotate(-45deg); }
610
- 5% {
611
- -webkit-transform: rotate(-45deg);
612
- transform: rotate(-45deg); }
613
- 12% {
614
- -webkit-transform: rotate(-405deg);
615
- transform: rotate(-405deg); }
616
- 100% {
617
- -webkit-transform: rotate(-405deg);
618
- transform: rotate(-405deg); } }
619
-
620
- .swal2-animate-success-line-tip {
621
- -webkit-animation: animate-success-tip 0.75s;
622
- animation: animate-success-tip 0.75s; }
623
-
624
- .swal2-animate-success-line-long {
625
- -webkit-animation: animate-success-long 0.75s;
626
- animation: animate-success-long 0.75s; }
627
-
628
- .swal2-success.swal2-animate-success-icon .swal2-success-circular-line-right {
629
- -webkit-animation: rotatePlaceholder 4.25s ease-in;
630
- animation: rotatePlaceholder 4.25s ease-in; }
631
-
632
- @-webkit-keyframes animate-error-icon {
633
- 0% {
634
- -webkit-transform: rotateX(100deg);
635
- transform: rotateX(100deg);
636
- opacity: 0; }
637
- 100% {
638
- -webkit-transform: rotateX(0deg);
639
- transform: rotateX(0deg);
640
- opacity: 1; } }
641
-
642
- @keyframes animate-error-icon {
643
- 0% {
644
- -webkit-transform: rotateX(100deg);
645
- transform: rotateX(100deg);
646
- opacity: 0; }
647
- 100% {
648
- -webkit-transform: rotateX(0deg);
649
- transform: rotateX(0deg);
650
- opacity: 1; } }
651
-
652
- .swal2-animate-error-icon {
653
- -webkit-animation: animate-error-icon 0.5s;
654
- animation: animate-error-icon 0.5s; }
655
-
656
- @-webkit-keyframes animate-x-mark {
657
- 0% {
658
- -webkit-transform: scale(0.4);
659
- transform: scale(0.4);
660
- margin-top: 26px;
661
- opacity: 0; }
662
- 50% {
663
- -webkit-transform: scale(0.4);
664
- transform: scale(0.4);
665
- margin-top: 26px;
666
- opacity: 0; }
667
- 80% {
668
- -webkit-transform: scale(1.15);
669
- transform: scale(1.15);
670
- margin-top: -6px; }
671
- 100% {
672
- -webkit-transform: scale(1);
673
- transform: scale(1);
674
- margin-top: 0;
675
- opacity: 1; } }
676
-
677
- @keyframes animate-x-mark {
678
- 0% {
679
- -webkit-transform: scale(0.4);
680
- transform: scale(0.4);
681
- margin-top: 26px;
682
- opacity: 0; }
683
- 50% {
684
- -webkit-transform: scale(0.4);
685
- transform: scale(0.4);
686
- margin-top: 26px;
687
- opacity: 0; }
688
- 80% {
689
- -webkit-transform: scale(1.15);
690
- transform: scale(1.15);
691
- margin-top: -6px; }
692
- 100% {
693
- -webkit-transform: scale(1);
694
- transform: scale(1);
695
- margin-top: 0;
696
- opacity: 1; } }
697
-
698
- .swal2-animate-x-mark {
699
- -webkit-animation: animate-x-mark 0.5s;
700
- animation: animate-x-mark 0.5s; }
701
-
702
- @-webkit-keyframes rotate-loading {
703
- 0% {
704
- -webkit-transform: rotate(0deg);
705
- transform: rotate(0deg); }
706
- 100% {
707
- -webkit-transform: rotate(360deg);
708
- transform: rotate(360deg); } }
709
-
710
- @keyframes rotate-loading {
711
- 0% {
712
- -webkit-transform: rotate(0deg);
713
- transform: rotate(0deg); }
714
- 100% {
715
- -webkit-transform: rotate(360deg);
716
- transform: rotate(360deg); } }
1
+ body.swal2-shown {
2
+ overflow-y: hidden; }
3
+
4
+ body.swal2-iosfix {
5
+ position: fixed;
6
+ left: 0;
7
+ right: 0; }
8
+
9
+ .swal2-container {
10
+ display: -webkit-box;
11
+ display: -ms-flexbox;
12
+ display: flex;
13
+ -webkit-box-align: center;
14
+ -ms-flex-align: center;
15
+ align-items: center;
16
+ position: fixed;
17
+ top: 0;
18
+ left: 0;
19
+ bottom: 0;
20
+ right: 0;
21
+ padding: 10px;
22
+ background-color: transparent;
23
+ z-index: 1060; }
24
+ .swal2-container.swal2-fade {
25
+ -webkit-transition: background-color .1s;
26
+ transition: background-color .1s; }
27
+ .swal2-container.swal2-shown {
28
+ background-color: rgba(0, 0, 0, 0.4); }
29
+
30
+ .swal2-modal {
31
+ background-color: #fff;
32
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
33
+ border-radius: 5px;
34
+ -webkit-box-sizing: border-box;
35
+ box-sizing: border-box;
36
+ text-align: center;
37
+ margin: auto;
38
+ overflow-x: hidden;
39
+ overflow-y: auto;
40
+ display: none;
41
+ position: relative;
42
+ max-width: 100%; }
43
+ .swal2-modal:focus {
44
+ outline: none; }
45
+ .swal2-modal.swal2-loading {
46
+ overflow-y: hidden; }
47
+ .swal2-modal .swal2-title {
48
+ color: #595959;
49
+ font-size: 30px;
50
+ text-align: center;
51
+ font-weight: 600;
52
+ text-transform: none;
53
+ position: relative;
54
+ margin: 0 0 .4em;
55
+ padding: 0;
56
+ display: block;
57
+ word-wrap: break-word; }
58
+ .swal2-modal .swal2-buttonswrapper {
59
+ margin-top: 15px; }
60
+ .swal2-modal .swal2-buttonswrapper:not(.swal2-loading) .swal2-styled[disabled] {
61
+ opacity: .4;
62
+ cursor: no-drop; }
63
+ .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-confirm {
64
+ -webkit-box-sizing: border-box;
65
+ box-sizing: border-box;
66
+ border: 4px solid transparent;
67
+ border-color: transparent;
68
+ width: 40px;
69
+ height: 40px;
70
+ padding: 0;
71
+ margin: 7.5px;
72
+ vertical-align: top;
73
+ background-color: transparent !important;
74
+ color: transparent;
75
+ cursor: default;
76
+ border-radius: 100%;
77
+ -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
78
+ animation: rotate-loading 1.5s linear 0s infinite normal;
79
+ -webkit-user-select: none;
80
+ -moz-user-select: none;
81
+ -ms-user-select: none;
82
+ user-select: none; }
83
+ .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-cancel {
84
+ margin-left: 30px;
85
+ margin-right: 30px; }
86
+ .swal2-modal .swal2-buttonswrapper.swal2-loading :not(.swal2-styled).swal2-confirm::after {
87
+ display: inline-block;
88
+ content: '';
89
+ margin-left: 5px 0 15px;
90
+ vertical-align: -1px;
91
+ height: 15px;
92
+ width: 15px;
93
+ border: 3px solid #999999;
94
+ -webkit-box-shadow: 1px 1px 1px #fff;
95
+ box-shadow: 1px 1px 1px #fff;
96
+ border-right-color: transparent;
97
+ border-radius: 50%;
98
+ -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
99
+ animation: rotate-loading 1.5s linear 0s infinite normal; }
100
+ .swal2-modal .swal2-styled {
101
+ border: 0;
102
+ border-radius: 3px;
103
+ -webkit-box-shadow: none;
104
+ box-shadow: none;
105
+ color: #fff;
106
+ cursor: pointer;
107
+ font-size: 17px;
108
+ font-weight: 500;
109
+ margin: 15px 5px 0;
110
+ padding: 10px 32px; }
111
+ .swal2-modal .swal2-image {
112
+ margin: 20px auto;
113
+ max-width: 100%; }
114
+ .swal2-modal .swal2-close {
115
+ background: transparent;
116
+ border: 0;
117
+ margin: 0;
118
+ padding: 0;
119
+ width: 38px;
120
+ height: 40px;
121
+ font-size: 36px;
122
+ line-height: 40px;
123
+ font-family: serif;
124
+ position: absolute;
125
+ top: 5px;
126
+ right: 8px;
127
+ cursor: pointer;
128
+ color: #cccccc;
129
+ -webkit-transition: color .1s ease;
130
+ transition: color .1s ease; }
131
+ .swal2-modal .swal2-close:hover {
132
+ color: #d55; }
133
+ .swal2-modal > .swal2-input,
134
+ .swal2-modal > .swal2-file,
135
+ .swal2-modal > .swal2-textarea,
136
+ .swal2-modal > .swal2-select,
137
+ .swal2-modal > .swal2-radio,
138
+ .swal2-modal > .swal2-checkbox {
139
+ display: none; }
140
+ .swal2-modal .swal2-content {
141
+ font-size: 18px;
142
+ text-align: center;
143
+ font-weight: 300;
144
+ position: relative;
145
+ float: none;
146
+ margin: 0;
147
+ padding: 0;
148
+ line-height: normal;
149
+ color: #545454;
150
+ word-wrap: break-word; }
151
+ .swal2-modal .swal2-input,
152
+ .swal2-modal .swal2-file,
153
+ .swal2-modal .swal2-textarea,
154
+ .swal2-modal .swal2-select,
155
+ .swal2-modal .swal2-radio,
156
+ .swal2-modal .swal2-checkbox {
157
+ margin: 20px auto; }
158
+ .swal2-modal .swal2-input,
159
+ .swal2-modal .swal2-file,
160
+ .swal2-modal .swal2-textarea {
161
+ width: 100%;
162
+ -webkit-box-sizing: border-box;
163
+ box-sizing: border-box;
164
+ font-size: 18px;
165
+ border-radius: 3px;
166
+ border: 1px solid #d9d9d9;
167
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
168
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
169
+ -webkit-transition: border-color box-shadow .3s;
170
+ transition: border-color box-shadow .3s; }
171
+ .swal2-modal .swal2-input.swal2-inputerror,
172
+ .swal2-modal .swal2-file.swal2-inputerror,
173
+ .swal2-modal .swal2-textarea.swal2-inputerror {
174
+ border-color: #f27474 !important;
175
+ -webkit-box-shadow: 0 0 2px #f27474 !important;
176
+ box-shadow: 0 0 2px #f27474 !important; }
177
+ .swal2-modal .swal2-input:focus,
178
+ .swal2-modal .swal2-file:focus,
179
+ .swal2-modal .swal2-textarea:focus {
180
+ outline: none;
181
+ border: 1px solid #b4dbed;
182
+ -webkit-box-shadow: 0 0 3px #c4e6f5;
183
+ box-shadow: 0 0 3px #c4e6f5; }
184
+ .swal2-modal .swal2-input:focus::-webkit-input-placeholder,
185
+ .swal2-modal .swal2-file:focus::-webkit-input-placeholder,
186
+ .swal2-modal .swal2-textarea:focus::-webkit-input-placeholder {
187
+ -webkit-transition: opacity .3s .03s ease;
188
+ transition: opacity .3s .03s ease;
189
+ opacity: .8; }
190
+ .swal2-modal .swal2-input:focus:-ms-input-placeholder,
191
+ .swal2-modal .swal2-file:focus:-ms-input-placeholder,
192
+ .swal2-modal .swal2-textarea:focus:-ms-input-placeholder {
193
+ -webkit-transition: opacity .3s .03s ease;
194
+ transition: opacity .3s .03s ease;
195
+ opacity: .8; }
196
+ .swal2-modal .swal2-input:focus::placeholder,
197
+ .swal2-modal .swal2-file:focus::placeholder,
198
+ .swal2-modal .swal2-textarea:focus::placeholder {
199
+ -webkit-transition: opacity .3s .03s ease;
200
+ transition: opacity .3s .03s ease;
201
+ opacity: .8; }
202
+ .swal2-modal .swal2-input::-webkit-input-placeholder,
203
+ .swal2-modal .swal2-file::-webkit-input-placeholder,
204
+ .swal2-modal .swal2-textarea::-webkit-input-placeholder {
205
+ color: #e6e6e6; }
206
+ .swal2-modal .swal2-input:-ms-input-placeholder,
207
+ .swal2-modal .swal2-file:-ms-input-placeholder,
208
+ .swal2-modal .swal2-textarea:-ms-input-placeholder {
209
+ color: #e6e6e6; }
210
+ .swal2-modal .swal2-input::placeholder,
211
+ .swal2-modal .swal2-file::placeholder,
212
+ .swal2-modal .swal2-textarea::placeholder {
213
+ color: #e6e6e6; }
214
+ .swal2-modal .swal2-range input {
215
+ float: left;
216
+ width: 80%; }
217
+ .swal2-modal .swal2-range output {
218
+ float: right;
219
+ width: 20%;
220
+ font-size: 20px;
221
+ font-weight: 600;
222
+ text-align: center; }
223
+ .swal2-modal .swal2-range input,
224
+ .swal2-modal .swal2-range output {
225
+ height: 43px;
226
+ line-height: 43px;
227
+ vertical-align: middle;
228
+ margin: 20px auto;
229
+ padding: 0; }
230
+ .swal2-modal .swal2-input {
231
+ height: 43px;
232
+ padding: 0 12px; }
233
+ .swal2-modal .swal2-input[type='number'] {
234
+ max-width: 150px; }
235
+ .swal2-modal .swal2-file {
236
+ font-size: 20px; }
237
+ .swal2-modal .swal2-textarea {
238
+ height: 108px;
239
+ padding: 12px; }
240
+ .swal2-modal .swal2-select {
241
+ color: #545454;
242
+ font-size: inherit;
243
+ padding: 5px 10px;
244
+ min-width: 40%;
245
+ max-width: 100%; }
246
+ .swal2-modal .swal2-radio {
247
+ border: 0; }
248
+ .swal2-modal .swal2-radio label:not(:first-child) {
249
+ margin-left: 20px; }
250
+ .swal2-modal .swal2-radio input,
251
+ .swal2-modal .swal2-radio span {
252
+ vertical-align: middle; }
253
+ .swal2-modal .swal2-radio input {
254
+ margin: 0 3px 0 0; }
255
+ .swal2-modal .swal2-checkbox {
256
+ color: #545454; }
257
+ .swal2-modal .swal2-checkbox input,
258
+ .swal2-modal .swal2-checkbox span {
259
+ vertical-align: middle; }
260
+ .swal2-modal .swal2-validationerror {
261
+ background-color: #f0f0f0;
262
+ margin: 0 -20px;
263
+ overflow: hidden;
264
+ padding: 10px;
265
+ color: gray;
266
+ font-size: 16px;
267
+ font-weight: 300;
268
+ display: none; }
269
+ .swal2-modal .swal2-validationerror::before {
270
+ content: '!';
271
+ display: inline-block;
272
+ width: 24px;
273
+ height: 24px;
274
+ border-radius: 50%;
275
+ background-color: #ea7d7d;
276
+ color: #fff;
277
+ line-height: 24px;
278
+ text-align: center;
279
+ margin-right: 10px; }
280
+
281
+ @supports (-ms-accelerator: true) {
282
+ .swal2-range input {
283
+ width: 100% !important; }
284
+ .swal2-range output {
285
+ display: none; } }
286
+
287
+ @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
288
+ .swal2-range input {
289
+ width: 100% !important; }
290
+ .swal2-range output {
291
+ display: none; } }
292
+
293
+ .swal2-icon {
294
+ width: 80px;
295
+ height: 80px;
296
+ border: 4px solid transparent;
297
+ border-radius: 50%;
298
+ margin: 20px auto 30px;
299
+ padding: 0;
300
+ position: relative;
301
+ -webkit-box-sizing: content-box;
302
+ box-sizing: content-box;
303
+ cursor: default;
304
+ -webkit-user-select: none;
305
+ -moz-user-select: none;
306
+ -ms-user-select: none;
307
+ user-select: none; }
308
+ .swal2-icon.swal2-error {
309
+ border-color: #f27474; }
310
+ .swal2-icon.swal2-error .swal2-x-mark {
311
+ position: relative;
312
+ display: block; }
313
+ .swal2-icon.swal2-error [class^='swal2-x-mark-line'] {
314
+ position: absolute;
315
+ height: 5px;
316
+ width: 47px;
317
+ background-color: #f27474;
318
+ display: block;
319
+ top: 37px;
320
+ border-radius: 2px; }
321
+ .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='left'] {
322
+ -webkit-transform: rotate(45deg);
323
+ transform: rotate(45deg);
324
+ left: 17px; }
325
+ .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='right'] {
326
+ -webkit-transform: rotate(-45deg);
327
+ transform: rotate(-45deg);
328
+ right: 16px; }
329
+ .swal2-icon.swal2-warning {
330
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
331
+ color: #f8bb86;
332
+ border-color: #facea8;
333
+ font-size: 60px;
334
+ line-height: 80px;
335
+ text-align: center; }
336
+ .swal2-icon.swal2-info {
337
+ font-family: 'Open Sans', sans-serif;
338
+ color: #3fc3ee;
339
+ border-color: #9de0f6;
340
+ font-size: 60px;
341
+ line-height: 80px;
342
+ text-align: center; }
343
+ .swal2-icon.swal2-question {
344
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
345
+ color: #87adbd;
346
+ border-color: #c9dae1;
347
+ font-size: 60px;
348
+ line-height: 80px;
349
+ text-align: center; }
350
+ .swal2-icon.swal2-success {
351
+ border-color: #a5dc86; }
352
+ .swal2-icon.swal2-success [class^='swal2-success-circular-line'] {
353
+ border-radius: 50%;
354
+ position: absolute;
355
+ width: 60px;
356
+ height: 120px;
357
+ -webkit-transform: rotate(45deg);
358
+ transform: rotate(45deg); }
359
+ .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='left'] {
360
+ border-radius: 120px 0 0 120px;
361
+ top: -7px;
362
+ left: -33px;
363
+ -webkit-transform: rotate(-45deg);
364
+ transform: rotate(-45deg);
365
+ -webkit-transform-origin: 60px 60px;
366
+ transform-origin: 60px 60px; }
367
+ .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='right'] {
368
+ border-radius: 0 120px 120px 0;
369
+ top: -11px;
370
+ left: 30px;
371
+ -webkit-transform: rotate(-45deg);
372
+ transform: rotate(-45deg);
373
+ -webkit-transform-origin: 0 60px;
374
+ transform-origin: 0 60px; }
375
+ .swal2-icon.swal2-success .swal2-success-ring {
376
+ width: 80px;
377
+ height: 80px;
378
+ border: 4px solid rgba(165, 220, 134, 0.2);
379
+ border-radius: 50%;
380
+ -webkit-box-sizing: content-box;
381
+ box-sizing: content-box;
382
+ position: absolute;
383
+ left: -4px;
384
+ top: -4px;
385
+ z-index: 2; }
386
+ .swal2-icon.swal2-success .swal2-success-fix {
387
+ width: 7px;
388
+ height: 90px;
389
+ position: absolute;
390
+ left: 28px;
391
+ top: 8px;
392
+ z-index: 1;
393
+ -webkit-transform: rotate(-45deg);
394
+ transform: rotate(-45deg); }
395
+ .swal2-icon.swal2-success [class^='swal2-success-line'] {
396
+ height: 5px;
397
+ background-color: #a5dc86;
398
+ display: block;
399
+ border-radius: 2px;
400
+ position: absolute;
401
+ z-index: 2; }
402
+ .swal2-icon.swal2-success [class^='swal2-success-line'][class$='tip'] {
403
+ width: 25px;
404
+ left: 14px;
405
+ top: 46px;
406
+ -webkit-transform: rotate(45deg);
407
+ transform: rotate(45deg); }
408
+ .swal2-icon.swal2-success [class^='swal2-success-line'][class$='long'] {
409
+ width: 47px;
410
+ right: 8px;
411
+ top: 38px;
412
+ -webkit-transform: rotate(-45deg);
413
+ transform: rotate(-45deg); }
414
+
415
+ .swal2-progresssteps {
416
+ font-weight: 600;
417
+ margin: 0 0 20px;
418
+ padding: 0; }
419
+ .swal2-progresssteps li {
420
+ display: inline-block;
421
+ position: relative; }
422
+ .swal2-progresssteps .swal2-progresscircle {
423
+ background: #3085d6;
424
+ border-radius: 2em;
425
+ color: #fff;
426
+ height: 2em;
427
+ line-height: 2em;
428
+ text-align: center;
429
+ width: 2em;
430
+ z-index: 20; }
431
+ .swal2-progresssteps .swal2-progresscircle:first-child {
432
+ margin-left: 0; }
433
+ .swal2-progresssteps .swal2-progresscircle:last-child {
434
+ margin-right: 0; }
435
+ .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep {
436
+ background: #3085d6; }
437
+ .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progresscircle {
438
+ background: #add8e6; }
439
+ .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progressline {
440
+ background: #add8e6; }
441
+ .swal2-progresssteps .swal2-progressline {
442
+ background: #3085d6;
443
+ height: .4em;
444
+ margin: 0 -1px;
445
+ z-index: 10; }
446
+
447
+ [class^='swal2'] {
448
+ -webkit-tap-highlight-color: transparent; }
449
+
450
+ @-webkit-keyframes showSweetAlert {
451
+ 0% {
452
+ -webkit-transform: scale(0.7);
453
+ transform: scale(0.7); }
454
+ 45% {
455
+ -webkit-transform: scale(1.05);
456
+ transform: scale(1.05); }
457
+ 80% {
458
+ -webkit-transform: scale(0.95);
459
+ transform: scale(0.95); }
460
+ 100% {
461
+ -webkit-transform: scale(1);
462
+ transform: scale(1); } }
463
+
464
+ @keyframes showSweetAlert {
465
+ 0% {
466
+ -webkit-transform: scale(0.7);
467
+ transform: scale(0.7); }
468
+ 45% {
469
+ -webkit-transform: scale(1.05);
470
+ transform: scale(1.05); }
471
+ 80% {
472
+ -webkit-transform: scale(0.95);
473
+ transform: scale(0.95); }
474
+ 100% {
475
+ -webkit-transform: scale(1);
476
+ transform: scale(1); } }
477
+
478
+ @-webkit-keyframes hideSweetAlert {
479
+ 0% {
480
+ -webkit-transform: scale(1);
481
+ transform: scale(1);
482
+ opacity: 1; }
483
+ 100% {
484
+ -webkit-transform: scale(0.5);
485
+ transform: scale(0.5);
486
+ opacity: 0; } }
487
+
488
+ @keyframes hideSweetAlert {
489
+ 0% {
490
+ -webkit-transform: scale(1);
491
+ transform: scale(1);
492
+ opacity: 1; }
493
+ 100% {
494
+ -webkit-transform: scale(0.5);
495
+ transform: scale(0.5);
496
+ opacity: 0; } }
497
+
498
+ .swal2-show {
499
+ -webkit-animation: showSweetAlert 0.3s;
500
+ animation: showSweetAlert 0.3s; }
501
+ .swal2-show.swal2-noanimation {
502
+ -webkit-animation: none;
503
+ animation: none; }
504
+
505
+ .swal2-hide {
506
+ -webkit-animation: hideSweetAlert 0.15s forwards;
507
+ animation: hideSweetAlert 0.15s forwards; }
508
+ .swal2-hide.swal2-noanimation {
509
+ -webkit-animation: none;
510
+ animation: none; }
511
+
512
+ @-webkit-keyframes animate-success-tip {
513
+ 0% {
514
+ width: 0;
515
+ left: 1px;
516
+ top: 19px; }
517
+ 54% {
518
+ width: 0;
519
+ left: 1px;
520
+ top: 19px; }
521
+ 70% {
522
+ width: 50px;
523
+ left: -8px;
524
+ top: 37px; }
525
+ 84% {
526
+ width: 17px;
527
+ left: 21px;
528
+ top: 48px; }
529
+ 100% {
530
+ width: 25px;
531
+ left: 14px;
532
+ top: 45px; } }
533
+
534
+ @keyframes animate-success-tip {
535
+ 0% {
536
+ width: 0;
537
+ left: 1px;
538
+ top: 19px; }
539
+ 54% {
540
+ width: 0;
541
+ left: 1px;
542
+ top: 19px; }
543
+ 70% {
544
+ width: 50px;
545
+ left: -8px;
546
+ top: 37px; }
547
+ 84% {
548
+ width: 17px;
549
+ left: 21px;
550
+ top: 48px; }
551
+ 100% {
552
+ width: 25px;
553
+ left: 14px;
554
+ top: 45px; } }
555
+
556
+ @-webkit-keyframes animate-success-long {
557
+ 0% {
558
+ width: 0;
559
+ right: 46px;
560
+ top: 54px; }
561
+ 65% {
562
+ width: 0;
563
+ right: 46px;
564
+ top: 54px; }
565
+ 84% {
566
+ width: 55px;
567
+ right: 0;
568
+ top: 35px; }
569
+ 100% {
570
+ width: 47px;
571
+ right: 8px;
572
+ top: 38px; } }
573
+
574
+ @keyframes animate-success-long {
575
+ 0% {
576
+ width: 0;
577
+ right: 46px;
578
+ top: 54px; }
579
+ 65% {
580
+ width: 0;
581
+ right: 46px;
582
+ top: 54px; }
583
+ 84% {
584
+ width: 55px;
585
+ right: 0;
586
+ top: 35px; }
587
+ 100% {
588
+ width: 47px;
589
+ right: 8px;
590
+ top: 38px; } }
591
+
592
+ @-webkit-keyframes rotatePlaceholder {
593
+ 0% {
594
+ -webkit-transform: rotate(-45deg);
595
+ transform: rotate(-45deg); }
596
+ 5% {
597
+ -webkit-transform: rotate(-45deg);
598
+ transform: rotate(-45deg); }
599
+ 12% {
600
+ -webkit-transform: rotate(-405deg);
601
+ transform: rotate(-405deg); }
602
+ 100% {
603
+ -webkit-transform: rotate(-405deg);
604
+ transform: rotate(-405deg); } }
605
+
606
+ @keyframes rotatePlaceholder {
607
+ 0% {
608
+ -webkit-transform: rotate(-45deg);
609
+ transform: rotate(-45deg); }
610
+ 5% {
611
+ -webkit-transform: rotate(-45deg);
612
+ transform: rotate(-45deg); }
613
+ 12% {
614
+ -webkit-transform: rotate(-405deg);
615
+ transform: rotate(-405deg); }
616
+ 100% {
617
+ -webkit-transform: rotate(-405deg);
618
+ transform: rotate(-405deg); } }
619
+
620
+ .swal2-animate-success-line-tip {
621
+ -webkit-animation: animate-success-tip 0.75s;
622
+ animation: animate-success-tip 0.75s; }
623
+
624
+ .swal2-animate-success-line-long {
625
+ -webkit-animation: animate-success-long 0.75s;
626
+ animation: animate-success-long 0.75s; }
627
+
628
+ .swal2-success.swal2-animate-success-icon .swal2-success-circular-line-right {
629
+ -webkit-animation: rotatePlaceholder 4.25s ease-in;
630
+ animation: rotatePlaceholder 4.25s ease-in; }
631
+
632
+ @-webkit-keyframes animate-error-icon {
633
+ 0% {
634
+ -webkit-transform: rotateX(100deg);
635
+ transform: rotateX(100deg);
636
+ opacity: 0; }
637
+ 100% {
638
+ -webkit-transform: rotateX(0deg);
639
+ transform: rotateX(0deg);
640
+ opacity: 1; } }
641
+
642
+ @keyframes animate-error-icon {
643
+ 0% {
644
+ -webkit-transform: rotateX(100deg);
645
+ transform: rotateX(100deg);
646
+ opacity: 0; }
647
+ 100% {
648
+ -webkit-transform: rotateX(0deg);
649
+ transform: rotateX(0deg);
650
+ opacity: 1; } }
651
+
652
+ .swal2-animate-error-icon {
653
+ -webkit-animation: animate-error-icon 0.5s;
654
+ animation: animate-error-icon 0.5s; }
655
+
656
+ @-webkit-keyframes animate-x-mark {
657
+ 0% {
658
+ -webkit-transform: scale(0.4);
659
+ transform: scale(0.4);
660
+ margin-top: 26px;
661
+ opacity: 0; }
662
+ 50% {
663
+ -webkit-transform: scale(0.4);
664
+ transform: scale(0.4);
665
+ margin-top: 26px;
666
+ opacity: 0; }
667
+ 80% {
668
+ -webkit-transform: scale(1.15);
669
+ transform: scale(1.15);
670
+ margin-top: -6px; }
671
+ 100% {
672
+ -webkit-transform: scale(1);
673
+ transform: scale(1);
674
+ margin-top: 0;
675
+ opacity: 1; } }
676
+
677
+ @keyframes animate-x-mark {
678
+ 0% {
679
+ -webkit-transform: scale(0.4);
680
+ transform: scale(0.4);
681
+ margin-top: 26px;
682
+ opacity: 0; }
683
+ 50% {
684
+ -webkit-transform: scale(0.4);
685
+ transform: scale(0.4);
686
+ margin-top: 26px;
687
+ opacity: 0; }
688
+ 80% {
689
+ -webkit-transform: scale(1.15);
690
+ transform: scale(1.15);
691
+ margin-top: -6px; }
692
+ 100% {
693
+ -webkit-transform: scale(1);
694
+ transform: scale(1);
695
+ margin-top: 0;
696
+ opacity: 1; } }
697
+
698
+ .swal2-animate-x-mark {
699
+ -webkit-animation: animate-x-mark 0.5s;
700
+ animation: animate-x-mark 0.5s; }
701
+
702
+ @-webkit-keyframes rotate-loading {
703
+ 0% {
704
+ -webkit-transform: rotate(0deg);
705
+ transform: rotate(0deg); }
706
+ 100% {
707
+ -webkit-transform: rotate(360deg);
708
+ transform: rotate(360deg); } }
709
+
710
+ @keyframes rotate-loading {
711
+ 0% {
712
+ -webkit-transform: rotate(0deg);
713
+ transform: rotate(0deg); }
714
+ 100% {
715
+ -webkit-transform: rotate(360deg);
716
+ transform: rotate(360deg); } }
admin/assets/img/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/assets/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/assets/js/Chart.min.js CHANGED
@@ -1,10 +1,10 @@
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)});
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-conversion.js ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function ($) {
2
+ var bulkConversion = {
3
+ inprogress: false,
4
+ serverDown: false,
5
+ i18n: {},
6
+ settings: {},
7
+ startConvertButton: $('#wrio-start-conversion'),
8
+ startOptButton: $('#wrio-start-optimization'),
9
+
10
+ init: function () {
11
+ this.i18n = wrio_l18n_bulk_page;
12
+ this.settings = wrio_settings_bulk_page;
13
+
14
+ this.registerEvents();
15
+ },
16
+
17
+ registerEvents: function () {
18
+ var self = this;
19
+ this.startConvertButton.on('click', function () {
20
+
21
+ if ($(this).hasClass('wio-running')) {
22
+ self.startOptButton.prop('disabled', false);
23
+ self.stop();
24
+ return;
25
+ }
26
+
27
+ self.showModal();
28
+
29
+ return false;
30
+ });
31
+ },
32
+
33
+ showModal: function () {
34
+ var self = this;
35
+ var infosModal = $('#wrio-tmpl-webp-conversion');
36
+
37
+ if ('server_5' !== $('#wrio-change-optimization-server').val()) {
38
+ $.wrio_modal.showErrorModal(this.i18n.webp_premium_server_disabled);
39
+ console.log('[Error]: ' + this.i18n.webp_premium_server_disabled);
40
+ return;
41
+ }
42
+
43
+ if (!infosModal.length) {
44
+ console.log('[Error]: Html template for modal not found.');
45
+ return;
46
+ }
47
+
48
+ // Swal Information before loading the optimize process.
49
+ swal({
50
+ title: this.i18n.modal_conversion_title,
51
+ html: infosModal.html(),
52
+ type: '',
53
+ customClass: 'wrio-modal wrio-modal-optimization-way',
54
+ showCancelButton: true,
55
+ showCloseButton: true,
56
+ padding: 0,
57
+ width: 740,
58
+ confirmButtonText: this.i18n.modal_conversion_manual_button,
59
+ cancelButtonText: this.i18n.modal_conversion_cron_button,
60
+ reverseButtons: true,
61
+ }).then(function (result) {
62
+
63
+ self.startOptButton.prop('disabled', true);
64
+ self.process();
65
+
66
+ window.onbeforeunload = function () {
67
+ return self.i18n.leave_page_warning;
68
+ }
69
+
70
+ }, function (dismiss) {
71
+ if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
72
+ self.startOptButton.prop('disabled', true);
73
+ self.process('cron');
74
+ } else {
75
+ throw dismiss;
76
+ }
77
+ });
78
+
79
+ },
80
+
81
+ /**
82
+ * Start conversion
83
+ * @param {string} type
84
+ */
85
+ process: function (type) {
86
+ var self = this;
87
+ this.inprogress = true;
88
+
89
+ var sendData = {
90
+ 'action': 'wrio-bulk-conversion-process',
91
+ 'scope': this.settings.scope,
92
+ 'multisite': 0,
93
+ '_wpnonce': this.settings.conversion_nonce,
94
+ };
95
+
96
+ this.setButtonStyleRun(type);
97
+
98
+ if ('cron' === type) {
99
+ this.startConvertButton.addClass('wrio-cron-mode');
100
+
101
+ sendData['action'] = 'wrio-webp-cron-start';
102
+
103
+ $.post(ajaxurl, sendData, function (response) {
104
+ if (!response || !response.success) {
105
+ console.log('[Error]: Failed ajax request (Start cron).');
106
+ console.log(sendData);
107
+ console.log(response);
108
+
109
+ if (response.data && response.data.error_message) {
110
+ self.throwError(response.data.error_message);
111
+ }
112
+ } else {
113
+ if (response.data && response.data.stop) {
114
+ self.stop();
115
+ }
116
+ }
117
+ }).fail(function (xhr, status, error) {
118
+ console.log(xhr);
119
+ console.log(status);
120
+ console.log(error);
121
+
122
+ self.throwError(error);
123
+ });
124
+
125
+ return;
126
+ }
127
+
128
+ this.showMessage(this.i18n.conversion_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
129
+
130
+ // show message: Optimization remined
131
+ /*if( "1" === this.settings.is_network_admin ) {
132
+ sendData['multisite'] = 1;
133
+ }*/
134
+
135
+ sendData['reset_current_errors'] = 1;
136
+
137
+ this.sendRequest(sendData);
138
+ },
139
+
140
+ stop: function () {
141
+ var self = this;
142
+ this.inprogress = false;
143
+
144
+ window.onbeforeunload = null;
145
+ self.setButtonStyleStop();
146
+ self.destroyMessages();
147
+
148
+ if (this.startConvertButton.hasClass('wrio-cron-mode')) {
149
+ this.startConvertButton.removeClass('wrio-cron-mode');
150
+
151
+ $.post(ajaxurl, {
152
+ 'action': 'wrio-webp-cron-stop',
153
+ '_wpnonce': self.settings.conversion_nonce,
154
+ 'scope': self.settings.scope
155
+ }, function (response) {
156
+ if (!response || !response.success) {
157
+ console.log('[Error]: Failed ajax request (Stop cron).');
158
+ console.log(response);
159
+
160
+ if (response.data && response.data.error_message) {
161
+ self.throwError(response.data.error_message);
162
+ }
163
+ } else {
164
+ self.startOptButton.prop('disabled', false);
165
+ }
166
+ }).fail(function (xhr, status, error) {
167
+ console.log(xhr);
168
+ console.log(status);
169
+ console.log(error);
170
+
171
+ self.throwError(error);
172
+ });
173
+ }
174
+
175
+ },
176
+
177
+ complete: function () {
178
+ this.inprogress = false;
179
+ window.onbeforeunload = null;
180
+ this.setButtonStyleComplete();
181
+ },
182
+
183
+ setButtonStyleRun: function (mode) {
184
+
185
+ this.startConvertButton.addClass('wio-running');
186
+
187
+ if ("cron" === mode) {
188
+ this.startConvertButton.text(this.i18n.modal_conversion_cron_button_stop);
189
+ return;
190
+ }
191
+
192
+ this.startConvertButton.text(this.i18n.button_stop);
193
+ },
194
+
195
+ setButtonStyleComplete: function () {
196
+ this.showMessage(this.i18n.conversion_complete);
197
+ this.startConvertButton.text(this.i18n.button_completed);
198
+ this.startConvertButton.removeClass('wio-running');
199
+ this.startConvertButton.prop('disabled', true);
200
+ this.startOptButton.prop('disabled', false);
201
+ },
202
+
203
+ setButtonStyleStop: function () {
204
+ this.startConvertButton.removeClass('wio-running');
205
+ this.startConvertButton.text(this.i18n.webp_button_start);
206
+ },
207
+
208
+ showMessage: function (text) {
209
+ var contanier = $('.wio-page-statistic'),
210
+ message;
211
+
212
+ if (contanier.find('.wrio-statistic-message').length) {
213
+ message = contanier.find('.wrio-statistic-message');
214
+ } else {
215
+ message = $('<div>');
216
+ message.addClass('wrio-statistic-message');
217
+ contanier.append(message);
218
+ }
219
+
220
+ message.html(text);
221
+ },
222
+
223
+ throwError: function (error_message) {
224
+ this.stop();
225
+
226
+ var noticeId = $.wbcr_factory_templates_102.app.showNotice(error_message, 'danger');
227
+
228
+ setTimeout(function () {
229
+ $.wbcr_factory_templates_102.app.hideNotice(noticeId);
230
+ }, 10000);
231
+ },
232
+
233
+ destroyMessages: function () {
234
+ $('.wio-page-statistic').find('.wrio-statistic-message').empty();
235
+ },
236
+
237
+ sendRequest: function (data) {
238
+ var self = this;
239
+
240
+ if (!this.inprogress) {
241
+ return;
242
+ }
243
+
244
+ $.post(ajaxurl, data, function (response) {
245
+ if (!self.inprogress) {
246
+ return;
247
+ }
248
+
249
+ if (!response || !response.success) {
250
+ console.log('[Error]: Failed ajax request (Try to optimize images).');
251
+ console.log(response);
252
+
253
+ if (response.data && response.data.error_message) {
254
+ self.throwError(response.data.error_message);
255
+ }
256
+
257
+ return;
258
+ }
259
+
260
+ data.reset_current_errors = 0;
261
+
262
+ if (!response.data.end) {
263
+ $('#wio-total-unoptimized').text(parseInt(response.data.remain));
264
+ self.showMessage(self.i18n.conversion_inprogress.replace("%s", parseInt(response.data.remain)));
265
+ self.sendRequest(data);
266
+ } else {
267
+ $('#wio-total-unoptimized').text(response.data.remain);
268
+ self.complete();
269
+
270
+ // если мультисайт режим, то не скрываем кнопку запуска оптимизации
271
+ /*if( $('#wbcr-rio-current-blog').length ) {
272
+ $('#wio-start-conversion').toggleClass('wio-running');
273
+ } else {
274
+ $('#wio-start-conversion').hide();
275
+ }*/
276
+ }
277
+
278
+ redraw_statistics(response.data.statistic);
279
+
280
+ if (response.data.last_optimized) {
281
+ self.updateLog(response.data.last_optimized);
282
+ }
283
+ if (response.data.last_converted) {
284
+ self.updateLog(response.data.last_converted);
285
+ }
286
+ }).fail(function (xhr, status, error) {
287
+ console.log(xhr);
288
+ console.log(status);
289
+ console.log(error);
290
+
291
+ self.throwError(error);
292
+ });
293
+ },
294
+
295
+ updateLog: function (new_item_data) {
296
+ var self = this;
297
+
298
+ var limit = 100,
299
+ tableEl = $('.wrio-optimization-progress .wrio-table');
300
+
301
+ if (!tableEl.length || !new_item_data) {
302
+ return;
303
+ }
304
+
305
+ // если таблица была пустая
306
+ if ($('.wrio-table-container-empty').length) {
307
+ $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
308
+ if (tableEl.find('tbody').length) {
309
+ tableEl.find('tbody').empty();
310
+ }
311
+ }
312
+
313
+ $.each(new_item_data, function (index, value) {
314
+ var trEl = $('<tr>'),
315
+ tdEl = $('<td>'),
316
+ webpSize = value.webp_size ? value.webp_size : '-';
317
+
318
+ if (tableEl.find('.wrio-row-id-' + value.id).length) {
319
+ tableEl.find('.wrio-row-id-' + value.id).remove();
320
+ }
321
+
322
+ trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
323
+
324
+ if ('error' === value.type) {
325
+ trEl.addClass('wrio-error');
326
+ }
327
+
328
+ var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
329
+ previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
330
+
331
+ tableEl.prepend(trEl);
332
+
333
+ trEl.append(tdEl.clone().append(preview));
334
+ trEl.append(tdEl.clone().append(previewUrl));
335
+
336
+ if ('error' === value.type) {
337
+ var colspan = value.scope !== 'custom-folders' ? '6' : '5';
338
+ trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
339
+ } else {
340
+ trEl.append(tdEl.clone().text(value.original_size));
341
+ trEl.append(tdEl.clone().text(value.optimized_size));
342
+ trEl.append(tdEl.clone().text(webpSize));
343
+ trEl.append(tdEl.clone().text(value.original_saving));
344
+
345
+ if ("custom-folders" !== self.settings.scope) {
346
+ trEl.append(tdEl.clone().text(value.thumbnails_count));
347
+ }
348
+
349
+ trEl.append(tdEl.clone().text(value.total_saving));
350
+ }
351
+ });
352
+
353
+ if (tableEl.find('tr').length > limit) {
354
+ var diff = tableEl.find('tr').length - limit;
355
+
356
+ for (var i = 0; i < diff; i++) {
357
+ tableEl.find('tr:last').remove();
358
+ }
359
+ }
360
+ }
361
+
362
+ };
363
+
364
+ $(document).ready(function () {
365
+ bulkConversion.init();
366
+ $('[data-toggle="tooltip"]').tooltip();
367
+ });
368
+
369
+ var ajaxUrl = ajaxurl;
370
+ var ai_data;
371
+
372
+ function redraw_statistics(statistic) {
373
+ $('#wio-webp-chart').attr('data-unoptimized', statistic.unconverted)
374
+ .attr('data-optimized', statistic.converted)
375
+ .attr('data-errors', statistic.webp_error);
376
+ $('#wio-overview-chart-percent-webp').html(statistic.webp_percent_line + '<span>%</span>');
377
+ $('.wio-total-percent-webp').text(statistic.webp_percent_line + '%');
378
+
379
+ var credits = $('.wrio-premium-user-balance');
380
+ if (credits.attr('data-server') !== "server_5") {
381
+ credits.text(statistic.credits);
382
+ }
383
+
384
+ window.wio_chart_webp.data.datasets[0].data[0] = statistic.unconverted; // unoptimized
385
+ window.wio_chart_webp.data.datasets[0].data[1] = statistic.converted; // optimized
386
+ window.wio_chart_webp.data.datasets[0].data[2] = statistic.webp_error; // errors
387
+ window.wio_chart_webp.update();
388
+ if ($('#wio-overview-chart-percent-webp').text() == '100%') {
389
+ window.onbeforeunload = null;
390
+ }
391
+ }
392
+
393
+ });
admin/assets/js/bulk-optimization.js CHANGED
@@ -1,633 +1,639 @@
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
- $(".wrio-premium-user-update-wrap").hide();
20
- }
21
- if ('server_5' === $('#wrio-change-optimization-server').val()) {
22
- if (!this.settings.is_premium) {
23
- $.wrio_modal.showErrorModal(this.i18n.premium_server_disabled);
24
- }
25
- }
26
-
27
- this.i18n = wrio_l18n_bulk_page;
28
- this.settings = wrio_settings_bulk_page;
29
- this.startOptButton = $('#wrio-start-optimization');
30
-
31
- this.registerEvents();
32
- this.checkServerStatus();
33
- this.calculateTotalImages();
34
- this.checkPremiumUserBalance();
35
-
36
- },
37
-
38
- registerEvents: function () {
39
- var self = this,
40
- selectedServer = $("#wrio-change-optimization-server option:selected");
41
-
42
- $('#wrio-change-optimization-server').on('change', function () {
43
- $(this).prop('disabled', true);
44
- $('.wrio-premium-user-balance').attr('data-server', $(this).val());
45
- $(".wrio-premium-user-balance-wrap").show();
46
- $(".wrio-premium-user-update-wrap").show();
47
-
48
- if ('server_1' === $(this).val()) {
49
- $(".wrio-premium-user-balance-wrap").hide();
50
- $(".wrio-premium-user-update-wrap").hide();
51
- }
52
- if ('server_5' === $(this).val()) {
53
- if (!self.settings.is_premium) {
54
- $.wrio_modal.showErrorModal(self.i18n.premium_server_disabled);
55
- selectedServer.prop('selected', true);
56
- $(this).prop('disabled', false);
57
-
58
- return;
59
- }
60
- }
61
-
62
- self.checkPremiumUserBalance();
63
-
64
- selectedServer = $(this).find('option:selected');
65
- self.checkServerStatus();
66
- });
67
-
68
- this.startOptButton.on('click', function () {
69
- self.startOptButton = $(this);
70
-
71
- if ($(this).hasClass('wio-running')) {
72
- self.stop();
73
- return;
74
- }
75
-
76
- if (self.serverDown) {
77
- $.wrio_modal.showErrorModal(self.i18n.server_down_warning);
78
- return;
79
- }
80
-
81
- if ("1" === self.settings.need_migration) {
82
- $.wrio_modal.showErrorModal(self.i18n.need_migrations);
83
- return;
84
- }
85
-
86
- if ("0" === self.settings.images_backup) {
87
- $.wrio_modal.showWarningModal(self.i18n.process_without_backup, function () {
88
- self.showModal();
89
- });
90
- return;
91
- }
92
-
93
- self.showModal();
94
-
95
- return false;
96
- });
97
- },
98
-
99
- checkPremiumUserBalance: function () {
100
- var self = this,
101
- userBalance = $('.wrio-premium-user-balance'),
102
- balanceResetAt = $('.wrio-premium-user-update'),
103
- data = {
104
- 'action': 'wbcr-rio-check-user-balance',
105
- '_wpnonce': self.settings.nonce
106
- };
107
-
108
- data['server_name'] = $('#wrio-change-optimization-server').val();
109
-
110
- userBalance.addClass('wrio-premium-user-balance-check-proccess');
111
- userBalance.text('');
112
-
113
- if ("server_5" === data['server_name']) {
114
- balanceResetAt.addClass('wrio-premium-user-update-check-proccess');
115
- balanceResetAt.text('');
116
- }
117
-
118
- $.post(ajaxurl, data, function (response) {
119
- console.log(response);
120
- userBalance.removeClass('wrio-premium-user-balance-check-proccess');
121
- if ("server_5" === data['server_name']) {
122
- balanceResetAt.removeClass('wrio-premium-user-update-check-proccess');
123
- }
124
-
125
- if (!response || !response.data || !response.success) {
126
- console.log('[Error]: Response error');
127
- response.data && response.data.error && console.log(response.data.error);
128
-
129
- if (!response || !response.data) {
130
- console.log(response);
131
- }
132
-
133
- userBalance.text('error');
134
- if ("server_5" === data['server_name']) {
135
- balanceResetAt.text('error');
136
- }
137
- } else {
138
- userBalance.text(response.data.balance);
139
- if ("server_5" === data['server_name']) {
140
- balanceResetAt.text(response.data.reset_at);
141
- }
142
- }
143
- }).fail(function (xhr, status, error) {
144
- console.log(xhr);
145
- console.log(status);
146
- console.log(error);
147
-
148
- self.throwError(error);
149
- });
150
- },
151
-
152
- checkServerStatus: function () {
153
- var self = this,
154
- serverStatus = $('.wrio-server-status'),
155
- data = {
156
- 'action': 'wbcr-rio-check-servers-status',
157
- '_wpnonce': self.settings.nonce
158
- };
159
-
160
- self.serverDown = false;
161
-
162
- data['server_name'] = $('#wrio-change-optimization-server').val();
163
-
164
- serverStatus.addClass('wrio-server-check-proccess');
165
- serverStatus.text('');
166
- serverStatus.removeClass('wrio-down').removeClass('wrio-stable');
167
-
168
- self.startOptButton.prop('disabled', true);
169
-
170
- $.post(ajaxurl, data, function (response) {
171
- serverStatus.removeClass('wrio-server-check-proccess');
172
- $('#wrio-change-optimization-server').prop('disabled', false);
173
-
174
- if (!response || !response.data || !response.success) {
175
- console.log('[Error]: Response error');
176
- response.data && response.data.error && console.log(response.data.error);
177
-
178
- if (!response || !response.data) {
179
- console.log(response);
180
- }
181
-
182
- $('option[name="' + data['server_name'] + '"]').prop('disabled', true);
183
- serverStatus.addClass('wrio-down');
184
- serverStatus.text(self.i18n.server_status_down);
185
- self.serverDown = true;
186
-
187
- return;
188
- } else {
189
- serverStatus.addClass('wrio-stable');
190
- serverStatus.text(self.i18n.server_status_stable);
191
- }
192
-
193
- self.startOptButton.prop('disabled', false);
194
-
195
- }).fail(function (xhr, status, error) {
196
- console.log(xhr);
197
- console.log(status);
198
- console.log(error);
199
-
200
- self.throwError(error);
201
- });
202
- },
203
-
204
- calculateTotalImages: function () {
205
- var self = this,
206
- total_num = $('#wio-total-num'),
207
- data = {
208
- 'action': 'wbcr-rio-calculate-total-images',
209
- '_wpnonce': self.settings.nonce
210
- };
211
-
212
- total_num.addClass('wrio-calculate-process');
213
- total_num.text('');
214
-
215
- $.post(ajaxurl, data, function (response) {
216
- total_num.removeClass('wrio-calculate-process');
217
-
218
- if (!response || !response.data || !response.success) {
219
- console.log('[Error]: Response error');
220
- response.data && response.data.error && console.log(response.data.error);
221
-
222
- if (!response || !response.data) {
223
- console.log(response);
224
- }
225
-
226
- total_num.text('');
227
-
228
- return;
229
- } else {
230
- if (typeof (response.data.total) !== "undefined") {
231
- total_num.addClass('wrio-total-images');
232
- total_num.text(response.data.total);
233
- }
234
- }
235
- }).fail(function (xhr, status, error) {
236
- console.log(xhr);
237
- console.log(status);
238
- console.log(error);
239
-
240
- self.throwError(error);
241
- });
242
- },
243
-
244
- showModal: function () {
245
- var self = this;
246
- var infosModal = $('#wrio-tmpl-bulk-optimization');
247
-
248
- if (!infosModal.length) {
249
- console.log('[Error]: Html template for modal not found.');
250
- return;
251
- }
252
-
253
- // Swal Information before loading the optimize process.
254
- swal({
255
- title: this.i18n.modal_optimization_title,
256
- html: infosModal.html(),
257
- type: '',
258
- customClass: 'wrio-modal wrio-modal-optimization-way',
259
- showCancelButton: true,
260
- showCloseButton: true,
261
- padding: 0,
262
- width: 740,
263
- confirmButtonText: this.i18n.modal_optimization_manual_button,
264
- cancelButtonText: this.i18n.modal_optimization_cron_button,
265
- reverseButtons: true,
266
- }).then(function (result) {
267
-
268
- self.process();
269
-
270
- window.onbeforeunload = function () {
271
- return self.i18n.leave_page_warning;
272
- }
273
-
274
- }, function (dismiss) {
275
- if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
276
- self.process('cron');
277
- } else {
278
- throw dismiss;
279
- }
280
- });
281
-
282
- },
283
-
284
- /**
285
- * Start optimization
286
- * @param {string} type
287
- */
288
- process: function (type) {
289
- var self = this;
290
-
291
- this.inprogress = true;
292
-
293
- var sendData = {
294
- 'action': 'wrio-bulk-optimization-process',
295
- 'scope': this.settings.scope,
296
- 'multisite': 0,
297
- '_wpnonce': this.settings.nonce,
298
- };
299
-
300
- this.setButtonStyleRun(type);
301
-
302
- if ('cron' === type) {
303
- this.startOptButton.addClass('wrio-cron-mode');
304
-
305
- sendData['action'] = 'wrio-cron-start';
306
-
307
- $.post(ajaxurl, sendData, function (response) {
308
- if (!response || !response.success) {
309
- console.log('[Error]: Failed ajax request (Start cron).');
310
- console.log(sendData);
311
- console.log(response);
312
-
313
- if (response.data && response.data.error_message) {
314
- self.throwError(response.data.error_message);
315
- }
316
- } else {
317
- if (response.data && response.data.stop) {
318
- self.stop();
319
- }
320
- }
321
- }).fail(function (xhr, status, error) {
322
- console.log(xhr);
323
- console.log(status);
324
- console.log(error);
325
-
326
- self.throwError(error);
327
- });
328
-
329
- return;
330
- }
331
-
332
- this.showMessage(this.i18n.optimization_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
333
-
334
- // show message: Optimization remined
335
- /*if( "1" === this.settings.is_network_admin ) {
336
- sendData['multisite'] = 1;
337
- }*/
338
-
339
- sendData['reset_current_errors'] = 1;
340
-
341
- this.sendRequest(sendData);
342
- },
343
-
344
- stop: function () {
345
- var self = this;
346
-
347
- this.inprogress = false;
348
-
349
- window.onbeforeunload = null;
350
- self.setButtonStyleStop();
351
- self.destroyMessages();
352
-
353
- if (this.startOptButton.hasClass('wrio-cron-mode')) {
354
- this.startOptButton.removeClass('wrio-cron-mode');
355
-
356
- $.post(ajaxurl, {
357
- 'action': 'wrio-cron-stop',
358
- '_wpnonce': self.settings.nonce,
359
- 'scope': self.settings.scope
360
- }, function (response) {
361
- if (!response || !response.success) {
362
- console.log('[Error]: Failed ajax request (Stop cron).');
363
- console.log(response);
364
-
365
- if (response.data && response.data.error_message) {
366
- self.throwError(response.data.error_message);
367
- }
368
- }
369
- }).fail(function (xhr, status, error) {
370
- console.log(xhr);
371
- console.log(status);
372
- console.log(error);
373
-
374
- self.throwError(error);
375
- });
376
- }
377
-
378
- },
379
-
380
- complete: function () {
381
- this.inprogress = false;
382
- window.onbeforeunload = null;
383
- this.setButtonStyleComplete();
384
- },
385
-
386
- setButtonStyleRun: function (mode) {
387
-
388
- this.startOptButton.addClass('wio-running');
389
-
390
- if ("cron" === mode) {
391
- this.startOptButton.text(this.i18n.button_stop_cron);
392
- return;
393
- }
394
-
395
- this.startOptButton.text(this.i18n.button_stop);
396
- },
397
-
398
- setButtonStyleComplete: function () {
399
- this.showMessage(this.i18n.optimization_complete);
400
- this.startOptButton.text(this.i18n.button_completed);
401
- this.startOptButton.removeClass('wio-running');
402
- this.startOptButton.prop('disabled', true);
403
- },
404
-
405
- setButtonStyleStop: function () {
406
- this.startOptButton.removeClass('wio-running');
407
- this.startOptButton.text(this.i18n.buttom_start);
408
- },
409
-
410
- showMessage: function (text) {
411
- var contanier = $('.wio-page-statistic'),
412
- message;
413
-
414
- if (contanier.find('.wrio-statistic-message').length) {
415
- message = contanier.find('.wrio-statistic-message');
416
- } else {
417
- message = $('<div>');
418
- message.addClass('wrio-statistic-message');
419
- contanier.append(message);
420
- }
421
-
422
- message.html(text);
423
- },
424
-
425
- throwError: function (error_message) {
426
- this.stop();
427
-
428
- var noticeId = $.wbcr_factory_clearfy_237.app.showNotice(error_message, 'danger');
429
-
430
- setTimeout(function () {
431
- $.wbcr_factory_clearfy_237.app.hideNotice(noticeId);
432
- }, 10000);
433
- },
434
-
435
- destroyMessages: function () {
436
- $('.wio-page-statistic').find('.wrio-statistic-message').remove();
437
- },
438
-
439
- sendRequest: function (data) {
440
- var self = this;
441
-
442
- if (!this.inprogress) {
443
- return;
444
- }
445
-
446
- $.post(ajaxurl, data, function (response) {
447
- if (!self.inprogress) {
448
- return;
449
- }
450
-
451
- if (!response || !response.success) {
452
- console.log('[Error]: Failed ajax request (Try to optimize images).');
453
- console.log(response);
454
-
455
- if (response.data && response.data.error_message) {
456
- self.throwError(response.data.error_message);
457
- }
458
-
459
- return;
460
- }
461
-
462
- data.reset_current_errors = 0;
463
-
464
- if (!response.data.end) {
465
- $('#wio-total-unoptimized').text(parseInt(response.data.remain));
466
- self.showMessage(self.i18n.optimization_inprogress.replace("%s", parseInt(response.data.remain)));
467
- self.sendRequest(data);
468
- } else {
469
- $('#wio-total-unoptimized').text(response.data.remain);
470
- self.complete();
471
-
472
- // если мультисайт режим, то не скрываем кнопку запуска оптимизации
473
- /*if( $('#wbcr-rio-current-blog').length ) {
474
- $('#wio-start-optimization').toggleClass('wio-running');
475
- } else {
476
- $('#wio-start-optimization').hide();
477
- }*/
478
- }
479
-
480
- redraw_statistics(response.data.statistic);
481
-
482
- self.updateLog(response.data.last_optimized);
483
- }).fail(function (xhr, status, error) {
484
- console.log(xhr);
485
- console.log(status);
486
- console.log(error);
487
-
488
- self.throwError(error);
489
- });
490
- },
491
-
492
- updateLog: function (new_item_data) {
493
- var self = this;
494
-
495
- var limit = 100,
496
- tableEl = $('.wrio-optimization-progress .wrio-table');
497
-
498
- if (!tableEl.length || !new_item_data) {
499
- return;
500
- }
501
-
502
- // если таблица была пустая
503
- if ($('.wrio-table-container-empty').length) {
504
- $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
505
- if (tableEl.find('tbody').length) {
506
- tableEl.find('tbody').empty();
507
- }
508
- }
509
-
510
- $.each(new_item_data, function (index, value) {
511
- var trEl = $('<tr>'),
512
- tdEl = $('<td>'),
513
- webpSize = value.webp_size ? value.webp_size : '-';
514
-
515
- if (tableEl.find('.wrio-row-id-' + value.id).length) {
516
- tableEl.find('.wrio-row-id-' + value.id).remove();
517
- }
518
-
519
- trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
520
-
521
- if ('error' === value.type) {
522
- trEl.addClass('wrio-error');
523
- }
524
-
525
- var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
526
- previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
527
-
528
- tableEl.prepend(trEl);
529
-
530
- trEl.append(tdEl.clone().append(preview));
531
- trEl.append(tdEl.clone().append(previewUrl));
532
-
533
- if ('error' === value.type) {
534
- var colspan = value.scope !== 'custom-folders' ? '6' : '5';
535
- trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
536
- } else {
537
- trEl.append(tdEl.clone().text(value.original_size));
538
- trEl.append(tdEl.clone().text(value.optimized_size));
539
- trEl.append(tdEl.clone().text(webpSize));
540
- trEl.append(tdEl.clone().text(value.original_saving));
541
-
542
- if ("custom-folders" !== self.settings.scope) {
543
- trEl.append(tdEl.clone().text(value.thumbnails_count));
544
- }
545
-
546
- trEl.append(tdEl.clone().text(value.total_saving));
547
- }
548
- });
549
-
550
- if (tableEl.find('tr').length > limit) {
551
- var diff = tableEl.find('tr').length - limit;
552
-
553
- for (var i = 0; i < diff; i++) {
554
- tableEl.find('tr:last').remove();
555
- }
556
- }
557
- }
558
-
559
- };
560
-
561
- $(document).ready(function () {
562
- bulkOptimization.init();
563
- $('[data-toggle="tooltip"]').tooltip();
564
- });
565
-
566
- var ajaxUrl = ajaxurl;
567
- var ai_data;
568
-
569
- function redraw_statistics(statistic) {
570
- $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized)
571
- .attr('data-optimized', statistic.optimized)
572
- .attr('data-errors', statistic.error);
573
- $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
574
- $('#wio-original-size').text(bytesToSize(statistic.original_size));
575
- $('#wio-optimized-size').text(bytesToSize(statistic.optimized_size));
576
- $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
577
- $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
578
- $('.wio-total-percent').text(statistic.optimized_percent + '%');
579
- $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
580
-
581
- $('#wio-unoptimized-num').text(statistic.unoptimized);
582
- $('#wio-optimized-num').text(statistic.optimized);
583
- $('#wio-error-num').text(statistic.error);
584
-
585
- var credits = $('.wrio-premium-user-balance');
586
- if (credits.attr('data-server') !== "server_5") {
587
- credits.text(statistic.credits);
588
- }
589
-
590
- if ($('.wrio-statistic-nav li.active').length) {
591
- $('.wrio-statistic-nav li.active').find('span.wio-statistic-tab-percent').text(statistic.optimized_percent + '%');
592
- }
593
-
594
- window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
595
- window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
596
- window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
597
- window.wio_chart.update();
598
- if ($('#wio-overview-chart-percent').text() == '100%') {
599
- window.onbeforeunload = null;
600
- }
601
- }
602
-
603
- function bytesToSize(bytes) {
604
- var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
605
- if (bytes == 0) {
606
- return '0 Byte';
607
- }
608
- var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
609
- if (i == 0) {
610
- return bytes + ' ' + sizes[i];
611
- }
612
- return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
613
- }
614
-
615
- /*$('#wbcr-rio-current-blog').on('change', function() {
616
- var self = $(this);
617
- $('#wio-start-msg-complete').hide();
618
- $(this).attr('disabled', true);
619
- $('#wio-start-optimization').attr('disabled', true);
620
- var ai_data = {
621
- 'action': 'wbcr_rio_update_current_blog',
622
- 'wpnonce': $(this).data('nonce'),
623
- 'current_blog_id': $(this).find('option:selected').val(),
624
- 'context': $(this).attr('data-context')
625
- };
626
- $.post(ajaxUrl, ai_data, function(response) {
627
- self.removeAttr('disabled');
628
- $('#wio-start-optimization').removeAttr('disabled');
629
- redraw_statistics(response.data.statistic);
630
- });
631
- });*/
632
-
633
- });
 
 
 
 
 
 
1
+ function bytesToSize(bytes) {
2
+ var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
3
+ if (bytes === 0) {
4
+ return '0 Byte';
5
+ }
6
+ var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
7
+ if (i === 0) {
8
+ return bytes + ' ' + sizes[i];
9
+ }
10
+ return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
11
+ }
12
+
13
+ jQuery(function ($) {
14
+ var bulkOptimization = {
15
+ inprogress: false,
16
+ serverDown: false,
17
+ i18n: {},
18
+ settings: {},
19
+
20
+ init: function () {
21
+ if (wrio_l18n_bulk_page === undefined || wrio_settings_bulk_page === undefined) {
22
+ console.log('[Error]: Required global variables are not declared.');
23
+ return;
24
+ }
25
+
26
+ this.i18n = wrio_l18n_bulk_page;
27
+ this.settings = wrio_settings_bulk_page;
28
+ this.startOptButton = $('#wrio-start-optimization');
29
+ this.startConvButton = $('#wrio-start-conversion');
30
+
31
+ if ('server_1' === $('#wrio-change-optimization-server').val()) {
32
+ $(".wrio-premium-user-balance-wrap").hide();
33
+ $(".wrio-premium-user-update-wrap").hide();
34
+ }
35
+ if ('server_5' === $('#wrio-change-optimization-server').val()) {
36
+ if (!this.settings.is_premium) {
37
+ $.wrio_modal.showErrorModal(this.i18n.premium_server_disabled);
38
+ }
39
+ }
40
+
41
+ this.registerEvents();
42
+ this.checkServerStatus();
43
+ this.calculateTotalImages();
44
+ this.checkPremiumUserBalance();
45
+
46
+ },
47
+
48
+ registerEvents: function () {
49
+ var self = this,
50
+ selectedServer = $("#wrio-change-optimization-server option:selected");
51
+
52
+ $('#wrio-change-optimization-server').on('change', function () {
53
+ $(this).prop('disabled', true);
54
+ $('.wrio-premium-user-balance').attr('data-server', $(this).val());
55
+ $(".wrio-premium-user-balance-wrap").show();
56
+ $(".wrio-premium-user-update-wrap").show();
57
+
58
+ if ('server_1' === $(this).val()) {
59
+ $(".wrio-premium-user-balance-wrap").hide();
60
+ $(".wrio-premium-user-update-wrap").hide();
61
+ }
62
+ if ('server_5' === $(this).val()) {
63
+ if (!self.settings.is_premium) {
64
+ $.wrio_modal.showErrorModal(self.i18n.premium_server_disabled);
65
+ selectedServer.prop('selected', true);
66
+ $(this).prop('disabled', false);
67
+
68
+ return;
69
+ }
70
+ }
71
+
72
+ self.checkPremiumUserBalance();
73
+
74
+ selectedServer = $(this).find('option:selected');
75
+ self.checkServerStatus();
76
+ });
77
+
78
+ this.startOptButton.on('click', function () {
79
+ self.startOptButton = $(this);
80
+
81
+ if ($(this).hasClass('wio-running')) {
82
+ self.startConvButton.prop('disabled', false);
83
+ self.stop();
84
+ return;
85
+ }
86
+
87
+ if (self.serverDown) {
88
+ $.wrio_modal.showErrorModal(self.i18n.server_down_warning);
89
+ return;
90
+ }
91
+
92
+ if ("1" === self.settings.need_migration) {
93
+ $.wrio_modal.showErrorModal(self.i18n.need_migrations);
94
+ return;
95
+ }
96
+
97
+ if ("0" === self.settings.images_backup) {
98
+ $.wrio_modal.showWarningModal(self.i18n.process_without_backup, function () {
99
+ self.showModal();
100
+ });
101
+ return;
102
+ }
103
+
104
+ self.showModal();
105
+
106
+ return false;
107
+ });
108
+ },
109
+
110
+ checkPremiumUserBalance: function () {
111
+ var self = this,
112
+ userBalance = $('.wrio-premium-user-balance'),
113
+ balanceResetAt = $('.wrio-premium-user-update'),
114
+ data = {
115
+ 'action': 'wbcr-rio-check-user-balance',
116
+ '_wpnonce': self.settings.optimization_nonce
117
+ };
118
+
119
+ data['server_name'] = $('#wrio-change-optimization-server').val();
120
+
121
+ userBalance.addClass('wrio-premium-user-balance-check-proccess');
122
+ userBalance.text('');
123
+
124
+ if ("server_5" === data['server_name']) {
125
+ balanceResetAt.addClass('wrio-premium-user-update-check-proccess');
126
+ balanceResetAt.text('');
127
+ }
128
+
129
+ $.post(ajaxurl, data, function (response) {
130
+ console.log(response);
131
+ userBalance.removeClass('wrio-premium-user-balance-check-proccess');
132
+ if ("server_5" === data['server_name']) {
133
+ balanceResetAt.removeClass('wrio-premium-user-update-check-proccess');
134
+ }
135
+
136
+ if (!response || !response.data || !response.success) {
137
+ console.log('[Error]: Response error');
138
+ response.data && response.data.error && console.log(response.data.error);
139
+
140
+ if (!response || !response.data) {
141
+ console.log(response);
142
+ }
143
+
144
+ userBalance.text('error');
145
+ if ("server_5" === data['server_name']) {
146
+ balanceResetAt.text('error');
147
+ }
148
+ } else {
149
+ userBalance.text(response.data.balance);
150
+ if ("server_5" === data['server_name']) {
151
+ balanceResetAt.text(response.data.reset_at);
152
+ }
153
+ }
154
+ }).fail(function (xhr, status, error) {
155
+ console.log(xhr);
156
+ console.log(status);
157
+ console.log(error);
158
+
159
+ self.throwError(error);
160
+ });
161
+ },
162
+
163
+ checkServerStatus: function () {
164
+ var self = this,
165
+ serverStatus = $('.wrio-server-status'),
166
+ data = {
167
+ 'action': 'wbcr-rio-check-servers-status',
168
+ '_wpnonce': self.settings.optimization_nonce
169
+ };
170
+
171
+ self.serverDown = false;
172
+
173
+ data['server_name'] = $('#wrio-change-optimization-server').val();
174
+
175
+ serverStatus.addClass('wrio-server-check-proccess');
176
+ serverStatus.text('');
177
+ serverStatus.removeClass('wrio-down').removeClass('wrio-stable');
178
+
179
+ self.startOptButton.prop('disabled', true);
180
+ self.startConvButton.prop('disabled', true);
181
+
182
+ $.post(ajaxurl, data, function (response) {
183
+ serverStatus.removeClass('wrio-server-check-proccess');
184
+ $('#wrio-change-optimization-server').prop('disabled', false);
185
+
186
+ if (!response || !response.data || !response.success) {
187
+ console.log('[Error]: Response error');
188
+ response.data && response.data.error && console.log(response.data.error);
189
+
190
+ if (!response || !response.data) {
191
+ console.log(response);
192
+ }
193
+
194
+ $('option[name="' + data['server_name'] + '"]').prop('disabled', true);
195
+ serverStatus.addClass('wrio-down');
196
+ serverStatus.text(self.i18n.server_status_down);
197
+ self.serverDown = true;
198
+
199
+ return;
200
+ } else {
201
+ serverStatus.addClass('wrio-stable');
202
+ serverStatus.text(self.i18n.server_status_stable);
203
+ }
204
+
205
+ self.startOptButton.prop('disabled', false);
206
+ self.startConvButton.prop('disabled', false);
207
+
208
+ }).fail(function (xhr, status, error) {
209
+ console.log(xhr);
210
+ console.log(status);
211
+ console.log(error);
212
+
213
+ self.throwError(error);
214
+ });
215
+ },
216
+
217
+ calculateTotalImages: function () {
218
+ var self = this,
219
+ total_num = $('#wio-total-num'),
220
+ data = {
221
+ 'action': 'wbcr-rio-calculate-total-images',
222
+ '_wpnonce': self.settings.optimization_nonce
223
+ };
224
+
225
+ total_num.addClass('wrio-calculate-process');
226
+ total_num.text('');
227
+
228
+ $.post(ajaxurl, data, function (response) {
229
+ total_num.removeClass('wrio-calculate-process');
230
+
231
+ if (!response || !response.data || !response.success) {
232
+ console.log('[Error]: Response error');
233
+ response.data && response.data.error && console.log(response.data.error);
234
+
235
+ if (!response || !response.data) {
236
+ console.log(response);
237
+ }
238
+
239
+ total_num.text('');
240
+
241
+ return;
242
+ } else {
243
+ if (typeof (response.data.total) !== "undefined") {
244
+ total_num.addClass('wrio-total-images');
245
+ total_num.text(response.data.total);
246
+ }
247
+ }
248
+ }).fail(function (xhr, status, error) {
249
+ console.log(xhr);
250
+ console.log(status);
251
+ console.log(error);
252
+
253
+ self.throwError(error);
254
+ });
255
+ },
256
+
257
+ showModal: function () {
258
+ var self = this;
259
+ var infosModal = $('#wrio-tmpl-bulk-optimization');
260
+
261
+ if (!infosModal.length) {
262
+ console.log('[Error]: Html template for modal not found.');
263
+ return;
264
+ }
265
+
266
+ // Swal Information before loading the optimize process.
267
+ swal({
268
+ title: this.i18n.modal_optimization_title,
269
+ html: infosModal.html(),
270
+ type: '',
271
+ customClass: 'wrio-modal wrio-modal-optimization-way',
272
+ showCancelButton: true,
273
+ showCloseButton: true,
274
+ padding: 0,
275
+ width: 740,
276
+ confirmButtonText: this.i18n.modal_optimization_manual_button,
277
+ cancelButtonText: this.i18n.modal_optimization_cron_button,
278
+ reverseButtons: true,
279
+ }).then(function (result) {
280
+
281
+ self.startConvButton.prop('disabled', true);
282
+ self.process();
283
+
284
+ window.onbeforeunload = function () {
285
+ return self.i18n.leave_page_warning;
286
+ }
287
+
288
+ }, function (dismiss) {
289
+ if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
290
+ self.startConvButton.prop('disabled', true);
291
+ self.process('cron');
292
+ } else {
293
+ throw dismiss;
294
+ }
295
+ });
296
+
297
+ },
298
+
299
+ /**
300
+ * Start optimization
301
+ * @param {string} type
302
+ */
303
+ process: function (type) {
304
+ var self = this;
305
+
306
+ this.inprogress = true;
307
+
308
+ var sendData = {
309
+ 'action': 'wrio-bulk-optimization-process',
310
+ 'scope': this.settings.scope,
311
+ 'multisite': 0,
312
+ '_wpnonce': this.settings.optimization_nonce,
313
+ };
314
+
315
+ this.setButtonStyleRun(type);
316
+
317
+ if ('cron' === type) {
318
+ this.startOptButton.addClass('wrio-cron-mode');
319
+
320
+ sendData['action'] = 'wrio-cron-start';
321
+
322
+ $.post(ajaxurl, sendData, function (response) {
323
+ if (!response || !response.success) {
324
+ console.log('[Error]: Failed ajax request (Start cron).');
325
+ console.log(sendData);
326
+ console.log(response);
327
+
328
+ if (response.data && response.data.error_message) {
329
+ self.throwError(response.data.error_message);
330
+ }
331
+ } else {
332
+ if (response.data && response.data.stop) {
333
+ self.stop();
334
+ }
335
+ }
336
+ }).fail(function (xhr, status, error) {
337
+ console.log(xhr);
338
+ console.log(status);
339
+ console.log(error);
340
+
341
+ self.throwError(error);
342
+ });
343
+
344
+ return;
345
+ }
346
+
347
+ this.showMessage(this.i18n.optimization_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
348
+
349
+ // show message: Optimization remined
350
+ /*if( "1" === this.settings.is_network_admin ) {
351
+ sendData['multisite'] = 1;
352
+ }*/
353
+
354
+ sendData['reset_current_errors'] = 1;
355
+
356
+ this.sendRequest(sendData);
357
+ },
358
+
359
+ stop: function () {
360
+ var self = this;
361
+
362
+ this.inprogress = false;
363
+
364
+ window.onbeforeunload = null;
365
+ self.setButtonStyleStop();
366
+ self.destroyMessages();
367
+
368
+ if (this.startOptButton.hasClass('wrio-cron-mode')) {
369
+ this.startOptButton.removeClass('wrio-cron-mode');
370
+
371
+ $.post(ajaxurl, {
372
+ 'action': 'wrio-cron-stop',
373
+ '_wpnonce': self.settings.optimization_nonce,
374
+ 'scope': self.settings.scope
375
+ }, function (response) {
376
+ if (!response || !response.success) {
377
+ console.log('[Error]: Failed ajax request (Stop cron).');
378
+ console.log(response);
379
+
380
+ if (response.data && response.data.error_message) {
381
+ self.throwError(response.data.error_message);
382
+ }
383
+ } else {
384
+ self.startConvButton.prop('disabled', false);
385
+ }
386
+ }).fail(function (xhr, status, error) {
387
+ console.log(xhr);
388
+ console.log(status);
389
+ console.log(error);
390
+
391
+ self.throwError(error);
392
+ });
393
+ }
394
+
395
+ },
396
+
397
+ complete: function () {
398
+ this.inprogress = false;
399
+ window.onbeforeunload = null;
400
+ this.setButtonStyleComplete();
401
+ },
402
+
403
+ setButtonStyleRun: function (mode) {
404
+
405
+ this.startOptButton.addClass('wio-running');
406
+
407
+ if ("cron" === mode) {
408
+ this.startOptButton.text(this.i18n.modal_optimization_cron_button_stop);
409
+ return;
410
+ }
411
+
412
+ this.startOptButton.text(this.i18n.button_stop);
413
+ },
414
+
415
+ setButtonStyleComplete: function () {
416
+ this.showMessage(this.i18n.optimization_complete);
417
+ this.startOptButton.text(this.i18n.button_completed);
418
+ this.startOptButton.removeClass('wio-running');
419
+ this.startOptButton.prop('disabled', true);
420
+ this.startConvButton.prop('disabled', false);
421
+ },
422
+
423
+ setButtonStyleStop: function () {
424
+ this.startOptButton.removeClass('wio-running');
425
+ this.startOptButton.text(this.i18n.button_start);
426
+ },
427
+
428
+ showMessage: function (text) {
429
+ var contanier = $('.wio-page-statistic'),
430
+ message;
431
+
432
+ if (contanier.find('.wrio-statistic-message').length) {
433
+ message = contanier.find('.wrio-statistic-message');
434
+ } else {
435
+ message = $('<div>');
436
+ message.addClass('wrio-statistic-message');
437
+ contanier.append(message);
438
+ }
439
+
440
+ message.html(text);
441
+ },
442
+
443
+ throwError: function (error_message) {
444
+ this.stop();
445
+
446
+ var noticeId = $.wbcr_factory_templates_102.app.showNotice(error_message, 'danger');
447
+
448
+ setTimeout(function () {
449
+ $.wbcr_factory_templates_102.app.hideNotice(noticeId);
450
+ }, 10000);
451
+ },
452
+
453
+ destroyMessages: function () {
454
+ $('.wio-page-statistic').find('.wrio-statistic-message').empty();
455
+ },
456
+
457
+ sendRequest: function (data) {
458
+ var self = this;
459
+
460
+ if (!this.inprogress) {
461
+ return;
462
+ }
463
+
464
+ $.post(ajaxurl, data, function (response) {
465
+ if (!self.inprogress) {
466
+ return;
467
+ }
468
+
469
+ if (!response || !response.success) {
470
+ console.log('[Error]: Failed ajax request (Try to optimize images).');
471
+ console.log(response);
472
+
473
+ if (response.data && response.data.error_message) {
474
+ self.throwError(response.data.error_message);
475
+ }
476
+
477
+ return;
478
+ }
479
+
480
+ data.reset_current_errors = 0;
481
+
482
+ if (!response.data.end) {
483
+ $('#wio-total-unoptimized').text(parseInt(response.data.remain));
484
+ self.showMessage(self.i18n.optimization_inprogress.replace("%s", parseInt(response.data.remain)));
485
+ self.sendRequest(data);
486
+ } else {
487
+ $('#wio-total-unoptimized').text(response.data.remain);
488
+ self.complete();
489
+
490
+ // если мультисайт режим, то не скрываем кнопку запуска оптимизации
491
+ /*if( $('#wbcr-rio-current-blog').length ) {
492
+ $('#wio-start-optimization').toggleClass('wio-running');
493
+ } else {
494
+ $('#wio-start-optimization').hide();
495
+ }*/
496
+ }
497
+
498
+ redraw_statistics(response.data.statistic);
499
+
500
+ self.updateLog(response.data.last_optimized);
501
+ }).fail(function (xhr, status, error) {
502
+ console.log(xhr);
503
+ console.log(status);
504
+ console.log(error);
505
+
506
+ self.throwError(error);
507
+ });
508
+ },
509
+
510
+ updateLog: function (new_item_data) {
511
+ var self = this;
512
+
513
+ var limit = 100,
514
+ tableEl = $('.wrio-optimization-progress .wrio-table');
515
+
516
+ if (!tableEl.length || !new_item_data) {
517
+ return;
518
+ }
519
+
520
+ // если таблица была пустая
521
+ if ($('.wrio-table-container-empty').length) {
522
+ $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
523
+ if (tableEl.find('tbody').length) {
524
+ tableEl.find('tbody').empty();
525
+ }
526
+ }
527
+
528
+ $.each(new_item_data, function (index, value) {
529
+ var trEl = $('<tr>'),
530
+ tdEl = $('<td>'),
531
+ webpSize = value.webp_size ? value.webp_size : '-';
532
+
533
+ if (tableEl.find('.wrio-row-id-' + value.id).length) {
534
+ tableEl.find('.wrio-row-id-' + value.id).remove();
535
+ }
536
+
537
+ trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
538
+
539
+ if ('error' === value.type) {
540
+ trEl.addClass('wrio-error');
541
+ }
542
+
543
+ var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
544
+ previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
545
+
546
+ tableEl.prepend(trEl);
547
+
548
+ trEl.append(tdEl.clone().append(preview));
549
+ trEl.append(tdEl.clone().append(previewUrl));
550
+
551
+ if ('error' === value.type) {
552
+ var colspan = value.scope !== 'custom-folders' ? '6' : '5';
553
+ trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
554
+ } else {
555
+ trEl.append(tdEl.clone().text(value.original_size));
556
+ trEl.append(tdEl.clone().text(value.optimized_size));
557
+ trEl.append(tdEl.clone().text(webpSize));
558
+ trEl.append(tdEl.clone().text(value.original_saving));
559
+
560
+ if ("custom-folders" !== self.settings.scope) {
561
+ trEl.append(tdEl.clone().text(value.thumbnails_count));
562
+ }
563
+
564
+ trEl.append(tdEl.clone().text(value.total_saving));
565
+ }
566
+ });
567
+
568
+ if (tableEl.find('tr').length > limit) {
569
+ var diff = tableEl.find('tr').length - limit;
570
+
571
+ for (var i = 0; i < diff; i++) {
572
+ tableEl.find('tr:last').remove();
573
+ }
574
+ }
575
+ }
576
+
577
+ };
578
+
579
+ $(document).ready(function () {
580
+ bulkOptimization.init();
581
+ $('[data-toggle="tooltip"]').tooltip();
582
+ });
583
+
584
+ var ajaxUrl = ajaxurl;
585
+ var ai_data;
586
+
587
+ function redraw_statistics(statistic) {
588
+ $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized)
589
+ .attr('data-optimized', statistic.optimized)
590
+ .attr('data-errors', statistic.error);
591
+ $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
592
+ $('#wio-original-size').text(bytesToSize(statistic.original_size));
593
+ $('#wio-optimized-size').text(bytesToSize(statistic.optimized_size));
594
+ $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
595
+ $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
596
+ $('.wio-total-percent').text(statistic.optimized_percent + '%');
597
+ $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
598
+
599
+ $('#wio-unoptimized-num').text(statistic.unoptimized);
600
+ $('#wio-optimized-num').text(statistic.optimized);
601
+ $('#wio-error-num').text(statistic.error);
602
+
603
+ var credits = $('.wrio-premium-user-balance');
604
+ if (credits.attr('data-server') !== "server_5") {
605
+ credits.text(statistic.credits);
606
+ }
607
+
608
+ if ($('.wrio-statistic-nav li.active').length) {
609
+ $('.wrio-statistic-nav li.active').find('span.wio-statistic-tab-percent').text(statistic.optimized_percent + '%');
610
+ }
611
+
612
+ window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
613
+ window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
614
+ window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
615
+ window.wio_chart.update();
616
+ if ($('#wio-overview-chart-percent').text() == '100%') {
617
+ window.onbeforeunload = null;
618
+ }
619
+ }
620
+
621
+ /*$('#wbcr-rio-current-blog').on('change', function() {
622
+ var self = $(this);
623
+ $('#wio-start-msg-complete').hide();
624
+ $(this).attr('disabled', true);
625
+ $('#wio-start-optimization').attr('disabled', true);
626
+ var ai_data = {
627
+ 'action': 'wbcr_rio_update_current_blog',
628
+ 'wpnonce': $(this).data('nonce'),
629
+ 'current_blog_id': $(this).find('option:selected').val(),
630
+ 'context': $(this).attr('data-context')
631
+ };
632
+ $.post(ajaxUrl, ai_data, function(response) {
633
+ self.removeAttr('disabled');
634
+ $('#wio-start-optimization').removeAttr('disabled');
635
+ redraw_statistics(response.data.statistic);
636
+ });
637
+ });*/
638
+
639
+ });
admin/assets/js/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/assets/js/meta-migrations.js CHANGED
@@ -1,52 +1,52 @@
1
- jQuery(function($) {
2
- $('#wbcr-wio-meta-migration-action').on('click', function() {
3
-
4
- var data = {
5
- 'action': 'wrio_meta_migrations',
6
- '_wpnonce': $(this).data('nonce'),
7
- };
8
-
9
- $(this).addClass('disabled').text('Please wait...');
10
-
11
- send_request($(this), data);
12
- });
13
-
14
- function send_request(button, data) {
15
- $.post(window.ajaxurl, data, function(response) {
16
-
17
- console.log(response);
18
-
19
- if( !response || !response.data ) {
20
- console.log('An unknown server error has occurred.');
21
- console.log(response);
22
- return false;
23
- }
24
-
25
- if( !response.data.need_more_time ) {
26
- if( button.closest('.notice').length ) {
27
- button.closest('.notice').remove();
28
- }
29
- if( button.closest('.alert').length ) {
30
- button.closest('.alert').remove();
31
- }
32
-
33
- return false;
34
- }
35
-
36
- button.text(response.data.message);
37
-
38
- send_request(button, data);
39
- }).fail(function(xhr, status, error) {
40
- console.log(xhr);
41
- console.log(status);
42
- console.log(error);
43
-
44
- data.limit = 5;
45
- data.error = 1;
46
-
47
- setTimeout(function() {
48
- send_request(button, data);
49
- }, 2000);
50
- });
51
- }
52
- });
1
+ jQuery(function($) {
2
+ $('#wbcr-wio-meta-migration-action').on('click', function() {
3
+
4
+ var data = {
5
+ 'action': 'wrio_meta_migrations',
6
+ '_wpnonce': $(this).data('nonce'),
7
+ };
8
+
9
+ $(this).addClass('disabled').text('Please wait...');
10
+
11
+ send_request($(this), data);
12
+ });
13
+
14
+ function send_request(button, data) {
15
+ $.post(window.ajaxurl, data, function(response) {
16
+
17
+ console.log(response);
18
+
19
+ if( !response || !response.data ) {
20
+ console.log('An unknown server error has occurred.');
21
+ console.log(response);
22
+ return false;
23
+ }
24
+
25
+ if( !response.data.need_more_time ) {
26
+ if( button.closest('.notice').length ) {
27
+ button.closest('.notice').remove();
28
+ }
29
+ if( button.closest('.alert').length ) {
30
+ button.closest('.alert').remove();
31
+ }
32
+
33
+ return false;
34
+ }
35
+
36
+ button.text(response.data.message);
37
+
38
+ send_request(button, data);
39
+ }).fail(function(xhr, status, error) {
40
+ console.log(xhr);
41
+ console.log(status);
42
+ console.log(error);
43
+
44
+ data.limit = 5;
45
+ data.error = 1;
46
+
47
+ setTimeout(function() {
48
+ send_request(button, data);
49
+ }, 2000);
50
+ });
51
+ }
52
+ });
admin/assets/js/modals.js CHANGED
@@ -1,59 +1,59 @@
1
- /**
2
- * A set of tools for creating pop-ups. You can create a popup
3
- * using a global method call.
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright (c) 05.04.2019, Webcraftic
7
- * @version 1.0
8
- */
9
-
10
-
11
- (function($) {
12
- 'use strict';
13
-
14
- if( !$.wrio_modal ) {
15
- $.wrio_modal = {};
16
- }
17
-
18
- $.wrio_modal = $.wrio_popup || {
19
-
20
- showErrorModal: function(text) {
21
- if( !text ) {
22
- console.log('[Error]: Text required.');
23
- return;
24
- }
25
-
26
- swal({
27
- title: 'Error',
28
- text: text,
29
- type: 'error',
30
- customClass: 'wrio-modal wrio-modal-error',
31
- width: 500,
32
- confirmButtonText: 'OK',
33
- });
34
- },
35
-
36
- showWarningModal: function(text, callback) {
37
- if( !text ) {
38
- console.log('[Error]: Text required.');
39
- return;
40
- }
41
-
42
- swal({
43
- title: 'Warning',
44
- text: text,
45
- type: 'warning',
46
- customClass: 'wrio-modal wrio-modal-warning',
47
- width: 500,
48
- showCancelButton: true,
49
- showCloseButton: true,
50
- confirmButtonText: 'OK',
51
- }).then(function(result) {
52
- if( callback ) {
53
- callback();
54
- }
55
- }).catch(swal.noop);
56
- },
57
- };
58
-
59
- })(jQuery);
1
+ /**
2
+ * A set of tools for creating pop-ups. You can create a popup
3
+ * using a global method call.
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright (c) 05.04.2019, Webcraftic
7
+ * @version 1.0
8
+ */
9
+
10
+
11
+ (function($) {
12
+ 'use strict';
13
+
14
+ if( !$.wrio_modal ) {
15
+ $.wrio_modal = {};
16
+ }
17
+
18
+ $.wrio_modal = $.wrio_popup || {
19
+
20
+ showErrorModal: function(text) {
21
+ if( !text ) {
22
+ console.log('[Error]: Text required.');
23
+ return;
24
+ }
25
+
26
+ swal({
27
+ title: 'Error',
28
+ text: text,
29
+ type: 'error',
30
+ customClass: 'wrio-modal wrio-modal-error',
31
+ width: 500,
32
+ confirmButtonText: 'OK',
33
+ });
34
+ },
35
+
36
+ showWarningModal: function(text, callback) {
37
+ if( !text ) {
38
+ console.log('[Error]: Text required.');
39
+ return;
40
+ }
41
+
42
+ swal({
43
+ title: 'Warning',
44
+ text: text,
45
+ type: 'warning',
46
+ customClass: 'wrio-modal wrio-modal-warning',
47
+ width: 500,
48
+ showCancelButton: true,
49
+ showCloseButton: true,
50
+ confirmButtonText: 'OK',
51
+ }).then(function(result) {
52
+ if( callback ) {
53
+ callback();
54
+ }
55
+ }).catch(swal.noop);
56
+ },
57
+ };
58
+
59
+ })(jQuery);
admin/assets/js/restore-backup.js CHANGED
@@ -1,162 +1,162 @@
1
- jQuery(function($){
2
- var ajaxUrl = ajaxurl;
3
-
4
- $('#wio-restore-backup-btn').on('click', function() {
5
- if ( $('#wio-multisite-mode').length ) {
6
- $('#wio-multisite-mode').toggle();
7
- $('#wio-multisite-confirm').attr('data-action', 'restore');
8
- $('#wio-multisite-restore-progress').empty();
9
- return false;
10
- }
11
- result = confirm( $(this).attr('data-confirm') );
12
- if ( ! result ) {
13
- return false;
14
- }
15
- $(this).hide();
16
- $('#wio-restore-backup-progress').show();
17
- var ai_data = {
18
- 'total' : '?',
19
- 'action': 'wio_restore_backup',
20
- '_wpnonce': $('#wio-iph-nonce').val()
21
- };
22
- send_post_data(ai_data);
23
- return false;
24
- });
25
-
26
- $('#wio-clear-backup-btn').on('click', function() {
27
- $('#wio-restore-backup-msg').hide();
28
- if ( $('#wio-multisite-mode').length ) {
29
- $('#wio-multisite-mode').toggle();
30
- $('#wio-multisite-confirm').attr('data-action', 'clear');
31
- $('#wio-multisite-restore-progress').empty();
32
- return false;
33
- }
34
- result = confirm( $(this).attr('data-confirm') );
35
- if ( ! result ) {
36
- return false;
37
- }
38
- var data = {
39
- 'action': 'wio_clear_backup',
40
- '_wpnonce': $('#wio-iph-nonce').val()
41
- };
42
- $.post(ajaxUrl, data, function(response) {
43
- $('#wio-clear-backup-msg').show();
44
- });
45
- });
46
-
47
- $('#wio-multisite-confirm').on('click', function() {
48
- var action = $(this).attr('data-action');
49
- // если запущена очистка резервных копий
50
- if ( action == 'clear' ) {
51
- result = confirm( $('#wio-clear-backup-btn').attr('data-confirm') ); // берём сообщение из основной кнопки
52
- if ( ! result ) {
53
- return false;
54
- }
55
- var blogs = [];
56
- $('.wbcr_io_multisite_blogs:checked').each(function() {
57
- blogs.push( $(this).val() );
58
- });
59
- var data = {
60
- 'action': 'wio_clear_backup',
61
- '_wpnonce': $('#wio-iph-nonce').val(),
62
- 'blogs': blogs
63
- };
64
-
65
- $.post(ajaxUrl, data, function(response) {
66
- $('#wio-clear-backup-msg').show();
67
- $('#wio-multisite-mode').toggle();
68
- });
69
- return false;
70
- }
71
-
72
- // если запущено восстановление из резервных копий
73
- if ( action == 'restore' ) {
74
- result = confirm( $('#wio-restore-backup-btn').attr('data-confirm') ); // берём сообщение из основной кнопки
75
- if ( ! result ) {
76
- return false;
77
- }
78
- $('#wio-multisite-mode').toggle();
79
- $('#wio-multisite-restore-progress').empty();
80
- $('.wbcr_io_multisite_blogs:checked').each(function() {
81
- $('#wio-multisite-restore-progress').append('\
82
- <label>'+$(this).attr('data-name')+'</label>\
83
- <div class="progress">\
84
- <div id="wio-restore-backup-progress-'+$(this).val()+'" class="wio-restore-backup-progressbar progress-bar progress-bar-success" data-id="'+$(this).val()+'" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">\
85
- </div>\
86
- </div>\
87
- ');
88
- });
89
- $('#wio-multisite-restore-progress').show();
90
- if ( ! $('.wio-restore-backup-progressbar').length ) {
91
- $('#wio-restore-backup-msg').show();
92
- return false;
93
- }
94
- var ai_data = {
95
- 'total' : '?',
96
- 'action': 'wio_restore_backup',
97
- '_wpnonce': $('#wio-iph-nonce').val(),
98
- 'blog_id': $('.wio-restore-backup-progressbar:eq(0)').attr('data-id')
99
- };
100
- send_multisite_post_data(ai_data);
101
- return false;
102
- }
103
- });
104
-
105
- $('#wbcr_io_multisite_blog_all').on('change', function() {
106
- if ( $(this).attr('checked') == 'checked' ) {
107
- $('.wbcr_io_multisite_blogs').attr('checked', true);
108
- } else {
109
- $('.wbcr_io_multisite_blogs').removeAttr('checked');
110
- }
111
- });
112
-
113
- $('.wbcr_io_multisite_blogs').on('change', function() {
114
- var all_checked = true;
115
- $('.wbcr_io_multisite_blogs').each(function() {
116
- if ( $(this).attr('checked') != 'checked' ) {
117
- all_checked = false;
118
- }
119
- });
120
- if ( all_checked ) {
121
- $('#wbcr_io_multisite_blog_all').attr('checked', true);
122
- } else {
123
- $('#wbcr_io_multisite_blog_all').removeAttr('checked');
124
- }
125
- });
126
-
127
- function send_post_data(data){
128
- $.post(ajaxUrl, data, function(response) {
129
- if ( ! response.end ) {
130
- data.total = response.total;
131
- send_post_data(data);
132
- $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', response.percent + '%' );
133
- } else {
134
- $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', '100%' );
135
- $('#wio-restore-backup-msg').show();
136
- }
137
- });
138
- }
139
-
140
- function send_multisite_post_data(data){
141
- $.post(ajaxUrl, data, function(response) {
142
- if ( ! response.end ) {
143
- data.total = response.total;
144
- send_multisite_post_data(data);
145
- $('#wio-restore-backup-progress-' + data.blog_id).css( 'width', response.percent + '%' );
146
- } else {
147
- $('#wio-restore-backup-progress-' + data.blog_id).css( 'width', '100%' ).removeClass('wio-restore-backup-progressbar');
148
- if ( $('.wio-restore-backup-progressbar').length ) {
149
- var ai_data = {
150
- 'total' : '?',
151
- 'action': 'wio_restore_backup',
152
- '_wpnonce': $('#wio-iph-nonce').val(),
153
- 'blog_id': $('.wio-restore-backup-progressbar:eq(0)').attr('data-id')
154
- };
155
- send_multisite_post_data(ai_data);
156
- } else {
157
- $('#wio-restore-backup-msg').show();
158
- }
159
- }
160
- });
161
- }
162
- });
1
+ jQuery(function($){
2
+ var ajaxUrl = ajaxurl;
3
+
4
+ $('#wio-restore-backup-btn').on('click', function() {
5
+ if ( $('#wio-multisite-mode').length ) {
6
+ $('#wio-multisite-mode').toggle();
7
+ $('#wio-multisite-confirm').attr('data-action', 'restore');
8
+ $('#wio-multisite-restore-progress').empty();
9
+ return false;
10
+ }
11
+ result = confirm( $(this).attr('data-confirm') );
12
+ if ( ! result ) {
13
+ return false;
14
+ }
15
+ $(this).hide();
16
+ $('#wio-restore-backup-progress').show();
17
+ var ai_data = {
18
+ 'total' : '?',
19
+ 'action': 'wio_restore_backup',
20
+ '_wpnonce': $('#wio-iph-nonce').val()
21
+ };
22
+ send_post_data(ai_data);
23
+ return false;
24
+ });
25
+
26
+ $('#wio-clear-backup-btn').on('click', function() {
27
+ $('#wio-restore-backup-msg').hide();
28
+ if ( $('#wio-multisite-mode').length ) {
29
+ $('#wio-multisite-mode').toggle();
30
+ $('#wio-multisite-confirm').attr('data-action', 'clear');
31
+ $('#wio-multisite-restore-progress').empty();
32
+ return false;
33
+ }
34
+ result = confirm( $(this).attr('data-confirm') );
35
+ if ( ! result ) {
36
+ return false;
37
+ }
38
+ var data = {
39
+ 'action': 'wio_clear_backup',
40
+ '_wpnonce': $('#wio-iph-nonce').val()
41
+ };
42
+ $.post(ajaxUrl, data, function(response) {
43
+ $('#wio-clear-backup-msg').show();
44
+ });
45
+ });
46
+
47
+ $('#wio-multisite-confirm').on('click', function() {
48
+ var action = $(this).attr('data-action');
49
+ // если запущена очистка резервных копий
50
+ if ( action == 'clear' ) {
51
+ result = confirm( $('#wio-clear-backup-btn').attr('data-confirm') ); // берём сообщение из основной кнопки
52
+ if ( ! result ) {
53
+ return false;
54
+ }
55
+ var blogs = [];
56
+ $('.wbcr_io_multisite_blogs:checked').each(function() {
57
+ blogs.push( $(this).val() );
58
+ });
59
+ var data = {
60
+ 'action': 'wio_clear_backup',
61
+ '_wpnonce': $('#wio-iph-nonce').val(),
62
+ 'blogs': blogs
63
+ };
64
+
65
+ $.post(ajaxUrl, data, function(response) {
66
+ $('#wio-clear-backup-msg').show();
67
+ $('#wio-multisite-mode').toggle();
68
+ });
69
+ return false;
70
+ }
71
+
72
+ // если запущено восстановление из резервных копий
73
+ if ( action == 'restore' ) {
74
+ result = confirm( $('#wio-restore-backup-btn').attr('data-confirm') ); // берём сообщение из основной кнопки
75
+ if ( ! result ) {
76
+ return false;
77
+ }
78
+ $('#wio-multisite-mode').toggle();
79
+ $('#wio-multisite-restore-progress').empty();
80
+ $('.wbcr_io_multisite_blogs:checked').each(function() {
81
+ $('#wio-multisite-restore-progress').append('\
82
+ <label>'+$(this).attr('data-name')+'</label>\
83
+ <div class="progress">\
84
+ <div id="wio-restore-backup-progress-'+$(this).val()+'" class="wio-restore-backup-progressbar progress-bar progress-bar-success" data-id="'+$(this).val()+'" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">\
85
+ </div>\
86
+ </div>\
87
+ ');
88
+ });
89
+ $('#wio-multisite-restore-progress').show();
90
+ if ( ! $('.wio-restore-backup-progressbar').length ) {
91
+ $('#wio-restore-backup-msg').show();
92
+ return false;
93
+ }
94
+ var ai_data = {
95
+ 'total' : '?',
96
+ 'action': 'wio_restore_backup',
97
+ '_wpnonce': $('#wio-iph-nonce').val(),
98
+ 'blog_id': $('.wio-restore-backup-progressbar:eq(0)').attr('data-id')
99
+ };
100
+ send_multisite_post_data(ai_data);
101
+ return false;
102
+ }
103
+ });
104
+
105
+ $('#wbcr_io_multisite_blog_all').on('change', function() {
106
+ if ( $(this).attr('checked') == 'checked' ) {
107
+ $('.wbcr_io_multisite_blogs').attr('checked', true);
108
+ } else {
109
+ $('.wbcr_io_multisite_blogs').removeAttr('checked');
110
+ }
111
+ });
112
+
113
+ $('.wbcr_io_multisite_blogs').on('change', function() {
114
+ var all_checked = true;
115
+ $('.wbcr_io_multisite_blogs').each(function() {
116
+ if ( $(this).attr('checked') != 'checked' ) {
117
+ all_checked = false;
118
+ }
119
+ });
120
+ if ( all_checked ) {
121
+ $('#wbcr_io_multisite_blog_all').attr('checked', true);
122
+ } else {
123
+ $('#wbcr_io_multisite_blog_all').removeAttr('checked');
124
+ }
125
+ });
126
+
127
+ function send_post_data(data){
128
+ $.post(ajaxUrl, data, function(response) {
129
+ if ( ! response.end ) {
130
+ data.total = response.total;
131
+ send_post_data(data);
132
+ $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', response.percent + '%' );
133
+ } else {
134
+ $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', '100%' );
135
+ $('#wio-restore-backup-msg').show();
136
+ }
137
+ });
138
+ }
139
+
140
+ function send_multisite_post_data(data){
141
+ $.post(ajaxUrl, data, function(response) {
142
+ if ( ! response.end ) {
143
+ data.total = response.total;
144
+ send_multisite_post_data(data);
145
+ $('#wio-restore-backup-progress-' + data.blog_id).css( 'width', response.percent + '%' );
146
+ } else {
147
+ $('#wio-restore-backup-progress-' + data.blog_id).css( 'width', '100%' ).removeClass('wio-restore-backup-progressbar');
148
+ if ( $('.wio-restore-backup-progressbar').length ) {
149
+ var ai_data = {
150
+ 'total' : '?',
151
+ 'action': 'wio_restore_backup',
152
+ '_wpnonce': $('#wio-iph-nonce').val(),
153
+ 'blog_id': $('.wio-restore-backup-progressbar:eq(0)').attr('data-id')
154
+ };
155
+ send_multisite_post_data(ai_data);
156
+ } else {
157
+ $('#wio-restore-backup-msg').show();
158
+ }
159
+ }
160
+ });
161
+ }
162
+ });
admin/assets/js/settings-premium.js CHANGED
@@ -1,2 +1,2 @@
1
- jQuery('button[data-value="googlepage"]').attr('disabled', 'disabled');
2
- jQuery('button[data-value="background"]').attr('disabled', 'disabled');
1
+ jQuery('button[data-value="googlepage"]').attr('disabled', 'disabled');
2
+ jQuery('button[data-value="background"]').attr('disabled', 'disabled');
admin/assets/js/single-optimization.js CHANGED
@@ -1,64 +1,101 @@
1
- jQuery(function($) {
2
- var ajaxUrl = ajaxurl;
3
-
4
- $(document).on('click', '.wio-reoptimize', function() {
5
- var ai_data = {
6
- 'action' : $(this).attr('data-action'),
7
- 'id' : $(this).attr('data-id'),
8
- 'level' : $(this).attr('data-level')
9
- };
10
- var td = $(this).closest('td');
11
- var msg = $(this).attr( 'data-waiting-label' );
12
- td.html('<p>'+msg+'</p>');
13
- wio_reoptimize( ai_data, td );
14
- return false;
15
- });
16
-
17
- function wio_reoptimize( ai_data, td ) {
18
- $.post(ajaxUrl, ai_data, function(response) {
19
- if ( response === 'processing' ) {
20
- wio_reoptimize( ai_data, td );
21
- return false;
22
- }
23
- td.html(response);
24
- var btn = $('.wio-reoptimize').first();
25
-
26
- if ( btn.closest('.media-frame-content').length ) {
27
- if ( btn.closest('table').find('.wio-datas-list').length ) {
28
- var diminsionName = $('.dimensions').find('strong').clone();
29
- var fileSizeName = $('.file-size').find('strong').clone();
30
- var diminsionSize = btn.closest('table').find('.wio-datas-list').data('dimensions');
31
- var fileSize = btn.closest('table').find('.wio-datas-list').data('size');
32
- $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
33
- $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
34
- }
35
- }
36
- });
37
- }
38
-
39
- $(document).on('click', '.button-wio-restore', function() {
40
- var ai_data = {
41
- 'action' : $(this).attr('data-action'),
42
- 'id' : $(this).attr('data-id')
43
- };
44
- var td = $(this).closest('td');
45
- var msg = $(this).attr( 'data-waiting-label' );
46
- td.html('<p>'+msg+'</p>');
47
- $.post(ajaxUrl, ai_data, function(response) {
48
- td.html(response);
49
- var btn = $('.wio-reoptimize');
50
- if ( btn.closest('.media-frame-content').length ) {
51
- if ( btn.length ) {
52
- btn = btn.first();
53
- var diminsionName = $('.dimensions').find('strong').clone();
54
- var fileSizeName = $('.file-size').find('strong').clone();
55
- var diminsionSize = btn.data('dimensions');
56
- var fileSize = btn.data('size');
57
- $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
58
- $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
59
- }
60
- }
61
- });
62
- return false;
63
- });
64
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ var ajaxUrl = ajaxurl;
3
+
4
+ $(document).on('click', '.wio-reoptimize', function() {
5
+ var ai_data = {
6
+ 'action' : $(this).attr('data-action'),
7
+ 'id' : $(this).attr('data-id'),
8
+ 'level' : $(this).attr('data-level'),
9
+ '_wpnonce' : $(this).attr('data-nonce')
10
+ };
11
+ var td = $(this).closest('td');
12
+ var msg = $(this).attr( 'data-waiting-label' );
13
+ td.html('<p>'+msg+'</p>');
14
+ wio_reoptimize( ai_data, td );
15
+ return false;
16
+ });
17
+
18
+ $(document).on('click', '.wio-convert', function() {
19
+ var ai_data = {
20
+ 'action' : $(this).attr('data-action'),
21
+ 'id' : $(this).attr('data-id'),
22
+ '_wpnonce' : $(this).attr('data-nonce')
23
+ };
24
+ var td = $(this).closest('td');
25
+ var msg = $(this).attr( 'data-waiting-label' );
26
+ td.html('<p>'+msg+'</p>');
27
+ wio_convert( ai_data, td );
28
+ return false;
29
+ });
30
+
31
+ function wio_reoptimize( ai_data, td ) {
32
+ $.post(ajaxUrl, ai_data, function(response) {
33
+ if ( response === 'processing' ) {
34
+ wio_reoptimize( ai_data, td );
35
+ return false;
36
+ }
37
+ td.html(response);
38
+ var btn = $('.wio-reoptimize').first();
39
+
40
+ if ( btn.closest('.media-frame-content').length ) {
41
+ if ( btn.closest('table').find('.wio-datas-list').length ) {
42
+ var diminsionName = $('.dimensions').find('strong').clone();
43
+ var fileSizeName = $('.file-size').find('strong').clone();
44
+ var diminsionSize = btn.closest('table').find('.wio-datas-list').data('dimensions');
45
+ var fileSize = btn.closest('table').find('.wio-datas-list').data('size');
46
+ $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
47
+ $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
48
+ }
49
+ }
50
+ });
51
+ }
52
+
53
+ function wio_convert( ai_data, td ) {
54
+ $.post(ajaxUrl, ai_data, function(response) {
55
+ if ( response === 'processing' ) {
56
+ wio_convert( ai_data, td );
57
+ return false;
58
+ }
59
+ td.html(response);
60
+ var btn = $('.wio-convert').first();
61
+
62
+ if ( btn.closest('.media-frame-content').length ) {
63
+ if ( btn.closest('table').find('.wio-datas-list').length ) {
64
+ var diminsionName = $('.dimensions').find('strong').clone();
65
+ var fileSizeName = $('.file-size').find('strong').clone();
66
+ var diminsionSize = btn.closest('table').find('.wio-datas-list').data('dimensions');
67
+ var fileSize = btn.closest('table').find('.wio-datas-list').data('size');
68
+ $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
69
+ $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
70
+ }
71
+ }
72
+ });
73
+ }
74
+
75
+ $(document).on('click', '.button-wio-restore', function() {
76
+ var ai_data = {
77
+ 'action' : $(this).attr('data-action'),
78
+ 'id' : $(this).attr('data-id'),
79
+ '_wpnonce' : $(this).attr('data-nonce')
80
+ };
81
+ var td = $(this).closest('td');
82
+ var msg = $(this).attr( 'data-waiting-label' );
83
+ td.html('<p>'+msg+'</p>');
84
+ $.post(ajaxUrl, ai_data, function(response) {
85
+ td.html(response);
86
+ var btn = $('.wio-reoptimize');
87
+ if ( btn.closest('.media-frame-content').length ) {
88
+ if ( btn.length ) {
89
+ btn = btn.first();
90
+ var diminsionName = $('.dimensions').find('strong').clone();
91
+ var fileSizeName = $('.file-size').find('strong').clone();
92
+ var diminsionSize = btn.data('dimensions');
93
+ var fileSize = btn.data('size');
94
+ $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
95
+ $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
96
+ }
97
+ }
98
+ });
99
+ return false;
100
+ });
101
+ });
admin/assets/js/statistic.js CHANGED
@@ -1,38 +1,76 @@
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
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function ($) {
2
+
3
+ var chart_html_id = 'wio-main-chart';
4
+ var webp_chart_html_id = 'wio-webp-chart';
5
+
6
+ var ctx = document.getElementById(chart_html_id);
7
+ var ctx_webp = document.getElementById(webp_chart_html_id);
8
+
9
+ window.wio_chart = new window.robin.Chart(ctx, {
10
+ type: 'doughnut',
11
+ data: {
12
+ datasets: [
13
+ {
14
+ data: [
15
+ $('#' + chart_html_id).attr('data-unoptimized'),
16
+ $('#' + chart_html_id).attr('data-optimized'),
17
+ $('#' + chart_html_id).attr('data-errors'),
18
+ ],
19
+ backgroundColor: [
20
+ '#d6d6d6',
21
+ '#8bc34a',
22
+ '#f1b1b6',
23
+ ],
24
+ borderWidth: 0,
25
+ label: 'Dataset 1'
26
+ }
27
+ ]
28
+ },
29
+ options: {
30
+ legend: {
31
+ display: false
32
+ },
33
+ events: [],
34
+ animation: {
35
+ easing: 'easeOutBounce'
36
+ },
37
+ responsive: false,
38
+ cutoutPercentage: 80
39
+ }
40
+ });
41
+
42
+ if (ctx_webp) {
43
+ window.wio_chart_webp = new window.robin.Chart(ctx_webp, {
44
+ type: 'doughnut',
45
+ data: {
46
+ datasets: [
47
+ {
48
+ data: [
49
+ $('#' + webp_chart_html_id).attr('data-unoptimized'),
50
+ $('#' + webp_chart_html_id).attr('data-optimized'),
51
+ $('#' + webp_chart_html_id).attr('data-errors'),
52
+ ],
53
+ backgroundColor: [
54
+ '#d6d6d6',
55
+ '#8bc34a',
56
+ '#f1b1b6',
57
+ ],
58
+ borderWidth: 0,
59
+ label: 'Dataset 1'
60
+ }
61
+ ]
62
+ },
63
+ options: {
64
+ legend: {
65
+ display: false
66
+ },
67
+ events: [],
68
+ animation: {
69
+ easing: 'easeOutBounce'
70
+ },
71
+ responsive: false,
72
+ cutoutPercentage: 80
73
+ }
74
+ });
75
+ }
76
+ });
admin/assets/js/sweetalert2.js CHANGED
@@ -1,1641 +1,1641 @@
1
- /*!
2
- * sweetalert2 v6.6.6
3
- * Released under the MIT License.
4
- */
5
- (function (global, factory) {
6
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
7
- typeof define === 'function' && define.amd ? define(factory) :
8
- (global.Sweetalert2 = factory());
9
- }(this, (function () { 'use strict';
10
-
11
- var defaultParams = {
12
- title: '',
13
- titleText: '',
14
- text: '',
15
- html: '',
16
- type: null,
17
- customClass: '',
18
- target: 'body',
19
- animation: true,
20
- allowOutsideClick: true,
21
- allowEscapeKey: true,
22
- allowEnterKey: true,
23
- showConfirmButton: true,
24
- showCancelButton: false,
25
- preConfirm: null,
26
- confirmButtonText: 'OK',
27
- confirmButtonColor: '#3085d6',
28
- confirmButtonClass: null,
29
- cancelButtonText: 'Cancel',
30
- cancelButtonColor: '#aaa',
31
- cancelButtonClass: null,
32
- buttonsStyling: true,
33
- reverseButtons: false,
34
- focusCancel: false,
35
- showCloseButton: false,
36
- showLoaderOnConfirm: false,
37
- imageUrl: null,
38
- imageWidth: null,
39
- imageHeight: null,
40
- imageClass: null,
41
- timer: null,
42
- width: 500,
43
- padding: 20,
44
- background: '#fff',
45
- input: null,
46
- inputPlaceholder: '',
47
- inputValue: '',
48
- inputOptions: {},
49
- inputAutoTrim: true,
50
- inputClass: null,
51
- inputAttributes: {},
52
- inputValidator: null,
53
- progressSteps: [],
54
- currentProgressStep: null,
55
- progressStepsDistance: '40px',
56
- onOpen: null,
57
- onClose: null,
58
- useRejections: true
59
- };
60
-
61
- var swalPrefix = 'swal2-';
62
-
63
- var prefix = function prefix(items) {
64
- var result = {};
65
- for (var i in items) {
66
- result[items[i]] = swalPrefix + items[i];
67
- }
68
- return result;
69
- };
70
-
71
- var swalClasses = prefix(['container', 'shown', 'iosfix', 'modal', 'overlay', 'fade', 'show', 'hide', 'noanimation', 'close', 'title', 'content', 'buttonswrapper', 'confirm', 'cancel', 'icon', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea', 'inputerror', 'validationerror', 'progresssteps', 'activeprogressstep', 'progresscircle', 'progressline', 'loading', 'styled']);
72
-
73
- var iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
74
-
75
- /*
76
- * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color)
77
- */
78
- var colorLuminance = function colorLuminance(hex, lum) {
79
- // Validate hex string
80
- hex = String(hex).replace(/[^0-9a-f]/gi, '');
81
- if (hex.length < 6) {
82
- hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
83
- }
84
- lum = lum || 0;
85
-
86
- // Convert to decimal and change luminosity
87
- var rgb = '#';
88
- for (var i = 0; i < 3; i++) {
89
- var c = parseInt(hex.substr(i * 2, 2), 16);
90
- c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
91
- rgb += ('00' + c).substr(c.length);
92
- }
93
-
94
- return rgb;
95
- };
96
-
97
- var uniqueArray = function uniqueArray(arr) {
98
- var result = [];
99
- for (var i in arr) {
100
- if (result.indexOf(arr[i]) === -1) {
101
- result.push(arr[i]);
102
- }
103
- }
104
- return result;
105
- };
106
-
107
- /* global MouseEvent */
108
-
109
- // Remember state in cases where opening and handling a modal will fiddle with it.
110
- var states = {
111
- previousWindowKeyDown: null,
112
- previousActiveElement: null,
113
- previousBodyPadding: null
114
-
115
- /*
116
- * Add modal + overlay to DOM
117
- */
118
- };var init = function init(params) {
119
- if (typeof document === 'undefined') {
120
- console.error('SweetAlert2 requires document to initialize');
121
- return;
122
- }
123
-
124
- var container = document.createElement('div');
125
- container.className = swalClasses.container;
126
- container.innerHTML = sweetHTML;
127
-
128
- var targetElement = document.querySelector(params.target);
129
- if (!targetElement) {
130
- console.warn('SweetAlert2: Can\'t find the target "' + params.target + '"');
131
- targetElement = document.body;
132
- }
133
- targetElement.appendChild(container);
134
-
135
- var modal = getModal();
136
- var input = getChildByClass(modal, swalClasses.input);
137
- var file = getChildByClass(modal, swalClasses.file);
138
- var range = modal.querySelector('.' + swalClasses.range + ' input');
139
- var rangeOutput = modal.querySelector('.' + swalClasses.range + ' output');
140
- var select = getChildByClass(modal, swalClasses.select);
141
- var checkbox = modal.querySelector('.' + swalClasses.checkbox + ' input');
142
- var textarea = getChildByClass(modal, swalClasses.textarea);
143
-
144
- input.oninput = function () {
145
- sweetAlert.resetValidationError();
146
- };
147
-
148
- input.onkeydown = function (event) {
149
- setTimeout(function () {
150
- if (event.keyCode === 13 && params.allowEnterKey) {
151
- event.stopPropagation();
152
- sweetAlert.clickConfirm();
153
- }
154
- }, 0);
155
- };
156
-
157
- file.onchange = function () {
158
- sweetAlert.resetValidationError();
159
- };
160
-
161
- range.oninput = function () {
162
- sweetAlert.resetValidationError();
163
- rangeOutput.value = range.value;
164
- };
165
-
166
- range.onchange = function () {
167
- sweetAlert.resetValidationError();
168
- range.previousSibling.value = range.value;
169
- };
170
-
171
- select.onchange = function () {
172
- sweetAlert.resetValidationError();
173
- };
174
-
175
- checkbox.onchange = function () {
176
- sweetAlert.resetValidationError();
177
- };
178
-
179
- textarea.oninput = function () {
180
- sweetAlert.resetValidationError();
181
- };
182
-
183
- return modal;
184
- };
185
-
186
- /*
187
- * Manipulate DOM
188
- */
189
-
190
- var sweetHTML = ('\n <div role="dialog" aria-labelledby="' + swalClasses.title + '" aria-describedby="' + swalClasses.content + '" class="' + swalClasses.modal + '" tabindex="-1">\n <ul class="' + swalClasses.progresssteps + '"></ul>\n <div class="' + swalClasses.icon + ' ' + iconTypes.error + '">\n <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n </div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.question + '">?</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.warning + '">!</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.info + '">i</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.success + '">\n <div class="swal2-success-circular-line-left"></div>\n <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n <div class="swal2-success-circular-line-right"></div>\n </div>\n <img class="' + swalClasses.image + '" />\n <h2 class="' + swalClasses.title + '" id="' + swalClasses.title + '"></h2>\n <div id="' + swalClasses.content + '" class="' + swalClasses.content + '"></div>\n <input class="' + swalClasses.input + '" />\n <input type="file" class="' + swalClasses.file + '" />\n <div class="' + swalClasses.range + '">\n <output></output>\n <input type="range" />\n </div>\n <select class="' + swalClasses.select + '"></select>\n <div class="' + swalClasses.radio + '"></div>\n <label for="' + swalClasses.checkbox + '" class="' + swalClasses.checkbox + '">\n <input type="checkbox" />\n </label>\n <textarea class="' + swalClasses.textarea + '"></textarea>\n <div class="' + swalClasses.validationerror + '"></div>\n <div class="' + swalClasses.buttonswrapper + '">\n <button type="button" class="' + swalClasses.confirm + '">OK</button>\n <button type="button" class="' + swalClasses.cancel + '">Cancel</button>\n </div>\n <button type="button" class="' + swalClasses.close + '" aria-label="Close this dialog">\xD7</button>\n </div>\n').replace(/(^|\n)\s*/g, '');
191
-
192
- var getContainer = function getContainer() {
193
- return document.body.querySelector('.' + swalClasses.container);
194
- };
195
-
196
- var getModal = function getModal() {
197
- return getContainer() ? getContainer().querySelector('.' + swalClasses.modal) : null;
198
- };
199
-
200
- var getIcons = function getIcons() {
201
- var modal = getModal();
202
- return modal.querySelectorAll('.' + swalClasses.icon);
203
- };
204
-
205
- var elementByClass = function elementByClass(className) {
206
- return getContainer() ? getContainer().querySelector('.' + className) : null;
207
- };
208
-
209
- var getTitle = function getTitle() {
210
- return elementByClass(swalClasses.title);
211
- };
212
-
213
- var getContent = function getContent() {
214
- return elementByClass(swalClasses.content);
215
- };
216
-
217
- var getImage = function getImage() {
218
- return elementByClass(swalClasses.image);
219
- };
220
-
221
- var getButtonsWrapper = function getButtonsWrapper() {
222
- return elementByClass(swalClasses.buttonswrapper);
223
- };
224
-
225
- var getProgressSteps = function getProgressSteps() {
226
- return elementByClass(swalClasses.progresssteps);
227
- };
228
-
229
- var getValidationError = function getValidationError() {
230
- return elementByClass(swalClasses.validationerror);
231
- };
232
-
233
- var getConfirmButton = function getConfirmButton() {
234
- return elementByClass(swalClasses.confirm);
235
- };
236
-
237
- var getCancelButton = function getCancelButton() {
238
- return elementByClass(swalClasses.cancel);
239
- };
240
-
241
- var getCloseButton = function getCloseButton() {
242
- return elementByClass(swalClasses.close);
243
- };
244
-
245
- var getFocusableElements = function getFocusableElements(focusCancel) {
246
- var buttons = [getConfirmButton(), getCancelButton()];
247
- if (focusCancel) {
248
- buttons.reverse();
249
- }
250
- var focusableElements = buttons.concat(Array.prototype.slice.call(getModal().querySelectorAll('button, input:not([type=hidden]), textarea, select, a, *[tabindex]:not([tabindex="-1"])')));
251
- return uniqueArray(focusableElements);
252
- };
253
-
254
- var hasClass = function hasClass(elem, className) {
255
- if (elem.classList) {
256
- return elem.classList.contains(className);
257
- }
258
- return false;
259
- };
260
-
261
- var focusInput = function focusInput(input) {
262
- input.focus();
263
-
264
- // place cursor at end of text in text input
265
- if (input.type !== 'file') {
266
- // http://stackoverflow.com/a/2345915/1331425
267
- var val = input.value;
268
- input.value = '';
269
- input.value = val;
270
- }
271
- };
272
-
273
- var addClass = function addClass(elem, className) {
274
- if (!elem || !className) {
275
- return;
276
- }
277
- var classes = className.split(/\s+/).filter(Boolean);
278
- classes.forEach(function (className) {
279
- elem.classList.add(className);
280
- });
281
- };
282
-
283
- var removeClass = function removeClass(elem, className) {
284
- if (!elem || !className) {
285
- return;
286
- }
287
- var classes = className.split(/\s+/).filter(Boolean);
288
- classes.forEach(function (className) {
289
- elem.classList.remove(className);
290
- });
291
- };
292
-
293
- var getChildByClass = function getChildByClass(elem, className) {
294
- for (var i = 0; i < elem.childNodes.length; i++) {
295
- if (hasClass(elem.childNodes[i], className)) {
296
- return elem.childNodes[i];
297
- }
298
- }
299
- };
300
-
301
- var show = function show(elem, display) {
302
- if (!display) {
303
- display = 'block';
304
- }
305
- elem.style.opacity = '';
306
- elem.style.display = display;
307
- };
308
-
309
- var hide = function hide(elem) {
310
- elem.style.opacity = '';
311
- elem.style.display = 'none';
312
- };
313
-
314
- var empty = function empty(elem) {
315
- while (elem.firstChild) {
316
- elem.removeChild(elem.firstChild);
317
- }
318
- };
319
-
320
- // borrowed from jqeury $(elem).is(':visible') implementation
321
- var isVisible = function isVisible(elem) {
322
- return elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length;
323
- };
324
-
325
- var removeStyleProperty = function removeStyleProperty(elem, property) {
326
- if (elem.style.removeProperty) {
327
- elem.style.removeProperty(property);
328
- } else {
329
- elem.style.removeAttribute(property);
330
- }
331
- };
332
-
333
- var fireClick = function fireClick(node) {
334
- if (!isVisible(node)) {
335
- return false;
336
- }
337
-
338
- // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
339
- // Then fixed for today's Chrome browser.
340
- if (typeof MouseEvent === 'function') {
341
- // Up-to-date approach
342
- var mevt = new MouseEvent('click', {
343
- view: window,
344
- bubbles: false,
345
- cancelable: true
346
- });
347
- node.dispatchEvent(mevt);
348
- } else if (document.createEvent) {
349
- // Fallback
350
- var evt = document.createEvent('MouseEvents');
351
- evt.initEvent('click', false, false);
352
- node.dispatchEvent(evt);
353
- } else if (document.createEventObject) {
354
- node.fireEvent('onclick');
355
- } else if (typeof node.onclick === 'function') {
356
- node.onclick();
357
- }
358
- };
359
-
360
- var animationEndEvent = function () {
361
- var testEl = document.createElement('div');
362
- var transEndEventNames = {
363
- 'WebkitAnimation': 'webkitAnimationEnd',
364
- 'OAnimation': 'oAnimationEnd oanimationend',
365
- 'msAnimation': 'MSAnimationEnd',
366
- 'animation': 'animationend'
367
- };
368
- for (var i in transEndEventNames) {
369
- if (transEndEventNames.hasOwnProperty(i) && testEl.style[i] !== undefined) {
370
- return transEndEventNames[i];
371
- }
372
- }
373
-
374
- return false;
375
- }();
376
-
377
- // Reset previous window keydown handler and focued element
378
- var resetPrevState = function resetPrevState() {
379
- window.onkeydown = states.previousWindowKeyDown;
380
- if (states.previousActiveElement && states.previousActiveElement.focus) {
381
- var x = window.scrollX;
382
- var y = window.scrollY;
383
- states.previousActiveElement.focus();
384
- if (x && y) {
385
- // IE has no scrollX/scrollY support
386
- window.scrollTo(x, y);
387
- }
388
- }
389
- };
390
-
391
- // Measure width of scrollbar
392
- // https://github.com/twbs/bootstrap/blob/master/js/modal.js#L279-L286
393
- var measureScrollbar = function measureScrollbar() {
394
- var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
395
- if (supportsTouch) {
396
- return 0;
397
- }
398
- var scrollDiv = document.createElement('div');
399
- scrollDiv.style.width = '50px';
400
- scrollDiv.style.height = '50px';
401
- scrollDiv.style.overflow = 'scroll';
402
- document.body.appendChild(scrollDiv);
403
- var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
404
- document.body.removeChild(scrollDiv);
405
- return scrollbarWidth;
406
- };
407
-
408
- // JavaScript Debounce Function
409
- // Simplivied version of https://davidwalsh.name/javascript-debounce-function
410
- var debounce = function debounce(func, wait) {
411
- var timeout = void 0;
412
- return function () {
413
- var later = function later() {
414
- timeout = null;
415
- func();
416
- };
417
- clearTimeout(timeout);
418
- timeout = setTimeout(later, wait);
419
- };
420
- };
421
-
422
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
423
- return typeof obj;
424
- } : function (obj) {
425
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
426
- };
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
- var _extends = Object.assign || function (target) {
449
- for (var i = 1; i < arguments.length; i++) {
450
- var source = arguments[i];
451
-
452
- for (var key in source) {
453
- if (Object.prototype.hasOwnProperty.call(source, key)) {
454
- target[key] = source[key];
455
- }
456
- }
457
- }
458
-
459
- return target;
460
- };
461
-
462
- var modalParams = _extends({}, defaultParams);
463
- var queue = [];
464
- var swal2Observer = void 0;
465
-
466
- /*
467
- * Set type, text and actions on modal
468
- */
469
- var setParameters = function setParameters(params) {
470
- var modal = getModal() || init(params);
471
-
472
- for (var param in params) {
473
- if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
474
- console.warn('SweetAlert2: Unknown parameter "' + param + '"');
475
- }
476
- }
477
-
478
- // Set modal width
479
- modal.style.width = typeof params.width === 'number' ? params.width + 'px' : params.width;
480
-
481
- modal.style.padding = params.padding + 'px';
482
- modal.style.background = params.background;
483
- var successIconParts = modal.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');
484
- for (var i = 0; i < successIconParts.length; i++) {
485
- successIconParts[i].style.background = params.background;
486
- }
487
-
488
- var title = getTitle();
489
- var content = getContent();
490
- var buttonsWrapper = getButtonsWrapper();
491
- var confirmButton = getConfirmButton();
492
- var cancelButton = getCancelButton();
493
- var closeButton = getCloseButton();
494
-
495
- // Title
496
- if (params.titleText) {
497
- title.innerText = params.titleText;
498
- } else {
499
- title.innerHTML = params.title.split('\n').join('<br />');
500
- }
501
-
502
- // Content
503
- if (params.text || params.html) {
504
- if (_typeof(params.html) === 'object') {
505
- content.innerHTML = '';
506
- if (0 in params.html) {
507
- for (var _i = 0; _i in params.html; _i++) {
508
- content.appendChild(params.html[_i].cloneNode(true));
509
- }
510
- } else {
511
- content.appendChild(params.html.cloneNode(true));
512
- }
513
- } else if (params.html) {
514
- content.innerHTML = params.html;
515
- } else if (params.text) {
516
- content.textContent = params.text;
517
- }
518
- show(content);
519
- } else {
520
- hide(content);
521
- }
522
-
523
- // Close button
524
- if (params.showCloseButton) {
525
- show(closeButton);
526
- } else {
527
- hide(closeButton);
528
- }
529
-
530
- // Custom Class
531
- modal.className = swalClasses.modal;
532
- if (params.customClass) {
533
- addClass(modal, params.customClass);
534
- }
535
-
536
- // Progress steps
537
- var progressStepsContainer = getProgressSteps();
538
- var currentProgressStep = parseInt(params.currentProgressStep === null ? sweetAlert.getQueueStep() : params.currentProgressStep, 10);
539
- if (params.progressSteps.length) {
540
- show(progressStepsContainer);
541
- empty(progressStepsContainer);
542
- if (currentProgressStep >= params.progressSteps.length) {
543
- console.warn('SweetAlert2: Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)');
544
- }
545
- params.progressSteps.forEach(function (step, index) {
546
- var circle = document.createElement('li');
547
- addClass(circle, swalClasses.progresscircle);
548
- circle.innerHTML = step;
549
- if (index === currentProgressStep) {
550
- addClass(circle, swalClasses.activeprogressstep);
551
- }
552
- progressStepsContainer.appendChild(circle);
553
- if (index !== params.progressSteps.length - 1) {
554
- var line = document.createElement('li');
555
- addClass(line, swalClasses.progressline);
556
- line.style.width = params.progressStepsDistance;
557
- progressStepsContainer.appendChild(line);
558
- }
559
- });
560
- } else {
561
- hide(progressStepsContainer);
562
- }
563
-
564
- // Icon
565
- var icons = getIcons();
566
- for (var _i2 = 0; _i2 < icons.length; _i2++) {
567
- hide(icons[_i2]);
568
- }
569
- if (params.type) {
570
- var validType = false;
571
- for (var iconType in iconTypes) {
572
- if (params.type === iconType) {
573
- validType = true;
574
- break;
575
- }
576
- }
577
- if (!validType) {
578
- console.error('SweetAlert2: Unknown alert type: ' + params.type);
579
- return false;
580
- }
581
- var icon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes[params.type]);
582
- show(icon);
583
-
584
- // Animate icon
585
- if (params.animation) {
586
- switch (params.type) {
587
- case 'success':
588
- addClass(icon, 'swal2-animate-success-icon');
589
- addClass(icon.querySelector('.swal2-success-line-tip'), 'swal2-animate-success-line-tip');
590
- addClass(icon.querySelector('.swal2-success-line-long'), 'swal2-animate-success-line-long');
591
- break;
592
- case 'error':
593
- addClass(icon, 'swal2-animate-error-icon');
594
- addClass(icon.querySelector('.swal2-x-mark'), 'swal2-animate-x-mark');
595
- break;
596
- default:
597
- break;
598
- }
599
- }
600
- }
601
-
602
- // Custom image
603
- var image = getImage();
604
- if (params.imageUrl) {
605
- image.setAttribute('src', params.imageUrl);
606
- show(image);
607
-
608
- if (params.imageWidth) {
609
- image.setAttribute('width', params.imageWidth);
610
- } else {
611
- image.removeAttribute('width');
612
- }
613
-
614
- if (params.imageHeight) {
615
- image.setAttribute('height', params.imageHeight);
616
- } else {
617
- image.removeAttribute('height');
618
- }
619
-
620
- image.className = swalClasses.image;
621
- if (params.imageClass) {
622
- addClass(image, params.imageClass);
623
- }
624
- } else {
625
- hide(image);
626
- }
627
-
628
- // Cancel button
629
- if (params.showCancelButton) {
630
- cancelButton.style.display = 'inline-block';
631
- } else {
632
- hide(cancelButton);
633
- }
634
-
635
- // Confirm button
636
- if (params.showConfirmButton) {
637
- removeStyleProperty(confirmButton, 'display');
638
- } else {
639
- hide(confirmButton);
640
- }
641
-
642
- // Buttons wrapper
643
- if (!params.showConfirmButton && !params.showCancelButton) {
644
- hide(buttonsWrapper);
645
- } else {
646
- show(buttonsWrapper);
647
- }
648
-
649
- // Edit text on cancel and confirm buttons
650
- confirmButton.innerHTML = params.confirmButtonText;
651
- cancelButton.innerHTML = params.cancelButtonText;
652
-
653
- // Set buttons to selected background colors
654
- if (params.buttonsStyling) {
655
- confirmButton.style.backgroundColor = params.confirmButtonColor;
656
- cancelButton.style.backgroundColor = params.cancelButtonColor;
657
- }
658
-
659
- // Add buttons custom classes
660
- confirmButton.className = swalClasses.confirm;
661
- addClass(confirmButton, params.confirmButtonClass);
662
- cancelButton.className = swalClasses.cancel;
663
- addClass(cancelButton, params.cancelButtonClass);
664
-
665
- // Buttons styling
666
- if (params.buttonsStyling) {
667
- addClass(confirmButton, swalClasses.styled);
668
- addClass(cancelButton, swalClasses.styled);
669
- } else {
670
- removeClass(confirmButton, swalClasses.styled);
671
- removeClass(cancelButton, swalClasses.styled);
672
-
673
- confirmButton.style.backgroundColor = confirmButton.style.borderLeftColor = confirmButton.style.borderRightColor = '';
674
- cancelButton.style.backgroundColor = cancelButton.style.borderLeftColor = cancelButton.style.borderRightColor = '';
675
- }
676
-
677
- // CSS animation
678
- if (params.animation === true) {
679
- removeClass(modal, swalClasses.noanimation);
680
- } else {
681
- addClass(modal, swalClasses.noanimation);
682
- }
683
- };
684
-
685
- /*
686
- * Animations
687
- */
688
- var openModal = function openModal(animation, onComplete) {
689
- var container = getContainer();
690
- var modal = getModal();
691
-
692
- if (animation) {
693
- addClass(modal, swalClasses.show);
694
- addClass(container, swalClasses.fade);
695
- removeClass(modal, swalClasses.hide);
696
- } else {
697
- removeClass(modal, swalClasses.fade);
698
- }
699
- show(modal);
700
-
701
- // scrolling is 'hidden' until animation is done, after that 'auto'
702
- container.style.overflowY = 'hidden';
703
- if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
704
- modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
705
- modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
706
- container.style.overflowY = 'auto';
707
- });
708
- } else {
709
- container.style.overflowY = 'auto';
710
- }
711
-
712
- addClass(document.documentElement, swalClasses.shown);
713
- addClass(document.body, swalClasses.shown);
714
- addClass(container, swalClasses.shown);
715
- fixScrollbar();
716
- iOSfix();
717
- states.previousActiveElement = document.activeElement;
718
- if (onComplete !== null && typeof onComplete === 'function') {
719
- setTimeout(function () {
720
- onComplete(modal);
721
- });
722
- }
723
- };
724
-
725
- var fixScrollbar = function fixScrollbar() {
726
- // for queues, do not do this more than once
727
- if (states.previousBodyPadding !== null) {
728
- return;
729
- }
730
- // if the body has overflow
731
- if (document.body.scrollHeight > window.innerHeight) {
732
- // add padding so the content doesn't shift after removal of scrollbar
733
- states.previousBodyPadding = document.body.style.paddingRight;
734
- document.body.style.paddingRight = measureScrollbar() + 'px';
735
- }
736
- };
737
-
738
- var undoScrollbar = function undoScrollbar() {
739
- if (states.previousBodyPadding !== null) {
740
- document.body.style.paddingRight = states.previousBodyPadding;
741
- states.previousBodyPadding = null;
742
- }
743
- };
744
-
745
- // Fix iOS scrolling http://stackoverflow.com/q/39626302/1331425
746
- var iOSfix = function iOSfix() {
747
- var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
748
- if (iOS && !hasClass(document.body, swalClasses.iosfix)) {
749
- var offset = document.body.scrollTop;
750
- document.body.style.top = offset * -1 + 'px';
751
- addClass(document.body, swalClasses.iosfix);
752
- }
753
- };
754
-
755
- var undoIOSfix = function undoIOSfix() {
756
- if (hasClass(document.body, swalClasses.iosfix)) {
757
- var offset = parseInt(document.body.style.top, 10);
758
- removeClass(document.body, swalClasses.iosfix);
759
- document.body.style.top = '';
760
- document.body.scrollTop = offset * -1;
761
- }
762
- };
763
-
764
- // SweetAlert entry point
765
- var sweetAlert = function sweetAlert() {
766
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
767
- args[_key] = arguments[_key];
768
- }
769
-
770
- if (args[0] === undefined) {
771
- console.error('SweetAlert2 expects at least 1 attribute!');
772
- return false;
773
- }
774
-
775
- var params = _extends({}, modalParams);
776
-
777
- switch (_typeof(args[0])) {
778
- case 'string':
779
- params.title = args[0];
780
- params.html = args[1];
781
- params.type = args[2];
782
-
783
- break;
784
-
785
- case 'object':
786
- _extends(params, args[0]);
787
- params.extraParams = args[0].extraParams;
788
-
789
- if (params.input === 'email' && params.inputValidator === null) {
790
- params.inputValidator = function (email) {
791
- return new Promise(function (resolve, reject) {
792
- var emailRegex = /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
793
- if (emailRegex.test(email)) {
794
- resolve();
795
- } else {
796
- reject('Invalid email address');
797
- }
798
- });
799
- };
800
- }
801
-
802
- if (params.input === 'url' && params.inputValidator === null) {
803
- params.inputValidator = function (url) {
804
- return new Promise(function (resolve, reject) {
805
- // taken from https://stackoverflow.com/a/3809435/1331425
806
- var urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/;
807
- if (urlRegex.test(url)) {
808
- resolve();
809
- } else {
810
- reject('Invalid URL');
811
- }
812
- });
813
- };
814
- }
815
- break;
816
-
817
- default:
818
- console.error('SweetAlert2: Unexpected type of argument! Expected "string" or "object", got ' + _typeof(args[0]));
819
- return false;
820
- }
821
-
822
- setParameters(params);
823
-
824
- var container = getContainer();
825
- var modal = getModal();
826
-
827
- return new Promise(function (resolve, reject) {
828
- // Close on timer
829
- if (params.timer) {
830
- modal.timeout = setTimeout(function () {
831
- sweetAlert.closeModal(params.onClose);
832
- if (params.useRejections) {
833
- reject('timer');
834
- } else {
835
- resolve({ dismiss: 'timer' });
836
- }
837
- }, params.timer);
838
- }
839
-
840
- // Get input element by specified type or, if type isn't specified, by params.input
841
- var getInput = function getInput(inputType) {
842
- inputType = inputType || params.input;
843
- if (!inputType) {
844
- return null;
845
- }
846
- switch (inputType) {
847
- case 'select':
848
- case 'textarea':
849
- case 'file':
850
- return getChildByClass(modal, swalClasses[inputType]);
851
- case 'checkbox':
852
- return modal.querySelector('.' + swalClasses.checkbox + ' input');
853
- case 'radio':
854
- return modal.querySelector('.' + swalClasses.radio + ' input:checked') || modal.querySelector('.' + swalClasses.radio + ' input:first-child');
855
- case 'range':
856
- return modal.querySelector('.' + swalClasses.range + ' input');
857
- default:
858
- return getChildByClass(modal, swalClasses.input);
859
- }
860
- };
861
-
862
- // Get the value of the modal input
863
- var getInputValue = function getInputValue() {
864
- var input = getInput();
865
- if (!input) {
866
- return null;
867
- }
868
- switch (params.input) {
869
- case 'checkbox':
870
- return input.checked ? 1 : 0;
871
- case 'radio':
872
- return input.checked ? input.value : null;
873
- case 'file':
874
- return input.files.length ? input.files[0] : null;
875
- default:
876
- return params.inputAutoTrim ? input.value.trim() : input.value;
877
- }
878
- };
879
-
880
- // input autofocus
881
- if (params.input) {
882
- setTimeout(function () {
883
- var input = getInput();
884
- if (input) {
885
- focusInput(input);
886
- }
887
- }, 0);
888
- }
889
-
890
- var confirm = function confirm(value) {
891
- if (params.showLoaderOnConfirm) {
892
- sweetAlert.showLoading();
893
- }
894
-
895
- if (params.preConfirm) {
896
- params.preConfirm(value, params.extraParams).then(function (preConfirmValue) {
897
- sweetAlert.closeModal(params.onClose);
898
- resolve(preConfirmValue || value);
899
- }, function (error) {
900
- sweetAlert.hideLoading();
901
- if (error) {
902
- sweetAlert.showValidationError(error);
903
- }
904
- });
905
- } else {
906
- sweetAlert.closeModal(params.onClose);
907
- if (params.useRejections) {
908
- resolve(value);
909
- } else {
910
- resolve({ value: value });
911
- }
912
- }
913
- };
914
-
915
- // Mouse interactions
916
- var onButtonEvent = function onButtonEvent(event) {
917
- var e = event || window.event;
918
- var target = e.target || e.srcElement;
919
- var confirmButton = getConfirmButton();
920
- var cancelButton = getCancelButton();
921
- var targetedConfirm = confirmButton && (confirmButton === target || confirmButton.contains(target));
922
- var targetedCancel = cancelButton && (cancelButton === target || cancelButton.contains(target));
923
-
924
- switch (e.type) {
925
- case 'mouseover':
926
- case 'mouseup':
927
- if (params.buttonsStyling) {
928
- if (targetedConfirm) {
929
- confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.1);
930
- } else if (targetedCancel) {
931
- cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.1);
932
- }
933
- }
934
- break;
935
- case 'mouseout':
936
- if (params.buttonsStyling) {
937
- if (targetedConfirm) {
938
- confirmButton.style.backgroundColor = params.confirmButtonColor;
939
- } else if (targetedCancel) {
940
- cancelButton.style.backgroundColor = params.cancelButtonColor;
941
- }
942
- }
943
- break;
944
- case 'mousedown':
945
- if (params.buttonsStyling) {
946
- if (targetedConfirm) {
947
- confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.2);
948
- } else if (targetedCancel) {
949
- cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.2);
950
- }
951
- }
952
- break;
953
- case 'click':
954
- // Clicked 'confirm'
955
- if (targetedConfirm && sweetAlert.isVisible()) {
956
- sweetAlert.disableButtons();
957
- if (params.input) {
958
- var inputValue = getInputValue();
959
-
960
- if (params.inputValidator) {
961
- sweetAlert.disableInput();
962
- params.inputValidator(inputValue, params.extraParams).then(function () {
963
- sweetAlert.enableButtons();
964
- sweetAlert.enableInput();
965
- confirm(inputValue);
966
- }, function (error) {
967
- sweetAlert.enableButtons();
968
- sweetAlert.enableInput();
969
- if (error) {
970
- sweetAlert.showValidationError(error);
971
- }
972
- });
973
- } else {
974
- confirm(inputValue);
975
- }
976
- } else {
977
- confirm(true);
978
- }
979
-
980
- // Clicked 'cancel'
981
- } else if (targetedCancel && sweetAlert.isVisible()) {
982
- sweetAlert.disableButtons();
983
- sweetAlert.closeModal(params.onClose);
984
- if (params.useRejections) {
985
- reject('cancel');
986
- } else {
987
- resolve({ dismiss: 'cancel' });
988
- }
989
- }
990
- break;
991
- default:
992
- }
993
- };
994
-
995
- var buttons = modal.querySelectorAll('button');
996
- for (var i = 0; i < buttons.length; i++) {
997
- buttons[i].onclick = onButtonEvent;
998
- buttons[i].onmouseover = onButtonEvent;
999
- buttons[i].onmouseout = onButtonEvent;
1000
- buttons[i].onmousedown = onButtonEvent;
1001
- }
1002
-
1003
- // Closing modal by close button
1004
- getCloseButton().onclick = function () {
1005
- sweetAlert.closeModal(params.onClose);
1006
- if (params.useRejections) {
1007
- reject('close');
1008
- } else {
1009
- resolve({ dismiss: 'close' });
1010
- }
1011
- };
1012
-
1013
- // Closing modal by overlay click
1014
- container.onclick = function (e) {
1015
- if (e.target !== container) {
1016
- return;
1017
- }
1018
- if (params.allowOutsideClick) {
1019
- sweetAlert.closeModal(params.onClose);
1020
- if (params.useRejections) {
1021
- reject('overlay');
1022
- } else {
1023
- resolve({ dismiss: 'overlay' });
1024
- }
1025
- }
1026
- };
1027
-
1028
- var buttonsWrapper = getButtonsWrapper();
1029
- var confirmButton = getConfirmButton();
1030
- var cancelButton = getCancelButton();
1031
-
1032
- // Reverse buttons (Confirm on the right side)
1033
- if (params.reverseButtons) {
1034
- confirmButton.parentNode.insertBefore(cancelButton, confirmButton);
1035
- } else {
1036
- confirmButton.parentNode.insertBefore(confirmButton, cancelButton);
1037
- }
1038
-
1039
- // Focus handling
1040
- var setFocus = function setFocus(index, increment) {
1041
- var focusableElements = getFocusableElements(params.focusCancel);
1042
- // search for visible elements and select the next possible match
1043
- for (var _i3 = 0; _i3 < focusableElements.length; _i3++) {
1044
- index = index + increment;
1045
-
1046
- // rollover to first item
1047
- if (index === focusableElements.length) {
1048
- index = 0;
1049
-
1050
- // go to last item
1051
- } else if (index === -1) {
1052
- index = focusableElements.length - 1;
1053
- }
1054
-
1055
- // determine if element is visible
1056
- var el = focusableElements[index];
1057
- if (isVisible(el)) {
1058
- return el.focus();
1059
- }
1060
- }
1061
- };
1062
-
1063
- var handleKeyDown = function handleKeyDown(event) {
1064
- var e = event || window.event;
1065
- var keyCode = e.keyCode || e.which;
1066
-
1067
- if ([9, 13, 32, 27, 37, 38, 39, 40].indexOf(keyCode) === -1) {
1068
- // Don't do work on keys we don't care about.
1069
- return;
1070
- }
1071
-
1072
- var targetElement = e.target || e.srcElement;
1073
-
1074
- var focusableElements = getFocusableElements(params.focusCancel);
1075
- var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
1076
- for (var _i4 = 0; _i4 < focusableElements.length; _i4++) {
1077
- if (targetElement === focusableElements[_i4]) {
1078
- btnIndex = _i4;
1079
- break;
1080
- }
1081
- }
1082
-
1083
- // TAB
1084
- if (keyCode === 9) {
1085
- if (!e.shiftKey) {
1086
- // Cycle to the next button
1087
- setFocus(btnIndex, 1);
1088
- } else {
1089
- // Cycle to the prev button
1090
- setFocus(btnIndex, -1);
1091
- }
1092
- e.stopPropagation();
1093
- e.preventDefault();
1094
-
1095
- // ARROWS - switch focus between buttons
1096
- } else if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
1097
- // focus Cancel button if Confirm button is currently focused
1098
- if (document.activeElement === confirmButton && isVisible(cancelButton)) {
1099
- cancelButton.focus();
1100
- // and vice versa
1101
- } else if (document.activeElement === cancelButton && isVisible(confirmButton)) {
1102
- confirmButton.focus();
1103
- }
1104
-
1105
- // ENTER/SPACE
1106
- } else if (keyCode === 13 || keyCode === 32) {
1107
- if (btnIndex === -1 && params.allowEnterKey) {
1108
- // ENTER/SPACE clicked outside of a button.
1109
- if (params.focusCancel) {
1110
- fireClick(cancelButton, e);
1111
- } else {
1112
- fireClick(confirmButton, e);
1113
- }
1114
- e.stopPropagation();
1115
- e.preventDefault();
1116
- }
1117
-
1118
- // ESC
1119
- } else if (keyCode === 27 && params.allowEscapeKey === true) {
1120
- sweetAlert.closeModal(params.onClose);
1121
- if (params.useRejections) {
1122
- reject('esc');
1123
- } else {
1124
- resolve({ dismiss: 'esc' });
1125
- }
1126
- }
1127
- };
1128
-
1129
- if (!window.onkeydown || window.onkeydown.toString() !== handleKeyDown.toString()) {
1130
- states.previousWindowKeyDown = window.onkeydown;
1131
- window.onkeydown = handleKeyDown;
1132
- }
1133
-
1134
- // Loading state
1135
- if (params.buttonsStyling) {
1136
- confirmButton.style.borderLeftColor = params.confirmButtonColor;
1137
- confirmButton.style.borderRightColor = params.confirmButtonColor;
1138
- }
1139
-
1140
- /**
1141
- * Show spinner instead of Confirm button and disable Cancel button
1142
- */
1143
- sweetAlert.hideLoading = sweetAlert.disableLoading = function () {
1144
- if (!params.showConfirmButton) {
1145
- hide(confirmButton);
1146
- if (!params.showCancelButton) {
1147
- hide(getButtonsWrapper());
1148
- }
1149
- }
1150
- removeClass(buttonsWrapper, swalClasses.loading);
1151
- removeClass(modal, swalClasses.loading);
1152
- confirmButton.disabled = false;
1153
- cancelButton.disabled = false;
1154
- };
1155
-
1156
- sweetAlert.getTitle = function () {
1157
- return getTitle();
1158
- };
1159
- sweetAlert.getContent = function () {
1160
- return getContent();
1161
- };
1162
- sweetAlert.getInput = function () {
1163
- return getInput();
1164
- };
1165
- sweetAlert.getImage = function () {
1166
- return getImage();
1167
- };
1168
- sweetAlert.getButtonsWrapper = function () {
1169
- return getButtonsWrapper();
1170
- };
1171
- sweetAlert.getConfirmButton = function () {
1172
- return getConfirmButton();
1173
- };
1174
- sweetAlert.getCancelButton = function () {
1175
- return getCancelButton();
1176
- };
1177
-
1178
- sweetAlert.enableButtons = function () {
1179
- confirmButton.disabled = false;
1180
- cancelButton.disabled = false;
1181
- };
1182
-
1183
- sweetAlert.disableButtons = function () {
1184
- confirmButton.disabled = true;
1185
- cancelButton.disabled = true;
1186
- };
1187
-
1188
- sweetAlert.enableConfirmButton = function () {
1189
- confirmButton.disabled = false;
1190
- };
1191
-
1192
- sweetAlert.disableConfirmButton = function () {
1193
- confirmButton.disabled = true;
1194
- };
1195
-
1196
- sweetAlert.enableInput = function () {
1197
- var input = getInput();
1198
- if (!input) {
1199
- return false;
1200
- }
1201
- if (input.type === 'radio') {
1202
- var radiosContainer = input.parentNode.parentNode;
1203
- var radios = radiosContainer.querySelectorAll('input');
1204
- for (var _i5 = 0; _i5 < radios.length; _i5++) {
1205
- radios[_i5].disabled = false;
1206
- }
1207
- } else {
1208
- input.disabled = false;
1209
- }
1210
- };
1211
-
1212
- sweetAlert.disableInput = function () {
1213
- var input = getInput();
1214
- if (!input) {
1215
- return false;
1216
- }
1217
- if (input && input.type === 'radio') {
1218
- var radiosContainer = input.parentNode.parentNode;
1219
- var radios = radiosContainer.querySelectorAll('input');
1220
- for (var _i6 = 0; _i6 < radios.length; _i6++) {
1221
- radios[_i6].disabled = true;
1222
- }
1223
- } else {
1224
- input.disabled = true;
1225
- }
1226
- };
1227
-
1228
- // Set modal min-height to disable scrolling inside the modal
1229
- sweetAlert.recalculateHeight = debounce(function () {
1230
- var modal = getModal();
1231
- if (!modal) {
1232
- return;
1233
- }
1234
- var prevState = modal.style.display;
1235
- modal.style.minHeight = '';
1236
- show(modal);
1237
- modal.style.minHeight = modal.scrollHeight + 1 + 'px';
1238
- modal.style.display = prevState;
1239
- }, 50);
1240
-
1241
- // Show block with validation error
1242
- sweetAlert.showValidationError = function (error) {
1243
- var validationError = getValidationError();
1244
- validationError.innerHTML = error;
1245
- show(validationError);
1246
-
1247
- var input = getInput();
1248
- if (input) {
1249
- focusInput(input);
1250
- addClass(input, swalClasses.inputerror);
1251
- }
1252
- };
1253
-
1254
- // Hide block with validation error
1255
- sweetAlert.resetValidationError = function () {
1256
- var validationError = getValidationError();
1257
- hide(validationError);
1258
- sweetAlert.recalculateHeight();
1259
-
1260
- var input = getInput();
1261
- if (input) {
1262
- removeClass(input, swalClasses.inputerror);
1263
- }
1264
- };
1265
-
1266
- sweetAlert.getProgressSteps = function () {
1267
- return params.progressSteps;
1268
- };
1269
-
1270
- sweetAlert.setProgressSteps = function (progressSteps) {
1271
- params.progressSteps = progressSteps;
1272
- setParameters(params);
1273
- };
1274
-
1275
- sweetAlert.showProgressSteps = function () {
1276
- show(getProgressSteps());
1277
- };
1278
-
1279
- sweetAlert.hideProgressSteps = function () {
1280
- hide(getProgressSteps());
1281
- };
1282
-
1283
- sweetAlert.enableButtons();
1284
- sweetAlert.hideLoading();
1285
- sweetAlert.resetValidationError();
1286
-
1287
- // inputs
1288
- var inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];
1289
- var input = void 0;
1290
- for (var _i7 = 0; _i7 < inputTypes.length; _i7++) {
1291
- var inputClass = swalClasses[inputTypes[_i7]];
1292
- var inputContainer = getChildByClass(modal, inputClass);
1293
- input = getInput(inputTypes[_i7]);
1294
-
1295
- // set attributes
1296
- if (input) {
1297
- for (var j in input.attributes) {
1298
- if (input.attributes.hasOwnProperty(j)) {
1299
- var attrName = input.attributes[j].name;
1300
- if (attrName !== 'type' && attrName !== 'value') {
1301
- input.removeAttribute(attrName);
1302
- }
1303
- }
1304
- }
1305
- for (var attr in params.inputAttributes) {
1306
- input.setAttribute(attr, params.inputAttributes[attr]);
1307
- }
1308
- }
1309
-
1310
- // set class
1311
- inputContainer.className = inputClass;
1312
- if (params.inputClass) {
1313
- addClass(inputContainer, params.inputClass);
1314
- }
1315
-
1316
- hide(inputContainer);
1317
- }
1318
-
1319
- var populateInputOptions = void 0;
1320
- switch (params.input) {
1321
- case 'text':
1322
- case 'email':
1323
- case 'password':
1324
- case 'number':
1325
- case 'tel':
1326
- case 'url':
1327
- input = getChildByClass(modal, swalClasses.input);
1328
- input.value = params.inputValue;
1329
- input.placeholder = params.inputPlaceholder;
1330
- input.type = params.input;
1331
- show(input);
1332
- break;
1333
- case 'file':
1334
- input = getChildByClass(modal, swalClasses.file);
1335
- input.placeholder = params.inputPlaceholder;
1336
- input.type = params.input;
1337
- show(input);
1338
- break;
1339
- case 'range':
1340
- var range = getChildByClass(modal, swalClasses.range);
1341
- var rangeInput = range.querySelector('input');
1342
- var rangeOutput = range.querySelector('output');
1343
- rangeInput.value = params.inputValue;
1344
- rangeInput.type = params.input;
1345
- rangeOutput.value = params.inputValue;
1346
- show(range);
1347
- break;
1348
- case 'select':
1349
- var select = getChildByClass(modal, swalClasses.select);
1350
- select.innerHTML = '';
1351
- if (params.inputPlaceholder) {
1352
- var placeholder = document.createElement('option');
1353
- placeholder.innerHTML = params.inputPlaceholder;
1354
- placeholder.value = '';
1355
- placeholder.disabled = true;
1356
- placeholder.selected = true;
1357
- select.appendChild(placeholder);
1358
- }
1359
- populateInputOptions = function populateInputOptions(inputOptions) {
1360
- for (var optionValue in inputOptions) {
1361
- var option = document.createElement('option');
1362
- option.value = optionValue;
1363
- option.innerHTML = inputOptions[optionValue];
1364
- if (params.inputValue === optionValue) {
1365
- option.selected = true;
1366
- }
1367
- select.appendChild(option);
1368
- }
1369
- show(select);
1370
- select.focus();
1371
- };
1372
- break;
1373
- case 'radio':
1374
- var radio = getChildByClass(modal, swalClasses.radio);
1375
- radio.innerHTML = '';
1376
- populateInputOptions = function populateInputOptions(inputOptions) {
1377
- for (var radioValue in inputOptions) {
1378
- var radioInput = document.createElement('input');
1379
- var radioLabel = document.createElement('label');
1380
- var radioLabelSpan = document.createElement('span');
1381
- radioInput.type = 'radio';
1382
- radioInput.name = swalClasses.radio;
1383
- radioInput.value = radioValue;
1384
- if (params.inputValue === radioValue) {
1385
- radioInput.checked = true;
1386
- }
1387
- radioLabelSpan.innerHTML = inputOptions[radioValue];
1388
- radioLabel.appendChild(radioInput);
1389
- radioLabel.appendChild(radioLabelSpan);
1390
- radioLabel.for = radioInput.id;
1391
- radio.appendChild(radioLabel);
1392
- }
1393
- show(radio);
1394
- var radios = radio.querySelectorAll('input');
1395
- if (radios.length) {
1396
- radios[0].focus();
1397
- }
1398
- };
1399
- break;
1400
- case 'checkbox':
1401
- var checkbox = getChildByClass(modal, swalClasses.checkbox);
1402
- var checkboxInput = getInput('checkbox');
1403
- checkboxInput.type = 'checkbox';
1404
- checkboxInput.value = 1;
1405
- checkboxInput.id = swalClasses.checkbox;
1406
- checkboxInput.checked = Boolean(params.inputValue);
1407
- var label = checkbox.getElementsByTagName('span');
1408
- if (label.length) {
1409
- checkbox.removeChild(label[0]);
1410
- }
1411
- label = document.createElement('span');
1412
- label.innerHTML = params.inputPlaceholder;
1413
- checkbox.appendChild(label);
1414
- show(checkbox);
1415
- break;
1416
- case 'textarea':
1417
- var textarea = getChildByClass(modal, swalClasses.textarea);
1418
- textarea.value = params.inputValue;
1419
- textarea.placeholder = params.inputPlaceholder;
1420
- show(textarea);
1421
- break;
1422
- case null:
1423
- break;
1424
- default:
1425
- console.error('SweetAlert2: Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "' + params.input + '"');
1426
- break;
1427
- }
1428
-
1429
- if (params.input === 'select' || params.input === 'radio') {
1430
- if (params.inputOptions instanceof Promise) {
1431
- sweetAlert.showLoading();
1432
- params.inputOptions.then(function (inputOptions) {
1433
- sweetAlert.hideLoading();
1434
- populateInputOptions(inputOptions);
1435
- });
1436
- } else if (_typeof(params.inputOptions) === 'object') {
1437
- populateInputOptions(params.inputOptions);
1438
- } else {
1439
- console.error('SweetAlert2: Unexpected type of inputOptions! Expected object or Promise, got ' + _typeof(params.inputOptions));
1440
- }
1441
- }
1442
-
1443
- openModal(params.animation, params.onOpen);
1444
-
1445
- // Focus the first element (input or button)
1446
- if (params.allowEnterKey) {
1447
- setFocus(-1, 1);
1448
- } else {
1449
- if (document.activeElement) {
1450
- document.activeElement.blur();
1451
- }
1452
- }
1453
-
1454
- // fix scroll
1455
- getContainer().scrollTop = 0;
1456
-
1457
- // Observe changes inside the modal and adjust height
1458
- if (typeof MutationObserver !== 'undefined' && !swal2Observer) {
1459
- swal2Observer = new MutationObserver(sweetAlert.recalculateHeight);
1460
- swal2Observer.observe(modal, { childList: true, characterData: true, subtree: true });
1461
- }
1462
- });
1463
- };
1464
-
1465
- /*
1466
- * Global function to determine if swal2 modal is shown
1467
- */
1468
- sweetAlert.isVisible = function () {
1469
- return !!getModal();
1470
- };
1471
-
1472
- /*
1473
- * Global function for chaining sweetAlert modals
1474
- */
1475
- sweetAlert.queue = function (steps) {
1476
- queue = steps;
1477
- var resetQueue = function resetQueue() {
1478
- queue = [];
1479
- document.body.removeAttribute('data-swal2-queue-step');
1480
- };
1481
- var queueResult = [];
1482
- return new Promise(function (resolve, reject) {
1483
- (function step(i, callback) {
1484
- if (i < queue.length) {
1485
- document.body.setAttribute('data-swal2-queue-step', i);
1486
-
1487
- sweetAlert(queue[i]).then(function (result) {
1488
- queueResult.push(result);
1489
- step(i + 1, callback);
1490
- }, function (dismiss) {
1491
- resetQueue();
1492
- reject(dismiss);
1493
- });
1494
- } else {
1495
- resetQueue();
1496
- resolve(queueResult);
1497
- }
1498
- })(0);
1499
- });
1500
- };
1501
-
1502
- /*
1503
- * Global function for getting the index of current modal in queue
1504
- */
1505
- sweetAlert.getQueueStep = function () {
1506
- return document.body.getAttribute('data-swal2-queue-step');
1507
- };
1508
-
1509
- /*
1510
- * Global function for inserting a modal to the queue
1511
- */
1512
- sweetAlert.insertQueueStep = function (step, index) {
1513
- if (index && index < queue.length) {
1514
- return queue.splice(index, 0, step);
1515
- }
1516
- return queue.push(step);
1517
- };
1518
-
1519
- /*
1520
- * Global function for deleting a modal from the queue
1521
- */
1522
- sweetAlert.deleteQueueStep = function (index) {
1523
- if (typeof queue[index] !== 'undefined') {
1524
- queue.splice(index, 1);
1525
- }
1526
- };
1527
-
1528
- /*
1529
- * Global function to close sweetAlert
1530
- */
1531
- sweetAlert.close = sweetAlert.closeModal = function (onComplete) {
1532
- var container = getContainer();
1533
- var modal = getModal();
1534
- if (!modal) {
1535
- return;
1536
- }
1537
- removeClass(modal, swalClasses.show);
1538
- addClass(modal, swalClasses.hide);
1539
- clearTimeout(modal.timeout);
1540
-
1541
- resetPrevState();
1542
-
1543
- var removeModalAndResetState = function removeModalAndResetState() {
1544
- if (container.parentNode) {
1545
- container.parentNode.removeChild(container);
1546
- }
1547
- removeClass(document.documentElement, swalClasses.shown);
1548
- removeClass(document.body, swalClasses.shown);
1549
- undoScrollbar();
1550
- undoIOSfix();
1551
- };
1552
-
1553
- // If animation is supported, animate
1554
- if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
1555
- modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
1556
- modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
1557
- if (hasClass(modal, swalClasses.hide)) {
1558
- removeModalAndResetState();
1559
- }
1560
- });
1561
- } else {
1562
- // Otherwise, remove immediately
1563
- removeModalAndResetState();
1564
- }
1565
- if (onComplete !== null && typeof onComplete === 'function') {
1566
- setTimeout(function () {
1567
- onComplete(modal);
1568
- });
1569
- }
1570
- };
1571
-
1572
- /*
1573
- * Global function to click 'Confirm' button
1574
- */
1575
- sweetAlert.clickConfirm = function () {
1576
- return getConfirmButton().click();
1577
- };
1578
-
1579
- /*
1580
- * Global function to click 'Cancel' button
1581
- */
1582
- sweetAlert.clickCancel = function () {
1583
- return getCancelButton().click();
1584
- };
1585
-
1586
- /**
1587
- * Show spinner instead of Confirm button and disable Cancel button
1588
- */
1589
- sweetAlert.showLoading = sweetAlert.enableLoading = function () {
1590
- var modal = getModal();
1591
- if (!modal) {
1592
- sweetAlert('');
1593
- }
1594
- var buttonsWrapper = getButtonsWrapper();
1595
- var confirmButton = getConfirmButton();
1596
- var cancelButton = getCancelButton();
1597
-
1598
- show(buttonsWrapper);
1599
- show(confirmButton, 'inline-block');
1600
- addClass(buttonsWrapper, swalClasses.loading);
1601
- addClass(modal, swalClasses.loading);
1602
- confirmButton.disabled = true;
1603
- cancelButton.disabled = true;
1604
- };
1605
-
1606
- /**
1607
- * Set default params for each popup
1608
- * @param {Object} userParams
1609
- */
1610
- sweetAlert.setDefaults = function (userParams) {
1611
- if (!userParams || (typeof userParams === 'undefined' ? 'undefined' : _typeof(userParams)) !== 'object') {
1612
- return console.error('SweetAlert2: the argument for setDefaults() is required and has to be a object');
1613
- }
1614
-
1615
- for (var param in userParams) {
1616
- if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
1617
- console.warn('SweetAlert2: Unknown parameter "' + param + '"');
1618
- delete userParams[param];
1619
- }
1620
- }
1621
-
1622
- _extends(modalParams, userParams);
1623
- };
1624
-
1625
- /**
1626
- * Reset default params for each popup
1627
- */
1628
- sweetAlert.resetDefaults = function () {
1629
- modalParams = _extends({}, defaultParams);
1630
- };
1631
-
1632
- sweetAlert.noop = function () {};
1633
-
1634
- sweetAlert.version = '6.6.6';
1635
-
1636
- sweetAlert.default = sweetAlert;
1637
-
1638
- return sweetAlert;
1639
-
1640
- })));
1641
- if (window.Sweetalert2) window.sweetAlert = window.swal = window.Sweetalert2;
1
+ /*!
2
+ * sweetalert2 v6.6.6
3
+ * Released under the MIT License.
4
+ */
5
+ (function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
7
+ typeof define === 'function' && define.amd ? define(factory) :
8
+ (global.Sweetalert2 = factory());
9
+ }(this, (function () { 'use strict';
10
+
11
+ var defaultParams = {
12
+ title: '',
13
+ titleText: '',
14
+ text: '',
15
+ html: '',
16
+ type: null,
17
+ customClass: '',
18
+ target: 'body',
19
+ animation: true,
20
+ allowOutsideClick: true,
21
+ allowEscapeKey: true,
22
+ allowEnterKey: true,
23
+ showConfirmButton: true,
24
+ showCancelButton: false,
25
+ preConfirm: null,
26
+ confirmButtonText: 'OK',
27
+ confirmButtonColor: '#3085d6',
28
+ confirmButtonClass: null,
29
+ cancelButtonText: 'Cancel',
30
+ cancelButtonColor: '#aaa',
31
+ cancelButtonClass: null,
32
+ buttonsStyling: true,
33
+ reverseButtons: false,
34
+ focusCancel: false,
35
+ showCloseButton: false,
36
+ showLoaderOnConfirm: false,
37
+ imageUrl: null,
38
+ imageWidth: null,
39
+ imageHeight: null,
40
+ imageClass: null,
41
+ timer: null,
42
+ width: 500,
43
+ padding: 20,
44
+ background: '#fff',
45
+ input: null,
46
+ inputPlaceholder: '',
47
+ inputValue: '',
48
+ inputOptions: {},
49
+ inputAutoTrim: true,
50
+ inputClass: null,
51
+ inputAttributes: {},
52
+ inputValidator: null,
53
+ progressSteps: [],
54
+ currentProgressStep: null,
55
+ progressStepsDistance: '40px',
56
+ onOpen: null,
57
+ onClose: null,
58
+ useRejections: true
59
+ };
60
+
61
+ var swalPrefix = 'swal2-';
62
+
63
+ var prefix = function prefix(items) {
64
+ var result = {};
65
+ for (var i in items) {
66
+ result[items[i]] = swalPrefix + items[i];
67
+ }
68
+ return result;
69
+ };
70
+
71
+ var swalClasses = prefix(['container', 'shown', 'iosfix', 'modal', 'overlay', 'fade', 'show', 'hide', 'noanimation', 'close', 'title', 'content', 'buttonswrapper', 'confirm', 'cancel', 'icon', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea', 'inputerror', 'validationerror', 'progresssteps', 'activeprogressstep', 'progresscircle', 'progressline', 'loading', 'styled']);
72
+
73
+ var iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
74
+
75
+ /*
76
+ * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color)
77
+ */
78
+ var colorLuminance = function colorLuminance(hex, lum) {
79
+ // Validate hex string
80
+ hex = String(hex).replace(/[^0-9a-f]/gi, '');
81
+ if (hex.length < 6) {
82
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
83
+ }
84
+ lum = lum || 0;
85
+
86
+ // Convert to decimal and change luminosity
87
+ var rgb = '#';
88
+ for (var i = 0; i < 3; i++) {
89
+ var c = parseInt(hex.substr(i * 2, 2), 16);
90
+ c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
91
+ rgb += ('00' + c).substr(c.length);
92
+ }
93
+
94
+ return rgb;
95
+ };
96
+
97
+ var uniqueArray = function uniqueArray(arr) {
98
+ var result = [];
99
+ for (var i in arr) {
100
+ if (result.indexOf(arr[i]) === -1) {
101
+ result.push(arr[i]);
102
+ }
103
+ }
104
+ return result;
105
+ };
106
+
107
+ /* global MouseEvent */
108
+
109
+ // Remember state in cases where opening and handling a modal will fiddle with it.
110
+ var states = {
111
+ previousWindowKeyDown: null,
112
+ previousActiveElement: null,
113
+ previousBodyPadding: null
114
+
115
+ /*
116
+ * Add modal + overlay to DOM
117
+ */
118
+ };var init = function init(params) {
119
+ if (typeof document === 'undefined') {
120
+ console.error('SweetAlert2 requires document to initialize');
121
+ return;
122
+ }
123
+
124
+ var container = document.createElement('div');
125
+ container.className = swalClasses.container;
126
+ container.innerHTML = sweetHTML;
127
+
128
+ var targetElement = document.querySelector(params.target);
129
+ if (!targetElement) {
130
+ console.warn('SweetAlert2: Can\'t find the target "' + params.target + '"');
131
+ targetElement = document.body;
132
+ }
133
+ targetElement.appendChild(container);
134
+
135
+ var modal = getModal();
136
+ var input = getChildByClass(modal, swalClasses.input);
137
+ var file = getChildByClass(modal, swalClasses.file);
138
+ var range = modal.querySelector('.' + swalClasses.range + ' input');
139
+ var rangeOutput = modal.querySelector('.' + swalClasses.range + ' output');
140
+ var select = getChildByClass(modal, swalClasses.select);
141
+ var checkbox = modal.querySelector('.' + swalClasses.checkbox + ' input');
142
+ var textarea = getChildByClass(modal, swalClasses.textarea);
143
+
144
+ input.oninput = function () {
145
+ sweetAlert.resetValidationError();
146
+ };
147
+
148
+ input.onkeydown = function (event) {
149
+ setTimeout(function () {
150
+ if (event.keyCode === 13 && params.allowEnterKey) {
151
+ event.stopPropagation();
152
+ sweetAlert.clickConfirm();
153
+ }
154
+ }, 0);
155
+ };
156
+
157
+ file.onchange = function () {
158
+ sweetAlert.resetValidationError();
159
+ };
160
+
161
+ range.oninput = function () {
162
+ sweetAlert.resetValidationError();
163
+ rangeOutput.value = range.value;
164
+ };
165
+
166
+ range.onchange = function () {
167
+ sweetAlert.resetValidationError();
168
+ range.previousSibling.value = range.value;
169
+ };
170
+
171
+ select.onchange = function () {
172
+ sweetAlert.resetValidationError();
173
+ };
174
+
175
+ checkbox.onchange = function () {
176
+ sweetAlert.resetValidationError();
177
+ };
178
+
179
+ textarea.oninput = function () {
180
+ sweetAlert.resetValidationError();
181
+ };
182
+
183
+ return modal;
184
+ };
185
+
186
+ /*
187
+ * Manipulate DOM
188
+ */
189
+
190
+ var sweetHTML = ('\n <div role="dialog" aria-labelledby="' + swalClasses.title + '" aria-describedby="' + swalClasses.content + '" class="' + swalClasses.modal + '" tabindex="-1">\n <ul class="' + swalClasses.progresssteps + '"></ul>\n <div class="' + swalClasses.icon + ' ' + iconTypes.error + '">\n <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n </div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.question + '">?</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.warning + '">!</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.info + '">i</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.success + '">\n <div class="swal2-success-circular-line-left"></div>\n <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n <div class="swal2-success-circular-line-right"></div>\n </div>\n <img class="' + swalClasses.image + '" />\n <h2 class="' + swalClasses.title + '" id="' + swalClasses.title + '"></h2>\n <div id="' + swalClasses.content + '" class="' + swalClasses.content + '"></div>\n <input class="' + swalClasses.input + '" />\n <input type="file" class="' + swalClasses.file + '" />\n <div class="' + swalClasses.range + '">\n <output></output>\n <input type="range" />\n </div>\n <select class="' + swalClasses.select + '"></select>\n <div class="' + swalClasses.radio + '"></div>\n <label for="' + swalClasses.checkbox + '" class="' + swalClasses.checkbox + '">\n <input type="checkbox" />\n </label>\n <textarea class="' + swalClasses.textarea + '"></textarea>\n <div class="' + swalClasses.validationerror + '"></div>\n <div class="' + swalClasses.buttonswrapper + '">\n <button type="button" class="' + swalClasses.confirm + '">OK</button>\n <button type="button" class="' + swalClasses.cancel + '">Cancel</button>\n </div>\n <button type="button" class="' + swalClasses.close + '" aria-label="Close this dialog">\xD7</button>\n </div>\n').replace(/(^|\n)\s*/g, '');
191
+
192
+ var getContainer = function getContainer() {
193
+ return document.body.querySelector('.' + swalClasses.container);
194
+ };
195
+
196
+ var getModal = function getModal() {
197
+ return getContainer() ? getContainer().querySelector('.' + swalClasses.modal) : null;
198
+ };
199
+
200
+ var getIcons = function getIcons() {
201
+ var modal = getModal();
202
+ return modal.querySelectorAll('.' + swalClasses.icon);
203
+ };
204
+
205
+ var elementByClass = function elementByClass(className) {
206
+ return getContainer() ? getContainer().querySelector('.' + className) : null;
207
+ };
208
+
209
+ var getTitle = function getTitle() {
210
+ return elementByClass(swalClasses.title);
211
+ };
212
+
213
+ var getContent = function getContent() {
214
+ return elementByClass(swalClasses.content);
215
+ };
216
+
217
+ var getImage = function getImage() {
218
+ return elementByClass(swalClasses.image);
219
+ };
220
+
221
+ var getButtonsWrapper = function getButtonsWrapper() {
222
+ return elementByClass(swalClasses.buttonswrapper);
223
+ };
224
+
225
+ var getProgressSteps = function getProgressSteps() {
226
+ return elementByClass(swalClasses.progresssteps);
227
+ };
228
+
229
+ var getValidationError = function getValidationError() {
230
+ return elementByClass(swalClasses.validationerror);
231
+ };
232
+
233
+ var getConfirmButton = function getConfirmButton() {
234
+ return elementByClass(swalClasses.confirm);
235
+ };
236
+
237
+ var getCancelButton = function getCancelButton() {
238
+ return elementByClass(swalClasses.cancel);
239
+ };
240
+
241
+ var getCloseButton = function getCloseButton() {
242
+ return elementByClass(swalClasses.close);
243
+ };
244
+
245
+ var getFocusableElements = function getFocusableElements(focusCancel) {
246
+ var buttons = [getConfirmButton(), getCancelButton()];
247
+ if (focusCancel) {
248
+ buttons.reverse();
249
+ }
250
+ var focusableElements = buttons.concat(Array.prototype.slice.call(getModal().querySelectorAll('button, input:not([type=hidden]), textarea, select, a, *[tabindex]:not([tabindex="-1"])')));
251
+ return uniqueArray(focusableElements);
252
+ };
253
+
254
+ var hasClass = function hasClass(elem, className) {
255
+ if (elem.classList) {
256
+ return elem.classList.contains(className);
257
+ }
258
+ return false;
259
+ };
260
+
261
+ var focusInput = function focusInput(input) {
262
+ input.focus();
263
+
264
+ // place cursor at end of text in text input
265
+ if (input.type !== 'file') {
266
+ // http://stackoverflow.com/a/2345915/1331425
267
+ var val = input.value;
268
+ input.value = '';
269
+ input.value = val;
270
+ }
271
+ };
272
+
273
+ var addClass = function addClass(elem, className) {
274
+ if (!elem || !className) {
275
+ return;
276
+ }
277
+ var classes = className.split(/\s+/).filter(Boolean);
278
+ classes.forEach(function (className) {
279
+ elem.classList.add(className);
280
+ });
281
+ };
282
+
283
+ var removeClass = function removeClass(elem, className) {
284
+ if (!elem || !className) {
285
+ return;
286
+ }
287
+ var classes = className.split(/\s+/).filter(Boolean);
288
+ classes.forEach(function (className) {
289
+ elem.classList.remove(className);
290
+ });
291
+ };
292
+
293
+ var getChildByClass = function getChildByClass(elem, className) {
294
+ for (var i = 0; i < elem.childNodes.length; i++) {
295
+ if (hasClass(elem.childNodes[i], className)) {
296
+ return elem.childNodes[i];
297
+ }
298
+ }
299
+ };
300
+
301
+ var show = function show(elem, display) {
302
+ if (!display) {
303
+ display = 'block';
304
+ }
305
+ elem.style.opacity = '';
306
+ elem.style.display = display;
307
+ };
308
+
309
+ var hide = function hide(elem) {
310
+ elem.style.opacity = '';
311
+ elem.style.display = 'none';
312
+ };
313
+
314
+ var empty = function empty(elem) {
315
+ while (elem.firstChild) {
316
+ elem.removeChild(elem.firstChild);
317
+ }
318
+ };
319
+
320
+ // borrowed from jqeury $(elem).is(':visible') implementation
321
+ var isVisible = function isVisible(elem) {
322
+ return elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length;
323
+ };
324
+
325
+ var removeStyleProperty = function removeStyleProperty(elem, property) {
326
+ if (elem.style.removeProperty) {
327
+ elem.style.removeProperty(property);
328
+ } else {
329
+ elem.style.removeAttribute(property);
330
+ }
331
+ };
332
+
333
+ var fireClick = function fireClick(node) {
334
+ if (!isVisible(node)) {
335
+ return false;
336
+ }
337
+
338
+ // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
339
+ // Then fixed for today's Chrome browser.
340
+ if (typeof MouseEvent === 'function') {
341
+ // Up-to-date approach
342
+ var mevt = new MouseEvent('click', {
343
+ view: window,
344
+ bubbles: false,
345
+ cancelable: true
346
+ });
347
+ node.dispatchEvent(mevt);
348
+ } else if (document.createEvent) {
349
+ // Fallback
350
+ var evt = document.createEvent('MouseEvents');
351
+ evt.initEvent('click', false, false);
352
+ node.dispatchEvent(evt);
353
+ } else if (document.createEventObject) {
354
+ node.fireEvent('onclick');
355
+ } else if (typeof node.onclick === 'function') {
356
+ node.onclick();
357
+ }
358
+ };
359
+
360
+ var animationEndEvent = function () {
361
+ var testEl = document.createElement('div');
362
+ var transEndEventNames = {
363
+ 'WebkitAnimation': 'webkitAnimationEnd',
364
+ 'OAnimation': 'oAnimationEnd oanimationend',
365
+ 'msAnimation': 'MSAnimationEnd',
366
+ 'animation': 'animationend'
367
+ };
368
+ for (var i in transEndEventNames) {
369
+ if (transEndEventNames.hasOwnProperty(i) && testEl.style[i] !== undefined) {
370
+ return transEndEventNames[i];
371
+ }
372
+ }
373
+
374
+ return false;
375
+ }();
376
+
377
+ // Reset previous window keydown handler and focued element
378
+ var resetPrevState = function resetPrevState() {
379
+ window.onkeydown = states.previousWindowKeyDown;
380
+ if (states.previousActiveElement && states.previousActiveElement.focus) {
381
+ var x = window.scrollX;
382
+ var y = window.scrollY;
383
+ states.previousActiveElement.focus();
384
+ if (x && y) {
385
+ // IE has no scrollX/scrollY support
386
+ window.scrollTo(x, y);
387
+ }
388
+ }
389
+ };
390
+
391
+ // Measure width of scrollbar
392
+ // https://github.com/twbs/bootstrap/blob/master/js/modal.js#L279-L286
393
+ var measureScrollbar = function measureScrollbar() {
394
+ var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
395
+ if (supportsTouch) {
396
+ return 0;
397
+ }
398
+ var scrollDiv = document.createElement('div');
399
+ scrollDiv.style.width = '50px';
400
+ scrollDiv.style.height = '50px';
401
+ scrollDiv.style.overflow = 'scroll';
402
+ document.body.appendChild(scrollDiv);
403
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
404
+ document.body.removeChild(scrollDiv);
405
+ return scrollbarWidth;
406
+ };
407
+
408
+ // JavaScript Debounce Function
409
+ // Simplivied version of https://davidwalsh.name/javascript-debounce-function
410
+ var debounce = function debounce(func, wait) {
411
+ var timeout = void 0;
412
+ return function () {
413
+ var later = function later() {
414
+ timeout = null;
415
+ func();
416
+ };
417
+ clearTimeout(timeout);
418
+ timeout = setTimeout(later, wait);
419
+ };
420
+ };
421
+
422
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
423
+ return typeof obj;
424
+ } : function (obj) {
425
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
426
+ };
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+ var _extends = Object.assign || function (target) {
449
+ for (var i = 1; i < arguments.length; i++) {
450
+ var source = arguments[i];
451
+
452
+ for (var key in source) {
453
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
454
+ target[key] = source[key];
455
+ }
456
+ }
457
+ }
458
+
459
+ return target;
460
+ };
461
+
462
+ var modalParams = _extends({}, defaultParams);
463
+ var queue = [];
464
+ var swal2Observer = void 0;
465
+
466
+ /*
467
+ * Set type, text and actions on modal
468
+ */
469
+ var setParameters = function setParameters(params) {
470
+ var modal = getModal() || init(params);
471
+
472
+ for (var param in params) {
473
+ if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
474
+ console.warn('SweetAlert2: Unknown parameter "' + param + '"');
475
+ }
476
+ }
477
+
478
+ // Set modal width
479
+ modal.style.width = typeof params.width === 'number' ? params.width + 'px' : params.width;
480
+
481
+ modal.style.padding = params.padding + 'px';
482
+ modal.style.background = params.background;
483
+ var successIconParts = modal.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');
484
+ for (var i = 0; i < successIconParts.length; i++) {
485
+ successIconParts[i].style.background = params.background;
486
+ }
487
+
488
+ var title = getTitle();
489
+ var content = getContent();
490
+ var buttonsWrapper = getButtonsWrapper();
491
+ var confirmButton = getConfirmButton();
492
+ var cancelButton = getCancelButton();
493
+ var closeButton = getCloseButton();
494
+
495
+ // Title
496
+ if (params.titleText) {
497
+ title.innerText = params.titleText;
498
+ } else {
499
+ title.innerHTML = params.title.split('\n').join('<br />');
500
+ }
501
+
502
+ // Content
503
+ if (params.text || params.html) {
504
+ if (_typeof(params.html) === 'object') {
505
+ content.innerHTML = '';
506
+ if (0 in params.html) {
507
+ for (var _i = 0; _i in params.html; _i++) {
508
+ content.appendChild(params.html[_i].cloneNode(true));
509
+ }
510
+ } else {
511
+ content.appendChild(params.html.cloneNode(true));
512
+ }
513
+ } else if (params.html) {
514
+ content.innerHTML = params.html;
515
+ } else if (params.text) {
516
+ content.textContent = params.text;
517
+ }
518
+ show(content);
519
+ } else {
520
+ hide(content);
521
+ }
522
+
523
+ // Close button
524
+ if (params.showCloseButton) {
525
+ show(closeButton);
526
+ } else {
527
+ hide(closeButton);
528
+ }
529
+
530
+ // Custom Class
531
+ modal.className = swalClasses.modal;
532
+ if (params.customClass) {
533
+ addClass(modal, params.customClass);
534
+ }
535
+
536
+ // Progress steps
537
+ var progressStepsContainer = getProgressSteps();
538
+ var currentProgressStep = parseInt(params.currentProgressStep === null ? sweetAlert.getQueueStep() : params.currentProgressStep, 10);
539
+ if (params.progressSteps.length) {
540
+ show(progressStepsContainer);
541
+ empty(progressStepsContainer);
542
+ if (currentProgressStep >= params.progressSteps.length) {
543
+ console.warn('SweetAlert2: Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)');
544
+ }
545
+ params.progressSteps.forEach(function (step, index) {
546
+ var circle = document.createElement('li');
547
+ addClass(circle, swalClasses.progresscircle);
548
+ circle.innerHTML = step;
549
+ if (index === currentProgressStep) {
550
+ addClass(circle, swalClasses.activeprogressstep);
551
+ }
552
+ progressStepsContainer.appendChild(circle);
553
+ if (index !== params.progressSteps.length - 1) {
554
+ var line = document.createElement('li');
555
+ addClass(line, swalClasses.progressline);
556
+ line.style.width = params.progressStepsDistance;
557
+ progressStepsContainer.appendChild(line);
558
+ }
559
+ });
560
+ } else {
561
+ hide(progressStepsContainer);
562
+ }
563
+
564
+ // Icon
565
+ var icons = getIcons();
566
+ for (var _i2 = 0; _i2 < icons.length; _i2++) {
567
+ hide(icons[_i2]);
568
+ }
569
+ if (params.type) {
570
+ var validType = false;
571
+ for (var iconType in iconTypes) {
572
+ if (params.type === iconType) {
573
+ validType = true;
574
+ break;
575
+ }
576
+ }
577
+ if (!validType) {
578
+ console.error('SweetAlert2: Unknown alert type: ' + params.type);
579
+ return false;
580
+ }
581
+ var icon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes[params.type]);
582
+ show(icon);
583
+
584
+ // Animate icon
585
+ if (params.animation) {
586
+ switch (params.type) {
587
+ case 'success':
588
+ addClass(icon, 'swal2-animate-success-icon');
589
+ addClass(icon.querySelector('.swal2-success-line-tip'), 'swal2-animate-success-line-tip');
590
+ addClass(icon.querySelector('.swal2-success-line-long'), 'swal2-animate-success-line-long');
591
+ break;
592
+ case 'error':
593
+ addClass(icon, 'swal2-animate-error-icon');
594
+ addClass(icon.querySelector('.swal2-x-mark'), 'swal2-animate-x-mark');
595
+ break;
596
+ default:
597
+ break;
598
+ }
599
+ }
600
+ }
601
+
602
+ // Custom image
603
+ var image = getImage();
604
+ if (params.imageUrl) {
605
+ image.setAttribute('src', params.imageUrl);
606
+ show(image);
607
+
608
+ if (params.imageWidth) {
609
+ image.setAttribute('width', params.imageWidth);
610
+ } else {
611
+ image.removeAttribute('width');
612
+ }
613
+
614
+ if (params.imageHeight) {
615
+ image.setAttribute('height', params.imageHeight);
616
+ } else {
617
+ image.removeAttribute('height');
618
+ }
619
+
620
+ image.className = swalClasses.image;
621
+ if (params.imageClass) {
622
+ addClass(image, params.imageClass);
623
+ }
624
+ } else {
625
+ hide(image);
626
+ }
627
+
628
+ // Cancel button
629
+ if (params.showCancelButton) {
630
+ cancelButton.style.display = 'inline-block';
631
+ } else {
632
+ hide(cancelButton);
633
+ }
634
+
635
+ // Confirm button
636
+ if (params.showConfirmButton) {
637
+ removeStyleProperty(confirmButton, 'display');
638
+ } else {
639
+ hide(confirmButton);
640
+ }
641
+
642
+ // Buttons wrapper
643
+ if (!params.showConfirmButton && !params.showCancelButton) {
644
+ hide(buttonsWrapper);
645
+ } else {
646
+ show(buttonsWrapper);
647
+ }
648
+
649
+ // Edit text on cancel and confirm buttons
650
+ confirmButton.innerHTML = params.confirmButtonText;
651
+ cancelButton.innerHTML = params.cancelButtonText;
652
+
653
+ // Set buttons to selected background colors
654
+ if (params.buttonsStyling) {
655
+ confirmButton.style.backgroundColor = params.confirmButtonColor;
656
+ cancelButton.style.backgroundColor = params.cancelButtonColor;
657
+ }
658
+
659
+ // Add buttons custom classes
660
+ confirmButton.className = swalClasses.confirm;
661
+ addClass(confirmButton, params.confirmButtonClass);
662
+ cancelButton.className = swalClasses.cancel;
663
+ addClass(cancelButton, params.cancelButtonClass);
664
+
665
+ // Buttons styling
666
+ if (params.buttonsStyling) {
667
+ addClass(confirmButton, swalClasses.styled);
668
+ addClass(cancelButton, swalClasses.styled);
669
+ } else {
670
+ removeClass(confirmButton, swalClasses.styled);
671
+ removeClass(cancelButton, swalClasses.styled);
672
+
673
+ confirmButton.style.backgroundColor = confirmButton.style.borderLeftColor = confirmButton.style.borderRightColor = '';
674
+ cancelButton.style.backgroundColor = cancelButton.style.borderLeftColor = cancelButton.style.borderRightColor = '';
675
+ }
676
+
677
+ // CSS animation
678
+ if (params.animation === true) {
679
+ removeClass(modal, swalClasses.noanimation);
680
+ } else {
681
+ addClass(modal, swalClasses.noanimation);
682
+ }
683
+ };
684
+
685
+ /*
686
+ * Animations
687
+ */
688
+ var openModal = function openModal(animation, onComplete) {
689
+ var container = getContainer();
690
+ var modal = getModal();
691
+
692
+ if (animation) {
693
+ addClass(modal, swalClasses.show);
694
+ addClass(container, swalClasses.fade);
695
+ removeClass(modal, swalClasses.hide);
696
+ } else {
697
+ removeClass(modal, swalClasses.fade);
698
+ }
699
+ show(modal);
700
+
701
+ // scrolling is 'hidden' until animation is done, after that 'auto'
702
+ container.style.overflowY = 'hidden';
703
+ if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
704
+ modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
705
+ modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
706
+ container.style.overflowY = 'auto';
707
+ });
708
+ } else {
709
+ container.style.overflowY = 'auto';
710
+ }
711
+
712
+ addClass(document.documentElement, swalClasses.shown);
713
+ addClass(document.body, swalClasses.shown);
714
+ addClass(container, swalClasses.shown);
715
+ fixScrollbar();
716
+ iOSfix();
717
+ states.previousActiveElement = document.activeElement;
718
+ if (onComplete !== null && typeof onComplete === 'function') {
719
+ setTimeout(function () {
720
+ onComplete(modal);
721
+ });
722
+ }
723
+ };
724
+
725
+ var fixScrollbar = function fixScrollbar() {
726
+ // for queues, do not do this more than once
727
+ if (states.previousBodyPadding !== null) {
728
+ return;
729
+ }
730
+ // if the body has overflow
731
+ if (document.body.scrollHeight > window.innerHeight) {
732
+ // add padding so the content doesn't shift after removal of scrollbar
733
+ states.previousBodyPadding = document.body.style.paddingRight;
734
+ document.body.style.paddingRight = measureScrollbar() + 'px';
735
+ }
736
+ };
737
+
738
+ var undoScrollbar = function undoScrollbar() {
739
+ if (states.previousBodyPadding !== null) {
740
+ document.body.style.paddingRight = states.previousBodyPadding;
741
+ states.previousBodyPadding = null;
742
+ }
743
+ };
744
+
745
+ // Fix iOS scrolling http://stackoverflow.com/q/39626302/1331425
746
+ var iOSfix = function iOSfix() {
747
+ var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
748
+ if (iOS && !hasClass(document.body, swalClasses.iosfix)) {
749
+ var offset = document.body.scrollTop;
750
+ document.body.style.top = offset * -1 + 'px';
751
+ addClass(document.body, swalClasses.iosfix);
752
+ }
753
+ };
754
+
755
+ var undoIOSfix = function undoIOSfix() {
756
+ if (hasClass(document.body, swalClasses.iosfix)) {
757
+ var offset = parseInt(document.body.style.top, 10);
758
+ removeClass(document.body, swalClasses.iosfix);
759
+ document.body.style.top = '';
760
+ document.body.scrollTop = offset * -1;
761
+ }
762
+ };
763
+
764
+ // SweetAlert entry point
765
+ var sweetAlert = function sweetAlert() {
766
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
767
+ args[_key] = arguments[_key];
768
+ }
769
+
770
+ if (args[0] === undefined) {
771
+ console.error('SweetAlert2 expects at least 1 attribute!');
772
+ return false;
773
+ }
774
+
775
+ var params = _extends({}, modalParams);
776
+
777
+ switch (_typeof(args[0])) {
778
+ case 'string':
779
+ params.title = args[0];
780
+ params.html = args[1];
781
+ params.type = args[2];
782
+
783
+ break;
784
+
785
+ case 'object':
786
+ _extends(params, args[0]);
787
+ params.extraParams = args[0].extraParams;
788
+
789
+ if (params.input === 'email' && params.inputValidator === null) {
790
+ params.inputValidator = function (email) {
791
+ return new Promise(function (resolve, reject) {
792
+ var emailRegex = /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
793
+ if (emailRegex.test(email)) {
794
+ resolve();
795
+ } else {
796
+ reject('Invalid email address');
797
+ }
798
+ });
799
+ };
800
+ }
801
+
802
+ if (params.input === 'url' && params.inputValidator === null) {
803
+ params.inputValidator = function (url) {
804
+ return new Promise(function (resolve, reject) {
805
+ // taken from https://stackoverflow.com/a/3809435/1331425
806
+ var urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/;
807
+ if (urlRegex.test(url)) {
808
+ resolve();
809
+ } else {
810
+ reject('Invalid URL');
811
+ }
812
+ });
813
+ };
814
+ }
815
+ break;
816
+
817
+ default:
818
+ console.error('SweetAlert2: Unexpected type of argument! Expected "string" or "object", got ' + _typeof(args[0]));
819
+ return false;
820
+ }
821
+
822
+ setParameters(params);
823
+
824
+ var container = getContainer();
825
+ var modal = getModal();
826
+
827
+ return new Promise(function (resolve, reject) {
828
+ // Close on timer
829
+ if (params.timer) {
830
+ modal.timeout = setTimeout(function () {
831
+ sweetAlert.closeModal(params.onClose);
832
+ if (params.useRejections) {
833
+ reject('timer');
834
+ } else {
835
+ resolve({ dismiss: 'timer' });
836
+ }
837
+ }, params.timer);
838
+ }
839
+
840
+ // Get input element by specified type or, if type isn't specified, by params.input
841
+ var getInput = function getInput(inputType) {
842
+ inputType = inputType || params.input;
843
+ if (!inputType) {
844
+ return null;
845
+ }
846
+ switch (inputType) {
847
+ case 'select':
848
+ case 'textarea':
849
+ case 'file':
850
+ return getChildByClass(modal, swalClasses[inputType]);
851
+ case 'checkbox':
852
+ return modal.querySelector('.' + swalClasses.checkbox + ' input');
853
+ case 'radio':
854
+ return modal.querySelector('.' + swalClasses.radio + ' input:checked') || modal.querySelector('.' + swalClasses.radio + ' input:first-child');
855
+ case 'range':
856
+ return modal.querySelector('.' + swalClasses.range + ' input');
857
+ default:
858
+ return getChildByClass(modal, swalClasses.input);
859
+ }
860
+ };
861
+
862
+ // Get the value of the modal input
863
+ var getInputValue = function getInputValue() {
864
+ var input = getInput();
865
+ if (!input) {
866
+ return null;
867
+ }
868
+ switch (params.input) {
869
+ case 'checkbox':
870
+ return input.checked ? 1 : 0;
871
+ case 'radio':
872
+ return input.checked ? input.value : null;
873
+ case 'file':
874
+ return input.files.length ? input.files[0] : null;
875
+ default:
876
+ return params.inputAutoTrim ? input.value.trim() : input.value;
877
+ }
878
+ };
879
+
880
+ // input autofocus
881
+ if (params.input) {
882
+ setTimeout(function () {
883
+ var input = getInput();
884
+ if (input) {
885
+ focusInput(input);
886
+ }
887
+ }, 0);
888
+ }
889
+
890
+ var confirm = function confirm(value) {
891
+ if (params.showLoaderOnConfirm) {
892
+ sweetAlert.showLoading();
893
+ }
894
+
895
+ if (params.preConfirm) {
896
+ params.preConfirm(value, params.extraParams).then(function (preConfirmValue) {
897
+ sweetAlert.closeModal(params.onClose);
898
+ resolve(preConfirmValue || value);
899
+ }, function (error) {
900
+ sweetAlert.hideLoading();
901
+ if (error) {
902
+ sweetAlert.showValidationError(error);
903
+ }
904
+ });
905
+ } else {
906
+ sweetAlert.closeModal(params.onClose);
907
+ if (params.useRejections) {
908
+ resolve(value);
909
+ } else {
910
+ resolve({ value: value });
911
+ }
912
+ }
913
+ };
914
+
915
+ // Mouse interactions
916
+ var onButtonEvent = function onButtonEvent(event) {
917
+ var e = event || window.event;
918
+ var target = e.target || e.srcElement;
919
+ var confirmButton = getConfirmButton();
920
+ var cancelButton = getCancelButton();
921
+ var targetedConfirm = confirmButton && (confirmButton === target || confirmButton.contains(target));
922
+ var targetedCancel = cancelButton && (cancelButton === target || cancelButton.contains(target));
923
+
924
+ switch (e.type) {
925
+ case 'mouseover':
926
+ case 'mouseup':
927
+ if (params.buttonsStyling) {
928
+ if (targetedConfirm) {
929
+ confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.1);
930
+ } else if (targetedCancel) {
931
+ cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.1);
932
+ }
933
+ }
934
+ break;
935
+ case 'mouseout':
936
+ if (params.buttonsStyling) {
937
+ if (targetedConfirm) {
938
+ confirmButton.style.backgroundColor = params.confirmButtonColor;
939
+ } else if (targetedCancel) {
940
+ cancelButton.style.backgroundColor = params.cancelButtonColor;
941
+ }
942
+ }
943
+ break;
944
+ case 'mousedown':
945
+ if (params.buttonsStyling) {
946
+ if (targetedConfirm) {
947
+ confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.2);
948
+ } else if (targetedCancel) {
949
+ cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.2);
950
+ }
951
+ }
952
+ break;
953
+ case 'click':
954
+ // Clicked 'confirm'
955
+ if (targetedConfirm && sweetAlert.isVisible()) {
956
+ sweetAlert.disableButtons();
957
+ if (params.input) {
958
+ var inputValue = getInputValue();
959
+
960
+ if (params.inputValidator) {
961
+ sweetAlert.disableInput();
962
+ params.inputValidator(inputValue, params.extraParams).then(function () {
963
+ sweetAlert.enableButtons();
964
+ sweetAlert.enableInput();
965
+ confirm(inputValue);
966
+ }, function (error) {
967
+ sweetAlert.enableButtons();
968
+ sweetAlert.enableInput();
969
+ if (error) {
970
+ sweetAlert.showValidationError(error);
971
+ }
972
+ });
973
+ } else {
974
+ confirm(inputValue);
975
+ }
976
+ } else {
977
+ confirm(true);
978
+ }
979
+
980
+ // Clicked 'cancel'
981
+ } else if (targetedCancel && sweetAlert.isVisible()) {
982
+ sweetAlert.disableButtons();
983
+ sweetAlert.closeModal(params.onClose);
984
+ if (params.useRejections) {
985
+ reject('cancel');
986
+ } else {
987
+ resolve({ dismiss: 'cancel' });
988
+ }
989
+ }
990
+ break;
991
+ default:
992
+ }
993
+ };
994
+
995
+ var buttons = modal.querySelectorAll('button');
996
+ for (var i = 0; i < buttons.length; i++) {
997
+ buttons[i].onclick = onButtonEvent;
998
+ buttons[i].onmouseover = onButtonEvent;
999
+ buttons[i].onmouseout = onButtonEvent;
1000
+ buttons[i].onmousedown = onButtonEvent;
1001
+ }
1002
+
1003
+ // Closing modal by close button
1004
+ getCloseButton().onclick = function () {
1005
+ sweetAlert.closeModal(params.onClose);
1006
+ if (params.useRejections) {
1007
+ reject('close');
1008
+ } else {
1009
+ resolve({ dismiss: 'close' });
1010
+ }
1011
+ };
1012
+
1013
+ // Closing modal by overlay click
1014
+ container.onclick = function (e) {
1015
+ if (e.target !== container) {
1016
+ return;
1017
+ }
1018
+ if (params.allowOutsideClick) {
1019
+ sweetAlert.closeModal(params.onClose);
1020
+ if (params.useRejections) {
1021
+ reject('overlay');
1022
+ } else {
1023
+ resolve({ dismiss: 'overlay' });
1024
+ }
1025
+ }
1026
+ };
1027
+
1028
+ var buttonsWrapper = getButtonsWrapper();
1029
+ var confirmButton = getConfirmButton();
1030
+ var cancelButton = getCancelButton();
1031
+
1032
+ // Reverse buttons (Confirm on the right side)
1033
+ if (params.reverseButtons) {
1034
+ confirmButton.parentNode.insertBefore(cancelButton, confirmButton);
1035
+ } else {
1036
+ confirmButton.parentNode.insertBefore(confirmButton, cancelButton);
1037
+ }
1038
+
1039
+ // Focus handling
1040
+ var setFocus = function setFocus(index, increment) {
1041
+ var focusableElements = getFocusableElements(params.focusCancel);
1042
+ // search for visible elements and select the next possible match
1043
+ for (var _i3 = 0; _i3 < focusableElements.length; _i3++) {
1044
+ index = index + increment;
1045
+
1046
+ // rollover to first item
1047
+ if (index === focusableElements.length) {
1048
+ index = 0;
1049
+
1050
+ // go to last item
1051
+ } else if (index === -1) {
1052
+ index = focusableElements.length - 1;
1053
+ }
1054
+
1055
+ // determine if element is visible
1056
+ var el = focusableElements[index];
1057
+ if (isVisible(el)) {
1058
+ return el.focus();
1059
+ }
1060
+ }
1061
+ };
1062
+
1063
+ var handleKeyDown = function handleKeyDown(event) {
1064
+ var e = event || window.event;
1065
+ var keyCode = e.keyCode || e.which;
1066
+
1067
+ if ([9, 13, 32, 27, 37, 38, 39, 40].indexOf(keyCode) === -1) {
1068
+ // Don't do work on keys we don't care about.
1069
+ return;
1070
+ }
1071
+
1072
+ var targetElement = e.target || e.srcElement;
1073
+
1074
+ var focusableElements = getFocusableElements(params.focusCancel);
1075
+ var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
1076
+ for (var _i4 = 0; _i4 < focusableElements.length; _i4++) {
1077
+ if (targetElement === focusableElements[_i4]) {
1078
+ btnIndex = _i4;
1079
+ break;
1080
+ }
1081
+ }
1082
+
1083
+ // TAB
1084
+ if (keyCode === 9) {
1085
+ if (!e.shiftKey) {
1086
+ // Cycle to the next button
1087
+ setFocus(btnIndex, 1);
1088
+ } else {
1089
+ // Cycle to the prev button
1090
+ setFocus(btnIndex, -1);
1091
+ }
1092
+ e.stopPropagation();
1093
+ e.preventDefault();
1094
+
1095
+ // ARROWS - switch focus between buttons
1096
+ } else if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
1097
+ // focus Cancel button if Confirm button is currently focused
1098
+ if (document.activeElement === confirmButton && isVisible(cancelButton)) {
1099
+ cancelButton.focus();
1100
+ // and vice versa
1101
+ } else if (document.activeElement === cancelButton && isVisible(confirmButton)) {
1102
+ confirmButton.focus();
1103
+ }
1104
+
1105
+ // ENTER/SPACE
1106
+ } else if (keyCode === 13 || keyCode === 32) {
1107
+ if (btnIndex === -1 && params.allowEnterKey) {
1108
+ // ENTER/SPACE clicked outside of a button.
1109
+ if (params.focusCancel) {
1110
+ fireClick(cancelButton, e);
1111
+ } else {
1112
+ fireClick(confirmButton, e);
1113
+ }
1114
+ e.stopPropagation();
1115
+ e.preventDefault();
1116
+ }
1117
+
1118
+ // ESC
1119
+ } else if (keyCode === 27 && params.allowEscapeKey === true) {
1120
+ sweetAlert.closeModal(params.onClose);
1121
+ if (params.useRejections) {
1122
+ reject('esc');
1123
+ } else {
1124
+ resolve({ dismiss: 'esc' });
1125
+ }
1126
+ }
1127
+ };
1128
+
1129
+ if (!window.onkeydown || window.onkeydown.toString() !== handleKeyDown.toString()) {
1130
+ states.previousWindowKeyDown = window.onkeydown;
1131
+ window.onkeydown = handleKeyDown;
1132
+ }
1133
+
1134
+ // Loading state
1135
+ if (params.buttonsStyling) {
1136
+ confirmButton.style.borderLeftColor = params.confirmButtonColor;
1137
+ confirmButton.style.borderRightColor = params.confirmButtonColor;
1138
+ }
1139
+
1140
+ /**
1141
+ * Show spinner instead of Confirm button and disable Cancel button
1142
+ */
1143
+ sweetAlert.hideLoading = sweetAlert.disableLoading = function () {
1144
+ if (!params.showConfirmButton) {
1145
+ hide(confirmButton);
1146
+ if (!params.showCancelButton) {
1147
+ hide(getButtonsWrapper());
1148
+ }
1149
+ }
1150
+ removeClass(buttonsWrapper, swalClasses.loading);
1151
+ removeClass(modal, swalClasses.loading);
1152
+ confirmButton.disabled = false;
1153
+ cancelButton.disabled = false;
1154
+ };
1155
+
1156
+ sweetAlert.getTitle = function () {
1157
+ return getTitle();
1158
+ };
1159
+ sweetAlert.getContent = function () {
1160
+ return getContent();
1161
+ };
1162
+ sweetAlert.getInput = function () {
1163
+ return getInput();
1164
+ };
1165
+ sweetAlert.getImage = function () {
1166
+ return getImage();
1167
+ };
1168
+ sweetAlert.getButtonsWrapper = function () {
1169
+ return getButtonsWrapper();
1170
+ };
1171
+ sweetAlert.getConfirmButton = function () {
1172
+ return getConfirmButton();
1173
+ };
1174
+ sweetAlert.getCancelButton = function () {
1175
+ return getCancelButton();
1176
+ };
1177
+
1178
+ sweetAlert.enableButtons = function () {
1179
+ confirmButton.disabled = false;
1180
+ cancelButton.disabled = false;
1181
+ };
1182
+
1183
+ sweetAlert.disableButtons = function () {
1184
+ confirmButton.disabled = true;
1185
+ cancelButton.disabled = true;
1186
+ };
1187
+
1188
+ sweetAlert.enableConfirmButton = function () {
1189
+ confirmButton.disabled = false;
1190
+ };
1191
+
1192
+ sweetAlert.disableConfirmButton = function () {
1193
+ confirmButton.disabled = true;
1194
+ };
1195
+
1196
+ sweetAlert.enableInput = function () {
1197
+ var input = getInput();
1198
+ if (!input) {
1199
+ return false;
1200
+ }
1201
+ if (input.type === 'radio') {
1202
+ var radiosContainer = input.parentNode.parentNode;
1203
+ var radios = radiosContainer.querySelectorAll('input');
1204
+ for (var _i5 = 0; _i5 < radios.length; _i5++) {
1205
+ radios[_i5].disabled = false;
1206
+ }
1207
+ } else {
1208
+ input.disabled = false;
1209
+ }
1210
+ };
1211
+
1212
+ sweetAlert.disableInput = function () {
1213
+ var input = getInput();
1214
+ if (!input) {
1215
+ return false;
1216
+ }
1217
+ if (input && input.type === 'radio') {
1218
+ var radiosContainer = input.parentNode.parentNode;
1219
+ var radios = radiosContainer.querySelectorAll('input');
1220
+ for (var _i6 = 0; _i6 < radios.length; _i6++) {
1221
+ radios[_i6].disabled = true;
1222
+ }
1223
+ } else {
1224
+ input.disabled = true;
1225
+ }
1226
+ };
1227
+
1228
+ // Set modal min-height to disable scrolling inside the modal
1229
+ sweetAlert.recalculateHeight = debounce(function () {
1230
+ var modal = getModal();
1231
+ if (!modal) {
1232
+ return;
1233
+ }
1234
+ var prevState = modal.style.display;
1235
+ modal.style.minHeight = '';
1236
+ show(modal);
1237
+ modal.style.minHeight = modal.scrollHeight + 1 + 'px';
1238
+ modal.style.display = prevState;
1239
+ }, 50);
1240
+
1241
+ // Show block with validation error
1242
+ sweetAlert.showValidationError = function (error) {
1243
+ var validationError = getValidationError();
1244
+ validationError.innerHTML = error;
1245
+ show(validationError);
1246
+
1247
+ var input = getInput();
1248
+ if (input) {
1249
+ focusInput(input);
1250
+ addClass(input, swalClasses.inputerror);
1251
+ }
1252
+ };
1253
+
1254
+ // Hide block with validation error
1255
+ sweetAlert.resetValidationError = function () {
1256
+ var validationError = getValidationError();
1257
+ hide(validationError);
1258
+ sweetAlert.recalculateHeight();
1259
+
1260
+ var input = getInput();
1261
+ if (input) {
1262
+ removeClass(input, swalClasses.inputerror);
1263
+ }
1264
+ };
1265
+
1266
+ sweetAlert.getProgressSteps = function () {
1267
+ return params.progressSteps;
1268
+ };
1269
+
1270
+ sweetAlert.setProgressSteps = function (progressSteps) {
1271
+ params.progressSteps = progressSteps;
1272
+ setParameters(params);
1273
+ };
1274
+
1275
+ sweetAlert.showProgressSteps = function () {
1276
+ show(getProgressSteps());
1277
+ };
1278
+
1279
+ sweetAlert.hideProgressSteps = function () {
1280
+ hide(getProgressSteps());
1281
+ };
1282
+
1283
+ sweetAlert.enableButtons();
1284
+ sweetAlert.hideLoading();
1285
+ sweetAlert.resetValidationError();
1286
+
1287
+ // inputs
1288
+ var inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];
1289
+ var input = void 0;
1290
+ for (var _i7 = 0; _i7 < inputTypes.length; _i7++) {
1291
+ var inputClass = swalClasses[inputTypes[_i7]];
1292
+ var inputContainer = getChildByClass(modal, inputClass);
1293
+ input = getInput(inputTypes[_i7]);
1294
+
1295
+ // set attributes
1296
+ if (input) {
1297
+ for (var j in input.attributes) {
1298
+ if (input.attributes.hasOwnProperty(j)) {
1299
+ var attrName = input.attributes[j].name;
1300
+ if (attrName !== 'type' && attrName !== 'value') {
1301
+ input.removeAttribute(attrName);
1302
+ }
1303
+ }
1304
+ }
1305
+ for (var attr in params.inputAttributes) {
1306
+ input.setAttribute(attr, params.inputAttributes[attr]);
1307
+ }
1308
+ }
1309
+
1310
+ // set class
1311
+ inputContainer.className = inputClass;
1312
+ if (params.inputClass) {
1313
+ addClass(inputContainer, params.inputClass);
1314
+ }
1315
+
1316
+ hide(inputContainer);
1317
+ }
1318
+
1319
+ var populateInputOptions = void 0;
1320
+ switch (params.input) {
1321
+ case 'text':
1322
+ case 'email':
1323
+ case 'password':
1324
+ case 'number':
1325
+ case 'tel':
1326
+ case 'url':
1327
+ input = getChildByClass(modal, swalClasses.input);
1328
+ input.value = params.inputValue;
1329
+ input.placeholder = params.inputPlaceholder;
1330
+ input.type = params.input;
1331
+ show(input);
1332
+ break;
1333
+ case 'file':
1334
+ input = getChildByClass(modal, swalClasses.file);
1335
+ input.placeholder = params.inputPlaceholder;
1336
+ input.type = params.input;
1337
+ show(input);
1338
+ break;
1339
+ case 'range':
1340
+ var range = getChildByClass(modal, swalClasses.range);
1341
+ var rangeInput = range.querySelector('input');
1342
+ var rangeOutput = range.querySelector('output');
1343
+ rangeInput.value = params.inputValue;
1344
+ rangeInput.type = params.input;
1345
+ rangeOutput.value = params.inputValue;
1346
+ show(range);
1347
+ break;
1348
+ case 'select':
1349
+ var select = getChildByClass(modal, swalClasses.select);
1350
+ select.innerHTML = '';
1351
+ if (params.inputPlaceholder) {
1352
+ var placeholder = document.createElement('option');
1353
+ placeholder.innerHTML = params.inputPlaceholder;
1354
+ placeholder.value = '';
1355
+ placeholder.disabled = true;
1356
+ placeholder.selected = true;
1357
+ select.appendChild(placeholder);
1358
+ }
1359
+ populateInputOptions = function populateInputOptions(inputOptions) {
1360
+ for (var optionValue in inputOptions) {
1361
+ var option = document.createElement('option');
1362
+ option.value = optionValue;
1363
+ option.innerHTML = inputOptions[optionValue];
1364
+ if (params.inputValue === optionValue) {
1365
+ option.selected = true;
1366
+ }
1367
+ select.appendChild(option);
1368
+ }
1369
+ show(select);
1370
+ select.focus();
1371
+ };
1372
+ break;
1373
+ case 'radio':
1374
+ var radio = getChildByClass(modal, swalClasses.radio);
1375
+ radio.innerHTML = '';
1376
+ populateInputOptions = function populateInputOptions(inputOptions) {
1377
+ for (var radioValue in inputOptions) {
1378
+ var radioInput = document.createElement('input');
1379
+ var radioLabel = document.createElement('label');
1380
+ var radioLabelSpan = document.createElement('span');
1381
+ radioInput.type = 'radio';
1382
+ radioInput.name = swalClasses.radio;
1383
+ radioInput.value = radioValue;
1384
+ if (params.inputValue === radioValue) {
1385
+ radioInput.checked = true;
1386
+ }
1387
+ radioLabelSpan.innerHTML = inputOptions[radioValue];
1388
+ radioLabel.appendChild(radioInput);
1389
+ radioLabel.appendChild(radioLabelSpan);
1390
+ radioLabel.for = radioInput.id;
1391
+ radio.appendChild(radioLabel);
1392
+ }
1393
+ show(radio);
1394
+ var radios = radio.querySelectorAll('input');
1395
+ if (radios.length) {
1396
+ radios[0].focus();
1397
+ }
1398
+ };
1399
+ break;
1400
+ case 'checkbox':
1401
+ var checkbox = getChildByClass(modal, swalClasses.checkbox);
1402
+ var checkboxInput = getInput('checkbox');
1403
+ checkboxInput.type = 'checkbox';
1404
+ checkboxInput.value = 1;
1405
+ checkboxInput.id = swalClasses.checkbox;
1406
+ checkboxInput.checked = Boolean(params.inputValue);
1407
+ var label = checkbox.getElementsByTagName('span');
1408
+ if (label.length) {
1409
+ checkbox.removeChild(label[0]);
1410
+ }
1411
+ label = document.createElement('span');
1412
+ label.innerHTML = params.inputPlaceholder;
1413
+ checkbox.appendChild(label);
1414
+ show(checkbox);
1415
+ break;
1416
+ case 'textarea':
1417
+ var textarea = getChildByClass(modal, swalClasses.textarea);
1418
+ textarea.value = params.inputValue;
1419
+ textarea.placeholder = params.inputPlaceholder;
1420
+ show(textarea);
1421
+ break;
1422
+ case null:
1423
+ break;
1424
+ default:
1425
+ console.error('SweetAlert2: Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "' + params.input + '"');
1426
+ break;
1427
+ }
1428
+
1429
+ if (params.input === 'select' || params.input === 'radio') {
1430
+ if (params.inputOptions instanceof Promise) {
1431
+ sweetAlert.showLoading();
1432
+ params.inputOptions.then(function (inputOptions) {
1433
+ sweetAlert.hideLoading();
1434
+ populateInputOptions(inputOptions);
1435
+ });
1436
+ } else if (_typeof(params.inputOptions) === 'object') {
1437
+ populateInputOptions(params.inputOptions);
1438
+ } else {
1439
+ console.error('SweetAlert2: Unexpected type of inputOptions! Expected object or Promise, got ' + _typeof(params.inputOptions));
1440
+ }
1441
+ }
1442
+
1443
+ openModal(params.animation, params.onOpen);
1444
+
1445
+ // Focus the first element (input or button)
1446
+ if (params.allowEnterKey) {
1447
+ setFocus(-1, 1);
1448
+ } else {
1449
+ if (document.activeElement) {
1450
+ document.activeElement.blur();
1451
+ }
1452
+ }
1453
+
1454
+ // fix scroll
1455
+ getContainer().scrollTop = 0;
1456
+
1457
+ // Observe changes inside the modal and adjust height
1458
+ if (typeof MutationObserver !== 'undefined' && !swal2Observer) {
1459
+ swal2Observer = new MutationObserver(sweetAlert.recalculateHeight);
1460
+ swal2Observer.observe(modal, { childList: true, characterData: true, subtree: true });
1461
+ }
1462
+ });
1463
+ };
1464
+
1465
+ /*
1466
+ * Global function to determine if swal2 modal is shown
1467
+ */
1468
+ sweetAlert.isVisible = function () {
1469
+ return !!getModal();
1470
+ };
1471
+
1472
+ /*
1473
+ * Global function for chaining sweetAlert modals
1474
+ */
1475
+ sweetAlert.queue = function (steps) {
1476
+ queue = steps;
1477
+ var resetQueue = function resetQueue() {
1478
+ queue = [];
1479
+ document.body.removeAttribute('data-swal2-queue-step');
1480
+ };
1481
+ var queueResult = [];
1482
+ return new Promise(function (resolve, reject) {
1483
+ (function step(i, callback) {
1484
+ if (i < queue.length) {
1485
+ document.body.setAttribute('data-swal2-queue-step', i);
1486
+
1487
+ sweetAlert(queue[i]).then(function (result) {
1488
+ queueResult.push(result);
1489
+ step(i + 1, callback);
1490
+ }, function (dismiss) {
1491
+ resetQueue();
1492
+ reject(dismiss);
1493
+ });
1494
+ } else {
1495
+ resetQueue();
1496
+ resolve(queueResult);
1497
+ }
1498
+ })(0);
1499
+ });
1500
+ };
1501
+
1502
+ /*
1503
+ * Global function for getting the index of current modal in queue
1504
+ */
1505
+ sweetAlert.getQueueStep = function () {
1506
+ return document.body.getAttribute('data-swal2-queue-step');
1507
+ };
1508
+
1509
+ /*
1510
+ * Global function for inserting a modal to the queue
1511
+ */
1512
+ sweetAlert.insertQueueStep = function (step, index) {
1513
+ if (index && index < queue.length) {
1514
+ return queue.splice(index, 0, step);
1515
+ }
1516
+ return queue.push(step);
1517
+ };
1518
+
1519
+ /*
1520
+ * Global function for deleting a modal from the queue
1521
+ */
1522
+ sweetAlert.deleteQueueStep = function (index) {
1523
+ if (typeof queue[index] !== 'undefined') {
1524
+ queue.splice(index, 1);
1525
+ }
1526
+ };
1527
+
1528
+ /*
1529
+ * Global function to close sweetAlert
1530
+ */
1531
+ sweetAlert.close = sweetAlert.closeModal = function (onComplete) {
1532
+ var container = getContainer();
1533
+ var modal = getModal();
1534
+ if (!modal) {
1535
+ return;
1536
+ }
1537
+ removeClass(modal, swalClasses.show);
1538
+ addClass(modal, swalClasses.hide);
1539
+ clearTimeout(modal.timeout);
1540
+
1541
+ resetPrevState();
1542
+
1543
+ var removeModalAndResetState = function removeModalAndResetState() {
1544
+ if (container.parentNode) {
1545
+ container.parentNode.removeChild(container);
1546
+ }
1547
+ removeClass(document.documentElement, swalClasses.shown);
1548
+ removeClass(document.body, swalClasses.shown);
1549
+ undoScrollbar();
1550
+ undoIOSfix();
1551
+ };
1552
+
1553
+ // If animation is supported, animate
1554
+ if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
1555
+ modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
1556
+ modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
1557
+ if (hasClass(modal, swalClasses.hide)) {
1558
+ removeModalAndResetState();
1559
+ }
1560
+ });
1561
+ } else {
1562
+ // Otherwise, remove immediately
1563
+ removeModalAndResetState();
1564
+ }
1565
+ if (onComplete !== null && typeof onComplete === 'function') {
1566
+ setTimeout(function () {
1567
+ onComplete(modal);
1568
+ });
1569
+ }
1570
+ };
1571
+
1572
+ /*
1573
+ * Global function to click 'Confirm' button
1574
+ */
1575
+ sweetAlert.clickConfirm = function () {
1576
+ return getConfirmButton().click();
1577
+ };
1578
+
1579
+ /*
1580
+ * Global function to click 'Cancel' button
1581
+ */
1582
+ sweetAlert.clickCancel = function () {
1583
+ return getCancelButton().click();
1584
+ };
1585
+
1586
+ /**
1587
+ * Show spinner instead of Confirm button and disable Cancel button
1588
+ */
1589
+ sweetAlert.showLoading = sweetAlert.enableLoading = function () {
1590
+ var modal = getModal();
1591
+ if (!modal) {
1592
+ sweetAlert('');
1593
+ }
1594
+ var buttonsWrapper = getButtonsWrapper();
1595
+ var confirmButton = getConfirmButton();
1596
+ var cancelButton = getCancelButton();
1597
+
1598
+ show(buttonsWrapper);
1599
+ show(confirmButton, 'inline-block');
1600
+ addClass(buttonsWrapper, swalClasses.loading);
1601
+ addClass(modal, swalClasses.loading);
1602
+ confirmButton.disabled = true;
1603
+ cancelButton.disabled = true;
1604
+ };
1605
+
1606
+ /**
1607
+ * Set default params for each popup
1608
+ * @param {Object} userParams
1609
+ */
1610
+ sweetAlert.setDefaults = function (userParams) {
1611
+ if (!userParams || (typeof userParams === 'undefined' ? 'undefined' : _typeof(userParams)) !== 'object') {
1612
+ return console.error('SweetAlert2: the argument for setDefaults() is required and has to be a object');
1613
+ }
1614
+
1615
+ for (var param in userParams) {
1616
+ if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
1617
+ console.warn('SweetAlert2: Unknown parameter "' + param + '"');
1618
+ delete userParams[param];
1619
+ }
1620
+ }
1621
+
1622
+ _extends(modalParams, userParams);
1623
+ };
1624
+
1625
+ /**
1626
+ * Reset default params for each popup
1627
+ */
1628
+ sweetAlert.resetDefaults = function () {
1629
+ modalParams = _extends({}, defaultParams);
1630
+ };
1631
+
1632
+ sweetAlert.noop = function () {};
1633
+
1634
+ sweetAlert.version = '6.6.6';
1635
+
1636
+ sweetAlert.default = sweetAlert;
1637
+
1638
+ return sweetAlert;
1639
+
1640
+ })));
1641
+ if (window.Sweetalert2) window.sweetAlert = window.swal = window.Sweetalert2;
admin/boot.php CHANGED
@@ -1,347 +1,347 @@
1
- <?php
2
- /**
3
- * Admin boot
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright Webcraftic 25.05.2017
7
- * @version 1.0
8
- */
9
-
10
- // Exit if accessed directly
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
-
15
- /**
16
- * Проверяем таблицу в базе данных
17
- *
18
- * Если таблица не существует или её структура устарела, то обновляем.
19
- * Проверка проводится при каждой инициализации плагина т.к. структура может измениться
20
- * после очередного обновления плагина.
21
- *
22
- * @return bool
23
- */
24
- add_action( 'admin_init', function () {
25
- RIO_Process_Queue::try_create_plugin_tables();
26
- } );
27
-
28
- /**
29
- * Удаляет карточку компонента в плагине Clearfy.
30
- *
31
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
32
- * @since 1.3.0
33
- */
34
- add_filter( 'wbcr/clearfy/components/items_list', function ( $components ) {
35
- if ( wrio_is_clearfy_license_activate() ) {
36
- return $components;
37
- }
38
- if ( ! empty( $components ) ) {
39
- foreach ( $components as $key => $component ) {
40
- if ( "robin_image_optimizer" == $component['name'] ) {
41
- unset( $components[ $key ] );
42
- }
43
- }
44
- }
45
-
46
- return $components;
47
- } );
48
-
49
- /**
50
- * Добавляет карточку компонента на страницу компонентов
51
- * в плагине Clearfy.
52
- *
53
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
54
- * @since 1.3.0
55
- */
56
- add_action( 'wbcr/clearfy/components/custom_plugins_card', function () {
57
- if ( ! wrio_is_clearfy_license_activate() ) {
58
- $view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
59
- $view->print_template( 'clearfy-component-card' );
60
- }
61
- } );
62
-
63
- /**
64
- * We asset migration scripts to all admin panel pages
65
- *
66
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
67
- * @since 1.3.0
68
- */
69
- add_action( 'admin_enqueue_scripts', function () {
70
- if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
71
- return;
72
- }
73
-
74
- wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
- 'jquery',
76
- 'wbcr-factory-clearfy-237-global'
77
- ], WRIO_Plugin::app()->getPluginVersion() );
78
- } );
79
-
80
- /**
81
- * Plugin was heavy migrated into new architecture. Specifically, post meta was moved to separate table and
82
- * therefore it is required to migrate all of them to new table.
83
- *
84
- * This action prints a notice, which contains clickable link with JS onclick event, which invokes AJAX request
85
- * to migrate these post metas to new table.
86
- *
87
- * Once all post meta migrated, notice would not be shown anymore.
88
- *
89
- * @param $notices
90
- *
91
- * @return array
92
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
93
- * @since 1.3.0
94
- *
95
- * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
96
- * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
97
- *
98
- * @see RIO_Process_Queue for further information about new table.
99
- */
100
- add_action( "wbcr/factory/admin_notices", function ( $notices ) {
101
-
102
- if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
103
- return $notices;
104
- }
105
-
106
- $notices[] = [
107
- 'id' => WRIO_Plugin::app()->getPrefix() . 'meta_to_migration',
108
- 'type' => 'warning',
109
- 'dismissible' => false,
110
- 'dismiss_expires' => 0,
111
- 'text' => "<p><b>" . WRIO_Plugin::app()->getPluginTitle() . ":</b> " . wrio_get_meta_migration_notice_text() . '</p>'
112
- ];
113
-
114
- return $notices;
115
- } );
116
-
117
- /**
118
- * Plugin was heavy migrated into new architecture. Specifically, post meta was moved to separate table and
119
- * therefore it is required to migrate all of them to new table.
120
- *
121
- * This action prints a notice, which contains clickable link with JS onclick event, which invokes AJAX request
122
- * to migrate these post metas to new table.
123
- *
124
- * Once all post meta migrated, notice would not be shown anymore.
125
- *
126
- * @param Wbcr_Factory446_Plugin $plugin
127
- * @param Wbcr_FactoryPages445_ImpressiveThemplate $obj
128
- *
129
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
130
- * @since 1.3.0
131
- *
132
- * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
- * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
134
- *
135
- * @see RIO_Process_Queue for further information about new table.
136
- */
137
- add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugin, $obj ) {
138
- if ( ( $plugin->getPluginName() != WRIO_Plugin::app()->getPluginName() ) || ! wbcr_rio_has_meta_to_migrate() ) {
139
- return;
140
- }
141
-
142
- $obj->printWarningNotice( wrio_get_meta_migration_notice_text() );
143
- }, 10, 2 );
144
-
145
- /***
146
- * Flush configuration after saving the settings
147
- *
148
- * @param WRIO_Plugin $plugin
149
- * @param Wbcr_FactoryPages445_ImpressiveThemplate $obj
150
- *
151
- * @return bool
152
- */
153
- /*add_action('wbcr_factory_446_imppage_after_form_save', function ($plugin, $obj) {
154
- $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
-
156
- if( $is_rio ) {
157
- WRIO_Cron::check();
158
- }
159
- }, 10, 2);*/
160
-
161
- /**
162
- * Виджет отзывов
163
- *
164
- * @param string $page_url
165
- * @param string $plugin_name
166
- *
167
- * @return string
168
- */
169
- function wio_rating_widget_url( $page_url, $plugin_name ) {
170
- if ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) {
171
- return 'https://wordpress.org/support/plugin/robin-image-optimizer/reviews/#new-post';
172
- }
173
-
174
- return $page_url;
175
- }
176
-
177
- add_filter( 'wbcr_factory_pages_445_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_Factory446_Plugin $plugin
185
- */
186
- add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
- if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
188
- require_once WRIO_PLUGIN_DIR . '/admin/includes/sidebar-widgets.php';
189
-
190
- if ( wrio_is_license_activate() ) {
191
- unset( $widgets['donate_widget'] );
192
-
193
- if ( $position == 'right' ) {
194
- unset( $widgets['adverts_widget'] );
195
- unset( $widgets['business_suggetion'] );
196
- unset( $widgets['rating_widget'] );
197
- unset( $widgets['info_widget'] );
198
- }
199
-
200
- /*if ( $position == 'bottom' ) {
201
- $widgets['support'] = wrio_get_sidebar_support_widget();
202
- }*/
203
-
204
- return $widgets;
205
- } else {
206
- if ( $position == 'right' ) {
207
- unset( $widgets['info_widget'] );
208
- unset( $widgets['rating_widget'] );
209
- //$widgets['support'] = wrio_get_sidebar_support_widget();
210
- }
211
- }
212
-
213
- //if ( $position == 'bottom' ) {
214
- //$widgets['donate_widget'] = wrio_get_sidebar_premium_widget();
215
- //}
216
- }
217
-
218
- return $widgets;
219
- }, 20, 3 );
220
-
221
- /**
222
- * Заменяет заголовок в рекламном виджете
223
- *
224
- * @param array $features
225
- * @param string $plugin_name
226
- * @param string $page_id
227
- */
228
- add_filter( 'wbcr/clearfy/pages/suggetion_title', function ( $features, $plugin_name, $page_id ) {
229
- if ( ! empty( $plugin_name ) && ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) ) {
230
- return __( "ROBIN IMAGE OPTIMIZER PRO", 'robin-image-optimizer' );
231
- }
232
-
233
- return $features;
234
- }, 20, 3 );
235
-
236
- /**
237
- * Заменяем премиум возможности в рекламном виджете
238
- *
239
- * @param array $features
240
- * @param string $plugin_name
241
- * @param string $page_id
242
- */
243
- add_filter( 'wbcr/clearfy/pages/suggetion_features', function ( $features, $plugin_name, $page_id ) {
244
- if ( ! empty( $plugin_name ) && ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) ) {
245
- $upgrade_feature = [];
246
- $upgrade_feature[] = __( 'Automatic convertation in Webp', 'robin-image-optimizer' );
247
- $upgrade_feature[] = __( 'You can optimize custom folders', 'robin-image-optimizer' );
248
- $upgrade_feature[] = __( 'Support Nextgen gallery', 'robin-image-optimizer' );
249
- $upgrade_feature[] = __( 'Multisite support', 'robin-image-optimizer' );
250
- $upgrade_feature[] = __( 'Fast optimization servers', 'robin-image-optimizer' );
251
- $upgrade_feature[] = __( 'No ads', 'robin-image-optimizer' );
252
- $upgrade_feature[] = __( 'Best support', 'robin-image-optimizer' );
253
-
254
- return $upgrade_feature;
255
- }
256
-
257
- return $features;
258
- }, 20, 3 );
259
-
260
- /**
261
- * Заменяем премиум возможности в рекламном виджете
262
- *
263
- * @param array $messages
264
- * @param string $type
265
- * @param string $plugin_name
266
- */
267
- add_filter( 'wbcr/factory/premium/notice_text', function ( $text, $type, $plugin_name ) {
268
- if ( WRIO_Plugin::app()->getPluginName() != $plugin_name ) {
269
- return $text;
270
- }
271
-
272
- $license_page_url = WRIO_Plugin::app()->getPluginPageUrl( 'rio_license' );
273
-
274
- if ( 'need_activate_license' == $type ) {
275
- return sprintf( __( '<a href="%s">License activation</a> required. A license is required to get premium plugin updates, as well as to get additional services.', 'robin-image-optimizer' ), $license_page_url );
276
- } else if ( 'need_renew_license' == $type ) {
277
- return sprintf( __( 'Your <a href="%s">license</a> has expired. You can no longer get premium plugin updates, premium support and your access to Webcraftic services has been suspended.', 'robin-image-optimizer' ), $license_page_url );
278
- }
279
-
280
- return $text;
281
- }, 10, 3 );
282
-
283
- /**
284
- * Отправка уведомлений и скором окончании квоты
285
- * Уведомления создаются только если квота <= 100
286
- *
287
- * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
288
- * @since 1.4.2
289
- */
290
- add_action( 'wbcr/factory/admin_notices', function ( $notices, $plugin_name ) {
291
- if ( $plugin_name != WRIO_Plugin::app()->getPluginName() ) {
292
- return $notices;
293
- }
294
-
295
- if ( WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' ) != 'server_5' ) {
296
- return $notices;
297
- }
298
-
299
- $current_quota = WRIO_Plugin::app()->getOption( 'current_quota' );
300
- if ( $current_quota > 100 ) {
301
- return $notices;
302
- }
303
-
304
- $notice_text = __( 'The remainder of the quota is coming to an end. Remained credits: ' . $current_quota, 'robin_image_optimizer' );
305
-
306
- $plugin_title = WRIO_Plugin::app()->getPluginTitle();
307
- $notice_text = '<b>' . $plugin_title . '</b>: ' . $notice_text;
308
- $notices[] = [
309
- 'id' => 'wrio_remained_quota',
310
- 'type' => 'warning',
311
- 'dismissible' => true,
312
- 'where' => [ 'plugins', 'dashboard', 'edit' ],
313
- 'dismiss_expires' => time() + 3600 * 4,
314
- 'text' => $notice_text,
315
- ];
316
-
317
- return $notices;
318
- }, 10, 2 );
319
-
320
- /**
321
- * Отправка уведомлений и скором окончании квоты в Impressive
322
- * Уведомления создаются только если квота <= 100
323
- *
324
- * @param Wbcr_Factory446_Plugin $plugin Экземпляр плагина, который передается в функцию обратного вызова
325
- * @param Wbcr_FactoryPages445_ImpressiveThemplate $obj Экземпляр страницы, который передается в функцию обратного вызова
326
- *
327
- * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
328
- * @since 1.4.2
329
- */
330
- add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugin, $obj ) {
331
- if ( $plugin->getPluginName() != WRIO_Plugin::app()->getPluginName() ) {
332
- return false;
333
- }
334
-
335
- if ( WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' ) != 'server_5' ) {
336
- return false;
337
- }
338
-
339
- $current_quota = WRIO_Plugin::app()->getOption( 'current_quota' );
340
- if ( $current_quota > 100 ) {
341
- return false;
342
- }
343
-
344
- $notice_text = __( 'The remainder of the quota is coming to an end. Remained credits: ' . $current_quota, 'robin_image_optimizer' );
345
-
346
- $obj->printWarningNotice( $notice_text );
347
- }, 10, 2 );
1
+ <?php
2
+ /**
3
+ * Admin boot
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright Webcraftic 25.05.2017
7
+ * @version 1.0
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * Проверяем таблицу в базе данных
17
+ *
18
+ * Если таблица не существует или её структура устарела, то обновляем.
19
+ * Проверка проводится при каждой инициализации плагина т.к. структура может измениться
20
+ * после очередного обновления плагина.
21
+ *
22
+ * @return bool
23
+ */
24
+ add_action( 'admin_init', function () {
25
+ RIO_Process_Queue::try_create_plugin_tables();
26
+ } );
27
+
28
+ /**
29
+ * Удаляет карточку компонента в плагине Clearfy.
30
+ *
31
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
32
+ * @since 1.3.0
33
+ */
34
+ add_filter( 'wbcr/clearfy/components/items_list', function ( $components ) {
35
+ if ( wrio_is_clearfy_license_activate() ) {
36
+ return $components;
37
+ }
38
+ if ( ! empty( $components ) ) {
39
+ foreach ( $components as $key => $component ) {
40
+ if ( "robin_image_optimizer" == $component['name'] ) {
41
+ unset( $components[ $key ] );
42
+ }
43
+ }
44
+ }
45
+
46
+ return $components;
47
+ } );
48
+
49
+ /**
50
+ * Добавляет карточку компонента на страницу компонентов
51
+ * в плагине Clearfy.
52
+ *
53
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
54
+ * @since 1.3.0
55
+ */
56
+ add_action( 'wbcr/clearfy/components/custom_plugins_card', function () {
57
+ if ( ! wrio_is_clearfy_license_activate() ) {
58
+ $view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
59
+ $view->print_template( 'clearfy-component-card' );
60
+ }
61
+ } );
62
+
63
+ /**
64
+ * We asset migration scripts to all admin panel pages
65
+ *
66
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
67
+ * @since 1.3.0
68
+ */
69
+ add_action( 'admin_enqueue_scripts', function () {
70
+ if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
71
+ return;
72
+ }
73
+
74
+ wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
+ 'jquery',
76
+ 'wbcr-factory-clearfy-000-global'
77
+ ], WRIO_Plugin::app()->getPluginVersion() );
78
+ } );
79
+
80
+ /**
81
+ * Plugin was heavy migrated into new architecture. Specifically, post meta was moved to separate table and
82
+ * therefore it is required to migrate all of them to new table.
83
+ *
84
+ * This action prints a notice, which contains clickable link with JS onclick event, which invokes AJAX request
85
+ * to migrate these post metas to new table.
86
+ *
87
+ * Once all post meta migrated, notice would not be shown anymore.
88
+ *
89
+ * @param $notices
90
+ *
91
+ * @return array
92
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
93
+ * @since 1.3.0
94
+ *
95
+ * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
96
+ * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
97
+ *
98
+ * @see RIO_Process_Queue for further information about new table.
99
+ */
100
+ add_action( "wbcr/factory/admin_notices", function ( $notices ) {
101
+
102
+ if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
103
+ return $notices;
104
+ }
105
+
106
+ $notices[] = [
107
+ 'id' => WRIO_Plugin::app()->getPrefix() . 'meta_to_migration',
108
+ 'type' => 'warning',
109
+ 'dismissible' => false,
110
+ 'dismiss_expires' => 0,
111
+ 'text' => "<p><b>" . WRIO_Plugin::app()->getPluginTitle() . ":</b> " . wrio_get_meta_migration_notice_text() . '</p>'
112
+ ];
113
+
114
+ return $notices;
115
+ } );
116
+
117
+ /**
118
+ * Plugin was heavy migrated into new architecture. Specifically, post meta was moved to separate table and
119
+ * therefore it is required to migrate all of them to new table.
120
+ *
121
+ * This action prints a notice, which contains clickable link with JS onclick event, which invokes AJAX request
122
+ * to migrate these post metas to new table.
123
+ *
124
+ * Once all post meta migrated, notice would not be shown anymore.
125
+ *
126
+ * @param Wbcr_Factory450_Plugin $plugin
127
+ * @param Wbcr_FactoryPages449_ImpressiveThemplate $obj
128
+ *
129
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
130
+ * @since 1.3.0
131
+ *
132
+ * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
+ * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
134
+ *
135
+ * @see RIO_Process_Queue for further information about new table.
136
+ */
137
+ add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugin, $obj ) {
138
+ if ( ( $plugin->getPluginName() != WRIO_Plugin::app()->getPluginName() ) || ! wbcr_rio_has_meta_to_migrate() ) {
139
+ return;
140
+ }
141
+
142
+ $obj->printWarningNotice( wrio_get_meta_migration_notice_text() );
143
+ }, 10, 2 );
144
+
145
+ /***
146
+ * Flush configuration after saving the settings
147
+ *
148
+ * @param WRIO_Plugin $plugin
149
+ * @param Wbcr_FactoryPages449_ImpressiveThemplate $obj
150
+ *
151
+ * @return bool
152
+ */
153
+ /*add_action('wbcr_factory_450_imppage_after_form_save', function ($plugin, $obj) {
154
+ $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
+
156
+ if( $is_rio ) {
157
+ WRIO_Cron::check();
158
+ }
159
+ }, 10, 2);*/
160
+
161
+ /**
162
+ * Виджет отзывов
163
+ *
164
+ * @param string $page_url
165
+ * @param string $plugin_name
166
+ *
167
+ * @return string
168
+ */
169
+ function wio_rating_widget_url( $page_url, $plugin_name ) {
170
+ if ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) {
171
+ return 'https://wordpress.org/support/plugin/robin-image-optimizer/reviews/#new-post';
172
+ }
173
+
174
+ return $page_url;
175
+ }
176
+
177
+ add_filter( 'wbcr_factory_pages_449_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_Factory450_Plugin $plugin
185
+ */
186
+ add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
+ if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
188
+ require_once WRIO_PLUGIN_DIR . '/admin/includes/sidebar-widgets.php';
189
+
190
+ if ( wrio_is_license_activate() ) {
191
+ unset( $widgets['donate_widget'] );
192
+
193
+ if ( $position == 'right' ) {
194
+ unset( $widgets['adverts_widget'] );
195
+ unset( $widgets['business_suggetion'] );
196
+ unset( $widgets['rating_widget'] );
197
+ unset( $widgets['info_widget'] );
198
+ }
199
+
200
+ /*if ( $position == 'bottom' ) {
201
+ $widgets['support'] = wrio_get_sidebar_support_widget();
202
+ }*/
203
+
204
+ return $widgets;
205
+ } else {
206
+ if ( $position == 'right' ) {
207
+ unset( $widgets['info_widget'] );
208
+ unset( $widgets['rating_widget'] );
209
+ //$widgets['support'] = wrio_get_sidebar_support_widget();
210
+ }
211
+ }
212
+
213
+ //if ( $position == 'bottom' ) {
214
+ //$widgets['donate_widget'] = wrio_get_sidebar_premium_widget();
215
+ //}
216
+ }
217
+
218
+ return $widgets;
219
+ }, 20, 3 );
220
+
221
+ /**
222
+ * Заменяет заголовок в рекламном виджете
223
+ *
224
+ * @param array $features
225
+ * @param string $plugin_name
226
+ * @param string $page_id
227
+ */
228
+ add_filter( 'wbcr/clearfy/pages/suggetion_title', function ( $features, $plugin_name, $page_id ) {
229
+ if ( ! empty( $plugin_name ) && ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) ) {
230
+ return __( "ROBIN IMAGE OPTIMIZER PRO", 'robin-image-optimizer' );
231
+ }
232
+
233
+ return $features;
234
+ }, 20, 3 );
235
+
236
+ /**
237
+ * Заменяем премиум возможности в рекламном виджете
238
+ *
239
+ * @param array $features
240
+ * @param string $plugin_name
241
+ * @param string $page_id
242
+ */
243
+ add_filter( 'wbcr/clearfy/pages/suggetion_features', function ( $features, $plugin_name, $page_id ) {
244
+ if ( ! empty( $plugin_name ) && ( $plugin_name == WRIO_Plugin::app()->getPluginName() ) ) {
245
+ $upgrade_feature = [];
246
+ $upgrade_feature[] = __( 'Automatic convertation in Webp', 'robin-image-optimizer' );
247
+ $upgrade_feature[] = __( 'You can optimize custom folders', 'robin-image-optimizer' );
248
+ $upgrade_feature[] = __( 'Support Nextgen gallery', 'robin-image-optimizer' );
249
+ $upgrade_feature[] = __( 'Multisite support', 'robin-image-optimizer' );
250
+ $upgrade_feature[] = __( 'Fast optimization servers', 'robin-image-optimizer' );
251
+ $upgrade_feature[] = __( 'No ads', 'robin-image-optimizer' );
252
+ $upgrade_feature[] = __( 'Best support', 'robin-image-optimizer' );
253
+
254
+ return $upgrade_feature;
255
+ }
256
+
257
+ return $features;
258
+ }, 20, 3 );
259
+
260
+ /**
261
+ * Заменяем премиум возможности в рекламном виджете
262
+ *
263
+ * @param array $messages
264
+ * @param string $type
265
+ * @param string $plugin_name
266
+ */
267
+ add_filter( 'wbcr/factory/premium/notice_text', function ( $text, $type, $plugin_name ) {
268
+ if ( WRIO_Plugin::app()->getPluginName() != $plugin_name ) {
269
+ return $text;
270
+ }
271
+
272
+ $license_page_url = WRIO_Plugin::app()->getPluginPageUrl( 'rio_license' );
273
+
274
+ if ( 'need_activate_license' == $type ) {
275
+ return sprintf( __( '<a href="%s">License activation</a> required. A license is required to get premium plugin updates, as well as to get additional services.', 'robin-image-optimizer' ), $license_page_url );
276
+ } else if ( 'need_renew_license' == $type ) {
277
+ return sprintf( __( 'Your <a href="%s">license</a> has expired. You can no longer get premium plugin updates, premium support and your access to Webcraftic services has been suspended.', 'robin-image-optimizer' ), $license_page_url );
278
+ }
279
+
280
+ return $text;
281
+ }, 10, 3 );
282
+
283
+ /**
284
+ * Отправка уведомлений и скором окончании квоты
285
+ * Уведомления создаются только если квота <= 100
286
+ *
287
+ * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
288
+ * @since 1.4.2
289
+ */
290
+ add_action( 'wbcr/factory/admin_notices', function ( $notices, $plugin_name ) {
291
+ if ( $plugin_name != WRIO_Plugin::app()->getPluginName() ) {
292
+ return $notices;
293
+ }
294
+
295
+ if ( WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' ) != 'server_5' ) {
296
+ return $notices;
297
+ }
298
+
299
+ $current_quota = WRIO_Plugin::app()->getOption( 'current_quota' );
300
+ if ( $current_quota > 100 ) {
301
+ return $notices;
302
+ }
303
+
304
+ $notice_text = __( 'The remainder of the quota is coming to an end. Remained credits: ' . $current_quota, 'robin_image_optimizer' );
305
+
306
+ $plugin_title = WRIO_Plugin::app()->getPluginTitle();
307
+ $notice_text = '<b>' . $plugin_title . '</b>: ' . $notice_text;
308
+ $notices[] = [
309
+ 'id' => 'wrio_remained_quota',
310
+ 'type' => 'warning',
311
+ 'dismissible' => true,
312
+ 'where' => [ 'plugins', 'dashboard', 'edit' ],
313
+ 'dismiss_expires' => time() + 3600 * 4,
314
+ 'text' => $notice_text,
315
+ ];
316
+
317
+ return $notices;
318
+ }, 10, 2 );
319
+
320
+ /**
321
+ * Отправка уведомлений и скором окончании квоты в Impressive
322
+ * Уведомления создаются только если квота <= 100
323
+ *
324
+ * @param Wbcr_Factory450_Plugin $plugin Экземпляр плагина, который передается в функцию обратного вызова
325
+ * @param Wbcr_FactoryPages449_ImpressiveThemplate $obj Экземпляр страницы, который передается в функцию обратного вызова
326
+ *
327
+ * @author Alexander Gorenkov <g.a.androidjc2@ya.ru>
328
+ * @since 1.4.2
329
+ */
330
+ add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugin, $obj ) {
331
+ if ( $plugin->getPluginName() != WRIO_Plugin::app()->getPluginName() ) {
332
+ return false;
333
+ }
334
+
335
+ if ( WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server' ) != 'server_5' ) {
336
+ return false;
337
+ }
338
+
339
+ $current_quota = WRIO_Plugin::app()->getOption( 'current_quota' );
340
+ if ( $current_quota > 100 ) {
341
+ return false;
342
+ }
343
+
344
+ $notice_text = __( 'The remainder of the quota is coming to an end. Remained credits: ' . $current_quota, 'robin_image_optimizer' );
345
+
346
+ $obj->printWarningNotice( $notice_text );
347
+ }, 10, 2 );
admin/includes/classes/class-rio-nextgen-landing.php CHANGED
@@ -1,61 +1,61 @@
1
- <?php
2
-
3
-
4
- // Exit if accessed directly
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- /**
10
- * Класс используется для вывода страницы лендинга
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WIO_NextgenLanding {
16
-
17
- /**
18
- * Инициализация лендинга
19
- */
20
- public function __construct() {
21
- add_action( 'admin_menu', array( $this, 'removeSubMenu' ), 99999 );
22
- add_action( 'admin_menu', array( $this, 'addSubMenu' ), 20 );
23
- }
24
-
25
- /**
26
- * Удаляет лендинг nextgen
27
- */
28
- public function removeSubMenu() {
29
- remove_submenu_page( 'nextgen-gallery', 'ngg_imagify' );
30
- }
31
-
32
- /**
33
- * Добавляем свою страницу в меню Тextgen
34
- */
35
- public function addSubMenu() {
36
- add_submenu_page(
37
- 'nextgen-gallery',
38
- __( 'Image optimizer', 'robin-image-optimizer' ),
39
- __( 'Image optimizer', 'robin-image-optimizer' ),
40
- 'manage_options',
41
- 'ngg_robin', // если взять старый слаг ngg_imagify, то на странице выведет оба лендинга
42
- array( $this, 'nngLandingPage' )
43
- );
44
- }
45
-
46
- /**
47
- * Контент лендинга
48
- */
49
- public function nngLandingPage() {
50
- // если активна премиум версия - делаем редирект на страницу статистики nextgen
51
- if ( defined( 'WRIOP_PLUGIN_ACTIVE' ) && WRIOP_PLUGIN_ACTIVE ) {
52
- wp_redirect( admin_url( 'admin.php?page=io_nextgen_gallery_statistic-wbcr_image_optimizer' ) );
53
- die();
54
- }
55
- ?>
56
- рекламма установки премиум аддона
57
- <?php
58
- }
59
- }
60
-
61
- new WIO_NextgenLanding;
1
+ <?php
2
+
3
+
4
+ // Exit if accessed directly
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Класс используется для вывода страницы лендинга
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WIO_NextgenLanding {
16
+
17
+ /**
18
+ * Инициализация лендинга
19
+ */
20
+ public function __construct() {
21
+ add_action( 'admin_menu', array( $this, 'removeSubMenu' ), 99999 );
22
+ add_action( 'admin_menu', array( $this, 'addSubMenu' ), 20 );
23
+ }
24
+
25
+ /**
26
+ * Удаляет лендинг nextgen
27
+ */
28
+ public function removeSubMenu() {
29
+ remove_submenu_page( 'nextgen-gallery', 'ngg_imagify' );
30
+ }
31
+
32
+ /**
33
+ * Добавляем свою страницу в меню Тextgen
34
+ */
35
+ public function addSubMenu() {
36
+ add_submenu_page(
37
+ 'nextgen-gallery',
38
+ __( 'Image optimizer', 'robin-image-optimizer' ),
39
+ __( 'Image optimizer', 'robin-image-optimizer' ),
40
+ 'manage_options',
41
+ 'ngg_robin', // если взять старый слаг ngg_imagify, то на странице выведет оба лендинга
42
+ array( $this, 'nngLandingPage' )
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Контент лендинга
48
+ */
49
+ public function nngLandingPage() {
50
+ // если активна премиум версия - делаем редирект на страницу статистики nextgen
51
+ if ( defined( 'WRIOP_PLUGIN_ACTIVE' ) && WRIOP_PLUGIN_ACTIVE ) {
52
+ wp_redirect( admin_url( 'admin.php?page=io_nextgen_gallery_statistic-wbcr_image_optimizer' ) );
53
+ die();
54
+ }
55
+ ?>
56
+ рекламма установки премиум аддона
57
+ <?php
58
+ }
59
+ }
60
+
61
+ new WIO_NextgenLanding;
admin/includes/classes/class-rio-optimize-template.php CHANGED
@@ -1,226 +1,263 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * Класс реализует шаблон блока статистики
9
- *
10
- * @author Eugene Jokerov <jokerov@gmail.com>
11
- * @copyright (c) 2018, Webcraftic
12
- * @version 1.0
13
- */
14
- class WIO_OptimizePageTemplate {
15
-
16
- /**
17
- * Тип страницы
18
- */
19
- protected $page_type = 'media-library';
20
-
21
-
22
- public function __construct( $type = 'media-library' ) {
23
- $this->page_type = $type;
24
- }
25
-
26
- /**
27
- * Выводит контент страницы с учётом мультисайта
28
- *
29
- * @param Wbcr_FactoryClearfy237_PageBase $page
30
- *
31
- * @throws Exception
32
- */
33
-
34
- /*public function showPageContent( Wbcr_FactoryClearfy237_PageBase $page ) {
35
- do_action( 'wbcr/rio/multisite_current_blog' );
36
- $this->pageContent( $page );
37
- do_action( 'wbcr/rio/multisite_restore_blog' );
38
- }*/
39
-
40
- /**
41
- * Выбор сайта для мультисайт режима
42
- *
43
- */
44
- /*public function selectSite() {
45
- if ( ! WRIO_Plugin::app()->isNetworkAdmin() ) {
46
- return;
47
- }
48
- $blogs = WIO_Multisite::getBlogs( $this->page_type );
49
- $current_blog = WRIO_Plugin::app()->getPopulateOption( 'current_blog', 1 );
50
- ?>
51
- <select style="width:200px;display:inline-block; height: 45px; margin-left:40px;" id="wbcr-rio-current-blog"
52
- class="factory-dropdown factory-from-control-dropdown form-control"
53
- data-context="<?php echo esc_attr( $this->page_type ); ?>"
54
- data-nonce="<?php echo wp_create_nonce( 'update_blog_id' ); ?>">
55
- <?php foreach ( $blogs as $blog ) : ?>
56
- <?php
57
- $blog_name = $blog->domain . $blog->path;
58
- if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
59
- $blog_name = $blog->domain;
60
- }
61
- ?>
62
- <option <?php selected( $current_blog, $blog->blog_id ); ?>
63
- value="<?php echo esc_attr( $blog->blog_id ); ?>"><?php echo esc_attr( $blog_name ); ?></option>
64
- <?php endforeach; ?>
65
- </select>
66
- <?php
67
- }*/
68
-
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
93
- */
94
- public function getMediaColumnTemplate( $params ) {
95
- ob_start();
96
-
97
- $ajaxActionOptimize = apply_filters( 'wbcr/rio/optimize_template/reoptimize_ajax_action', 'wio_reoptimize_image', $this->page_type );
98
- $ajaxActionRestore = apply_filters( 'wbcr/rio/optimize_template/restore_ajax_action', 'wio_restore_image', $this->page_type );
99
-
100
- $attachment_id = $params['attachment_id'];
101
- $is_optimized = $params['is_optimized'];
102
- $attach_dimensions = $params['attach_dimensions'];
103
- $attachment_file_size = $params['attachment_file_size'];
104
- $is_skipped = $params['is_skipped'];
105
-
106
- if ( $is_skipped ) {
107
- return ob_get_clean();
108
- }
109
-
110
- if ( $is_optimized ) {
111
- $original_main_size = $params['original_main_size'];
112
- $thumbnails_optimized = $params['thumbnails_optimized'];
113
- $optimization_level = $params['optimization_level'];
114
- $error_msg = $params['error_msg'];
115
- $backuped = $params['backuped'];
116
- $diff_percent = $params['diff_percent'];
117
- $diff_percent_all = $params['diff_percent_all'];
118
-
119
- ?>
120
- <ul class="wio-datas-list" data-size="<?php echo esc_attr( size_format( $attachment_file_size ) ); ?>"
121
- data-dimensions="<?php echo esc_attr( $attach_dimensions ); ?>">
122
- <li class="wio-data-item"><span
123
- class="data"><?php _e( 'New Filesize:', 'robin-image-optimizer' ); ?></span>
124
- <strong class="big"><?php echo esc_attr( size_format( $attachment_file_size ) ); ?></strong></li>
125
- <li class="wio-data-item">
126
- <span class="data"><?php _e( 'Original Saving:', 'robin-image-optimizer' ); ?></span>
127
- <strong>
128
- <span class="wio-chart-value"><?php echo esc_attr( $diff_percent ); ?></span>%
129
- </strong>
130
- </li>
131
- <li class="wio-data-item">
132
- <span class="data"><?php _e( 'Original Filesize:', 'robin-image-optimizer' ); ?></span>
133
- <strong class="original"><?php echo esc_attr( size_format( $original_main_size ) ); ?></strong>
134
- </li>
135
- <li class="wio-data-item"><span class="data"><?php _e( 'Level:', 'robin-image-optimizer' ); ?></span>
136
- <strong>
137
- <?php
138
- if ( ! $error_msg ) {
139
- // если уровень кастомный от 1 до 100
140
- if ( is_numeric( $optimization_level ) ) {
141
- echo __( 'Custom', 'robin-image-optimizer' ) . ' ' . intval( $optimization_level ) . '%';
142
- } else {
143
- // если уровень один из настроек
144
- if ( $optimization_level == 'normal' ) {
145
- echo __( 'lossless', 'robin-image-optimizer' );
146
- } else if ( $optimization_level == 'aggresive' ) {
147
- echo __( 'lossy', 'robin-image-optimizer' );
148
- } else {
149
- echo __( 'High', 'robin-image-optimizer' );
150
- }
151
- }
152
- }
153
- ?>
154
- </strong>
155
- </li>
156
- <li class="wio-data-item">
157
- <span class="data"><?php _e( 'Thumbnails Optimized:', 'robin-image-optimizer' ); ?></span>
158
- <strong class="original"><?php echo intval( $thumbnails_optimized ); ?></strong>
159
- </li>
160
- <li class="wio-data-item">
161
- <span class="data"><?php _e( 'Overall Saving:', 'robin-image-optimizer' ); ?></span>
162
- <strong class="original"><?php echo esc_attr( $diff_percent_all ); ?>%</strong>
163
- </li>
164
- <?php if ( $error_msg ) : ?>
165
- <li class="wio-data-item">
166
- <span class="data"><?php _e( 'Error Message:', 'robin-image-optimizer' ); ?></span>
167
- <strong><?php echo esc_attr( $error_msg ); ?></strong></li>
168
- <?php endif; ?>
169
- </ul>
170
- <div class="wio-datas-actions-links" style="display:inline;">
171
- <?php if ( $optimization_level != 'normal' ) : ?>
172
- <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
173
- data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level="normal" href="#"
174
- class="wio-reoptimize button-wio-manual-override-upload"
175
- data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
176
- <span class="dashicons dashicons-admin-generic"></span><span
177
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossless', 'robin-image-optimizer' ); ?>
178
- <span class="wio-hide-if-small"></span>
179
- </a>
180
- <?php endif; ?>
181
- <?php if ( $optimization_level != 'aggresive' ) : ?>
182
- <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
183
- data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level="aggresive" href="#"
184
- class="wio-reoptimize button-wio-manual-override-upload"
185
- data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
186
- <span class="dashicons dashicons-admin-generic"></span><span
187
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossy', 'robin-image-optimizer' ); ?>
188
- <span class="wio-hide-if-small"></span>
189
- </a>
190
- <?php endif; ?>
191
- <?php if ( $optimization_level != 'ultra' ) : ?>
192
- <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
193
- data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level="ultra" href="#"
194
- class="wio-reoptimize button-wio-manual-override-upload"
195
- data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
196
- <span class="dashicons dashicons-admin-generic"></span><span
197
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'High', 'robin-image-optimizer' ); ?>
198
- <span class="wio-hide-if-small"></span>
199
- </a>
200
- <?php endif; ?>
201
- <?php if ( $backuped ) : ?>
202
- <a href="#" data-action="<?php echo esc_attr( $ajaxActionRestore ); ?>"
203
- data-id="<?php echo esc_attr( $attachment_id ); ?>"
204
- class="button-wio-restore attachment-has-backup"
205
- data-waiting-label="<?php _e( 'Recovery in progress', 'robin-image-optimizer' ); ?>"><span
206
- class="dashicons dashicons-image-rotate"></span><?php _e( 'Restore original', 'robin-image-optimizer' ); ?>
207
- </a>
208
- <?php endif; ?>
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=""
216
- class="wio-reoptimize button button-primary button-large"
217
- data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>"
218
- data-size="<?php echo esc_attr( size_format( $attachment_file_size ) ); ?>"
219
- data-dimensions="<?php echo esc_attr( $attach_dimensions ); ?>"><?php _e( 'Optimize', 'robin-image-optimizer' ); ?></button>
220
- <?php
221
- }
222
-
223
- return ob_get_clean();
224
- }
225
-
226
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Класс реализует шаблон блока статистики
9
+ *
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_OptimizePageTemplate {
15
+
16
+ /**
17
+ * Тип страницы
18
+ */
19
+ protected $page_type = 'media-library';
20
+
21
+
22
+ public function __construct( $type = 'media-library' ) {
23
+ $this->page_type = $type;
24
+ }
25
+
26
+ /**
27
+ * Выводит контент страницы с учётом мультисайта
28
+ *
29
+ * @param WRIO_Page $page
30
+ *
31
+ * @throws Exception
32
+ */
33
+
34
+ /*public function showPageContent( WRIO_Page $page ) {
35
+ do_action( 'wbcr/rio/multisite_current_blog' );
36
+ $this->pageContent( $page );
37
+ do_action( 'wbcr/rio/multisite_restore_blog' );
38
+ }*/
39
+
40
+ /**
41
+ * Выбор сайта для мультисайт режима
42
+ *
43
+ */
44
+ /*public function selectSite() {
45
+ if ( ! WRIO_Plugin::app()->isNetworkAdmin() ) {
46
+ return;
47
+ }
48
+ $blogs = WIO_Multisite::getBlogs( $this->page_type );
49
+ $current_blog = WRIO_Plugin::app()->getPopulateOption( 'current_blog', 1 );
50
+ ?>
51
+ <select style="width:200px;display:inline-block; height: 45px; margin-left:40px;" id="wbcr-rio-current-blog"
52
+ class="factory-dropdown factory-from-control-dropdown form-control"
53
+ data-context="<?php echo esc_attr( $this->page_type ); ?>"
54
+ data-nonce="<?php echo wp_create_nonce( 'update_blog_id' ); ?>">
55
+ <?php foreach ( $blogs as $blog ) : ?>
56
+ <?php
57
+ $blog_name = $blog->domain . $blog->path;
58
+ if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
59
+ $blog_name = $blog->domain;
60
+ }
61
+ ?>
62
+ <option <?php selected( $current_blog, $blog->blog_id ); ?>
63
+ value="<?php echo esc_attr( $blog->blog_id ); ?>"><?php echo esc_attr( $blog_name ); ?></option>
64
+ <?php endforeach; ?>
65
+ </select>
66
+ <?php
67
+ }*/
68
+
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
93
+ */
94
+ public function getMediaColumnTemplate( $params ) {
95
+ ob_start();
96
+
97
+ $ajaxActionOptimize = apply_filters( 'wbcr/rio/optimize_template/reoptimize_ajax_action', 'wio_reoptimize_image', $this->page_type );
98
+ $ajaxActionConvert = apply_filters( 'wbcr/rio/optimize_template/convert_ajax_action', 'wio_convert_image', $this->page_type );
99
+ $ajaxActionRestore = apply_filters( 'wbcr/rio/optimize_template/restore_ajax_action', 'wio_restore_image', $this->page_type );
100
+
101
+ $attachment_id = $params['attachment_id'];
102
+ $is_optimized = $params['is_optimized'];
103
+ $attach_dimensions = $params['attach_dimensions'];
104
+ $attachment_file_size = $params['attachment_file_size'];
105
+ $is_skipped = $params['is_skipped'];
106
+ $webp_size = $params['webp_size'];
107
+
108
+ if ( $is_skipped ) {
109
+ return ob_get_clean();
110
+ }
111
+
112
+ if ( $is_optimized ) {
113
+ $original_main_size = $params['original_main_size'];
114
+ $thumbnails_optimized = $params['thumbnails_optimized'];
115
+ $optimization_level = $params['optimization_level'];
116
+ $error_msg = $params['error_msg'];
117
+ $backuped = $params['backuped'];
118
+ $diff_percent = $params['diff_percent'];
119
+ $diff_percent_all = $params['diff_percent_all'];
120
+
121
+ ?>
122
+ <ul class="wio-datas-list" data-size="<?php echo esc_attr( size_format( $attachment_file_size ) ); ?>"
123
+ data-dimensions="<?php echo esc_attr( $attach_dimensions ); ?>">
124
+ <li class="wio-data-item"><span
125
+ class="data"><?php _e( 'New Filesize:', 'robin-image-optimizer' ); ?></span>
126
+ <strong class="big"><?php echo esc_attr( size_format( $attachment_file_size, 1 ) ); ?></strong></li>
127
+ <li class="wio-data-item"><span
128
+ class="data"><?php _e( 'WebP Filesize:', 'robin-image-optimizer' ); ?></span>
129
+ <strong class="big"><?php echo esc_attr( size_format( $webp_size, 1 ) ); ?></strong></li>
130
+ <li class="wio-data-item">
131
+ <span class="data"><?php _e( 'Original Saving:', 'robin-image-optimizer' ); ?></span>
132
+ <strong>
133
+ <span class="wio-chart-value"><?php echo esc_attr( $diff_percent ); ?></span>%
134
+ </strong>
135
+ </li>
136
+ <li class="wio-data-item">
137
+ <span class="data"><?php _e( 'Original Filesize:', 'robin-image-optimizer' ); ?></span>
138
+ <strong class="original"><?php echo esc_attr( size_format( $original_main_size, 1 ) ); ?></strong>
139
+ </li>
140
+ <li class="wio-data-item"><span class="data"><?php _e( 'Level:', 'robin-image-optimizer' ); ?></span>
141
+ <strong>
142
+ <?php
143
+ if ( ! $error_msg ) {
144
+ // если уровень кастомный от 1 до 100
145
+ if ( is_numeric( $optimization_level ) ) {
146
+ echo __( 'Custom', 'robin-image-optimizer' ) . ' ' . intval( $optimization_level ) . '%';
147
+ } else {
148
+ // если уровень один из настроек
149
+ if ( $optimization_level == 'normal' ) {
150
+ echo __( 'lossless', 'robin-image-optimizer' );
151
+ } else if ( $optimization_level == 'aggresive' ) {
152
+ echo __( 'lossy', 'robin-image-optimizer' );
153
+ } else {
154
+ echo __( 'High', 'robin-image-optimizer' );
155
+ }
156
+ }
157
+ }
158
+ ?>
159
+ </strong>
160
+ </li>
161
+ <li class="wio-data-item">
162
+ <span class="data"><?php _e( 'Thumbnails Optimized:', 'robin-image-optimizer' ); ?></span>
163
+ <strong class="original"><?php echo intval( $thumbnails_optimized ); ?></strong>
164
+ </li>
165
+ <li class="wio-data-item">
166
+ <span class="data"><?php _e( 'Overall Saving:', 'robin-image-optimizer' ); ?></span>
167
+ <strong class="original"><?php echo esc_attr( $diff_percent_all ); ?>%</strong>
168
+ </li>
169
+ <?php if ( $error_msg ) : ?>
170
+ <li class="wio-data-item">
171
+ <span class="data"><?php _e( 'Error Message:', 'robin-image-optimizer' ); ?></span>
172
+ <strong><?php echo esc_attr( $error_msg ); ?></strong></li>
173
+ <?php endif; ?>
174
+ </ul>
175
+ <div class="wio-datas-actions-links" style="display:inline;">
176
+ <?php if ( $optimization_level != 'normal' ) : ?>
177
+ <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
178
+ data-id="<?php echo esc_attr( $attachment_id ); ?>"
179
+ data-level="normal"
180
+ data-nonce="<?php echo wp_create_nonce('reoptimize'); ?>"
181
+ href="#"
182
+ class="wio-reoptimize button-wio-manual-override-upload"
183
+ data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
184
+ <span class="dashicons dashicons-admin-generic"></span><span
185
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossless', 'robin-image-optimizer' ); ?>
186
+ <span class="wio-hide-if-small"></span>
187
+ </a>
188
+ <?php endif; ?>
189
+ <?php if ( $optimization_level != 'aggresive' ) : ?>
190
+ <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
191
+ data-id="<?php echo esc_attr( $attachment_id ); ?>"
192
+ data-level="aggresive"
193
+ data-nonce="<?php echo wp_create_nonce('reoptimize'); ?>"
194
+ href="#"
195
+ class="wio-reoptimize button-wio-manual-override-upload"
196
+ data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
197
+ <span class="dashicons dashicons-admin-generic"></span><span
198
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossy', 'robin-image-optimizer' ); ?>
199
+ <span class="wio-hide-if-small"></span>
200
+ </a>
201
+ <?php endif; ?>
202
+ <?php if ( $optimization_level != 'ultra' ) : ?>
203
+ <a data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
204
+ data-id="<?php echo esc_attr( $attachment_id ); ?>"
205
+ data-level="ultra"
206
+ data-nonce="<?php echo wp_create_nonce('reoptimize'); ?>"
207
+ href="#"
208
+ class="wio-reoptimize button-wio-manual-override-upload"
209
+ data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
210
+ <span class="dashicons dashicons-admin-generic"></span><span
211
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'High', 'robin-image-optimizer' ); ?>
212
+ <span class="wio-hide-if-small"></span>
213
+ </a>
214
+ <?php endif; ?>
215
+ <?php if ( $backuped ) : ?>
216
+ <a href="#" data-action="<?php echo esc_attr( $ajaxActionRestore ); ?>"
217
+ data-id="<?php echo esc_attr( $attachment_id ); ?>"
218
+ data-nonce="<?php echo wp_create_nonce('restore'); ?>"
219
+ class="button-wio-restore attachment-has-backup"
220
+ data-waiting-label="<?php _e( 'Recovery in progress', 'robin-image-optimizer' ); ?>"><span
221
+ class="dashicons dashicons-image-rotate"></span><?php _e( 'Restore original', 'robin-image-optimizer' ); ?>
222
+ </a>
223
+ <?php endif; ?>
224
+ </div>
225
+ <!-- .wio-datas-actions-links -->
226
+ <?php
227
+ } elseif ( $attach_dimensions !== '0 x 0' ) {
228
+ if ( $webp_size ) {
229
+ ?>
230
+ <ul class="wio-datas-list">
231
+ <li class="wio-data-item">
232
+ <span class="data"><?php _e( 'WebP Filesize:', 'robin-image-optimizer' ); ?></span>
233
+ <strong class="big"><?php echo esc_attr( size_format( $webp_size, 1 ) ); ?></strong>
234
+ </li>
235
+ </ul>
236
+ <?php
237
+ }
238
+ ?>
239
+ <button type="button" data-action="<?php echo esc_attr( $ajaxActionOptimize ); ?>"
240
+ data-nonce="<?php echo wp_create_nonce( 'reoptimize' ); ?>"
241
+ data-id="<?php echo esc_attr( $attachment_id ); ?>" data-level=""
242
+ class="wio-reoptimize button button-primary button-large"
243
+ data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>"
244
+ data-size="<?php echo esc_attr( size_format( $attachment_file_size ) ); ?>"
245
+ data-dimensions="<?php echo esc_attr( $attach_dimensions ); ?>"><?php _e( 'Optimize', 'robin-image-optimizer' ); ?></button>
246
+ <?php
247
+ if ( ! $webp_size && wrio_is_license_activate() ) {
248
+ ?>
249
+ <button type="button" data-action="<?php echo esc_attr( $ajaxActionConvert ); ?>"
250
+ data-nonce="<?php echo wp_create_nonce( 'convert' ); ?>"
251
+ data-id="<?php echo esc_attr( $attachment_id ); ?>"
252
+ class="wio-convert button button-primary button-large"
253
+ data-waiting-label="<?php _e( 'Convert in progress', 'robin-image-optimizer' ); ?>"
254
+ data-size="<?php echo esc_attr( size_format( $attachment_file_size ) ); ?>"
255
+ data-dimensions="<?php echo esc_attr( $attach_dimensions ); ?>"><?php _e( 'Convert to WebP', 'robin-image-optimizer' ); ?></button>
256
+ <?php
257
+ }
258
+ }
259
+
260
+ return ob_get_clean();
261
+ }
262
+
263
+ }
admin/includes/classes/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/includes/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/includes/sidebar-widgets.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
- /**
3
- * Sidebar widgets
4
- *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>
6
- * @copyright (c) 01.12.2018, Webcraftic
7
- * @version 1.0
8
- */
9
-
10
- /**
11
- * Return premium widget markup
12
- *
13
- * @return string
14
- */
15
- function wrio_get_sidebar_premium_widget() {
16
-
17
- $purchase_url = WRIO_Plugin::app()->get_support()->get_pricing_url( true, 'license_page' );
18
- $upgrade_price = WRIO_Plugin::app()->premium->get_price();
19
-
20
- ob_start();
21
- ?>
22
- <div id="wbcr-clr-go-to-premium-widget" class="wbcr-factory-sidebar-widget">
23
- <p>
24
- <strong><?php _e( 'Activate Robin image optimizer pro', 'robin-image-optimizer' ); ?></strong>
25
- </p>
26
- <div class="wbcr-clr-go-to-premium-widget-body">
27
- <p><?php _e( '<b>Clearfy Business</b> is a paid package of components for the popular free WordPress plugin named Clearfy. You get access to all paid components at one price.', 'wrio-image-optimizer' ) ?></p>
28
- <p><?php _e( 'Paid license guarantees that you can download and update existing and future paid components of the plugin.', 'robin-image-optimizer' ) ?></p>
29
- <a href="<?= $purchase_url ?>" class="wbcr-clr-purchase-premium" target="_blank" rel="noopener">
30
- <span class="btn btn-gold btn-inner-wrap">
31
- <?php printf( __( 'Upgrade to Clearfy Business for $%s', 'robin-image-optimizer' ), $upgrade_price ) ?>
32
- </span>
33
- </a>
34
- </div>
35
- </div>
36
- <?php
37
-
38
- $output = ob_get_contents();
39
-
40
- ob_end_clean();
41
-
42
- return $output;
43
- }
44
-
45
- /**
46
- * Return support widget markup
47
- *
48
- * @return string
49
- */
50
- function wrio_get_sidebar_support_widget() {
51
-
52
- //$free_support_url = WRIO_Plugin::app()->get_support()->get_contacts_url( true, 'support_widget' );
53
- //$hot_support_url = WRIO_Plugin::app()->get_support()->get_tracking_page_url( 'hot-support', 'support_widget' );
54
-
55
- $support_url = "https://webcraftic.com/support/";
56
-
57
- ob_start();
58
- ?>
59
- <div id="wbcr-clr-support-widget" class="wbcr-factory-sidebar-widget">
60
- <p><strong><?php _e( 'Having Issues?', 'robin-image-optimizer' ); ?></strong></p>
61
- <div class="wbcr-clr-support-widget-body">
62
- <p>
63
- <?php _e( 'We provide free support for this plugin. If you are pushed with a problem, just create a new ticket. We will definitely help you!', 'robin-image-optimizer' ); ?>
64
- </p>
65
- <ul>
66
- <li><span class="dashicons dashicons-sos"></span>
67
- <a href="<?= $support_url ?>" target="_blank" rel="noopener"><?php _e( 'Get starting free support', 'robin-image-optimizer' ); ?></a>
68
- </li>
69
- <li style="margin-top: 15px;background: #fff4f1;padding: 10px;color: #a58074;">
70
- <span class="dashicons dashicons-warning"></span>
71
- <?php printf( __( 'If you find a php error or a vulnerability in plugin, you can <a href="%s" target="_blank" rel="noopener">create ticket</a> in hot support that we responded instantly.', 'wrio-image-optimizer' ), $support_url ); ?>
72
- </li>
73
- </ul>
74
- </div>
75
- </div>
76
- <?php
77
-
78
- $output = ob_get_contents();
79
-
80
- ob_end_clean();
81
-
82
- return $output;
83
- }
1
+ <?php
2
+ /**
3
+ * Sidebar widgets
4
+ *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
6
+ * @copyright (c) 01.12.2018, Webcraftic
7
+ * @version 1.0
8
+ */
9
+
10
+ /**
11
+ * Return premium widget markup
12
+ *
13
+ * @return string
14
+ */
15
+ function wrio_get_sidebar_premium_widget() {
16
+
17
+ $purchase_url = WRIO_Plugin::app()->get_support()->get_pricing_url( true, 'license_page' );
18
+ $upgrade_price = WRIO_Plugin::app()->premium->get_price();
19
+
20
+ ob_start();
21
+ ?>
22
+ <div id="wbcr-clr-go-to-premium-widget" class="wbcr-factory-sidebar-widget">
23
+ <p>
24
+ <strong><?php _e( 'Activate Robin image optimizer pro', 'robin-image-optimizer' ); ?></strong>
25
+ </p>
26
+ <div class="wbcr-clr-go-to-premium-widget-body">
27
+ <p><?php _e( '<b>Clearfy Business</b> is a paid package of components for the popular free WordPress plugin named Clearfy. You get access to all paid components at one price.', 'wrio-image-optimizer' ) ?></p>
28
+ <p><?php _e( 'Paid license guarantees that you can download and update existing and future paid components of the plugin.', 'robin-image-optimizer' ) ?></p>
29
+ <a href="<?= $purchase_url ?>" class="wbcr-clr-purchase-premium" target="_blank" rel="noopener">
30
+ <span class="btn btn-gold btn-inner-wrap">
31
+ <?php printf( __( 'Upgrade to Clearfy Business for $%s', 'robin-image-optimizer' ), $upgrade_price ) ?>
32
+ </span>
33
+ </a>
34
+ </div>
35
+ </div>
36
+ <?php
37
+
38
+ $output = ob_get_contents();
39
+
40
+ ob_end_clean();
41
+
42
+ return $output;
43
+ }
44
+
45
+ /**
46
+ * Return support widget markup
47
+ *
48
+ * @return string
49
+ */
50
+ function wrio_get_sidebar_support_widget() {
51
+
52
+ //$free_support_url = WRIO_Plugin::app()->get_support()->get_contacts_url( true, 'support_widget' );
53
+ //$hot_support_url = WRIO_Plugin::app()->get_support()->get_tracking_page_url( 'hot-support', 'support_widget' );
54
+
55
+ $support_url = "https://webcraftic.com/support/";
56
+
57
+ ob_start();
58
+ ?>
59
+ <div id="wbcr-clr-support-widget" class="wbcr-factory-sidebar-widget">
60
+ <p><strong><?php _e( 'Having Issues?', 'robin-image-optimizer' ); ?></strong></p>
61
+ <div class="wbcr-clr-support-widget-body">
62
+ <p>
63
+ <?php _e( 'We provide free support for this plugin. If you are pushed with a problem, just create a new ticket. We will definitely help you!', 'robin-image-optimizer' ); ?>
64
+ </p>
65
+ <ul>
66
+ <li><span class="dashicons dashicons-sos"></span>
67
+ <a href="<?= $support_url ?>" target="_blank" rel="noopener"><?php _e( 'Get starting free support', 'robin-image-optimizer' ); ?></a>
68
+ </li>
69
+ <li style="margin-top: 15px;background: #fff4f1;padding: 10px;color: #a58074;">
70
+ <span class="dashicons dashicons-warning"></span>
71
+ <?php printf( __( 'If you find a php error or a vulnerability in plugin, you can <a href="%s" target="_blank" rel="noopener">create ticket</a> in hot support that we responded instantly.', 'wrio-image-optimizer' ), $support_url ); ?>
72
+ </li>
73
+ </ul>
74
+ </div>
75
+ </div>
76
+ <?php
77
+
78
+ $output = ob_get_contents();
79
+
80
+ ob_end_clean();
81
+
82
+ return $output;
83
+ }
admin/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
admin/pages/class-rio-license.php CHANGED
@@ -1,126 +1,126 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * Class WRIOP_License
9
- *
10
- * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
- */
12
- class WRIO_License_Page extends Wbcr_FactoryClearfy237_LicensePage {
13
-
14
- /**
15
- * {@inheritdoc}
16
- */
17
- public $id = 'rio_license';
18
-
19
- /**
20
- * {@inheritdoc}
21
- */
22
- public $page_parent_page = null;
23
-
24
- /**
25
- * {@inheritdoc}
26
- */
27
- public $available_for_multisite = true;
28
-
29
- /**
30
- * {@inheritdoc}
31
- */
32
- public $clearfy_collaboration = false;
33
-
34
- /**
35
- * {@inheritdoc}
36
- */
37
- public $show_right_sidebar_in_options = true;
38
-
39
- /**
40
- * {@inheritdoc}
41
- */
42
- public $page_menu_position = 0;
43
-
44
- /**
45
- * {@inheritdoc}
46
- * @param Wbcr_Factory446_Plugin $plugin
47
- */
48
- public function __construct( Wbcr_Factory446_Plugin $plugin ) {
49
- $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
- $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
-
52
- $this->plan_name = __( 'Robin image optimizer Premium', 'robin-image-optimizer' );
53
-
54
- if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
55
- if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
56
- $this->clearfy_collaboration = true;
57
- }
58
- } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
59
- $this->clearfy_collaboration = true;
60
- }
61
-
62
- parent::__construct( $plugin );
63
-
64
- /**
65
- * Adds a new plugin card to license components page
66
- *
67
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
68
- * @since 1.3.0
69
- */
70
- add_filter( 'wbcr/clearfy/license/list_components', function ( $components ) {
71
- $title = 'Free';
72
- $icon = 'rio-premium-icon-256x256--lock.png';
73
- $description = "";
74
-
75
- if ( wrio_is_license_activate() ) {
76
- $title = 'Premium';
77
- $icon = 'rio-premium-icon-256x256--default.png';
78
- //$description = "Key: " . wrio_get_license_key();
79
- }
80
-
81
- $components[] = [
82
- 'name' => 'robin_image_optimizer',
83
- 'title' => sprintf( __( 'Robin image optimizer [%s]', 'clearfy' ), $title ),
84
- 'url' => 'https://wordpress.org/plugins/robin-image-optimizer/',
85
- 'type' => 'wordpress',
86
- 'build' => $this->is_premium ? 'premium' : 'free',
87
- 'key' => $this->get_hidden_license_key(),
88
- 'plan' => $this->get_plan(),
89
- 'expiration_days' => $this->get_expiration_days(),
90
- 'quota' => $this->is_premium ? $this->premium_license->get_count_active_sites() . ' ' . __( 'of', 'clearfy' ) . ' ' . $this->premium_license->get_sites_quota() : null,
91
- 'subscription' => $this->is_premium && $this->premium_has_subscription ? sprintf( __( 'Automatic renewal, every %s', '' ), esc_attr( $this->get_billing_cycle_readable() ) ) : null,
92
- 'base_path' => 'robin-image-optimizer/robin-image-optimizer.php',
93
- 'icon' => WCL_PLUGIN_URL . '/admin/assets/img/' . $icon,
94
- 'description' => $description . __( 'Public License is a GPLv3 compatible license allowing you to change and use this version of the plugin for free. Please keep in mind this license covers only free edition of the plugin. Premium versions are distributed with other type of a license.', 'clearfy' ),
95
- 'license_page_id' => 'rio_license'
96
- ];
97
-
98
- return $components;
99
- } );
100
- }
101
-
102
- /**
103
- * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
104
- * Меню текущего плагина будет добавлено в общее меню Clearfy
105
- *
106
- * @return string
107
- */
108
- public function getMenuScope() {
109
- if ( $this->clearfy_collaboration ) {
110
- //$this->page_parent_page = 'rio_general';
111
- $this->page_parent_page = 'none';
112
-
113
- return 'wbcr_clearfy';
114
- }
115
-
116
- return $this->plugin->getPluginName();
117
- }
118
-
119
- public function get_plan_description() {
120
- //$paragraf1 = sprintf( __( '<b>%s</b> is a premium image optimization plugin for WordPress. ', 'robin-image-optimizer' ), $this->plan_name ) . '</p>';
121
- //$paragraf2 = '<p style="font-size: 16px;">' . __( 'Paid license guarantees that you can optimize images under better conditions and WebP support.', 'robin-image-optimizer' );
122
- //return '<p style="font-size: 16px;">' . $paragraf1 . '</p><p style="font-size: 16px;">' . $paragraf2 . '</p>';
123
-
124
- //return '<p style="font-size: 16px;">' . $paragraf1 . '</p>';
125
- }
126
  }
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Class WRIOP_License
9
+ *
10
+ * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
+ */
12
+ class WRIO_License_Page extends WBCR\Factory_Templates_102\Pages\License {
13
+
14
+ /**
15
+ * {@inheritdoc}
16
+ */
17
+ public $id = 'rio_license';
18
+
19
+ /**
20
+ * {@inheritdoc}
21
+ */
22
+ public $page_parent_page = null;
23
+
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public $available_for_multisite = true;
28
+
29
+ /**
30
+ * {@inheritdoc}
31
+ */
32
+ public $clearfy_collaboration = false;
33
+
34
+ /**
35
+ * {@inheritdoc}
36
+ */
37
+ public $show_right_sidebar_in_options = true;
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ public $page_menu_position = 0;
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ * @param Wbcr_Factory450_Plugin $plugin
47
+ */
48
+ public function __construct( Wbcr_Factory450_Plugin $plugin ) {
49
+ $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
+ $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
+
52
+ $this->plan_name = __( 'Robin image optimizer Premium', 'robin-image-optimizer' );
53
+
54
+ if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
55
+ if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
56
+ $this->clearfy_collaboration = true;
57
+ }
58
+ } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
59
+ $this->clearfy_collaboration = true;
60
+ }
61
+
62
+ parent::__construct( $plugin );
63
+
64
+ /**
65
+ * Adds a new plugin card to license components page
66
+ *
67
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
68
+ * @since 1.3.0
69
+ */
70
+ add_filter( 'wbcr/clearfy/license/list_components', function ( $components ) {
71
+ $title = 'Free';
72
+ $icon = 'rio-premium-icon-256x256--lock.png';
73
+ $description = "";
74
+
75
+ if ( wrio_is_license_activate() ) {
76
+ $title = 'Premium';
77
+ $icon = 'rio-premium-icon-256x256--default.png';
78
+ //$description = "Key: " . wrio_get_license_key();
79
+ }
80
+
81
+ $components[] = [
82
+ 'name' => 'robin_image_optimizer',
83
+ 'title' => sprintf( __( 'Robin image optimizer [%s]', 'clearfy' ), $title ),
84
+ 'url' => 'https://wordpress.org/plugins/robin-image-optimizer/',
85
+ 'type' => 'wordpress',
86
+ 'build' => $this->is_premium ? 'premium' : 'free',
87
+ 'key' => $this->get_hidden_license_key(),
88
+ 'plan' => $this->get_plan(),
89
+ 'expiration_days' => $this->get_expiration_days(),
90
+ 'quota' => $this->is_premium ? $this->premium_license->get_count_active_sites() . ' ' . __( 'of', 'clearfy' ) . ' ' . $this->premium_license->get_sites_quota() : null,
91
+ 'subscription' => $this->is_premium && $this->premium_has_subscription ? sprintf( __( 'Automatic renewal, every %s', '' ), esc_attr( $this->get_billing_cycle_readable() ) ) : null,
92
+ 'base_path' => 'robin-image-optimizer/robin-image-optimizer.php',
93
+ 'icon' => WCL_PLUGIN_URL . '/admin/assets/img/' . $icon,
94
+ 'description' => $description . __( 'Public License is a GPLv3 compatible license allowing you to change and use this version of the plugin for free. Please keep in mind this license covers only free edition of the plugin. Premium versions are distributed with other type of a license.', 'clearfy' ),
95
+ 'license_page_id' => 'rio_license'
96
+ ];
97
+
98
+ return $components;
99
+ } );
100
+ }
101
+
102
+ /**
103
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
104
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
105
+ *
106
+ * @return string
107
+ */
108
+ public function getMenuScope() {
109
+ if ( $this->clearfy_collaboration ) {
110
+ //$this->page_parent_page = 'rio_general';
111
+ $this->page_parent_page = 'none';
112
+
113
+ return 'wbcr_clearfy';
114
+ }
115
+
116
+ return $this->plugin->getPluginName();
117
+ }
118
+
119
+ public function get_plan_description() {
120
+ //$paragraf1 = sprintf( __( '<b>%s</b> is a premium image optimization plugin for WordPress. ', 'robin-image-optimizer' ), $this->plan_name ) . '</p>';
121
+ //$paragraf2 = '<p style="font-size: 16px;">' . __( 'Paid license guarantees that you can optimize images under better conditions and WebP support.', 'robin-image-optimizer' );
122
+ //return '<p style="font-size: 16px;">' . $paragraf1 . '</p><p style="font-size: 16px;">' . $paragraf2 . '</p>';
123
+
124
+ //return '<p style="font-size: 16px;">' . $paragraf1 . '</p>';
125
+ }
126
  }
admin/pages/class-rio-log.php CHANGED
@@ -1,100 +1,100 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * Класс отвечает за работу страницы логов.
9
- *
10
- * @author Eugene Jokerov <jokerov@gmail.com>
11
- * @author Alexander Teshabaev <sasha.tesh@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WRIO_LogPage extends Wbcr_FactoryLogger111_PageBase {
16
-
17
- /**
18
- * {@inheritdoc}
19
- */
20
- public $id = 'rio_logs'; // Уникальный идентификатор страницы
21
-
22
- /**
23
- * {@inheritdoc}
24
- */
25
- public $page_parent_page = null;
26
-
27
- /**
28
- * {@inheritdoc}
29
- */
30
- public $available_for_multisite = false;
31
-
32
- /**
33
- * {@inheritdoc}
34
- */
35
- public $clearfy_collaboration = false;
36
-
37
- /**
38
- * {@inheritdoc}
39
- */
40
- public $show_right_sidebar_in_options = true;
41
-
42
- /**
43
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
44
- * @since 1.3.0
45
- * @var WRIO_Views
46
- */
47
- protected $view;
48
-
49
- /**
50
- * Подменяем пространство имен для меню плагина, если активирован плагин Clearfy
51
- * Меню текущего плагина будет добавлено в общее меню Clearfy
52
- *
53
- * @return string
54
- */
55
- public function getMenuScope() {
56
- if ( $this->clearfy_collaboration ) {
57
- $this->page_parent_page = 'rio_general';
58
-
59
- return 'wbcr_clearfy';
60
- }
61
-
62
- return $this->plugin->getPluginName();
63
- }
64
-
65
- /**
66
- * @param WRIO_Plugin $plugin
67
- */
68
- public function __construct( WRIO_Plugin $plugin ) {
69
- $this->menu_title = __( 'Error Log', 'robin-image-optimizer' );
70
- $this->page_menu_short_description = __( 'Plugin debug report', 'robin-image-optimizer' );
71
-
72
- $this->view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
73
- if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
74
- if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
75
- $this->clearfy_collaboration = true;
76
- }
77
- } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
78
- $this->clearfy_collaboration = true;
79
- }
80
-
81
- parent::__construct( $plugin );
82
- }
83
-
84
- /**
85
- * {@inheritdoc}
86
- *
87
- * @return void
88
- * @since 1.0.0
89
- */
90
- public function assets( $scripts, $styles ) {
91
- parent::assets( $scripts, $styles );
92
- }
93
-
94
- /**
95
- * {@inheritdoc}
96
- */
97
- public function getMenuTitle() {
98
- return defined( 'LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON' ) ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Error Log', 'robin-image-optimizer' );
99
- }
100
- }
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Класс отвечает за работу страницы логов.
9
+ *
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @author Alexander Teshabaev <sasha.tesh@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WRIO_LogPage extends Wbcr_FactoryLogger115_PageBase {
16
+
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ public $id = 'rio_logs'; // Уникальный идентификатор страницы
21
+
22
+ /**
23
+ * {@inheritdoc}
24
+ */
25
+ public $page_parent_page = null;
26
+
27
+ /**
28
+ * {@inheritdoc}
29
+ */
30
+ public $available_for_multisite = false;
31
+
32
+ /**
33
+ * {@inheritdoc}
34
+ */
35
+ public $clearfy_collaboration = false;
36
+
37
+ /**
38
+ * {@inheritdoc}
39
+ */
40
+ public $show_right_sidebar_in_options = true;
41
+
42
+ /**
43
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
44
+ * @since 1.3.0
45
+ * @var WRIO_Views
46
+ */
47
+ protected $view;
48
+
49
+ /**
50
+ * Подменяем пространство имен для меню плагина, если активирован плагин Clearfy
51
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
52
+ *
53
+ * @return string
54
+ */
55
+ public function getMenuScope() {
56
+ if ( $this->clearfy_collaboration ) {
57
+ $this->page_parent_page = 'rio_general';
58
+
59
+ return 'wbcr_clearfy';
60
+ }
61
+
62
+ return $this->plugin->getPluginName();
63
+ }
64
+
65
+ /**
66
+ * @param WRIO_Plugin $plugin
67
+ */
68
+ public function __construct( WRIO_Plugin $plugin ) {
69
+ $this->menu_title = __( 'Error Log', 'robin-image-optimizer' );
70
+ $this->page_menu_short_description = __( 'Plugin debug report', 'robin-image-optimizer' );
71
+
72
+ $this->view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
73
+ if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
74
+ if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
75
+ $this->clearfy_collaboration = true;
76
+ }
77
+ } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
78
+ $this->clearfy_collaboration = true;
79
+ }
80
+
81
+ parent::__construct( $plugin );
82
+ }
83
+
84
+ /**
85
+ * {@inheritdoc}
86
+ *
87
+ * @return void
88
+ * @since 1.0.0
89
+ */
90
+ public function assets( $scripts, $styles ) {
91
+ parent::assets( $scripts, $styles );
92
+ }
93
+
94
+ /**
95
+ * {@inheritdoc}
96
+ */
97
+ public function getMenuTitle() {
98
+ return defined( 'LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON' ) ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Error Log', 'robin-image-optimizer' );
99
+ }
100
+ }
admin/pages/class-rio-page.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
-
3
- /**
4
- * The page Settings.
5
- *
6
- * @since 1.0.0
7
- */
8
-
9
- // Exit if accessed directly
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- exit;
12
- }
13
-
14
- /**
15
- * Класс отвечает за работу страницы настроек
16
- *
17
- * @author Eugene Jokerov <jokerov@gmail.com>
18
- * @copyright (c) 2018, Webcraftic
19
- * @version 1.0
20
- */
21
- class WRIO_Page extends Wbcr_FactoryClearfy237_PageBase {
22
-
23
- /**
24
- * {@inheritdoc}
25
- */
26
- public $page_parent_page = null;
27
-
28
- /**
29
- * {@inheritdoc}
30
- */
31
- public $available_for_multisite = false;
32
-
33
- /**
34
- * {@inheritdoc}
35
- */
36
- public $clearfy_collaboration = false;
37
-
38
- /**
39
- * {@inheritdoc}
40
- */
41
- public $show_right_sidebar_in_options = true;
42
-
43
-
44
- /**
45
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
46
- * @since 1.3.0
47
- * @var WRIO_Views
48
- */
49
- protected $view;
50
-
51
- /**
52
- * @param WRIO_Plugin $plugin
53
- */
54
- public function __construct( WRIO_Plugin $plugin ) {
55
- $this->view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
56
-
57
- if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
58
- if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
59
- $this->clearfy_collaboration = true;
60
- }
61
- } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
62
- $this->clearfy_collaboration = true;
63
- }
64
-
65
- parent::__construct( $plugin );
66
- }
67
-
68
- /**
69
- * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
70
- * Меню текущего плагина будет добавлено в общее меню Clearfy
71
- *
72
- * @return string
73
- */
74
- public function getMenuScope() {
75
- if ( $this->clearfy_collaboration ) {
76
- $this->page_parent_page = 'rio_general';
77
-
78
- return 'wbcr_clearfy';
79
- }
80
-
81
- return $this->plugin->getPluginName();
82
- }
83
- }
1
+ <?php
2
+
3
+ /**
4
+ * The page Settings.
5
+ *
6
+ * @since 1.0.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Класс отвечает за работу страницы настроек
16
+ *
17
+ * @author Eugene Jokerov <jokerov@gmail.com>
18
+ * @copyright (c) 2018, Webcraftic
19
+ * @version 1.0
20
+ */
21
+ class WRIO_Page extends WBCR\Factory_Templates_102\Impressive {
22
+
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public $page_parent_page = null;
27
+
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public $available_for_multisite = false;
32
+
33
+ /**
34
+ * {@inheritdoc}
35
+ */
36
+ public $clearfy_collaboration = false;
37
+
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ public $show_right_sidebar_in_options = true;
42
+
43
+
44
+ /**
45
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
46
+ * @since 1.3.0
47
+ * @var WRIO_Views
48
+ */
49
+ protected $view;
50
+
51
+ /**
52
+ * @param WRIO_Plugin $plugin
53
+ */
54
+ public function __construct( WRIO_Plugin $plugin ) {
55
+ $this->view = WRIO_Views::get_instance( WRIO_PLUGIN_DIR );
56
+
57
+ if ( is_multisite() && defined( 'WCL_PLUGIN_ACTIVE' ) ) {
58
+ if ( WRIO_Plugin::app()->isNetworkActive() && WCL_Plugin::app()->isNetworkActive() ) {
59
+ $this->clearfy_collaboration = true;
60
+ }
61
+ } else if ( defined( 'WCL_PLUGIN_ACTIVE' ) ) {
62
+ $this->clearfy_collaboration = true;
63
+ }
64
+
65
+ parent::__construct( $plugin );
66
+ }
67
+
68
+ /**
69
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
70
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
71
+ *
72
+ * @return string
73
+ */
74
+ public function getMenuScope() {
75
+ if ( $this->clearfy_collaboration ) {
76
+ $this->page_parent_page = 'rio_general';
77
+
78
+ return 'wbcr_clearfy';
79
+ }
80
+
81
+ return $this->plugin->getPluginName();
82
+ }
83
+ }
admin/pages/class-rio-settings.php CHANGED
@@ -1,620 +1,625 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * Класс отвечает за работу страницы настроек
9
- *
10
- * @author Eugene Jokerov <jokerov@gmail.com>
11
- * @copyright (c) 2018, Webcraftic
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
- * {@inheritDoc}
33
- *
34
- * @since 1.1.3 - Added
35
- * @var bool - true show, false hide
36
- */
37
- public $show_search_options_form = false;
38
-
39
- /**
40
- * @param WRIO_Plugin $plugin
41
- */
42
- public function __construct( WRIO_Plugin $plugin ) {
43
-
44
- $this->menu_title = __( 'Settings', 'robin-image-optimizer' );
45
- $this->page_menu_short_description = __( 'Plugin configuration', 'robin-image-optimizer' );
46
-
47
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
48
- $this->show_search_options_form = true;
49
- }
50
-
51
- add_filter( "wbcr/factory/option_image_optimization_type", function ( $option_value ) {
52
- if ( ! wrio_is_license_activate() && $option_value === 'background' ) {
53
- $option_value = 'schedule';
54
- }
55
-
56
- return $option_value;
57
- } );
58
-
59
- parent::__construct( $plugin );
60
- }
61
-
62
- /**
63
- * Подключаем скрипты и стили для страницы
64
- *
65
- * @return void
66
- * @since 1.0.0
67
- * @see Wbcr_FactoryPages445_AdminPage
68
- *
69
- */
70
- public function assets( $scripts, $styles ) {
71
- parent::assets( $scripts, $styles );
72
-
73
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
74
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
75
-
76
- if ( ! wrio_is_license_activate() ) {
77
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/settings-premium.css' );
78
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/settings-premium.js' );
79
- }
80
-
81
- // Add Clearfy styles for HMWP pages
82
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
83
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
84
- }
85
- }
86
-
87
-
88
- /**
89
- * Выводим предупреждения
90
- *
91
- */
92
- protected function warningNotice() {
93
- $upload_dir = wp_upload_dir();
94
-
95
- if ( ! wp_is_writable( $upload_dir['basedir'] ) ) {
96
- $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
97
- }
98
-
99
- $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
100
- if ( file_exists( $wio_backup ) && ! wp_is_writable( $wio_backup ) ) {
101
- $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
102
- }
103
-
104
- if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true ) {
105
- $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
106
- }
107
- }
108
-
109
-
110
- /**
111
- * Метод должен передать массив опций для создания формы с полями.
112
- * Созданием страницы и формы занимается фреймворк
113
- *
114
- * @return mixed[]
115
- * @since 1.0.0
116
- */
117
- public function getPageOptions() {
118
- $options = [];
119
-
120
- $options[] = [
121
- 'type' => 'html',
122
- '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>'
123
- ];
124
-
125
- $options[] = [
126
- 'type' => 'dropdown',
127
- 'name' => 'image_optimization_server',
128
- 'title' => __( 'Optimization server', 'robin-image-optimizer' ),
129
- 'data' => [
130
- [
131
- 'server_1',
132
- __( 'Server 1 - image size limit up to 5 MB', 'robin-image-optimizer' ),
133
-
134
- ],
135
- [
136
- 'server_2',
137
- __( 'Server 2 - beta', 'robin-image-optimizer' )
138
-
139
- ],
140
- [
141
- 'server_5',
142
- __( 'Premium - no limits', 'robin-image-optimizer' )
143
- ],
144
- ],
145
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
146
- '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' ),
147
- 'default' => 'server_1',
148
- ];
149
-
150
- // Радио переключатель
151
- $options[] = [
152
- 'type' => 'dropdown',
153
- 'name' => 'image_optimization_level',
154
- 'way' => 'buttons',
155
- 'title' => __( 'Compression mode', 'robin-image-optimizer' ),
156
- 'data' => [
157
- [
158
- 'normal',
159
- __( 'Lossless', 'robin-image-optimizer' ),
160
- __( 'This mode provides lossless compression and your images will be optimized without visible changes. If you want an ideal image quality, we recommend this mode. The size of the files will be reduced approximately 2 times. If this is not enough for you, try other modes.', 'robin-image-optimizer' )
161
- ],
162
- [
163
- 'aggresive',
164
- __( 'Lossy', 'robin-image-optimizer' ),
165
- __( 'This mode provides an ideal optimization of your images without significant quality loss. The file size will be reduced approximately 5 times with a slight decrease in image quality. In most cases that cannot be seen with the naked eye.', 'robin-image-optimizer' )
166
- ],
167
- [
168
- 'ultra',
169
- __( 'High', 'robin-image-optimizer' ),
170
- __( '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' )
171
- ],
172
- [
173
- 'googlepage',
174
- __( 'G PageSpeed', 'robin-image-optimizer' ),
175
- __( 'This mode uses the optimal settings for Google Page Speed', 'robin-image-optimizer' ),
176
- ],
177
- [
178
- 'custom',
179
- __( 'Custom', 'robin-image-optimizer' ),
180
- __( 'This mode allows you to configure your own compression ratio.', 'robin-image-optimizer' )
181
- ]
182
- ],
183
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
184
- 'hint' => __( 'Select the compression mode appropriate for your case.', 'robin-image-optimizer' ),
185
- 'default' => 'normal',
186
- 'events' => [
187
- 'normal' => [
188
- 'hide' => '.factory-control-image_optimization_level_custom'
189
- ],
190
- 'aggresive' => [
191
- 'hide' => '.factory-control-image_optimization_level_custom'
192
- ],
193
- 'ultra' => [
194
- 'hide' => '.factory-control-image_optimization_level_custom'
195
- ],
196
- 'googlepage' => [
197
- 'hide' => '.factory-control-image_optimization_level_custom',
198
- ],
199
- 'custom' => [
200
- 'show' => '.factory-control-image_optimization_level_custom',
201
- ],
202
- ]
203
- ];
204
-
205
- // Текстовое поле
206
- $options[] = [
207
- 'type' => 'textbox',
208
- 'name' => 'image_optimization_level_custom',
209
- 'title' => __( 'Enter custom quality', 'robin-image-optimizer' ),
210
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
211
- 'hint' => __( 'custom quality 1-100', 'robin-image-optimizer' ),
212
- 'default' => '70'
213
- ];
214
-
215
- // Переключатель
216
- $options[] = [
217
- 'type' => 'checkbox',
218
- 'way' => 'buttons',
219
- 'name' => 'auto_optimize_when_upload',
220
- 'title' => __( 'Auto optimization on upload', 'robin-image-optimizer' ),
221
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
222
- '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' ),
223
- 'default' => false
224
- ];
225
-
226
- // Переключатель
227
- $options[] = [
228
- 'type' => 'checkbox',
229
- 'way' => 'buttons',
230
- 'name' => 'backup_origin_images',
231
- 'title' => __( 'Backup images', 'robin-image-optimizer' ),
232
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'green' ],
233
- 'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
234
- 'default' => true
235
- ];
236
-
237
- // Переключатель
238
- $options[] = [
239
- 'type' => 'checkbox',
240
- 'way' => 'buttons',
241
- 'name' => 'error_log',
242
- 'title' => __( 'Error Log', 'robin-image-optimizer' ),
243
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
244
- 'hint' => __( 'Enable error logging. The log will be displayed on a separate tab.', 'robin-image-optimizer' ),
245
- 'default' => false,
246
- 'eventsOn' => [
247
- 'show' => '#wrio-error-log-options'
248
- ],
249
- 'eventsOff' => [
250
- 'hide' => '#wrio-error-log-options'
251
- ]
252
- ];
253
-
254
- $options[] = [
255
- 'type' => 'html',
256
- 'html' => [ $this, 'error_log_options' ]
257
- ];
258
-
259
- $options[] = [
260
- 'type' => 'checkbox',
261
- 'way' => 'buttons',
262
- 'name' => 'convert_webp_format',
263
- 'title' => __( 'Convert Images to WebP', 'robin-image-optimizer' ),
264
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
265
- 'hint' => __( 'Convert JPEG & PNG images into WebP format and replace them for browsers which support it. Unsupported browsers would be skipped.', 'robin-image-optimizer' ),
266
- 'default' => false,
267
- 'cssClass' => ! wrio_is_license_activate() ? [ 'factory-checkbox-disabled wrio-checkbox-premium-label' ] : [],
268
- 'eventsOn' => [
269
- 'show' => '#wrio-webp-options'
270
- ],
271
- 'eventsOff' => [
272
- 'hide' => '#wrio-webp-options'
273
- ]
274
- ];
275
-
276
- $options[] = [
277
- 'type' => 'html',
278
- 'html' => [ $this, 'conver_webp_options' ]
279
- ];
280
-
281
- // восстановление
282
- $options[] = [
283
- 'type' => 'html',
284
- 'html' => [ $this, 'rollbackButton' ],
285
- ];
286
-
287
- // Переключатель
288
- $options[] = [
289
- 'type' => 'checkbox',
290
- 'way' => 'buttons',
291
- 'name' => 'save_exif_data',
292
- 'title' => __( 'Leave EXIF data', 'robin-image-optimizer' ),
293
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
294
- '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' ),
295
- 'default' => true
296
- ];
297
-
298
- $options[] = [
299
- 'type' => 'html',
300
- '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>'
301
- ];
302
-
303
- $options[] = [
304
- 'type' => 'dropdown',
305
- 'name' => 'image_optimization_order',
306
- 'way' => 'buttons',
307
- 'title' => __( 'Optimization order', 'robin-image-optimizer' ),
308
- 'data' => [
309
- [
310
- 'asc',
311
- __( 'Ascending', 'robin-image-optimizer' ),
312
- __( 'Optimization will start with old images in the media library', 'robin-image-optimizer' )
313
- ],
314
- [
315
- 'desc',
316
- __( 'Descending', 'robin-image-optimizer' ),
317
- __( 'Optimization will start with new images in the media library', 'robin-image-optimizer' )
318
- ],
319
- ],
320
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
321
- 'hint' => __( "Select the optimization order from the media library.", 'robin-image-optimizer' ),
322
- 'default' => 'asc',
323
- ];
324
-
325
- // Переключатель
326
- $options[] = [
327
- 'type' => 'checkbox',
328
- 'way' => 'buttons',
329
- 'name' => 'resize_larger',
330
- 'title' => __( 'Resizing large images', 'robin-image-optimizer' ),
331
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
332
- 'hint' => __( 'When you upload images from a camera or stock, they may be too high resolution and it is not necessary for web. The option allows you to automatically change images resolution on upload.', 'robin-image-optimizer' ),
333
- 'default' => false,
334
- // когда чекбокс включен показываем поле с классом .factory-control-resize_larger_w
335
- 'eventsOn' => [
336
- 'show' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
337
- ],
338
- // когда чекбокс выключен, скрываем поле с классом .factory-control-resize_larger_w
339
- 'eventsOff' => [
340
- 'hide' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
341
- ]
342
- ];
343
-
344
- // Текстовое поле
345
- $options[] = [
346
- 'type' => 'textbox',
347
- 'name' => 'resize_larger_w',
348
- 'title' => __( 'Enter the maximum width (px)', 'robin-image-optimizer' ),
349
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
350
- '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' ),
351
- 'default' => '1600'
352
- ];
353
-
354
- // Текстовое поле
355
- $options[] = [
356
- 'type' => 'textbox',
357
- 'name' => 'resize_larger_h',
358
- 'title' => __( 'Enter the maximum height (px)', 'robin-image-optimizer' ),
359
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
360
- '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' ),
361
- 'default' => '1600'
362
- ];
363
-
364
- $options[] = [
365
- 'type' => 'list',
366
- 'way' => 'checklist',
367
- 'name' => 'allowed_formats',
368
- 'title' => __( 'Optimize formats', 'robin-image-optimizer' ),
369
- 'data' => [
370
- [ 'image/jpeg', 'JPG' ],
371
- [ 'image/png', 'PNG' ],
372
- [ 'image/gif', 'GIF' ],
373
- ],
374
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
375
- 'hint' => __( 'Choose which formats of images should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
376
- 'default' => 'image/jpeg,image/png,image/gif'
377
- ];
378
-
379
- // получаем зарегистрированные размеры изображений
380
- $wp_image_sizes = wrio_get_image_sizes();
381
- $wio_image_sizes = [];
382
- foreach ( $wp_image_sizes as $key => $value ) {
383
- $wio_image_sizes[] = [
384
- $key,
385
- $key . ' - ' . $value['width'] . 'x' . $value['height'],
386
- ];
387
- }
388
-
389
- $options[] = [
390
- 'type' => 'list',
391
- 'way' => 'checklist',
392
- 'name' => 'allowed_sizes_thumbnail',
393
- 'title' => __( 'Optimize thumbnails', 'robin-image-optimizer' ),
394
- 'data' => $wio_image_sizes,
395
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
396
- 'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
397
- 'default' => 'thumbnail,medium'
398
- ];
399
-
400
- // cron
401
- $options[] = [
402
- 'type' => 'html',
403
- 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Scheduled and background optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Settings for scheduled and background image optimization.', 'robin-image-optimizer' ) . '</p></div>'
404
- ];
405
-
406
- $options[] = [
407
- 'type' => 'dropdown',
408
- 'name' => 'image_optimization_type',
409
- 'way' => 'buttons',
410
- 'title' => __( 'Background optimization type', 'robin-image-optimizer' ),
411
- 'data' => [
412
- [
413
- 'schedule',
414
- __( 'Scheduled', 'robin-image-optimizer' ),
415
- __( 'Optimization will take place on a schedule', 'robin-image-optimizer' )
416
- ],
417
- [
418
- 'background',
419
- __( 'Background', 'robin-image-optimizer' ),
420
- __( 'Optimization will occur in the background constantly', 'robin-image-optimizer' )
421
- ],
422
- ],
423
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
424
- 'hint' => __( "<b>Scheduled optimization</b> will occur on a scheduled basis.<br><b>Background optimization</b> will occur in the background constantly.", 'robin-image-optimizer' ),
425
- 'default' => 'schedule',
426
- 'events' => [
427
- 'schedule' => [
428
- 'show' => '#wbcr-io-shedule-options',
429
- ],
430
- 'background' => [
431
- 'hide' => '#wbcr-io-shedule-options',
432
- ],
433
- ],
434
- ];
435
-
436
- $group_items[] = [
437
- 'type' => 'dropdown',
438
- 'way' => 'buttons',
439
- 'name' => 'image_autooptimize_shedule_time',
440
- 'data' => [
441
- [ 'wio_1_min', __( '1 min', 'robin-image-optimizer' ) ],
442
- [ 'wio_2_min', __( '2 min', 'robin-image-optimizer' ) ],
443
- [ 'wio_5_min', __( '5 min', 'robin-image-optimizer' ) ],
444
- [ 'wio_10_min', __( '10 min', 'robin-image-optimizer' ) ],
445
- [ 'wio_30_min', __( '30 min', 'robin-image-optimizer' ) ],
446
- [ 'wio_hourly', __( 'Hour', 'robin-image-optimizer' ) ],
447
- [ 'wio_daily', __( 'Day', 'robin-image-optimizer' ) ],
448
- ],
449
- 'default' => 'wio_5_min',
450
- 'title' => __( 'Run every', 'robin-image-optimizer' ),
451
- 'hint' => __( 'Select time at which the task will be repeated.', 'robin-image-optimizer' )
452
- ];
453
-
454
- $group_items[] = [
455
- 'type' => 'textbox',
456
- 'name' => 'image_autooptimize_items_number_per_interation',
457
- 'title' => __( 'Images per iteration', 'robin-image-optimizer' ),
458
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
459
- 'hint' => __( 'Specify the number of images that will be optimized during the job. For example, if you enter 5 and select 5 min, the plugin will optimize 5 images every 5 minutes.', 'robin-image-optimizer' ),
460
- 'default' => '3'
461
- ];
462
-
463
- $options[] = [
464
- 'type' => 'div',
465
- 'id' => 'wbcr-io-shedule-options',
466
- 'items' => $group_items
467
- ];
468
-
469
- $options = apply_filters( 'wbcr/rio/settings_page/options', $options );
470
-
471
- $formOptions = [];
472
-
473
- $formOptions[] = [
474
- 'type' => 'form-group',
475
- 'items' => $options,
476
- //'cssClass' => 'postbox'
477
- ];
478
-
479
- return $formOptions;
480
- }
481
-
482
- /**
483
- * Save advanced options in database
484
- *
485
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
486
- * @since 1.3.6
487
- */
488
- public function beforeFormSave() {
489
-
490
- /**
491
- * Used to save webp options. It can also be used to intercept
492
- * other unregistered fields.
493
- *
494
- * @since 1.3.6
495
- */
496
- do_action( "wrio/settings_page/berfore_form_save" );
497
-
498
- $error_log = (int) WRIO_Plugin::app()->request->post( WRIO_Plugin::app()->getPrefix() . 'error_log', 0 );
499
-
500
- if ( ! $error_log ) {
501
- return;
502
- }
503
-
504
- $keep_error_log_on_frontend = (int) WRIO_Plugin::app()->request->post( 'wrio_keep_error_log_on_frontend', 0 );
505
-
506
- WRIO_Plugin::app()->updatePopulateOption( 'keep_error_log_on_frontend', $keep_error_log_on_frontend );
507
- }
508
-
509
- /**
510
- * This method adds advanced options for the "Convert Images to WebP" checkbox.
511
- *
512
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
513
- * @since 1.3.6
514
- */
515
- public function conver_webp_options() {
516
-
517
- /**
518
- * This hook prints options for delivering webp images.
519
- *
520
- * @since 1.3.6
521
- */
522
- do_action( "wrio/settings_page/conver_webp_options" );
523
- }
524
-
525
- /**
526
- * This method adds advanced options for the "Error log" checkbox.
527
- *
528
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
529
- * @since 1.3.6
530
- */
531
- public function error_log_options() {
532
- $this->view->print_template( 'part-settings-page-error-log-options', [
533
- 'keep_error_log_on_frontend' => (int) WRIO_Plugin::app()->getPopulateOption( 'keep_error_log_on_frontend', 0 )
534
- ] );
535
- }
536
-
537
- /**
538
- * Кнопка восстановления изображений
539
- */
540
- public function rollbackButton() {
541
- ?>
542
- <div class="form-group form-group-checkbox factory-control-rollback-button">
543
- <label for="wio-clear-backup-btn" class="col-sm-4 control-label">
544
- <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
545
- <span class="factory-hint-icon factory-hint-icon-red" data-toggle="factory-tooltip"
546
- data-placement="right" title=""
547
- data-original-title="<?php _e( 'You can restore the original images from a backup or clear them.', 'robin-image-optimizer' ); ?>">
548
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
549
- alt="">
550
- </span>
551
- </label>
552
- <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
553
- <div class="control-group col-sm-8">
554
- <div class="factory-buttons-way btn-group">
555
- <a class="btn btn-default" id="wio-restore-backup-btn"
556
- data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>"
557
- href="#"><?php _e( 'Restore', 'robin-image-optimizer' ); ?></a>
558
- <a class="btn btn-default" id="wio-clear-backup-btn"
559
- data-confirm="<?php _e( 'Are you sure that you want to clear image backups folder?', 'robin-image-optimizer' ); ?>"
560
- href="#"><?php _e( 'Clear Backup', 'robin-image-optimizer' ); ?></a>
561
- </div>
562
- <?php //if ( WRIO_Plugin::app()->isNetworkAdmin() ) : ?>
563
- <!-- <div id="wio-multisite-mode" style="display:none;">-->
564
- <!-- <ul class="factory-list factory-from-control-list factory-checklist-way">-->
565
- <!-- --><?php
566
- // $blogs = WIO_Multisite::getBlogs();
567
- // ?>
568
- <!-- <li>-->
569
- <!-- <label for="wbcr_io_multisite_blog_all">-->
570
- <!-- <span>-->
571
- <!-- <input value="all" id="wbcr_io_multisite_blog_all" type="checkbox">-->
572
- <!-- </span>-->
573
- <!-- <span>-->
574
- <?php //echo __( 'Select all', 'robin-image-optimizer' ); ?><!--</span>-->
575
- <!-- </label>-->
576
- <!-- </li>-->
577
- <!-- --><?php //foreach ( $blogs as $blog ) : ?>
578
- <!-- <li>-->
579
- <!-- <label for="wbcr_io_multisite_blog_-->
580
- <?php //echo esc_attr( $blog->blog_id ); ?><!--">-->
581
- <!-- --><?php
582
- // $blog_name = $blog->domain . $blog->path;
583
- // if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
584
- // $blog_name = $blog->domain;
585
- // }
586
- // ?>
587
- <!-- <span>-->
588
- <!-- <input data-name="--><?php //echo esc_attr( $blog_name ); ?><!--"-->
589
- <!-- class="wbcr_io_multisite_blogs"-->
590
- <!-- value="--><?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
591
- <!-- id="wbcr_io_multisite_blog_-->
592
- <?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
593
- <!-- type="checkbox">-->
594
- <!-- </span>-->
595
- <!-- <span>--><?php //echo esc_attr( $blog_name ); ?><!--</span>-->
596
- <!-- </label>-->
597
- <!-- </li>-->
598
- <!-- --><?php //endforeach; ?>
599
- <!-- </ul>-->
600
- <!-- <button id="wio-multisite-confirm" class="btn btn-default" type="button"-->
601
- <!-- data-action="">-->
602
- <?php //echo __( 'Start', 'robin-image-optimizer' ); ?><!--</button>-->
603
- <!-- </div>-->
604
- <!-- <div id="wio-multisite-restore-progress" style="display:none;">-->
605
- <!-- </div>-->
606
- <?php //endif; ?>
607
- <div class="progress" id="wio-restore-backup-progress" style="display:none;">
608
- <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0"
609
- aria-valuemin="0" aria-valuemax="100" style="width:0%">
610
- </div>
611
- </div>
612
- <p id="wio-restore-backup-msg"
613
- style="display:none;"><?php _e( 'Restore completed.', 'robin-image-optimizer' ); ?></p>
614
- <p id="wio-clear-backup-msg"
615
- style="display:none;"><?php _e( 'The backup folder was cleared.', 'robin-image-optimizer' ); ?></p>
616
- </div>
617
- </div>
618
- <?php
619
- }
620
- }
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Класс отвечает за работу страницы настроек
9
+ *
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
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
+ * {@inheritDoc}
33
+ *
34
+ * @since 1.1.3 - Added
35
+ * @var bool - true show, false hide
36
+ */
37
+ public $show_search_options_form = false;
38
+
39
+ /**
40
+ * @var bool
41
+ */
42
+ public $internal = true;
43
+
44
+ /**
45
+ * @param WRIO_Plugin $plugin
46
+ */
47
+ public function __construct( WRIO_Plugin $plugin ) {
48
+
49
+ $this->menu_title = __( 'Settings', 'robin-image-optimizer' );
50
+ $this->page_menu_short_description = __( 'Plugin configuration', 'robin-image-optimizer' );
51
+
52
+ if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
53
+ $this->show_search_options_form = true;
54
+ }
55
+
56
+ add_filter( "wbcr/factory/option_image_optimization_type", function ( $option_value ) {
57
+ if ( ! wrio_is_license_activate() && $option_value === 'background' ) {
58
+ $option_value = 'schedule';
59
+ }
60
+
61
+ return $option_value;
62
+ } );
63
+
64
+ parent::__construct( $plugin );
65
+ }
66
+
67
+ /**
68
+ * Подключаем скрипты и стили для страницы
69
+ *
70
+ * @return void
71
+ * @since 1.0.0
72
+ * @see Wbcr_FactoryPages449_AdminPage
73
+ *
74
+ */
75
+ public function assets( $scripts, $styles ) {
76
+ parent::assets( $scripts, $styles );
77
+
78
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
79
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
80
+
81
+ if ( ! wrio_is_license_activate() ) {
82
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/settings-premium.css' );
83
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/settings-premium.js' );
84
+ }
85
+
86
+ // Add Clearfy styles for HMWP pages
87
+ if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
88
+ $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
89
+ }
90
+ }
91
+
92
+
93
+ /**
94
+ * Выводим предупреждения
95
+ *
96
+ */
97
+ protected function warningNotice() {
98
+ $upload_dir = wp_upload_dir();
99
+
100
+ if ( ! wp_is_writable( $upload_dir['basedir'] ) ) {
101
+ $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
102
+ }
103
+
104
+ $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
105
+ if ( file_exists( $wio_backup ) && ! wp_is_writable( $wio_backup ) ) {
106
+ $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
107
+ }
108
+
109
+ if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true ) {
110
+ $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
111
+ }
112
+ }
113
+
114
+
115
+ /**
116
+ * Метод должен передать массив опций для создания формы с полями.
117
+ * Созданием страницы и формы занимается фреймворк
118
+ *
119
+ * @return mixed[]
120
+ * @since 1.0.0
121
+ */
122
+ public function getPageOptions() {
123
+ $options = [];
124
+
125
+ $options[] = [
126
+ 'type' => 'html',
127
+ '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>'
128
+ ];
129
+
130
+ $options[] = [
131
+ 'type' => 'dropdown',
132
+ 'name' => 'image_optimization_server',
133
+ 'title' => __( 'Optimization server', 'robin-image-optimizer' ),
134
+ 'data' => [
135
+ [
136
+ 'server_1',
137
+ __( 'Server 1 - image size limit up to 5 MB', 'robin-image-optimizer' ),
138
+
139
+ ],
140
+ [
141
+ 'server_2',
142
+ __( 'Server 2 - beta', 'robin-image-optimizer' )
143
+
144
+ ],
145
+ [
146
+ 'server_5',
147
+ __( 'Premium - no limits', 'robin-image-optimizer' )
148
+ ],
149
+ ],
150
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
151
+ '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' ),
152
+ 'default' => 'server_1',
153
+ ];
154
+
155
+ // Радио переключатель
156
+ $options[] = [
157
+ 'type' => 'dropdown',
158
+ 'name' => 'image_optimization_level',
159
+ 'way' => 'buttons',
160
+ 'title' => __( 'Compression mode', 'robin-image-optimizer' ),
161
+ 'data' => [
162
+ [
163
+ 'normal',
164
+ __( 'Lossless', 'robin-image-optimizer' ),
165
+ __( 'This mode provides lossless compression and your images will be optimized without visible changes. If you want an ideal image quality, we recommend this mode. The size of the files will be reduced approximately 2 times. If this is not enough for you, try other modes.', 'robin-image-optimizer' )
166
+ ],
167
+ [
168
+ 'aggresive',
169
+ __( 'Lossy', 'robin-image-optimizer' ),
170
+ __( 'This mode provides an ideal optimization of your images without significant quality loss. The file size will be reduced approximately 5 times with a slight decrease in image quality. In most cases that cannot be seen with the naked eye.', 'robin-image-optimizer' )
171
+ ],
172
+ [
173
+ 'ultra',
174
+ __( 'High', 'robin-image-optimizer' ),
175
+ __( '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' )
176
+ ],
177
+ [
178
+ 'googlepage',
179
+ __( 'G PageSpeed', 'robin-image-optimizer' ),
180
+ __( 'This mode uses the optimal settings for Google Page Speed', 'robin-image-optimizer' ),
181
+ ],
182
+ [
183
+ 'custom',
184
+ __( 'Custom', 'robin-image-optimizer' ),
185
+ __( 'This mode allows you to configure your own compression ratio.', 'robin-image-optimizer' )
186
+ ]
187
+ ],
188
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
189
+ 'hint' => __( 'Select the compression mode appropriate for your case.', 'robin-image-optimizer' ),
190
+ 'default' => 'normal',
191
+ 'events' => [
192
+ 'normal' => [
193
+ 'hide' => '.factory-control-image_optimization_level_custom'
194
+ ],
195
+ 'aggresive' => [
196
+ 'hide' => '.factory-control-image_optimization_level_custom'
197
+ ],
198
+ 'ultra' => [
199
+ 'hide' => '.factory-control-image_optimization_level_custom'
200
+ ],
201
+ 'googlepage' => [
202
+ 'hide' => '.factory-control-image_optimization_level_custom',
203
+ ],
204
+ 'custom' => [
205
+ 'show' => '.factory-control-image_optimization_level_custom',
206
+ ],
207
+ ]
208
+ ];
209
+
210
+ // Текстовое поле
211
+ $options[] = [
212
+ 'type' => 'textbox',
213
+ 'name' => 'image_optimization_level_custom',
214
+ 'title' => __( 'Enter custom quality', 'robin-image-optimizer' ),
215
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
216
+ 'hint' => __( 'custom quality 1-100', 'robin-image-optimizer' ),
217
+ 'default' => '70'
218
+ ];
219
+
220
+ // Переключатель
221
+ $options[] = [
222
+ 'type' => 'checkbox',
223
+ 'way' => 'buttons',
224
+ 'name' => 'auto_optimize_when_upload',
225
+ 'title' => __( 'Auto optimization on upload', 'robin-image-optimizer' ),
226
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
227
+ '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' ),
228
+ 'default' => false
229
+ ];
230
+
231
+ // Переключатель
232
+ $options[] = [
233
+ 'type' => 'checkbox',
234
+ 'way' => 'buttons',
235
+ 'name' => 'backup_origin_images',
236
+ 'title' => __( 'Backup images', 'robin-image-optimizer' ),
237
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'green' ],
238
+ 'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
239
+ 'default' => true
240
+ ];
241
+
242
+ // Переключатель
243
+ $options[] = [
244
+ 'type' => 'checkbox',
245
+ 'way' => 'buttons',
246
+ 'name' => 'error_log',
247
+ 'title' => __( 'Error Log', 'robin-image-optimizer' ),
248
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
249
+ 'hint' => __( 'Enable error logging. The log will be displayed on a separate tab.', 'robin-image-optimizer' ),
250
+ 'default' => false,
251
+ 'eventsOn' => [
252
+ 'show' => '#wrio-error-log-options'
253
+ ],
254
+ 'eventsOff' => [
255
+ 'hide' => '#wrio-error-log-options'
256
+ ]
257
+ ];
258
+
259
+ $options[] = [
260
+ 'type' => 'html',
261
+ 'html' => [ $this, 'error_log_options' ]
262
+ ];
263
+
264
+ $options[] = [
265
+ 'type' => 'checkbox',
266
+ 'way' => 'buttons',
267
+ 'name' => 'convert_webp_format',
268
+ 'title' => __( 'Convert Images to WebP', 'robin-image-optimizer' ),
269
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
270
+ 'hint' => __( 'Convert JPEG & PNG images into WebP format and replace them for browsers which support it. Unsupported browsers would be skipped.', 'robin-image-optimizer' ),
271
+ 'default' => false,
272
+ 'cssClass' => ! wrio_is_license_activate() ? [ 'factory-checkbox-disabled wrio-checkbox-premium-label' ] : [],
273
+ 'eventsOn' => [
274
+ 'show' => '#wrio-webp-options'
275
+ ],
276
+ 'eventsOff' => [
277
+ 'hide' => '#wrio-webp-options'
278
+ ]
279
+ ];
280
+
281
+ $options[] = [
282
+ 'type' => 'html',
283
+ 'html' => [ $this, 'conver_webp_options' ]
284
+ ];
285
+
286
+ // восстановление
287
+ $options[] = [
288
+ 'type' => 'html',
289
+ 'html' => [ $this, 'rollbackButton' ],
290
+ ];
291
+
292
+ // Переключатель
293
+ $options[] = [
294
+ 'type' => 'checkbox',
295
+ 'way' => 'buttons',
296
+ 'name' => 'save_exif_data',
297
+ 'title' => __( 'Leave EXIF data', 'robin-image-optimizer' ),
298
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
299
+ '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' ),
300
+ 'default' => true
301
+ ];
302
+
303
+ $options[] = [
304
+ 'type' => 'html',
305
+ '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>'
306
+ ];
307
+
308
+ $options[] = [
309
+ 'type' => 'dropdown',
310
+ 'name' => 'image_optimization_order',
311
+ 'way' => 'buttons',
312
+ 'title' => __( 'Optimization order', 'robin-image-optimizer' ),
313
+ 'data' => [
314
+ [
315
+ 'asc',
316
+ __( 'Ascending', 'robin-image-optimizer' ),
317
+ __( 'Optimization will start with old images in the media library', 'robin-image-optimizer' )
318
+ ],
319
+ [
320
+ 'desc',
321
+ __( 'Descending', 'robin-image-optimizer' ),
322
+ __( 'Optimization will start with new images in the media library', 'robin-image-optimizer' )
323
+ ],
324
+ ],
325
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
326
+ 'hint' => __( /** @lang text */ "Select the optimization order from the media library.", 'robin-image-optimizer' ),
327
+ 'default' => 'asc',
328
+ ];
329
+
330
+ // Переключатель
331
+ $options[] = [
332
+ 'type' => 'checkbox',
333
+ 'way' => 'buttons',
334
+ 'name' => 'resize_larger',
335
+ 'title' => __( 'Resizing large images', 'robin-image-optimizer' ),
336
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
337
+ 'hint' => __( 'When you upload images from a camera or stock, they may be too high resolution and it is not necessary for web. The option allows you to automatically change images resolution on upload.', 'robin-image-optimizer' ),
338
+ 'default' => false,
339
+ // когда чекбокс включен показываем поле с классом .factory-control-resize_larger_w
340
+ 'eventsOn' => [
341
+ 'show' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
342
+ ],
343
+ // когда чекбокс выключен, скрываем поле с классом .factory-control-resize_larger_w
344
+ 'eventsOff' => [
345
+ 'hide' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
346
+ ]
347
+ ];
348
+
349
+ // Текстовое поле
350
+ $options[] = [
351
+ 'type' => 'textbox',
352
+ 'name' => 'resize_larger_w',
353
+ 'title' => __( 'Enter the maximum width (px)', 'robin-image-optimizer' ),
354
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
355
+ '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' ),
356
+ 'default' => '1600'
357
+ ];
358
+
359
+ // Текстовое поле
360
+ $options[] = [
361
+ 'type' => 'textbox',
362
+ 'name' => 'resize_larger_h',
363
+ 'title' => __( 'Enter the maximum height (px)', 'robin-image-optimizer' ),
364
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
365
+ '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' ),
366
+ 'default' => '1600'
367
+ ];
368
+
369
+ $options[] = [
370
+ 'type' => 'list',
371
+ 'way' => 'checklist',
372
+ 'name' => 'allowed_formats',
373
+ 'title' => __( 'Optimize formats', 'robin-image-optimizer' ),
374
+ 'data' => [
375
+ [ 'image/jpeg', 'JPG' ],
376
+ [ 'image/png', 'PNG' ],
377
+ [ 'image/gif', 'GIF' ],
378
+ ],
379
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
380
+ 'hint' => __( 'Choose which formats of images should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
381
+ 'default' => 'image/jpeg,image/png,image/gif'
382
+ ];
383
+
384
+ // получаем зарегистрированные размеры изображений
385
+ $wp_image_sizes = wrio_get_image_sizes();
386
+ $wio_image_sizes = [];
387
+ foreach ( $wp_image_sizes as $key => $value ) {
388
+ $wio_image_sizes[] = [
389
+ $key,
390
+ $key . ' - ' . $value['width'] . 'x' . $value['height'],
391
+ ];
392
+ }
393
+
394
+ $options[] = [
395
+ 'type' => 'list',
396
+ 'way' => 'checklist',
397
+ 'name' => 'allowed_sizes_thumbnail',
398
+ 'title' => __( 'Optimize thumbnails', 'robin-image-optimizer' ),
399
+ 'data' => $wio_image_sizes,
400
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
401
+ 'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
402
+ 'default' => 'thumbnail,medium'
403
+ ];
404
+
405
+ // cron
406
+ $options[] = [
407
+ 'type' => 'html',
408
+ 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Scheduled and background optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Settings for scheduled and background image optimization.', 'robin-image-optimizer' ) . '</p></div>'
409
+ ];
410
+
411
+ $options[] = [
412
+ 'type' => 'dropdown',
413
+ 'name' => 'image_optimization_type',
414
+ 'way' => 'buttons',
415
+ 'title' => __( 'Background optimization type', 'robin-image-optimizer' ),
416
+ 'data' => [
417
+ [
418
+ 'schedule',
419
+ __( 'Scheduled', 'robin-image-optimizer' ),
420
+ __( 'Optimization will take place on a schedule', 'robin-image-optimizer' )
421
+ ],
422
+ [
423
+ 'background',
424
+ __( 'Background', 'robin-image-optimizer' ),
425
+ __( 'Optimization will occur in the background constantly', 'robin-image-optimizer' )
426
+ ],
427
+ ],
428
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
429
+ 'hint' => __( "<b>Scheduled optimization</b> will occur on a scheduled basis.<br><b>Background optimization</b> will occur in the background constantly.", 'robin-image-optimizer' ),
430
+ 'default' => 'schedule',
431
+ 'events' => [
432
+ 'schedule' => [
433
+ 'show' => '#wbcr-io-shedule-options',
434
+ ],
435
+ 'background' => [
436
+ 'hide' => '#wbcr-io-shedule-options',
437
+ ],
438
+ ],
439
+ ];
440
+
441
+ $group_items[] = [
442
+ 'type' => 'dropdown',
443
+ 'way' => 'buttons',
444
+ 'name' => 'image_autooptimize_shedule_time',
445
+ 'data' => [
446
+ [ 'wio_1_min', __( '1 min', 'robin-image-optimizer' ) ],
447
+ [ 'wio_2_min', __( '2 min', 'robin-image-optimizer' ) ],
448
+ [ 'wio_5_min', __( '5 min', 'robin-image-optimizer' ) ],
449
+ [ 'wio_10_min', __( '10 min', 'robin-image-optimizer' ) ],
450
+ [ 'wio_30_min', __( '30 min', 'robin-image-optimizer' ) ],
451
+ [ 'wio_hourly', __( 'Hour', 'robin-image-optimizer' ) ],
452
+ [ 'wio_daily', __( 'Day', 'robin-image-optimizer' ) ],
453
+ ],
454
+ 'default' => 'wio_5_min',
455
+ 'title' => __( 'Run every', 'robin-image-optimizer' ),
456
+ 'hint' => __( 'Select time at which the task will be repeated.', 'robin-image-optimizer' )
457
+ ];
458
+
459
+ $group_items[] = [
460
+ 'type' => 'textbox',
461
+ 'name' => 'image_autooptimize_items_number_per_interation',
462
+ 'title' => __( 'Images per iteration', 'robin-image-optimizer' ),
463
+ 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
464
+ 'hint' => __( 'Specify the number of images that will be optimized during the job. For example, if you enter 5 and select 5 min, the plugin will optimize 5 images every 5 minutes.', 'robin-image-optimizer' ),
465
+ 'default' => '3'
466
+ ];
467
+
468
+ $options[] = [
469
+ 'type' => 'div',
470
+ 'id' => 'wbcr-io-shedule-options',
471
+ 'items' => $group_items
472
+ ];
473
+
474
+ $options = apply_filters( 'wbcr/rio/settings_page/options', $options );
475
+
476
+ $formOptions = [];
477
+
478
+ $formOptions[] = [
479
+ 'type' => 'form-group',
480
+ 'items' => $options,
481
+ //'cssClass' => 'postbox'
482
+ ];
483
+
484
+ return $formOptions;
485
+ }
486
+
487
+ /**
488
+ * Save advanced options in database
489
+ *
490
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
491
+ * @since 1.3.6
492
+ */
493
+ public function beforeFormSave() {
494
+
495
+ /**
496
+ * Used to save webp options. It can also be used to intercept
497
+ * other unregistered fields.
498
+ *
499
+ * @since 1.3.6
500
+ */
501
+ do_action( "wrio/settings_page/berfore_form_save" );
502
+
503
+ $error_log = (int) WRIO_Plugin::app()->request->post( WRIO_Plugin::app()->getPrefix() . 'error_log', 0 );
504
+
505
+ if ( ! $error_log ) {
506
+ return;
507
+ }
508
+
509
+ $keep_error_log_on_frontend = (int) WRIO_Plugin::app()->request->post( 'wrio_keep_error_log_on_frontend', 0 );
510
+
511
+ WRIO_Plugin::app()->updatePopulateOption( 'keep_error_log_on_frontend', $keep_error_log_on_frontend );
512
+ }
513
+
514
+ /**
515
+ * This method adds advanced options for the "Convert Images to WebP" checkbox.
516
+ *
517
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
518
+ * @since 1.3.6
519
+ */
520
+ public function conver_webp_options() {
521
+
522
+ /**
523
+ * This hook prints options for delivering webp images.
524
+ *
525
+ * @since 1.3.6
526
+ */
527
+ do_action( "wrio/settings_page/conver_webp_options" );
528
+ }
529
+
530
+ /**
531
+ * This method adds advanced options for the "Error log" checkbox.
532
+ *
533
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
534
+ * @since 1.3.6
535
+ */
536
+ public function error_log_options() {
537
+ $this->view->print_template( 'part-settings-page-error-log-options', [
538
+ 'keep_error_log_on_frontend' => (int) WRIO_Plugin::app()->getPopulateOption( 'keep_error_log_on_frontend', 0 )
539
+ ] );
540
+ }
541
+
542
+ /**
543
+ * Кнопка восстановления изображений
544
+ */
545
+ public function rollbackButton() {
546
+ ?>
547
+ <div class="form-group form-group-checkbox factory-control-rollback-button">
548
+ <label for="wio-clear-backup-btn" class="col-sm-4 control-label">
549
+ <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
550
+ <span class="factory-hint-icon factory-hint-icon-red" data-toggle="factory-tooltip"
551
+ data-placement="right" title=""
552
+ data-original-title="<?php _e( 'You can restore the original images from a backup or clear them.', 'robin-image-optimizer' ); ?>">
553
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
554
+ alt="">
555
+ </span>
556
+ </label>
557
+ <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
558
+ <div class="control-group col-sm-8">
559
+ <div class="factory-buttons-way btn-group">
560
+ <a class="btn btn-default" id="wio-restore-backup-btn"
561
+ data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>"
562
+ href="#"><?php _e( 'Restore', 'robin-image-optimizer' ); ?></a>
563
+ <a class="btn btn-default" id="wio-clear-backup-btn"
564
+ data-confirm="<?php _e( 'Are you sure that you want to clear image backups folder?', 'robin-image-optimizer' ); ?>"
565
+ href="#"><?php _e( 'Clear Backup', 'robin-image-optimizer' ); ?></a>
566
+ </div>
567
+ <?php //if ( WRIO_Plugin::app()->isNetworkAdmin() ) : ?>
568
+ <!-- <div id="wio-multisite-mode" style="display:none;">-->
569
+ <!-- <ul class="factory-list factory-from-control-list factory-checklist-way">-->
570
+ <!-- --><?php
571
+ // $blogs = WIO_Multisite::getBlogs();
572
+ // ?>
573
+ <!-- <li>-->
574
+ <!-- <label for="wbcr_io_multisite_blog_all">-->
575
+ <!-- <span>-->
576
+ <!-- <input value="all" id="wbcr_io_multisite_blog_all" type="checkbox">-->
577
+ <!-- </span>-->
578
+ <!-- <span>-->
579
+ <?php //echo __( 'Select all', 'robin-image-optimizer' ); ?><!--</span>-->
580
+ <!-- </label>-->
581
+ <!-- </li>-->
582
+ <!-- --><?php //foreach ( $blogs as $blog ) : ?>
583
+ <!-- <li>-->
584
+ <!-- <label for="wbcr_io_multisite_blog_-->
585
+ <?php //echo esc_attr( $blog->blog_id ); ?><!--">-->
586
+ <!-- --><?php
587
+ // $blog_name = $blog->domain . $blog->path;
588
+ // if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
589
+ // $blog_name = $blog->domain;
590
+ // }
591
+ // ?>
592
+ <!-- <span>-->
593
+ <!-- <input data-name="--><?php //echo esc_attr( $blog_name ); ?><!--"-->
594
+ <!-- class="wbcr_io_multisite_blogs"-->
595
+ <!-- value="--><?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
596
+ <!-- id="wbcr_io_multisite_blog_-->
597
+ <?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
598
+ <!-- type="checkbox">-->
599
+ <!-- </span>-->
600
+ <!-- <span>--><?php //echo esc_attr( $blog_name ); ?><!--</span>-->
601
+ <!-- </label>-->
602
+ <!-- </li>-->
603
+ <!-- --><?php //endforeach; ?>
604
+ <!-- </ul>-->
605
+ <!-- <button id="wio-multisite-confirm" class="btn btn-default" type="button"-->
606
+ <!-- data-action="">-->
607
+ <?php //echo __( 'Start', 'robin-image-optimizer' ); ?><!--</button>-->
608
+ <!-- </div>-->
609
+ <!-- <div id="wio-multisite-restore-progress" style="display:none;">-->
610
+ <!-- </div>-->
611
+ <?php //endif; ?>
612
+ <div class="progress" id="wio-restore-backup-progress" style="display:none;">
613
+ <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0"
614
+ aria-valuemin="0" aria-valuemax="100" style="width:0%">
615
+ </div>
616
+ </div>
617
+ <p id="wio-restore-backup-msg"
618
+ style="display:none;"><?php _e( 'Restore completed.', 'robin-image-optimizer' ); ?></p>
619
+ <p id="wio-clear-backup-msg"
620
+ style="display:none;"><?php _e( 'The backup folder was cleared.', 'robin-image-optimizer' ); ?></p>
621
+ </div>
622
+ </div>
623
+ <?php
624
+ }
625
+ }
admin/pages/class-rio-statistic.php CHANGED
@@ -1,279 +1,306 @@
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
-
93
- /**
94
- * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
95
- * Меню текущего плагина будет добавлено в общее меню Clearfy
96
- *
97
- * @return string
98
- */
99
- public function getMenuScope() {
100
- if ( $this->clearfy_collaboration ) {
101
- //$this->internal = true;
102
-
103
- return 'wbcr_clearfy';
104
- }
105
-
106
- return $this->plugin->getPluginName();
107
- }
108
-
109
- /**
110
- * {@inheritdoc}
111
- */
112
- public function getMenuTitle() {
113
- return $this->clearfy_collaboration ? __( 'Robin Image Optimizer', 'robin-image-optimizer' ) : __( 'Robin image optimizer', 'robin-image-optimizer' );
114
- }
115
-
116
- /**
117
- * {@inheritdoc}
118
- */
119
- public function getPageTitle() {
120
- return $this->clearfy_collaboration ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Bulk optimization', 'robin-image-optimizer' );
121
- }
122
-
123
- /**
124
- * {@inheritdoc}
125
- */
126
- public function assets( $scripts, $styles ) {
127
- parent::assets( $scripts, $styles );
128
-
129
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
130
-
131
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/sweetalert2.js' );
132
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert2.css' );
133
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert-custom.css' );
134
-
135
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js' );
136
- //$this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js' );
137
-
138
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/modals.js', [ 'jquery' ], 'wrio-modals' );
139
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/bulk-optimization.js', [
140
- 'jquery',
141
- 'wrio-modals'
142
- ] );
143
-
144
- // Add Clearfy styles for HMWP pages
145
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
146
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
147
- }
148
- }
149
-
150
- /**
151
- * Print localization only current page
152
- *
153
- * @throws \Exception
154
- * @since 1.3.0
155
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
156
- */
157
- public function print_i18n() {
158
- $page = $this->plugin->request->get( 'page', null );
159
-
160
- if ( $page != $this->getResultId() ) {
161
- return;
162
- }
163
-
164
- $backup = new WIO_Backup();
165
-
166
- wp_enqueue_script( 'wio-statistic-page', WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
167
- wp_localize_script( 'wio-statistic-page', 'wrio_l18n_bulk_page', $this->get_i18n() );
168
-
169
- wp_localize_script( 'wio-statistic-page', 'wrio_settings_bulk_page', [
170
- 'is_premium' => wrio_is_license_activate(),
171
- 'is_network_admin' => WRIO_Plugin::app()->isNetworkAdmin() ? 1 : 0,
172
- 'is_writable_backup_dir' => $backup->isBackupWritable() ? 1 : 0,
173
- 'images_backup' => WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false ) ? 1 : 0,
174
- 'need_migration' => wbcr_rio_has_meta_to_migrate() ? 1 : 0,
175
- 'scope' => $this->scope,
176
- 'nonce' => wp_create_nonce( 'bulk_optimization' )
177
- ] );
178
- }
179
-
180
- /**
181
- * {@inheritdoc}
182
- */
183
- public function showPageContent() {
184
- $is_premium = wrio_is_license_activate();
185
- $statistics = $this->get_statisctic_data();
186
-
187
- $template_data = [
188
- 'is_premium' => $is_premium,
189
- 'scope' => $this->scope
190
- ];
191
-
192
- //do_action( 'wbcr/rio/multisite_current_blog' );
193
-
194
- // Page header
195
- $this->view->print_template( 'part-page-header', [
196
- 'title' => __( 'Image optimization dashboard', 'robin-image-optimizer' ),
197
- 'description' => __( 'Monitor image optimization statistics and run on demand or scheduled optimization.', 'robin-image-optimizer' )
198
- ], $this );
199
-
200
- // Page tabs
201
- $this->view->print_template( 'part-bulk-optimization-tabs', $template_data, $this );
202
-
203
- ?>
204
- <div class="wbcr-factory-page-group-body" style="padding:0; border-top: 1px solid #d4d4d4;">
205
- <?php
206
- // Servers
207
- $this->view->print_template( 'part-bulk-optimization-servers', $template_data, $this );
208
-
209
- // Total
210
- $this->view->print_template( 'part-bulk-optimization-total', $template_data, $this );
211
-
212
- // Statistic
213
- $this->view->print_template( 'part-bulk-optimization-statistic', array_merge( $template_data, [
214
- 'stats' => $statistics->get()
215
- ] ), $this );
216
-
217
- // Optimization log
218
- $this->view->print_template( 'part-bulk-optimization-log', array_merge( $template_data, [
219
- 'process_log' => $statistics->get_last_optimized_images()
220
- ] ), $this );
221
- ?>
222
- </div>
223
- <script type="text/html" id="wrio-tmpl-bulk-optimization">
224
- <?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
225
- </script>
226
- <?php
227
- //do_action( 'wbcr/rio/multisite_restore_blog' );
228
- }
229
-
230
- /**
231
- * @return object|\WRIO_Image_Statistic
232
- * @since 1.3.0
233
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
234
- */
235
- protected function get_statisctic_data() {
236
- return WRIO_Image_Statistic::get_instance();
237
- }
238
-
239
- /**
240
- * @return array
241
- * @since 1.3.0
242
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
243
- */
244
- protected function get_i18n() {
245
- $modal_optimization_cron_button = __( 'Scheduled optimization', 'robin-image-optimizer' );
246
- $button_stop_cron = __( 'Stop schedule optimization', 'robin-image-optimizer' );
247
-
248
- $optimize_type = WRIO_Plugin::app()->getOption( 'image_optimization_type', 'schedule' );
249
- if ( wrio_is_license_activate() && $optimize_type === 'background' ) {
250
- $modal_optimization_cron_button = __( 'Background optimization', 'robin-image-optimizer' );
251
- $button_stop_cron = __( 'Stop background optimization', 'robin-image-optimizer' );
252
- }
253
-
254
- return [
255
- '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' ),
256
- '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' ),
257
- 'server_status_down' => __( 'down', 'robin-image-optimizer' ),
258
- 'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
259
- 'modal_error' => __( 'Error', 'robin-image-optimizer' ),
260
- 'modal_cancel' => __( 'Cancel', 'robin-image-optimizer' ),
261
- 'modal_confirm' => __( 'Confirm', 'robin-image-optimizer' ),
262
- 'modal_optimization_title' => __( 'Select optimization way', 'robin-image-optimizer' ),
263
- 'modal_optimization_manual_button' => __( 'Optimize now', 'robin-image-optimizer' ),
264
- 'modal_optimization_cron_button' => $modal_optimization_cron_button,
265
- 'need_migrations' => __( 'To start optimizing, you must complete migration from old plugin version.', 'robin-image-optimizer' ),
266
- 'optimization_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
267
- 'optimization_inprogress' => __( 'Optimization in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
268
- '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' ),
269
- 'process_without_backup' => __( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ),
270
- 'button_resume' => __( 'Resume', 'robin-image-optimizer' ),
271
- 'button_completed' => __( 'Completed', 'robin-image-optimizer' ),
272
- 'buttom_start' => __( 'Run', 'robin-image-optimizer' ),
273
- 'button_stop' => __( 'Stop', 'robin-image-optimizer' ),
274
- 'button_stop_cron' => $button_stop_cron,
275
- //Don't Need a Parachute?
276
- //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.
277
- ];
278
- }
279
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
93
+ /**
94
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
95
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
96
+ *
97
+ * @return string
98
+ */
99
+ public function getMenuScope() {
100
+ if ( $this->clearfy_collaboration ) {
101
+ //$this->internal = true;
102
+
103
+ return 'wbcr_clearfy';
104
+ }
105
+
106
+ return $this->plugin->getPluginName();
107
+ }
108
+
109
+ /**
110
+ * {@inheritdoc}
111
+ */
112
+ public function getMenuTitle() {
113
+ return $this->clearfy_collaboration ? __( 'Robin Image Optimizer', 'robin-image-optimizer' ) : __( 'Robin image optimizer', 'robin-image-optimizer' );
114
+ }
115
+
116
+ /**
117
+ * {@inheritdoc}
118
+ */
119
+ public function getPageTitle() {
120
+ return $this->clearfy_collaboration ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Bulk optimization', 'robin-image-optimizer' );
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function assets( $scripts, $styles ) {
127
+ parent::assets( $scripts, $styles );
128
+
129
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
130
+
131
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/sweetalert2.js' );
132
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert2.css' );
133
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/sweetalert-custom.css' );
134
+
135
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js' );
136
+ //$this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js' );
137
+
138
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/modals.js', [ 'jquery' ], 'wrio-modals' );
139
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/bulk-optimization.js', [
140
+ 'jquery',
141
+ 'wrio-modals'
142
+ ] );
143
+ if ( wrio_is_license_activate() ) {
144
+ $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/bulk-conversion.js', [
145
+ 'jquery',
146
+ 'wrio-modals'
147
+ ] );
148
+
149
+ }
150
+
151
+ // Add Clearfy styles for HMWP pages
152
+ if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
153
+ $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Print localization only current page
159
+ *
160
+ * @throws \Exception
161
+ * @since 1.3.0
162
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
163
+ */
164
+ public function print_i18n() {
165
+ $page = $this->plugin->request->get( 'page', null );
166
+
167
+ if ( $page != $this->getResultId() ) {
168
+ return;
169
+ }
170
+
171
+ $backup = new WIO_Backup();
172
+
173
+ wp_enqueue_script( 'wio-statistic-page', WRIO_PLUGIN_URL . '/admin/assets/js/statistic.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
174
+ wp_localize_script( 'wio-statistic-page', 'wrio_l18n_bulk_page', $this->get_i18n() );
175
+
176
+ wp_localize_script( 'wio-statistic-page', 'wrio_settings_bulk_page', [
177
+ 'is_premium' => wrio_is_license_activate(),
178
+ 'is_network_admin' => WRIO_Plugin::app()->isNetworkAdmin() ? 1 : 0,
179
+ 'is_writable_backup_dir' => $backup->isBackupWritable() ? 1 : 0,
180
+ 'images_backup' => WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false ) ? 1 : 0,
181
+ 'need_migration' => wbcr_rio_has_meta_to_migrate() ? 1 : 0,
182
+ 'scope' => $this->scope,
183
+ 'optimization_nonce' => wp_create_nonce( 'bulk_optimization' ),
184
+ 'conversion_nonce' => wp_create_nonce( 'bulk_conversion' ),
185
+ ] );
186
+ }
187
+
188
+ /**
189
+ * {@inheritdoc}
190
+ */
191
+ public function showPageContent() {
192
+ $is_premium = wrio_is_license_activate();
193
+ $statistics = $this->get_statisctic_data();
194
+
195
+ $template_data = [
196
+ 'is_premium' => $is_premium,
197
+ 'scope' => $this->scope
198
+ ];
199
+
200
+ //do_action( 'wbcr/rio/multisite_current_blog' );
201
+
202
+ // Page header
203
+ $this->view->print_template( 'part-page-header', [
204
+ 'title' => __( 'Image optimization dashboard', 'robin-image-optimizer' ),
205
+ 'description' => __( 'Monitor image optimization statistics and run on demand or scheduled optimization.', 'robin-image-optimizer' )
206
+ ], $this );
207
+
208
+ // Page tabs
209
+ $this->view->print_template( 'part-bulk-optimization-tabs', $template_data, $this );
210
+
211
+ ?>
212
+ <div class="wbcr-factory-page-group-body" style="padding:0; border-top: 1px solid #d4d4d4;">
213
+ <?php
214
+ // Servers
215
+ $this->view->print_template( 'part-bulk-optimization-servers', $template_data, $this );
216
+
217
+ // Total
218
+ $this->view->print_template( 'part-bulk-optimization-total', $template_data, $this );
219
+
220
+ // Statistic
221
+ $this->view->print_template( 'part-bulk-optimization-statistic', array_merge( $template_data, [
222
+ 'stats' => $statistics->get()
223
+ ] ), $this );
224
+
225
+ // Optimization log
226
+ $this->view->print_template( 'part-bulk-optimization-log', array_merge( $template_data, [
227
+ 'process_log' => $statistics->get_last_optimized_images()
228
+ ] ), $this );
229
+ ?>
230
+ </div>
231
+ <script type="text/html" id="wrio-tmpl-bulk-optimization">
232
+ <?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
233
+ </script>
234
+ <?php if ( wrio_is_license_activate() ): ?>
235
+ <script type="text/html" id="wrio-tmpl-webp-conversion">
236
+ <?php $this->view->print_template( 'modal-webp-conversion' ); ?>
237
+ </script>
238
+ <?php endif; ?>
239
+ <?php
240
+ //do_action( 'wbcr/rio/multisite_restore_blog' );
241
+ }
242
+
243
+ /**
244
+ * @return object|\WRIO_Image_Statistic
245
+ * @since 1.3.0
246
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
247
+ */
248
+ protected function get_statisctic_data() {
249
+ return WRIO_Image_Statistic::get_instance();
250
+ }
251
+
252
+ /**
253
+ * @return array
254
+ * @since 1.3.0
255
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
256
+ */
257
+ protected function get_i18n() {
258
+ $modal_optimization_cron_button = __( 'Scheduled optimization', 'robin-image-optimizer' );
259
+ $modal_conversion_cron_button = __( 'Scheduled conversion', 'robin-image-optimizer' );
260
+ $modal_optimization_cron_button_stop = __( 'Stop schedule optimization', 'robin-image-optimizer' );
261
+ $modal_conversion_cron_button_stop = __( 'Stop schedule conversion', 'robin-image-optimizer' );
262
+
263
+ $optimize_type = WRIO_Plugin::app()->getOption( 'image_optimization_type', 'schedule' );
264
+ if ( wrio_is_license_activate() && $optimize_type === 'background' ) {
265
+ $modal_optimization_cron_button = __( 'Background optimization', 'robin-image-optimizer' );
266
+ $modal_conversion_cron_button = __( 'Background conversion', 'robin-image-optimizer' );
267
+ $modal_optimization_cron_button_stop = __( 'Stop background optimization', 'robin-image-optimizer' );
268
+ $modal_conversion_cron_button_stop = __( 'Stop background conversion', 'robin-image-optimizer' );
269
+ }
270
+
271
+ return [
272
+ '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' ),
273
+ 'webp_premium_server_disabled' => __( "You can't convert to WebP through a free optimization server. Select the premium optimization server.", 'robin-image-optimizer' ),
274
+ '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' ),
275
+ 'server_status_down' => __( 'down', 'robin-image-optimizer' ),
276
+ 'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
277
+ 'modal_error' => __( 'Error', 'robin-image-optimizer' ),
278
+ 'modal_cancel' => __( 'Cancel', 'robin-image-optimizer' ),
279
+ 'modal_confirm' => __( 'Confirm', 'robin-image-optimizer' ),
280
+
281
+ 'modal_optimization_title' => __( 'Select optimization way', 'robin-image-optimizer' ),
282
+ 'modal_optimization_manual_button' => __( 'Optimize now', 'robin-image-optimizer' ),
283
+ 'modal_optimization_cron_button' => $modal_optimization_cron_button,
284
+ 'modal_optimization_cron_button_stop' => $modal_optimization_cron_button_stop,
285
+ 'optimization_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
286
+ 'optimization_inprogress' => __( 'Optimization in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
287
+ 'modal_conversion_title' => __( 'Select conversion way', 'robin-image-optimizer' ),
288
+ 'modal_conversion_manual_button' => __( 'Convert now', 'robin-image-optimizer' ),
289
+ 'modal_conversion_cron_button' => $modal_conversion_cron_button,
290
+ 'modal_conversion_cron_button_stop' => $modal_conversion_cron_button_stop,
291
+ 'conversion_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
292
+ 'conversion_inprogress' => __( 'Conversion in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
293
+ 'webp_button_start' => __( 'Convert to WebP', 'robin-image-optimizer' ),
294
+
295
+ 'need_migrations' => __( 'To start optimizing, you must complete migration from old plugin version.', 'robin-image-optimizer' ),
296
+ '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' ),
297
+ 'process_without_backup' => __( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ),
298
+ 'button_resume' => __( 'Resume', 'robin-image-optimizer' ),
299
+ 'button_completed' => __( 'Completed', 'robin-image-optimizer' ),
300
+ 'button_start' => __( 'Optimize', 'robin-image-optimizer' ),
301
+ 'button_stop' => __( 'Stop', 'robin-image-optimizer' ),
302
+ //Don't Need a Parachute?
303
+ //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.
304
+ ];
305
+ }
306
+ }
admin/pages/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
assets/js/jquery.lazy.js DELETED
@@ -1,872 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
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 CHANGED
@@ -1,11 +1,11 @@
1
- /*if ('loading' in HTMLImageElement.prototype && wbcr_robin.wpCompatibleLazy === 'yes') {
2
- //loading="lazy" in WP >= 5.5
3
- } else {
4
- }*/
5
-
6
- const el = document.querySelectorAll('img');
7
- const observer = lozad(el, {
8
- loaded: function (el) {
9
- },
10
- });
11
- observer.observe();
1
+ /*if ('loading' in HTMLImageElement.prototype && wbcr_robin.wpCompatibleLazy === 'yes') {
2
+ //loading="lazy" in WP >= 5.5
3
+ } else {
4
+ }*/
5
+
6
+ const el = document.querySelectorAll('img');
7
+ const observer = lozad(el, {
8
+ loaded: function (el) {
9
+ },
10
+ });
11
+ observer.observe();
assets/js/lozad.min.js CHANGED
@@ -1,10 +1,10 @@
1
- /*! lozad.js - v1.16.0 - 2020-09-06
2
- * https://github.com/ApoorvSaxena/lozad.js
3
- * Copyright (c) 2020 Apoorv Saxena; Licensed MIT */
4
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.lozad=e()}(this,function(){"use strict";
5
- /**
6
- * Detect IE browser
7
- * @const {boolean}
8
- * @private
9
- */var g="undefined"!=typeof document&&document.documentMode,f={rootMargin:"0px",threshold:0,load:function(t){if("picture"===t.nodeName.toLowerCase()){var e=t.querySelector("img"),r=!1;null===e&&(e=document.createElement("img"),r=!0),g&&t.getAttribute("data-iesrc")&&(e.src=t.getAttribute("data-iesrc")),t.getAttribute("data-alt")&&(e.alt=t.getAttribute("data-alt")),r&&t.append(e)}if("video"===t.nodeName.toLowerCase()&&!t.getAttribute("data-src")&&t.children){for(var a=t.children,o=void 0,i=0;i<=a.length-1;i++)(o=a[i].getAttribute("data-src"))&&(a[i].src=o);t.load()}t.getAttribute("data-poster")&&(t.poster=t.getAttribute("data-poster")),t.getAttribute("data-src")&&(t.src=t.getAttribute("data-src")),t.getAttribute("data-srcset")&&t.setAttribute("srcset",t.getAttribute("data-srcset"));var n=",";if(t.getAttribute("data-background-delimiter")&&(n=t.getAttribute("data-background-delimiter")),t.getAttribute("data-background-image"))t.style.backgroundImage="url('"+t.getAttribute("data-background-image").split(n).join("'),url('")+"')";else if(t.getAttribute("data-background-image-set")){var d=t.getAttribute("data-background-image-set").split(n),u=d[0].substr(0,d[0].indexOf(" "))||d[0];// Substring before ... 1x
10
  u=-1===u.indexOf("url(")?"url("+u+")":u,1===d.length?t.style.backgroundImage=u:t.setAttribute("style",(t.getAttribute("style")||"")+"background-image: "+u+"; background-image: -webkit-image-set("+d+"); background-image: image-set("+d+")")}t.getAttribute("data-toggle-class")&&t.classList.toggle(t.getAttribute("data-toggle-class"))},loaded:function(){}};function A(t){t.setAttribute("data-loaded",!0)}var m=function(t){return"true"===t.getAttribute("data-loaded")},v=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:document;return t instanceof Element?[t]:t instanceof NodeList?t:e.querySelectorAll(t)};return function(){var r,a,o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".lozad",t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},e=Object.assign({},f,t),i=e.root,n=e.rootMargin,d=e.threshold,u=e.load,g=e.loaded,s=void 0;"undefined"!=typeof window&&window.IntersectionObserver&&(s=new IntersectionObserver((r=u,a=g,function(t,e){t.forEach(function(t){(0<t.intersectionRatio||t.isIntersecting)&&(e.unobserve(t.target),m(t.target)||(r(t.target),A(t.target),a(t.target)))})}),{root:i,rootMargin:n,threshold:d}));for(var c,l=v(o,i),b=0;b<l.length;b++)(c=l[b]).getAttribute("data-placeholder-background")&&(c.style.background=c.getAttribute("data-placeholder-background"));return{observe:function(){for(var t=v(o,i),e=0;e<t.length;e++)m(t[e])||(s?s.observe(t[e]):(u(t[e]),A(t[e]),g(t[e])))},triggerLoad:function(t){m(t)||(u(t),A(t),g(t))},observer:s}}});
1
+ /*! lozad.js - v1.16.0 - 2020-09-06
2
+ * https://github.com/ApoorvSaxena/lozad.js
3
+ * Copyright (c) 2020 Apoorv Saxena; Licensed MIT */
4
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.lozad=e()}(this,function(){"use strict";
5
+ /**
6
+ * Detect IE browser
7
+ * @const {boolean}
8
+ * @private
9
+ */var g="undefined"!=typeof document&&document.documentMode,f={rootMargin:"0px",threshold:0,load:function(t){if("picture"===t.nodeName.toLowerCase()){var e=t.querySelector("img"),r=!1;null===e&&(e=document.createElement("img"),r=!0),g&&t.getAttribute("data-iesrc")&&(e.src=t.getAttribute("data-iesrc")),t.getAttribute("data-alt")&&(e.alt=t.getAttribute("data-alt")),r&&t.append(e)}if("video"===t.nodeName.toLowerCase()&&!t.getAttribute("data-src")&&t.children){for(var a=t.children,o=void 0,i=0;i<=a.length-1;i++)(o=a[i].getAttribute("data-src"))&&(a[i].src=o);t.load()}t.getAttribute("data-poster")&&(t.poster=t.getAttribute("data-poster")),t.getAttribute("data-src")&&(t.src=t.getAttribute("data-src")),t.getAttribute("data-srcset")&&t.setAttribute("srcset",t.getAttribute("data-srcset"));var n=",";if(t.getAttribute("data-background-delimiter")&&(n=t.getAttribute("data-background-delimiter")),t.getAttribute("data-background-image"))t.style.backgroundImage="url('"+t.getAttribute("data-background-image").split(n).join("'),url('")+"')";else if(t.getAttribute("data-background-image-set")){var d=t.getAttribute("data-background-image-set").split(n),u=d[0].substr(0,d[0].indexOf(" "))||d[0];// Substring before ... 1x
10
  u=-1===u.indexOf("url(")?"url("+u+")":u,1===d.length?t.style.backgroundImage=u:t.setAttribute("style",(t.getAttribute("style")||"")+"background-image: "+u+"; background-image: -webkit-image-set("+d+"); background-image: image-set("+d+")")}t.getAttribute("data-toggle-class")&&t.classList.toggle(t.getAttribute("data-toggle-class"))},loaded:function(){}};function A(t){t.setAttribute("data-loaded",!0)}var m=function(t){return"true"===t.getAttribute("data-loaded")},v=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:document;return t instanceof Element?[t]:t instanceof NodeList?t:e.querySelectorAll(t)};return function(){var r,a,o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".lozad",t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},e=Object.assign({},f,t),i=e.root,n=e.rootMargin,d=e.threshold,u=e.load,g=e.loaded,s=void 0;"undefined"!=typeof window&&window.IntersectionObserver&&(s=new IntersectionObserver((r=u,a=g,function(t,e){t.forEach(function(t){(0<t.intersectionRatio||t.isIntersecting)&&(e.unobserve(t.target),m(t.target)||(r(t.target),A(t.target),a(t.target)))})}),{root:i,rootMargin:n,threshold:d}));for(var c,l=v(o,i),b=0;b<l.length;b++)(c=l[b]).getAttribute("data-placeholder-background")&&(c.style.background=c.getAttribute("data-placeholder-background"));return{observe:function(){for(var t=v(o,i),e=0;e<t.length;e++)m(t[e])||(s?s.observe(t[e]):(u(t[e]),A(t[e]),g(t[e])))},triggerLoad:function(t){m(t)||(u(t),A(t),g(t))},observer:s}}});
includes/class-rio-plugin.php CHANGED
@@ -1,209 +1,212 @@
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_Factory446_Plugin {
15
-
16
- /**
17
- * @see self::app()
18
- * @var Wbcr_Factory446_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 ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
48
- // Processing
49
- if ( wrio_is_license_activate() ) {
50
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-processing.php' );
51
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-media-processing.php' );
52
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-folder-processing.php' );
53
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-nextgen-processing.php' );
54
- }
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
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
70
- // Ajax files
71
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/backup.php' );
72
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-bulk-optimization.php' );
73
- new WRIO_Bulk_Optimization();
74
-
75
- //require_once( WRIO_PLUGIN_DIR . '/admin/ajax/logs.php' );
76
-
77
- // Not under AJAX logical operator above on purpose to have helpers available to find out whether
78
- // metas were migrated or not
79
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/meta-migrations.php' );
80
- }
81
- }
82
-
83
- add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
84
- }
85
-
86
- /**
87
- * Статический метод для быстрого доступа к интерфейсу плагина.
88
- *
89
- * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
90
- * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
91
- *
92
- * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
93
- * классам.
94
- *
95
- * @return \Wbcr_Factory446_Plugin|\WRIO_Plugin
96
- */
97
- public static function app() {
98
- return self::$app;
99
- }
100
-
101
- /**
102
- * Подключаем функции бекенда
103
- *
104
- * @throws Exception
105
- */
106
- public function pluginsLoaded() {
107
- if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
108
- $media_library = WRIO_Media_Library::get_instance();
109
- $media_library->initHooks();
110
- }
111
-
112
- if ( is_admin() ) {
113
- require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
114
- //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
115
-
116
- $this->registerPages();
117
- }
118
-
119
- if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
120
- $media_library = WRIO_Media_Library::get_instance();
121
- $media_library->initHooks();
122
- }
123
-
124
- if ( wrio_is_license_activate() ) {
125
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
126
- wrio_premium_load();
127
- }
128
- }
129
-
130
- /**
131
- * Подключаем модули классы и функции
132
- */
133
- protected function includes() {
134
-
135
- require_once( WRIO_PLUGIN_DIR . '/includes/functions.php' );
136
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-views.php' );
137
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-attachment.php' );
138
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-media-library.php' );
139
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-abstract.php' );
140
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-image-statistic.php' );
141
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-backup.php' );
142
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-optimization-tools.php' );
143
-
144
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-helper.php' );
145
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-object.php' ); // Base object
146
-
147
- // Database related models
148
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-active-record.php' );
149
- // Base class
150
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-extra-data.php' );
151
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-attachment-extra-data.php' );
152
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-server-smushit-extra-data.php' );
153
-
154
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-process-queue-table.php' ); // Processing queue model
155
-
156
- // Cron
157
- // ----------------
158
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-cron.php' );
159
- new WRIO_Cron();
160
- }
161
-
162
- /**
163
- * Инициализируем активацию плагина
164
- */
165
- protected function initActivation() {
166
- include_once( WRIO_PLUGIN_DIR . '/admin/activation.php' );
167
- self::app()->registerActivation( 'WIO_Activation' );
168
- }
169
-
170
- /**
171
- * Регистрируем страницы плагина
172
- *
173
- * @throws Exception
174
- */
175
- private function registerPages() {
176
- $admin_path = WRIO_PLUGIN_DIR . '/admin/pages/';
177
-
178
- // Parent page class
179
- require_once( $admin_path . '/class-rio-page.php' );
180
-
181
- if ( ! wrio_is_clearfy_license_activate() ) {
182
- self::app()->registerPage( 'WRIO_License_Page', $admin_path . '/class-rio-license.php' );
183
- }
184
-
185
- self::app()->registerPage( 'WRIO_SettingsPage', $admin_path . '/class-rio-settings.php' );
186
- self::app()->registerPage( 'WRIO_StatisticPage', $admin_path . '/class-rio-statistic.php' );
187
-
188
- if ( self::app()->getPopulateOption( 'error_log', false ) ) {
189
- self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
190
- }
191
- }
192
-
193
- /**
194
- * Option enables error logging on frontend. If for some reason webp images are not displayed on the front-end, you can use
195
- * this option to catch errors and send this report to the plugin support service.
196
- *
197
- * @return int
198
- * @since 1.3.6
199
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
200
- */
201
- public function is_keep_error_log_on_frontend() {
202
- if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
203
- return false;
204
- }
205
-
206
- return (int) $this->getPopulateOption( 'keep_error_log_on_frontend', 0 );
207
- }
208
- }
209
-
 
 
 
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_Factory450_Plugin {
15
+
16
+ /**
17
+ * @see self::app()
18
+ * @var Wbcr_Factory450_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 ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
48
+ // Processing
49
+ if ( wrio_is_license_activate() ) {
50
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-processing.php' );
51
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-media-processing.php' );
52
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-folder-processing.php' );
53
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-nextgen-processing.php' );
54
+
55
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processing/class-rio-media-processing-webp.php' );
56
+ }
57
+ }
58
+
59
+ if ( is_admin() ) {
60
+ $this->initActivation();
61
+
62
+ // completely disable image size threshold
63
+ add_filter( 'big_image_size_threshold', '__return_false' );
64
+
65
+ if ( wrio_is_license_activate() ) {
66
+ if ( ! defined( 'FACTORY_ADVERTS_BLOCK' ) ) {
67
+ define( 'FACTORY_ADVERTS_BLOCK', true );
68
+ }
69
+ }
70
+
71
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
72
+ // Ajax files
73
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/backup.php' );
74
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-bulk-optimization.php' );
75
+ new WRIO_Bulk_Optimization();
76
+
77
+ //require_once( WRIO_PLUGIN_DIR . '/admin/ajax/logs.php' );
78
+
79
+ // Not under AJAX logical operator above on purpose to have helpers available to find out whether
80
+ // metas were migrated or not
81
+ require_once( WRIO_PLUGIN_DIR . '/admin/ajax/meta-migrations.php' );
82
+ }
83
+ }
84
+
85
+ add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
86
+ }
87
+
88
+ /**
89
+ * Статический метод для быстрого доступа к интерфейсу плагина.
90
+ *
91
+ * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
92
+ * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
93
+ *
94
+ * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
95
+ * классам.
96
+ *
97
+ * @return \Wbcr_Factory450_Plugin|\WRIO_Plugin
98
+ */
99
+ public static function app() {
100
+ return self::$app;
101
+ }
102
+
103
+ /**
104
+ * Подключаем функции бекенда
105
+ *
106
+ * @throws Exception
107
+ */
108
+ public function pluginsLoaded() {
109
+ if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
110
+ $media_library = WRIO_Media_Library::get_instance();
111
+ $media_library->initHooks();
112
+ }
113
+
114
+ if ( is_admin() ) {
115
+ require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
116
+ //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
117
+
118
+ $this->registerPages();
119
+ }
120
+
121
+ if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
122
+ $media_library = WRIO_Media_Library::get_instance();
123
+ $media_library->initHooks();
124
+ }
125
+
126
+ if ( wrio_is_license_activate() ) {
127
+ require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
128
+ wrio_premium_load();
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Подключаем модули классы и функции
134
+ */
135
+ protected function includes() {
136
+
137
+ require_once( WRIO_PLUGIN_DIR . '/includes/functions.php' );
138
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-views.php' );
139
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-attachment.php' );
140
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-media-library.php' );
141
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-abstract.php' );
142
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-image-statistic.php' );
143
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-backup.php' );
144
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-optimization-tools.php' );
145
+
146
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-helper.php' );
147
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-object.php' ); // Base object
148
+
149
+ // Database related models
150
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-active-record.php' );
151
+ // Base class
152
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-extra-data.php' );
153
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-attachment-extra-data.php' );
154
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class.webp-extra-data.php' );
155
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-server-smushit-extra-data.php' );
156
+
157
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-process-queue-table.php' ); // Processing queue model
158
+
159
+ // Cron
160
+ // ----------------
161
+ require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-cron.php' );
162
+ new WRIO_Cron();
163
+ }
164
+
165
+ /**
166
+ * Инициализируем активацию плагина
167
+ */
168
+ protected function initActivation() {
169
+ include_once( WRIO_PLUGIN_DIR . '/admin/activation.php' );
170
+ self::app()->registerActivation( 'WIO_Activation' );
171
+ }
172
+
173
+ /**
174
+ * Регистрируем страницы плагина
175
+ *
176
+ * @throws Exception
177
+ */
178
+ private function registerPages() {
179
+ $admin_path = WRIO_PLUGIN_DIR . '/admin/pages/';
180
+
181
+ // Parent page class
182
+ require_once( $admin_path . '/class-rio-page.php' );
183
+
184
+ if ( ! wrio_is_clearfy_license_activate() ) {
185
+ self::app()->registerPage( 'WRIO_License_Page', $admin_path . '/class-rio-license.php' );
186
+ }
187
+
188
+ self::app()->registerPage( 'WRIO_SettingsPage', $admin_path . '/class-rio-settings.php' );
189
+ self::app()->registerPage( 'WRIO_StatisticPage', $admin_path . '/class-rio-statistic.php' );
190
+
191
+ if ( self::app()->getPopulateOption( 'error_log', false ) ) {
192
+ self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Option enables error logging on frontend. If for some reason webp images are not displayed on the front-end, you can use
198
+ * this option to catch errors and send this report to the plugin support service.
199
+ *
200
+ * @return int
201
+ * @since 1.3.6
202
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
203
+ */
204
+ public function is_keep_error_log_on_frontend() {
205
+ if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
206
+ return false;
207
+ }
208
+
209
+ return (int) $this->getPopulateOption( 'keep_error_log_on_frontend', 0 );
210
+ }
211
+ }
212
+
includes/classes/class-rio-attachment.php CHANGED
@@ -1,992 +1,1009 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы с WordPress attachment.
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WIO_Attachment {
16
-
17
- /**
18
- * @var int
19
- */
20
- private $id;
21
-
22
-
23
- /**
24
- * @var array meta-данные
25
- */
26
- private $attachment_meta;
27
-
28
- /**
29
- * @var array массив с данными о папке uploads
30
- */
31
- private $wp_upload_dir;
32
-
33
- /**
34
- * @var string
35
- */
36
- private $url;
37
-
38
- /**
39
- * @var string
40
- */
41
- private $path;
42
-
43
- /**
44
- * @var RIO_Process_Queue
45
- */
46
- private $optimization_data;
47
-
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;
56
- $this->wp_upload_dir = wp_upload_dir();
57
- $this->attachment_meta = $attachment_meta;
58
-
59
- if ( ! $attachment_meta ) {
60
- // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
61
- $this->attachment_meta = wp_get_attachment_metadata( $this->id );
62
- }
63
-
64
- $this->set_paths();
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'] );
74
- }
75
-
76
- /**
77
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
78
- * @since 1.3.9
79
- */
80
- public function set_paths() {
81
- if ( ! $this->isset_attachment_meta() ) {
82
- return;
83
- }
84
-
85
- $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
86
- $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
87
- }
88
-
89
- /**
90
- * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
91
- */
92
- public function reload( $attachment_meta = [] ) {
93
- if ( empty( $attachment_meta ) ) {
94
- $attachment_meta = wp_get_attachment_metadata( $this->id );
95
- }
96
- $this->attachment_meta = $attachment_meta;
97
- $this->optimization_data = new RIO_Process_Queue( [
98
- 'object_id' => $this->id,
99
- 'object_name' => '',
100
- 'item_type' => 'attachment',
101
- ] );
102
- $this->optimization_data->load();
103
- $this->set_paths();
104
- }
105
-
106
- /**
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() ) {
116
- return true;
117
- }
118
-
119
- WRIO_Plugin::app()->logger->info( sprintf( 'Try regenerate metadata for attachment #%d', $this->id ) );
120
-
121
- // Need to remove this filter, as it would start recursion
122
- remove_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload' );
123
-
124
- $file_path = get_attached_file( $this->id );
125
-
126
- if ( empty( $file_path ) ) {
127
- $attachment = get_post( $this->id );
128
-
129
- if ( empty( $attachment ) || 'attachment' !== $attachment->post_type ) {
130
- return false;
131
- }
132
-
133
- $file_path = wrio_url_to_abs_path( $attachment->guid );
134
- }
135
-
136
- if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
137
- WRIO_Plugin::app()->logger->info( sprintf( 'Failed regenerate attachment meta data. Attachment file (%s) doesn\'t exists!', $file_path ) );
138
-
139
- return false;
140
- }
141
-
142
- $attachment_meta = wp_generate_attachment_metadata( $this->id, $file_path );
143
-
144
- if ( empty( $attachment_meta ) ) {
145
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed regenerate meta data for attachment file (%s).', $file_path ) );
146
-
147
- return false;
148
- }
149
-
150
- WRIO_Plugin::app()->logger->debug( sprintf( 'Generated metadata: %s', var_export( $attachment_meta, true ) ) );
151
-
152
- # Updating metadata in database
153
- wp_update_attachment_metadata( $this->id, $attachment_meta );
154
-
155
- $this->reload( $attachment_meta );
156
-
157
- add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
158
-
159
- WRIO_Plugin::app()->logger->info( sprintf( 'Finish regenerate metadata for attachment #%d!', $this->id ) );
160
-
161
- return true;
162
- }
163
-
164
- /**
165
- * Добавляем сообщение в лог файл.
166
- *
167
- * @param string $message Текст сообщения об ошибке.
168
- */
169
- public function writeLog( $message ) {
170
-
171
- $char = "\t-> ";
172
- $nl = PHP_EOL;
173
-
174
- $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
175
- $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
176
- $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
177
- $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
178
- $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
179
- $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
180
-
181
- if ( ! empty( $this->attachment_meta['sizes'] ) ) {
182
- $error .= $char . ' Additional sizes:' . $nl;
183
- foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
184
- $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
185
- }
186
- }
187
-
188
- WRIO_Plugin::app()->logger->error( $error );
189
- }
190
-
191
- /**
192
- * Возвращает объект с информацией об оптимизации
193
- *
194
- * @return RIO_Process_Queue
195
- */
196
- public function getOptimizationData() {
197
- if ( ! isset( $optimization_data ) ) {
198
- $this->optimization_data = new RIO_Process_Queue( [
199
- 'object_id' => $this->id,
200
- 'object_name' => '',
201
- 'item_type' => 'attachment',
202
- ] );
203
- $this->optimization_data->load();
204
- }
205
-
206
- return $this->optimization_data;
207
- }
208
-
209
- /**
210
- * Оптимизация аттачмента.
211
- *
212
- * @param string $optimization_level Уровень оптимизации изображения.
213
- *
214
- * @return array
215
- */
216
- public function optimize( $optimization_level = '' ) {
217
- $optimize_results = [
218
- 'original_size' => 0,
219
- 'optimized_size' => 0,
220
- ];
221
-
222
- if ( empty( $optimization_level ) ) {
223
- $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
224
- }
225
-
226
- if ( $optimization_level == 'custom' ) {
227
- $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
228
- $optimization_level = intval( $custom_quality );
229
- }
230
-
231
- $optimization_data = $this->getOptimizationData();
232
- $results = [
233
- 'original_size' => 0,
234
- 'final_size' => 0,
235
- 'original_mime_type' => '',
236
- 'final_mime_type' => '',
237
- ];
238
- $results['processing_level'] = $optimization_level;
239
-
240
- # The path may be empty because no metadata has been created for the image.
241
- # We should try to create image metadata again.
242
- if ( ! $this->isset_attachment_meta() ) {
243
- WRIO_Plugin::app()->logger->warning( sprintf( 'Attachment #%d doesn\'t have metadata.', $this->id ) );
244
-
245
- $this->regenerate_metadata();
246
- }
247
-
248
- if ( empty( $this->path ) || ! file_exists( $this->path ) ) {
249
- $results['result_status'] = 'error';
250
-
251
- $error_message = __( 'Attachment cannot be optimized.', 'robin-image-optimizer' );
252
-
253
- if ( empty( $this->path ) ) {
254
- $error_message .= ' ' . sprintf( __( 'Attachment #%d doesn\'t have metadata, the image may be damaged.', 'robin-image-optimizer' ), $this->id );
255
- } else {
256
- $error_message .= ' ' . sprintf( __( 'File "(%s)" doesn\'t exist', 'robin-image-optimizer' ), $this->path );
257
- }
258
-
259
- $extra_data = [
260
- 'error' => 'path',
261
- 'error_msg' => $error_message,
262
- ];
263
-
264
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
265
- $optimization_data->configure( $results );
266
- $optimization_data->save();
267
-
268
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
269
-
270
- return $optimize_results;
271
- }
272
-
273
- // сначала бекапим
274
- $is_image_backuped = $this->backup();
275
-
276
- if ( is_wp_error( $is_image_backuped ) ) {
277
- $error_msg = $is_image_backuped->get_error_message();
278
- $this->writeLog( $error_msg );
279
-
280
- $results['result_status'] = 'error';
281
- $extra_data = [
282
- 'error' => 'backup',
283
- 'error_msg' => 'Failed to backup',
284
- ];
285
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
286
- $optimization_data->configure( $results );
287
- $optimization_data->save();
288
-
289
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
290
-
291
- return $optimize_results;
292
- }
293
-
294
- $results['is_backed_up'] = $is_image_backuped;
295
-
296
- $original_main_size = filesize( $this->path );
297
-
298
- // если файл большой - изменяем размер
299
- if ( $this->isNeedResize() ) {
300
- $this->resize();
301
- }
302
-
303
- $image_processor = WIO_OptimizationTools::getImageProcessor();
304
-
305
- clearstatcache(); // на всякий случай очистим кеш файловой статистики
306
-
307
- $optimized_img_data = $image_processor->process( [
308
- 'image_url' => $this->get( 'url' ),
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
- // проверяем на ошибку
316
- if ( is_wp_error( $optimized_img_data ) ) {
317
- $error_msg = $optimized_img_data->get_error_message();
318
- $this->writeLog( $error_msg );
319
-
320
- $results['result_status'] = 'error';
321
-
322
- $extra_data = [
323
- 'error' => 'optimization',
324
- 'error_msg' => $error_msg,
325
- ];
326
-
327
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
328
-
329
- $optimization_data->configure( $results );
330
- $optimization_data->save();
331
-
332
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
333
-
334
- return $optimize_results;
335
- }
336
-
337
- $results['original_mime_type'] = '';
338
- $results['final_mime_type'] = '';
339
-
340
- // отложенная оптимизация
341
- if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
342
- $results['result_status'] = 'processing';
343
- $results['original_size'] = 0;
344
- $results['final_size'] = 0;
345
-
346
- $extra_data = [
347
- 'main_optimized_data' => $optimized_img_data,
348
- 'thumbnails_optimized_data' => $this->optimizeImageSizes(),
349
- ];
350
-
351
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
352
-
353
- $optimization_data->configure( $results );
354
- $optimization_data->save();
355
- $optimize_results['processing'] = 1;
356
-
357
- return $optimize_results;
358
- }
359
-
360
- //скачиваем и заменяем главную картинку
361
- $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
362
-
363
- // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
364
- if ( ! $optimized_img_data['optimized_size'] ) {
365
- clearstatcache();
366
- $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
367
- }
368
-
369
- // при отрицательной оптимизации ставим значение оригинала
370
- if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
371
- $optimized_img_data['optimized_size'] = $original_main_size;
372
- }
373
-
374
- if ( $image_downloaded ) {
375
- //просчитываем статистику
376
- $optimize_results['original_size'] += $original_main_size;
377
- $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
378
- $thumbnails_count = 0;
379
-
380
- // оптимизируем дополнительные размеры
381
- $optimized_img_sizes_data = $this->optimizeImageSizes();
382
-
383
- // добавляем к статистике данные по оптимизации доп размеров
384
- if ( ! empty( $optimized_img_sizes_data ) ) {
385
- $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
386
- $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
387
- $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
388
- }
389
-
390
- $results['result_status'] = 'success';
391
- $results['final_size'] = $optimize_results['optimized_size'];
392
- $results['original_size'] = $optimize_results['original_size'];
393
-
394
- $extra_data = [
395
- 'thumbnails_count' => $thumbnails_count,
396
- 'original_main_size' => $original_main_size,
397
- ];
398
-
399
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
400
- $mime_type = '';
401
-
402
- if ( function_exists( 'wp_get_image_mime' ) ) {
403
- $mime_type = wp_get_image_mime( $this->get( 'path' ) );
404
- } else {
405
- WRIO_Plugin::app()->logger->error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
406
- }
407
-
408
- $results['original_mime_type'] = $mime_type;
409
- $results['final_mime_type'] = $mime_type;
410
- $optimization_data->configure( $results );
411
- } else {
412
- $error_msg = 'Failed to get optimized image from remote server';
413
- $this->writeLog( $error_msg );
414
-
415
- $results['result_status'] = 'error';
416
-
417
- $extra_data = [
418
- 'error' => 'download',
419
- 'error_msg' => $error_msg,
420
- ];
421
-
422
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
423
- $optimization_data->configure( $results );
424
- }
425
-
426
- $optimization_data->save();
427
-
428
- return $optimize_results;
429
- }
430
-
431
- /**
432
- * Отложенная оптимизация аттачмента
433
- *
434
- * @return bool|array
435
- */
436
- public function deferredOptimization() {
437
- $results = [
438
- 'original_size' => 0,
439
- 'optimized_size' => 0,
440
- 'optimized_count' => 0,
441
- 'processing' => 1,
442
- ];
443
-
444
- $image_processor = WIO_OptimizationTools::getImageProcessor();
445
- $optimization_data = $this->getOptimizationData();
446
-
447
- if ( $optimization_data->get_result_status() != 'processing' ) {
448
- return false;
449
- }
450
-
451
- // проверяем главную картинку
452
- /**
453
- * @var RIO_Attachment_Extra_Data $extra_data
454
- */
455
- $extra_data = $optimization_data->get_extra_data();
456
- $main_optimized_data = $extra_data->get_main_optimized_data();
457
- $main_image_url = '';
458
-
459
- if ( ! $main_optimized_data['optimized_img_url'] ) {
460
- $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
461
- if ( $main_image_url ) {
462
- $main_optimized_data['optimized_img_url'] = $main_image_url;
463
- $extra_data->set_main_optimized_data( $main_optimized_data );
464
- }
465
- }
466
-
467
- $thumbnails_processed = true;
468
- $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
469
- $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
470
-
471
- if ( is_array( $thumbnails['thumbnails'] ) ) {
472
- foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
473
- if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
474
- $thumbnail_image_url = $image_processor->checkDeferredOptimization( $thumbnail_optimized_data );
475
- if ( $thumbnail_image_url ) {
476
- $thumbnail_optimized_data['optimized_img_url'] = $thumbnail_image_url;
477
- } else {
478
- $thumbnails_processed = false;
479
- }
480
- }
481
- }
482
- $extra_data->set_thumbnails_optimized_data( $thumbnails );
483
- }
484
-
485
- // когда все файлы получены - сохраняем и возвращаем результат
486
- if ( $main_image_url && $thumbnails_processed ) {
487
- $original_size = 0;
488
- $optimized_size = 0;
489
- $thumbnails_count = 0;
490
- $original_main_size = filesize( $this->get( 'path' ) );
491
- $original_size = $original_size + $original_main_size;
492
-
493
- $this->replaceOriginalFile( [
494
- 'optimized_img_url' => $main_image_url,
495
- ] );
496
-
497
- clearstatcache();
498
-
499
- $optimized_main_size = filesize( $this->get( 'path' ) );
500
-
501
- // при отрицательной оптимизации ставим значение оригинала
502
- if ( $optimized_main_size > $original_main_size ) {
503
- $optimized_main_size = $original_main_size;
504
- }
505
-
506
- $optimized_size = $optimized_size + $optimized_main_size;
507
-
508
- if ( is_array( $thumbnails['thumbnails'] ) ) {
509
- foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
510
- $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
511
- $original_thumbnail_size = filesize( $thumbnail_file );
512
- $original_size = $original_size + $original_thumbnail_size;
513
-
514
- $this->replaceOriginalFile( [
515
- 'optimized_img_url' => $thumbnail['optimized_img_url'],
516
- ], $thumbnail_size );
517
-
518
- clearstatcache();
519
-
520
- $optimized_thumbnail_size = filesize( $thumbnail_file );
521
-
522
- // при отрицательной оптимизации ставим значение оригинала
523
- if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
524
- $optimized_thumbnail_size = $original_thumbnail_size;
525
- }
526
-
527
- $optimized_size = $optimized_size + $optimized_thumbnail_size;
528
-
529
- $thumbnails_count ++;
530
- }
531
- }
532
-
533
- $mime_type = '';
534
- if ( function_exists( 'wp_get_image_mime' ) ) {
535
- $mime_type = wp_get_image_mime( $this->get( 'path' ) );
536
- }
537
-
538
- $optimization_data->configure( [
539
- 'final_size' => $optimized_size,
540
- 'original_size' => $original_size,
541
- 'result_status' => 'success',
542
- 'original_mime_type' => $mime_type,
543
- 'final_mime_type' => $mime_type,
544
- ] );
545
-
546
- $extra_data->set_original_main_size( $original_main_size );
547
- $extra_data->set_thumbnails_count( $thumbnails_count );
548
-
549
- // удаляем промежуточные данные
550
- $extra_data->set_main_optimized_data( null );
551
- $extra_data->set_thumbnails_optimized_data( null );
552
- $extra_data->set_main_optimized_data( null );
553
-
554
- $results['optimized_count'] = 1;
555
- $results['original_size'] = $original_size;
556
- $results['optimized_size'] = $optimized_size;
557
-
558
- unset( $results['processing'] );
559
- }
560
- $optimization_data->set_extra_data( $extra_data );
561
- $optimization_data->save();
562
-
563
- return $results;
564
- }
565
-
566
- /**
567
- * Метод проверяет, оптимизирован ли аттачмент
568
- *
569
- * @return bool
570
- */
571
- public function isOptimized() {
572
- $optimization_data = $this->getOptimizationData();
573
- if ( $optimization_data->is_optimized() ) {
574
- return true;
575
- }
576
-
577
- return false;
578
- }
579
-
580
- /**
581
- * Возвращает все размеры аттачмента, которые нужно оптимизировать
582
- *
583
- * @return array|false
584
- */
585
- public function getAllowedSizes() {
586
- $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
587
-
588
- if ( ! $allowed_sizes ) {
589
- return false;
590
- }
591
-
592
- $allowed_sizes = explode( ',', $allowed_sizes );
593
-
594
- return $allowed_sizes;
595
- }
596
-
597
- /**
598
- * Оптимизация других размеров аттачмента.
599
- *
600
- * @return array
601
- */
602
- public function optimizeImageSizes() {
603
- $allowed_sizes = $this->getAllowedSizes();
604
-
605
- if ( $allowed_sizes === false ) {
606
- return [];
607
- }
608
-
609
- $image_processor = WIO_OptimizationTools::getImageProcessor();
610
- $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
611
-
612
- if ( $quality == 'custom' ) {
613
- $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
614
- $quality = intval( $custom_quality );
615
- }
616
-
617
- $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
618
-
619
- $original_size = 0;
620
- $optimized_size = 0;
621
- $errors_count = 0;
622
- $optimized_count = 0;
623
- $thumbnails = [];
624
-
625
- foreach ( $allowed_sizes as $image_size ) {
626
- $url = $this->getImageSizeUrl( $image_size );
627
- $path = $this->getImageSizePath( $image_size );
628
-
629
- if ( ! $url || ! $path ) {
630
- continue;
631
- }
632
-
633
- $original_file_size = 0;
634
-
635
- if ( is_file( $path ) ) {
636
- $original_file_size = filesize( $path );
637
- }
638
-
639
- $optimized_img_data = $image_processor->process( [
640
- 'image_url' => $url,
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 ) ) {
648
- $errors_count ++;
649
- } else {
650
- //скачиваем и заменяем картинку
651
- $this->replaceOriginalFile( $optimized_img_data, $image_size );
652
- // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
653
- if ( ! $optimized_img_data['optimized_size'] ) {
654
- clearstatcache();
655
- $optimized_img_data['optimized_size'] = filesize( $path );
656
- }
657
- if ( ! $optimized_img_data['src_size'] ) {
658
- $optimized_img_data['src_size'] = $original_file_size;
659
- }
660
-
661
- // при отрицательной оптимизации ставим значение оригинала
662
- if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
663
- $optimized_img_data['optimized_size'] = $original_file_size;
664
- }
665
-
666
- $thumbnails[ $image_size ] = $optimized_img_data;
667
-
668
- //просчитываем статистику
669
- $original_size += $optimized_img_data['src_size'];
670
- $optimized_size += $optimized_img_data['optimized_size'];
671
- $optimized_count ++;
672
- }
673
- }
674
-
675
- return [
676
- 'errors_count' => $errors_count,
677
- 'original_size' => $original_size,
678
- 'optimized_size' => $optimized_size,
679
- 'thumbnails_count' => $optimized_count,
680
- 'thumbnails' => $thumbnails,
681
- ];
682
- }
683
-
684
- /**
685
- * Возвращает путь.
686
- *
687
- * @param string $image_size Размер(thumbnail, medium ... )
688
- *
689
- * @return string
690
- */
691
- public function getPath( $image_size = '' ) {
692
-
693
- if ( empty( $image_size ) ) {
694
- $path = $this->path;
695
- } else {
696
- $path = $this->getImageSizePath( $image_size );
697
- }
698
-
699
- return $path;
700
- }
701
-
702
- /**
703
- * Заменяет оригинальный файл на оптимизированный.
704
- *
705
- * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
706
- * @param string $image_size Размер (thumbnail, medium ... )
707
- *
708
- * @return bool
709
- */
710
- public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
711
-
712
- $optimized_img_url = $optimized_img_data['optimized_img_url'];
713
-
714
- if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
715
- $optimized_file = $optimized_img_url;
716
- } else {
717
- $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
718
- }
719
-
720
- if ( empty( $optimized_file ) ) {
721
- WRIO_Plugin::app()->logger->error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
722
-
723
- return false;
724
- }
725
-
726
- if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
727
- // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
728
- return true;
729
- }
730
-
731
- $attachment_size_path = $this->getPath( $image_size );
732
-
733
- if ( ! is_file( $attachment_size_path ) ) {
734
- return false;
735
- }
736
-
737
- $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
738
-
739
- if ( $bytes === false ) {
740
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
741
-
742
- return false;
743
- }
744
-
745
- return true;
746
- }
747
-
748
- /**
749
- * Скачивание изображения с удалённого сервера
750
- *
751
- * @param string $url
752
- *
753
- * @return string|null Image content on success, NULL on failure.
754
- */
755
- protected function remoteDownloadImage( $url ) {
756
-
757
- if ( ! function_exists( 'curl_version' ) ) {
758
- $content = @file_get_contents( $url );
759
-
760
- if ( $content === false ) {
761
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
762
-
763
- return null;
764
- }
765
-
766
- return $content;
767
- }
768
-
769
- $ch = curl_init();
770
- curl_setopt( $ch, CURLOPT_HEADER, 0 );
771
- curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
772
- curl_setopt( $ch, CURLOPT_URL, $url );
773
-
774
- $image_body = curl_exec( $ch );
775
- $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
776
- if ( $http_code != '200' ) {
777
- $image_body = false;
778
- }
779
- curl_close( $ch );
780
-
781
- if ( $image_body === false ) {
782
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
783
-
784
- return null;
785
- }
786
-
787
- return $image_body;
788
- }
789
-
790
- /**
791
- * Возвращает свойство аттачмента
792
- *
793
- * @param string $property имя свойства
794
- *
795
- * @return mixed
796
- */
797
- public function get( $property ) {
798
- if ( isset( $this->$property ) ) {
799
- return $this->$property;
800
- }
801
-
802
- return false;
803
- }
804
-
805
- /**
806
- * Возвращает URL изображения по указанному размеру
807
- *
808
- * @param string $size - размер изображения(thumbnail,medium,large...)
809
- *
810
- * @return string|null
811
- */
812
- public function getImageSizeUrl( $size = 'thumbnail' ) {
813
- if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
814
- return null;
815
- }
816
-
817
- $file = $this->attachment_meta['sizes'][ $size ]['file'];
818
- $url = str_replace( wp_basename( $this->url ), $file, $this->url );
819
-
820
- return $url;
821
- }
822
-
823
- /**
824
- * Возвращает путь к изображению по указанному размеру.
825
- *
826
- * @param string $size Размер изображения (thumbnail, medium, large ...)
827
- *
828
- * @return string Путь до изображения.
829
- */
830
- public function getImageSizePath( $size = 'thumbnail' ) {
831
- if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
832
- return null;
833
- }
834
-
835
- $file = $this->attachment_meta['sizes'][ $size ]['file'];
836
- $path = str_replace( wp_basename( $this->path ), $file, $this->path );
837
-
838
- return $path;
839
- }
840
-
841
- /**
842
- * Проверка необходимости делать изменение размера.
843
- *
844
- * @return bool
845
- */
846
- protected function isNeedResize() {
847
- $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
848
-
849
- if ( ! $resize_large_images ) {
850
- return false;
851
- }
852
-
853
- $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
854
- $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
855
-
856
- if ( ! $resize_larger_w && ! $resize_larger_h ) {
857
- return false;
858
- }
859
-
860
- // если ширина и высота установлены и > 0
861
- if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
862
- $larger_side = $this->attachment_meta['width'];
863
- $resize_larger_side = $resize_larger_w;
864
- } else {
865
- $larger_side = $this->attachment_meta['height'];
866
- $resize_larger_side = $resize_larger_h;
867
- }
868
- // если ширина 0, то рисайзим по высоте
869
- if ( ! $resize_larger_w ) {
870
- $resize_larger_side = $resize_larger_h;
871
- $larger_side = $this->attachment_meta['height'];
872
- }
873
- // если высота 0, то рисайзим по ширине
874
- if ( ! $resize_larger_h ) {
875
- $resize_larger_side = $resize_larger_w;
876
- $larger_side = $this->attachment_meta['width'];
877
- }
878
- // если большая сторона картинки меньше, чем задано в настройках, то не рисайзим.
879
- if ( $larger_side <= $resize_larger_side ) {
880
- return false;
881
- }
882
-
883
- return true;
884
- }
885
-
886
- /**
887
- * Возвращает метаданные аттачмента
888
- *
889
- * @return array
890
- */
891
- public function getMetaData() {
892
- return $this->attachment_meta;
893
- }
894
-
895
- /**
896
- * Изменяет размер изображения до заданного в настройках размера.
897
- *
898
- * @return bool
899
- */
900
- protected function resize() {
901
- $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
902
- $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
903
-
904
- $image = wp_get_image_editor( $this->path );
905
-
906
- if ( is_wp_error( $image ) ) {
907
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
908
-
909
- return false;
910
- }
911
-
912
- $current_size = $image->get_size();
913
- $new_width = 0;
914
- $new_height = 0;
915
-
916
- // если обе стороны заданы
917
- if ( $resize_larger_h && $resize_larger_w ) {
918
- // определяем большую сторону и по ней маштабируем
919
- if ( $current_size['width'] >= $current_size['height'] ) {
920
- $new_width = $resize_larger_w;
921
- $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
922
- } else {
923
- $new_height = $resize_larger_h;
924
- $new_width = round( $current_size['width'] * $new_height / $current_size['height'] );
925
- }
926
- } else {
927
- // если задана одна из сторон
928
- if ( ! $resize_larger_w ) {
929
- // если ширина 0, то рисайзим по высоте
930
- $new_height = $resize_larger_h;
931
- $new_width = round( $current_size['width'] * $new_height / $current_size['height'] );
932
- }
933
- if ( ! $resize_larger_h ) {
934
- // если высота 0, то рисайзим по ширине
935
- $new_width = $resize_larger_w;
936
- $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
937
- }
938
- }
939
-
940
- $nl = PHP_EOL;
941
- $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
942
- $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
943
- $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
944
-
945
- $resize_result = $image->resize( $new_width, $new_height, false );
946
-
947
- if ( is_wp_error( $resize_result ) ) {
948
- $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
949
-
950
- return false;
951
- }
952
-
953
- $save_result = $image->save( $this->path );
954
-
955
- if ( is_wp_error( $save_result ) ) {
956
- $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
957
-
958
- return false;
959
- }
960
-
961
- $this->attachment_meta['width'] = $new_width;
962
- $this->attachment_meta['height'] = $new_height;
963
- $this->attachment_meta['old_width'] = $current_size['width'];
964
- $this->attachment_meta['old_height'] = $current_size['height'];
965
-
966
- wp_update_attachment_metadata( $this->id, $this->attachment_meta );
967
-
968
- return true;
969
- }
970
-
971
- /**
972
- * Делает резервную копию
973
- *
974
- * @return true|WP_Error
975
- */
976
- protected function backup() {
977
- $backup = WIO_Backup::get_instance();
978
-
979
- return $backup->backupAttachment( $this );
980
- }
981
-
982
- /**
983
- * Восстанавливает файлы из резервной копии
984
- *
985
- * @return true|WP_Error
986
- */
987
- public function restore() {
988
- $backup = WIO_Backup::get_instance();
989
-
990
- return $backup->restoreAttachment( $this );
991
- }
992
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с WordPress attachment.
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WIO_Attachment {
16
+
17
+ /**
18
+ * @var int
19
+ */
20
+ private $id;
21
+
22
+
23
+ /**
24
+ * @var array meta-данные
25
+ */
26
+ private $attachment_meta;
27
+
28
+ /**
29
+ * @var array массив с данными о папке uploads
30
+ */
31
+ private $wp_upload_dir;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ private $url;
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ private $path;
42
+
43
+ /**
44
+ * @var RIO_Process_Queue
45
+ */
46
+ private $optimization_data;
47
+
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;
56
+ $this->wp_upload_dir = wp_upload_dir();
57
+ $this->attachment_meta = $attachment_meta;
58
+
59
+ if ( ! $attachment_meta ) {
60
+ // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
61
+ $this->attachment_meta = wp_get_attachment_metadata( $this->id );
62
+ }
63
+
64
+ $this->set_paths();
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'] );
74
+ }
75
+
76
+ /**
77
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
78
+ * @since 1.3.9
79
+ */
80
+ public function set_paths() {
81
+ if ( ! $this->isset_attachment_meta() ) {
82
+ return;
83
+ }
84
+
85
+ $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
86
+ $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
87
+ }
88
+
89
+ /**
90
+ * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
91
+ */
92
+ public function reload( $attachment_meta = [] ) {
93
+ if ( empty( $attachment_meta ) ) {
94
+ $attachment_meta = wp_get_attachment_metadata( $this->id );
95
+ }
96
+ $this->attachment_meta = $attachment_meta;
97
+ $this->optimization_data = new RIO_Process_Queue( [
98
+ 'object_id' => $this->id,
99
+ 'object_name' => '',
100
+ 'item_type' => 'attachment',
101
+ ] );
102
+ $this->optimization_data->load();
103
+ $this->set_paths();
104
+ }
105
+
106
+ /**
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() ) {
116
+ return true;
117
+ }
118
+
119
+ WRIO_Plugin::app()->logger->info( sprintf( 'Try regenerate metadata for attachment #%d', $this->id ) );
120
+
121
+ // Need to remove this filter, as it would start recursion
122
+ remove_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload' );
123
+
124
+ $file_path = get_attached_file( $this->id );
125
+
126
+ if ( empty( $file_path ) ) {
127
+ $attachment = get_post( $this->id );
128
+
129
+ if ( empty( $attachment ) || 'attachment' !== $attachment->post_type ) {
130
+ return false;
131
+ }
132
+
133
+ $file_path = wrio_url_to_abs_path( $attachment->guid );
134
+ }
135
+
136
+ if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
137
+ WRIO_Plugin::app()->logger->info( sprintf( 'Failed regenerate attachment meta data. Attachment file (%s) doesn\'t exists!', $file_path ) );
138
+
139
+ return false;
140
+ }
141
+
142
+ if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
143
+ require ABSPATH . 'wp-admin/includes/image.php';
144
+ }
145
+ $attachment_meta = wp_generate_attachment_metadata( $this->id, $file_path );
146
+
147
+ if ( empty( $attachment_meta ) ) {
148
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed regenerate meta data for attachment file (%s).', $file_path ) );
149
+
150
+ return false;
151
+ }
152
+
153
+ WRIO_Plugin::app()->logger->debug( sprintf( 'Generated metadata: %s', var_export( $attachment_meta, true ) ) );
154
+
155
+ # Updating metadata in database
156
+ wp_update_attachment_metadata( $this->id, $attachment_meta );
157
+
158
+ $this->reload( $attachment_meta );
159
+
160
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
161
+
162
+ WRIO_Plugin::app()->logger->info( sprintf( 'Finish regenerate metadata for attachment #%d!', $this->id ) );
163
+
164
+ return true;
165
+ }
166
+
167
+ /**
168
+ * Добавляем сообщение в лог файл.
169
+ *
170
+ * @param string $message Текст сообщения об ошибке.
171
+ */
172
+ public function writeLog( $message ) {
173
+
174
+ $char = "\t-> ";
175
+ $nl = PHP_EOL;
176
+
177
+ $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
178
+ $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
179
+ $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
180
+ $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
181
+ $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
182
+ $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
183
+
184
+ if ( ! empty( $this->attachment_meta['sizes'] ) ) {
185
+ $error .= $char . ' Additional sizes:' . $nl;
186
+ foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
187
+ $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
188
+ }
189
+ }
190
+
191
+ WRIO_Plugin::app()->logger->error( $error );
192
+ }
193
+
194
+ /**
195
+ * Возвращает объект с информацией об оптимизации
196
+ *
197
+ * @return RIO_Process_Queue
198
+ */
199
+ public function getOptimizationData() {
200
+ $this->optimization_data = new RIO_Process_Queue( [
201
+ 'object_id' => $this->id,
202
+ 'object_name' => '',
203
+ 'item_type' => 'attachment',
204
+ ] );
205
+ $this->optimization_data->load();
206
+
207
+ return $this->optimization_data;
208
+ }
209
+
210
+ /**
211
+ * Возвращает объект с информацией об оптимизации
212
+ *
213
+ * @return RIO_Process_Queue
214
+ */
215
+ public function getConversionData() {
216
+ $optimization_data = new RIO_Process_Queue( [
217
+ 'object_id' => $this->id,
218
+ 'object_name' => '',
219
+ 'item_type' => 'webp',
220
+ ] );
221
+ $optimization_data->load();
222
+
223
+ return $optimization_data;
224
+ }
225
+
226
+ /**
227
+ * Оптимизация аттачмента.
228
+ *
229
+ * @param string $optimization_level Уровень оптимизации изображения.
230
+ *
231
+ * @return array
232
+ */
233
+ public function optimize( $optimization_level = '' ) {
234
+ $optimize_results = [
235
+ 'original_size' => 0,
236
+ 'optimized_size' => 0,
237
+ ];
238
+
239
+ if ( empty( $optimization_level ) ) {
240
+ $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
241
+ }
242
+
243
+ if ( $optimization_level == 'custom' ) {
244
+ $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
245
+ $optimization_level = intval( $custom_quality );
246
+ }
247
+
248
+ $optimization_data = $this->getOptimizationData();
249
+ $results = [
250
+ 'original_size' => 0,
251
+ 'final_size' => 0,
252
+ 'original_mime_type' => '',
253
+ 'final_mime_type' => '',
254
+ ];
255
+ $results['processing_level'] = $optimization_level;
256
+
257
+ # The path may be empty because no metadata has been created for the image.
258
+ # We should try to create image metadata again.
259
+ if ( ! $this->isset_attachment_meta() ) {
260
+ WRIO_Plugin::app()->logger->warning( sprintf( 'Attachment #%d doesn\'t have metadata.', $this->id ) );
261
+
262
+ $this->regenerate_metadata();
263
+ }
264
+
265
+ if ( empty( $this->path ) || ! file_exists( $this->path ) ) {
266
+ $results['result_status'] = 'error';
267
+
268
+ $error_message = __( 'Attachment cannot be optimized.', 'robin-image-optimizer' );
269
+
270
+ if ( empty( $this->path ) ) {
271
+ $error_message .= ' ' . sprintf( __( 'Attachment #%d doesn\'t have metadata, the image may be damaged.', 'robin-image-optimizer' ), $this->id );
272
+ } else {
273
+ $error_message .= ' ' . sprintf( __( 'File "(%s)" doesn\'t exist', 'robin-image-optimizer' ), $this->path );
274
+ }
275
+
276
+ $extra_data = [
277
+ 'error' => 'path',
278
+ 'error_msg' => $error_message,
279
+ ];
280
+
281
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
282
+ $optimization_data->configure( $results );
283
+ $optimization_data->save();
284
+
285
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
286
+
287
+ return $optimize_results;
288
+ }
289
+
290
+ // сначала бекапим
291
+ $is_image_backuped = $this->backup();
292
+
293
+ if ( is_wp_error( $is_image_backuped ) ) {
294
+ $error_msg = $is_image_backuped->get_error_message();
295
+ $this->writeLog( $error_msg );
296
+
297
+ $results['result_status'] = 'error';
298
+ $extra_data = [
299
+ 'error' => 'backup',
300
+ 'error_msg' => 'Failed to backup',
301
+ ];
302
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
303
+ $optimization_data->configure( $results );
304
+ $optimization_data->save();
305
+
306
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
307
+
308
+ return $optimize_results;
309
+ }
310
+
311
+ $results['is_backed_up'] = $is_image_backuped;
312
+
313
+ $original_main_size = filesize( $this->path );
314
+
315
+ // если файл большой - изменяем размер
316
+ if ( $this->isNeedResize() ) {
317
+ $this->resize();
318
+ }
319
+
320
+ $image_processor = WIO_OptimizationTools::getImageProcessor();
321
+
322
+ clearstatcache(); // на всякий случай очистим кеш файловой статистики
323
+
324
+ $optimized_img_data = $image_processor->process( [
325
+ 'image_url' => $this->get( 'url' ),
326
+ 'image_path' => $this->get( 'path' ),
327
+ 'quality' => $image_processor->quality( $optimization_level ),
328
+ 'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
329
+ 'is_thumb' => false,
330
+ ] );
331
+
332
+ // проверяем на ошибку
333
+ if ( is_wp_error( $optimized_img_data ) ) {
334
+ $error_msg = $optimized_img_data->get_error_message();
335
+ $this->writeLog( $error_msg );
336
+
337
+ $results['result_status'] = 'error';
338
+
339
+ $extra_data = [
340
+ 'error' => 'optimization',
341
+ 'error_msg' => $error_msg,
342
+ ];
343
+
344
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
345
+
346
+ $optimization_data->configure( $results );
347
+ $optimization_data->save();
348
+
349
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
350
+
351
+ return $optimize_results;
352
+ }
353
+
354
+ $results['original_mime_type'] = '';
355
+ $results['final_mime_type'] = '';
356
+
357
+ // отложенная оптимизация
358
+ if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
359
+ $results['result_status'] = 'processing';
360
+ $results['original_size'] = 0;
361
+ $results['final_size'] = 0;
362
+
363
+ $extra_data = [
364
+ 'main_optimized_data' => $optimized_img_data,
365
+ 'thumbnails_optimized_data' => $this->optimizeImageSizes(),
366
+ ];
367
+
368
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
369
+
370
+ $optimization_data->configure( $results );
371
+ $optimization_data->save();
372
+ $optimize_results['processing'] = 1;
373
+
374
+ return $optimize_results;
375
+ }
376
+
377
+ //скачиваем и заменяем главную картинку
378
+ $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
379
+
380
+ // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
381
+ if ( ! $optimized_img_data['optimized_size'] ) {
382
+ clearstatcache();
383
+ $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
384
+ }
385
+
386
+ // при отрицательной оптимизации ставим значение оригинала
387
+ if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
388
+ $optimized_img_data['optimized_size'] = $original_main_size;
389
+ }
390
+
391
+ if ( $image_downloaded ) {
392
+ //просчитываем статистику
393
+ $optimize_results['original_size'] += $original_main_size;
394
+ $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
395
+ $thumbnails_count = 0;
396
+
397
+ // оптимизируем дополнительные размеры
398
+ $optimized_img_sizes_data = $this->optimizeImageSizes();
399
+
400
+ // добавляем к статистике данные по оптимизации доп размеров
401
+ if ( ! empty( $optimized_img_sizes_data ) ) {
402
+ $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
403
+ $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
404
+ $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
405
+ }
406
+
407
+ $results['result_status'] = 'success';
408
+ $results['final_size'] = $optimize_results['optimized_size'];
409
+ $results['original_size'] = $optimize_results['original_size'];
410
+
411
+ $extra_data = [
412
+ 'thumbnails_count' => $thumbnails_count,
413
+ 'original_main_size' => $original_main_size,
414
+ ];
415
+
416
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
417
+ $mime_type = '';
418
+
419
+ if ( function_exists( 'wp_get_image_mime' ) ) {
420
+ $mime_type = wp_get_image_mime( $this->get( 'path' ) );
421
+ } else {
422
+ WRIO_Plugin::app()->logger->error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
423
+ }
424
+
425
+ $results['original_mime_type'] = $mime_type;
426
+ $results['final_mime_type'] = $mime_type;
427
+ $optimization_data->configure( $results );
428
+ } else {
429
+ $error_msg = 'Failed to get optimized image from remote server';
430
+ $this->writeLog( $error_msg );
431
+
432
+ $results['result_status'] = 'error';
433
+
434
+ $extra_data = [
435
+ 'error' => 'download',
436
+ 'error_msg' => $error_msg,
437
+ ];
438
+
439
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
440
+ $optimization_data->configure( $results );
441
+ }
442
+
443
+ $optimization_data->save();
444
+
445
+ return $optimize_results;
446
+ }
447
+
448
+ /**
449
+ * Отложенная оптимизация аттачмента
450
+ *
451
+ * @return bool|array
452
+ */
453
+ public function deferredOptimization() {
454
+ $results = [
455
+ 'original_size' => 0,
456
+ 'optimized_size' => 0,
457
+ 'optimized_count' => 0,
458
+ 'processing' => 1,
459
+ ];
460
+
461
+ $image_processor = WIO_OptimizationTools::getImageProcessor();
462
+ $optimization_data = $this->getOptimizationData();
463
+
464
+ if ( $optimization_data->get_result_status() != 'processing' ) {
465
+ return false;
466
+ }
467
+
468
+ // проверяем главную картинку
469
+ /**
470
+ * @var RIO_Attachment_Extra_Data $extra_data
471
+ */
472
+ $extra_data = $optimization_data->get_extra_data();
473
+ $main_optimized_data = $extra_data->get_main_optimized_data();
474
+ $main_image_url = '';
475
+
476
+ if ( ! $main_optimized_data['optimized_img_url'] ) {
477
+ $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
478
+ if ( $main_image_url ) {
479
+ $main_optimized_data['optimized_img_url'] = $main_image_url;
480
+ $extra_data->set_main_optimized_data( $main_optimized_data );
481
+ }
482
+ }
483
+
484
+ $thumbnails_processed = true;
485
+ $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
486
+ $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
487
+
488
+ if ( is_array( $thumbnails['thumbnails'] ) ) {
489
+ foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
490
+ if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
491
+ $thumbnail_image_url = $image_processor->checkDeferredOptimization( $thumbnail_optimized_data );
492
+ if ( $thumbnail_image_url ) {
493
+ $thumbnail_optimized_data['optimized_img_url'] = $thumbnail_image_url;
494
+ } else {
495
+ $thumbnails_processed = false;
496
+ }
497
+ }
498
+ }
499
+ $extra_data->set_thumbnails_optimized_data( $thumbnails );
500
+ }
501
+
502
+ // когда все файлы получены - сохраняем и возвращаем результат
503
+ if ( $main_image_url && $thumbnails_processed ) {
504
+ $original_size = 0;
505
+ $optimized_size = 0;
506
+ $thumbnails_count = 0;
507
+ $original_main_size = filesize( $this->get( 'path' ) );
508
+ $original_size = $original_size + $original_main_size;
509
+
510
+ $this->replaceOriginalFile( [
511
+ 'optimized_img_url' => $main_image_url,
512
+ ] );
513
+
514
+ clearstatcache();
515
+
516
+ $optimized_main_size = filesize( $this->get( 'path' ) );
517
+
518
+ // при отрицательной оптимизации ставим значение оригинала
519
+ if ( $optimized_main_size > $original_main_size ) {
520
+ $optimized_main_size = $original_main_size;
521
+ }
522
+
523
+ $optimized_size = $optimized_size + $optimized_main_size;
524
+
525
+ if ( is_array( $thumbnails['thumbnails'] ) ) {
526
+ foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
527
+ $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
528
+ $original_thumbnail_size = filesize( $thumbnail_file );
529
+ $original_size = $original_size + $original_thumbnail_size;
530
+
531
+ $this->replaceOriginalFile( [
532
+ 'optimized_img_url' => $thumbnail['optimized_img_url'],
533
+ ], $thumbnail_size );
534
+
535
+ clearstatcache();
536
+
537
+ $optimized_thumbnail_size = filesize( $thumbnail_file );
538
+
539
+ // при отрицательной оптимизации ставим значение оригинала
540
+ if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
541
+ $optimized_thumbnail_size = $original_thumbnail_size;
542
+ }
543
+
544
+ $optimized_size = $optimized_size + $optimized_thumbnail_size;
545
+
546
+ $thumbnails_count ++;
547
+ }
548
+ }
549
+
550
+ $mime_type = '';
551
+ if ( function_exists( 'wp_get_image_mime' ) ) {
552
+ $mime_type = wp_get_image_mime( $this->get( 'path' ) );
553
+ }
554
+
555
+ $optimization_data->configure( [
556
+ 'final_size' => $optimized_size,
557
+ 'original_size' => $original_size,
558
+ 'result_status' => 'success',
559
+ 'original_mime_type' => $mime_type,
560
+ 'final_mime_type' => $mime_type,
561
+ ] );
562
+
563
+ $extra_data->set_original_main_size( $original_main_size );
564
+ $extra_data->set_thumbnails_count( $thumbnails_count );
565
+
566
+ // удаляем промежуточные данные
567
+ $extra_data->set_main_optimized_data( null );
568
+ $extra_data->set_thumbnails_optimized_data( null );
569
+ $extra_data->set_main_optimized_data( null );
570
+
571
+ $results['optimized_count'] = 1;
572
+ $results['original_size'] = $original_size;
573
+ $results['optimized_size'] = $optimized_size;
574
+
575
+ unset( $results['processing'] );
576
+ }
577
+ $optimization_data->set_extra_data( $extra_data );
578
+ $optimization_data->save();
579
+
580
+ return $results;
581
+ }
582
+
583
+ /**
584
+ * Метод проверяет, оптимизирован ли аттачмент
585
+ *
586
+ * @return bool
587
+ */
588
+ public function isOptimized() {
589
+ $optimization_data = $this->getOptimizationData();
590
+ if ( $optimization_data->is_optimized() ) {
591
+ return true;
592
+ }
593
+
594
+ return false;
595
+ }
596
+
597
+ /**
598
+ * Возвращает все размеры аттачмента, которые нужно оптимизировать
599
+ *
600
+ * @return array|false
601
+ */
602
+ public function getAllowedSizes() {
603
+ $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
604
+
605
+ if ( ! $allowed_sizes ) {
606
+ return false;
607
+ }
608
+
609
+ $allowed_sizes = explode( ',', $allowed_sizes );
610
+
611
+ return $allowed_sizes;
612
+ }
613
+
614
+ /**
615
+ * Оптимизация других размеров аттачмента.
616
+ *
617
+ * @return array
618
+ */
619
+ public function optimizeImageSizes() {
620
+ $allowed_sizes = $this->getAllowedSizes();
621
+
622
+ if ( $allowed_sizes === false ) {
623
+ return [];
624
+ }
625
+
626
+ $image_processor = WIO_OptimizationTools::getImageProcessor();
627
+ $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
628
+
629
+ if ( $quality == 'custom' ) {
630
+ $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
631
+ $quality = intval( $custom_quality );
632
+ }
633
+
634
+ $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
635
+
636
+ $original_size = 0;
637
+ $optimized_size = 0;
638
+ $errors_count = 0;
639
+ $optimized_count = 0;
640
+ $thumbnails = [];
641
+
642
+ foreach ( $allowed_sizes as $image_size ) {
643
+ $url = $this->getImageSizeUrl( $image_size );
644
+ $path = $this->getImageSizePath( $image_size );
645
+
646
+ if ( ! $url || ! $path ) {
647
+ continue;
648
+ }
649
+
650
+ $original_file_size = 0;
651
+
652
+ if ( is_file( $path ) ) {
653
+ $original_file_size = filesize( $path );
654
+ }
655
+
656
+ $optimized_img_data = $image_processor->process( [
657
+ 'image_url' => $url,
658
+ 'image_path' => $path,
659
+ 'quality' => $image_processor->quality( $quality ),
660
+ 'save_exif' => $exif,
661
+ 'is_thumb' => true,
662
+ ] );
663
+ // проверяем на ошибку
664
+ if ( is_wp_error( $optimized_img_data ) ) {
665
+ $errors_count ++;
666
+ } else {
667
+ //скачиваем и заменяем картинку
668
+ $this->replaceOriginalFile( $optimized_img_data, $image_size );
669
+ // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
670
+ if ( ! $optimized_img_data['optimized_size'] ) {
671
+ clearstatcache();
672
+ $optimized_img_data['optimized_size'] = filesize( $path );
673
+ }
674
+ if ( ! $optimized_img_data['src_size'] ) {
675
+ $optimized_img_data['src_size'] = $original_file_size;
676
+ }
677
+
678
+ // при отрицательной оптимизации ставим значение оригинала
679
+ if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
680
+ $optimized_img_data['optimized_size'] = $original_file_size;
681
+ }
682
+
683
+ $thumbnails[ $image_size ] = $optimized_img_data;
684
+
685
+ //просчитываем статистику
686
+ $original_size += $optimized_img_data['src_size'];
687
+ $optimized_size += $optimized_img_data['optimized_size'];
688
+ $optimized_count ++;
689
+ }
690
+ }
691
+
692
+ return [
693
+ 'errors_count' => $errors_count,
694
+ 'original_size' => $original_size,
695
+ 'optimized_size' => $optimized_size,
696
+ 'thumbnails_count' => $optimized_count,
697
+ 'thumbnails' => $thumbnails,
698
+ ];
699
+ }
700
+
701
+ /**
702
+ * Возвращает путь.
703
+ *
704
+ * @param string $image_size Размер(thumbnail, medium ... )
705
+ *
706
+ * @return string
707
+ */
708
+ public function getPath( $image_size = '' ) {
709
+
710
+ if ( empty( $image_size ) ) {
711
+ $path = $this->path;
712
+ } else {
713
+ $path = $this->getImageSizePath( $image_size );
714
+ }
715
+
716
+ return $path;
717
+ }
718
+
719
+ /**
720
+ * Заменяет оригинальный файл на оптимизированный.
721
+ *
722
+ * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
723
+ * @param string $image_size Размер (thumbnail, medium ... )
724
+ *
725
+ * @return bool
726
+ */
727
+ public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
728
+
729
+ $optimized_img_url = $optimized_img_data['optimized_img_url'];
730
+
731
+ if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
732
+ $optimized_file = $optimized_img_url;
733
+ } else {
734
+ $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
735
+ }
736
+
737
+ if ( empty( $optimized_file ) ) {
738
+ WRIO_Plugin::app()->logger->error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
739
+
740
+ return false;
741
+ }
742
+
743
+ if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
744
+ // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
745
+ return true;
746
+ }
747
+
748
+ $attachment_size_path = $this->getPath( $image_size );
749
+
750
+ if ( ! is_file( $attachment_size_path ) ) {
751
+ return false;
752
+ }
753
+
754
+ $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
755
+
756
+ if ( $bytes === false ) {
757
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
758
+
759
+ return false;
760
+ }
761
+
762
+ return true;
763
+ }
764
+
765
+ /**
766
+ * Скачивание изображения с удалённого сервера
767
+ *
768
+ * @param string $url
769
+ *
770
+ * @return string|null Image content on success, NULL on failure.
771
+ */
772
+ protected function remoteDownloadImage( $url ) {
773
+
774
+ if ( ! function_exists( 'curl_version' ) ) {
775
+ $content = @file_get_contents( $url );
776
+
777
+ if ( $content === false ) {
778
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
779
+
780
+ return null;
781
+ }
782
+
783
+ return $content;
784
+ }
785
+
786
+ $ch = curl_init();
787
+ curl_setopt( $ch, CURLOPT_HEADER, 0 );
788
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
789
+ curl_setopt( $ch, CURLOPT_URL, $url );
790
+
791
+ $image_body = curl_exec( $ch );
792
+ $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
793
+ if ( $http_code != '200' ) {
794
+ $image_body = false;
795
+ }
796
+ curl_close( $ch );
797
+
798
+ if ( $image_body === false ) {
799
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
800
+
801
+ return null;
802
+ }
803
+
804
+ return $image_body;
805
+ }
806
+
807
+ /**
808
+ * Возвращает свойство аттачмента
809
+ *
810
+ * @param string $property имя свойства
811
+ *
812
+ * @return mixed
813
+ */
814
+ public function get( $property ) {
815
+ if ( isset( $this->$property ) ) {
816
+ return $this->$property;
817
+ }
818
+
819
+ return false;
820
+ }
821
+
822
+ /**
823
+ * Возвращает URL изображения по указанному размеру
824
+ *
825
+ * @param string $size - размер изображения(thumbnail,medium,large...)
826
+ *
827
+ * @return string|null
828
+ */
829
+ public function getImageSizeUrl( $size = 'thumbnail' ) {
830
+ if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
831
+ return null;
832
+ }
833
+
834
+ $file = $this->attachment_meta['sizes'][ $size ]['file'];
835
+ $url = str_replace( wp_basename( $this->url ), $file, $this->url );
836
+
837
+ return $url;
838
+ }
839
+
840
+ /**
841
+ * Возвращает путь к изображению по указанному размеру.
842
+ *
843
+ * @param string $size Размер изображения (thumbnail, medium, large ...)
844
+ *
845
+ * @return string Путь до изображения.
846
+ */
847
+ public function getImageSizePath( $size = 'thumbnail' ) {
848
+ if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
849
+ return null;
850
+ }
851
+
852
+ $file = $this->attachment_meta['sizes'][ $size ]['file'];
853
+ $path = str_replace( wp_basename( $this->path ), $file, $this->path );
854
+
855
+ return $path;
856
+ }
857
+
858
+ /**
859
+ * Проверка необходимости делать изменение размера.
860
+ *
861
+ * @return bool
862
+ */
863
+ protected function isNeedResize() {
864
+ $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
865
+
866
+ if ( ! $resize_large_images ) {
867
+ return false;
868
+ }
869
+
870
+ $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
871
+ $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
872
+
873
+ if ( ! $resize_larger_w && ! $resize_larger_h ) {
874
+ return false;
875
+ }
876
+
877
+ // если ширина и высота установлены и > 0
878
+ if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
879
+ $larger_side = $this->attachment_meta['width'];
880
+ $resize_larger_side = $resize_larger_w;
881
+ } else {
882
+ $larger_side = $this->attachment_meta['height'];
883
+ $resize_larger_side = $resize_larger_h;
884
+ }
885
+ // если ширина 0, то рисайзим по высоте
886
+ if ( ! $resize_larger_w ) {
887
+ $resize_larger_side = $resize_larger_h;
888
+ $larger_side = $this->attachment_meta['height'];
889
+ }
890
+ // если высота 0, то рисайзим по ширине
891
+ if ( ! $resize_larger_h ) {
892
+ $resize_larger_side = $resize_larger_w;
893
+ $larger_side = $this->attachment_meta['width'];
894
+ }
895
+ // если большая сторона картинки меньше, чем задано в настройках, то не рисайзим.
896
+ if ( $larger_side <= $resize_larger_side ) {
897
+ return false;
898
+ }
899
+
900
+ return true;
901
+ }
902
+
903
+ /**
904
+ * Возвращает метаданные аттачмента
905
+ *
906
+ * @return array
907
+ */
908
+ public function getMetaData() {
909
+ return $this->attachment_meta;
910
+ }
911
+
912
+ /**
913
+ * Изменяет размер изображения до заданного в настройках размера.
914
+ *
915
+ * @return bool
916
+ */
917
+ protected function resize() {
918
+ $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
919
+ $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
920
+
921
+ $image = wp_get_image_editor( $this->path );
922
+
923
+ if ( is_wp_error( $image ) ) {
924
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
925
+
926
+ return false;
927
+ }
928
+
929
+ $current_size = $image->get_size();
930
+ $new_width = 0;
931
+ $new_height = 0;
932
+
933
+ // если обе стороны заданы
934
+ if ( $resize_larger_h && $resize_larger_w ) {
935
+ // определяем большую сторону и по ней маштабируем
936
+ if ( $current_size['width'] >= $current_size['height'] ) {
937
+ $new_width = $resize_larger_w;
938
+ $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
939
+ } else {
940
+ $new_height = $resize_larger_h;
941
+ $new_width = round( $current_size['width'] * $new_height / $current_size['height'] );
942
+ }
943
+ } else {
944
+ // если задана одна из сторон
945
+ if ( ! $resize_larger_w ) {
946
+ // если ширина 0, то рисайзим по высоте
947
+ $new_height = $resize_larger_h;
948
+ $new_width = round( $current_size['width'] * $new_height / $current_size['height'] );
949
+ }
950
+ if ( ! $resize_larger_h ) {
951
+ // если высота 0, то рисайзим по ширине
952
+ $new_width = $resize_larger_w;
953
+ $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
954
+ }
955
+ }
956
+
957
+ $nl = PHP_EOL;
958
+ $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
959
+ $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
960
+ $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
961
+
962
+ $resize_result = $image->resize( $new_width, $new_height, false );
963
+
964
+ if ( is_wp_error( $resize_result ) ) {
965
+ $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
966
+
967
+ return false;
968
+ }
969
+
970
+ $save_result = $image->save( $this->path );
971
+
972
+ if ( is_wp_error( $save_result ) ) {
973
+ $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
974
+
975
+ return false;
976
+ }
977
+
978
+ $this->attachment_meta['width'] = $new_width;
979
+ $this->attachment_meta['height'] = $new_height;
980
+ $this->attachment_meta['old_width'] = $current_size['width'];
981
+ $this->attachment_meta['old_height'] = $current_size['height'];
982
+
983
+ wp_update_attachment_metadata( $this->id, $this->attachment_meta );
984
+
985
+ return true;
986
+ }
987
+
988
+ /**
989
+ * Делает резервную копию
990
+ *
991
+ * @return true|WP_Error
992
+ */
993
+ protected function backup() {
994
+ $backup = WIO_Backup::get_instance();
995
+
996
+ return $backup->backupAttachment( $this );
997
+ }
998
+
999
+ /**
1000
+ * Восстанавливает файлы из резервной копии
1001
+ *
1002
+ * @return true|WP_Error
1003
+ */
1004
+ public function restore() {
1005
+ $backup = WIO_Backup::get_instance();
1006
+
1007
+ return $backup->restoreAttachment( $this );
1008
+ }
1009
+ }
includes/classes/class-rio-backup.php CHANGED
@@ -1,535 +1,535 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы с резервным копированием изображений.
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WIO_Backup {
16
-
17
- CONST BACKUP_DIR_NAME = 'wio_backup';
18
- CONST TEMP_DIR_NAME = 'temp';
19
-
20
- /**
21
- * The single instance of the class.
22
- *
23
- * @since 1.3.0
24
- * @access protected
25
- * @var object
26
- */
27
- protected static $_instance;
28
-
29
- /**
30
- * @var array Данные о папке uploads, возвращаемые функцией wp_upload_dir()
31
- */
32
- protected $wp_upload_dir;
33
-
34
- /**
35
- * @var string Путь к папке с резервными копиями изображений
36
- */
37
- private $backup_dir;
38
-
39
- /**
40
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
41
- * @since 1.3.0
42
- * @var string
43
- */
44
- private $blog_backup_dir;
45
-
46
- /**
47
- * Инициализация бекапа
48
- */
49
- public function __construct() {
50
- $this->wp_upload_dir = wp_upload_dir();
51
- }
52
-
53
- /**
54
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
55
- * @since 1.3.0
56
- *
57
- * @return object|\static object Main instance.
58
- */
59
- public static function get_instance() {
60
- if ( ! isset( static::$_instance ) ) {
61
- static::$_instance = new static();
62
- }
63
-
64
- return static::$_instance;
65
- }
66
-
67
- /**
68
- * Проверка возможности записи в папку uploads.
69
- *
70
- * @return bool
71
- */
72
- public function isUploadWritable() {
73
- $upload_dir = $this->wp_upload_dir['basedir'];
74
-
75
- if ( is_dir( $upload_dir ) && wp_is_writable( $upload_dir ) ) {
76
- return true;
77
- }
78
-
79
- return false;
80
- }
81
-
82
- /**
83
- * Проверка возможности записи в папку бекап.
84
- *
85
- * @return bool
86
- */
87
- public function isBackupWritable() {
88
-
89
- $backup_dir = $this->getBackupDir();
90
-
91
- if ( is_wp_error( $backup_dir ) || ! wp_is_writable( $backup_dir ) ) {
92
- return false;
93
- }
94
-
95
- return true;
96
- }
97
-
98
- /**
99
- * Путь к папке с бекапами
100
- *
101
- * @return string|WP_Error
102
- */
103
- public function getBackupDir() {
104
- if ( $this->backup_dir ) {
105
- return $this->backup_dir;
106
- }
107
-
108
- $backup_dir = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . self::BACKUP_DIR_NAME );
109
-
110
- if ( ! is_dir( $backup_dir ) ) {
111
- $backup_dir = $this->mkdir( $backup_dir );
112
-
113
- if ( is_wp_error( $backup_dir ) ) {
114
- return $backup_dir;
115
- }
116
- }
117
-
118
- $this->backup_dir = apply_filters( 'wbcr/rio/backup/backup_dir', trailingslashit( $backup_dir ) );
119
-
120
- return $this->backup_dir;
121
- }
122
-
123
- /**
124
- * Путь к папке с бекапами блога.
125
- *
126
- * Используется в мультисайт режиме.
127
- *
128
- * @return string|WP_Error
129
- */
130
- public function getBlogBackupDir() {
131
- if ( $this->blog_backup_dir ) {
132
- return $this->blog_backup_dir;
133
- }
134
-
135
- $wp_upload_dir = wp_upload_dir();
136
- $backup_dir = wp_normalize_path( trailingslashit( $wp_upload_dir['basedir'] ) . self::BACKUP_DIR_NAME );
137
-
138
- if ( ! is_dir( $backup_dir ) ) {
139
- $backup_dir = $this->mkdir( $backup_dir );
140
-
141
- if ( is_wp_error( $backup_dir ) ) {
142
- return $backup_dir;
143
- }
144
- }
145
-
146
- $this->blog_backup_dir = trailingslashit( $backup_dir );
147
-
148
- return $this->blog_backup_dir;
149
- }
150
-
151
- /**
152
- * Очищает папку с резервными копиями
153
- *
154
- * @return bool
155
- */
156
- public function removeBackupDir() {
157
- $backup_dir = $this->getBackupDir();
158
-
159
- return wrio_rmdir( $backup_dir );
160
- }
161
-
162
- /**
163
- * Очищает папку с резервными копиями блога
164
- * Используется в мультисайт режиме
165
- *
166
- * @return bool
167
- */
168
- public function removeBlogBackupDir() {
169
- $backup_dir = $this->getBlogBackupDir();
170
-
171
- return wrio_rmdir( $backup_dir );
172
- }
173
-
174
- /**
175
- * Получает путь к папке с резервными копиями
176
- *
177
- * @param array $attachment_meta метаданные аттачмента
178
- *
179
- * @return string
180
- */
181
- public function getAttachmentBackupDir( $attachment_meta ) {
182
- $backup_dir = $this->getBackupDir();
183
-
184
- // Get all subfolders in which the image is stored.
185
- // This is necessary to create an alternate subfolders
186
- // in directory where they are stored in backups.
187
- $subfolders = dirname( $attachment_meta['file'] );
188
-
189
- $backup_dir .= $subfolders;
190
-
191
- if ( ! is_dir( $backup_dir ) ) {
192
- $backup_dir = $this->mkdir( $backup_dir );
193
-
194
- if ( is_wp_error( $backup_dir ) ) {
195
- return $backup_dir;
196
- }
197
- }
198
-
199
- return trailingslashit( $backup_dir );
200
- }
201
-
202
- /**
203
- * Делаем резервную копию аттачмента
204
- *
205
- * @param WIO_Attachment $wio_attachment аттачмент
206
- *
207
- * @return bool|WP_Error
208
- */
209
- public function backupAttachment( WIO_Attachment $wio_attachment ) {
210
- $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
211
-
212
- if ( ! $backup_origin_images ) {
213
- return false; // если бекап не требуется
214
- }
215
-
216
- $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
217
-
218
- if ( is_wp_error( $backup_dir ) ) {
219
- return $backup_dir;
220
- }
221
-
222
- $full = $this->backupAttachmentSize( $wio_attachment );
223
-
224
- if ( is_wp_error( $full ) ) {
225
- return $full;
226
- }
227
-
228
- $allowed_sizes = $wio_attachment->getAllowedSizes();
229
-
230
- if ( ! empty( $allowed_sizes ) ) {
231
- foreach ( (array) $allowed_sizes as $image_size ) {
232
- $size_backup = $this->backupAttachmentSize( $wio_attachment, $image_size );
233
-
234
- if ( is_wp_error( $size_backup ) ) {
235
- return $size_backup;
236
- }
237
- }
238
- }
239
-
240
- return true;
241
- }
242
-
243
- /**
244
- * Восстанавливаем аттачмент из резервной копии
245
- *
246
- * @param WIO_Attachment $wio_attachment аттачмент
247
- *
248
- * @return bool|WP_Error
249
- */
250
- public function restoreAttachment( WIO_Attachment $wio_attachment ) {
251
- $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
252
-
253
- if ( is_wp_error( $backup_dir ) ) {
254
- return $backup_dir;
255
- }
256
-
257
- $restore_result = $this->restoreAttachmentSize( $wio_attachment );
258
-
259
- if ( is_wp_error( $restore_result ) ) {
260
- return $restore_result;
261
- }
262
-
263
- $attachment_meta = wp_get_attachment_metadata( $wio_attachment->get( 'id' ) );
264
-
265
- if ( isset( $attachment_meta['old_width'] ) && isset( $attachment_meta['old_width'] ) ) {
266
- $attachment_meta['width'] = $attachment_meta['old_width'];
267
- $attachment_meta['height'] = $attachment_meta['old_height'];
268
- wp_update_attachment_metadata( $wio_attachment->get( 'id' ), $attachment_meta );
269
- }
270
-
271
- $allowed_sizes = $wio_attachment->getAllowedSizes();
272
-
273
- if ( $allowed_sizes ) {
274
- foreach ( $allowed_sizes as $image_size ) {
275
- $this->restoreAttachmentSize( $wio_attachment, $image_size );
276
- }
277
- }
278
-
279
- return true;
280
- }
281
-
282
- /**
283
- * Создает временное изображение с уникальным именем.
284
- *
285
- * Необходимо для провайдеров, который кешируют изображения по имени файла,
286
- * чтобы сбросить кеш, нужно отдать провайдеру изображение с другим именем.
287
- *
288
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
289
- * @since 1.1.2
290
- *
291
- * @param string $file_path путь к изображению
292
- *
293
- * @return array|WP_Error
294
- */
295
- public function createTempAttachment( $file_path ) {
296
- if ( $this->isBackupWritable() ) {
297
-
298
- $temp_dir = $this->getBackupDir() . self::TEMP_DIR_NAME . '/';
299
- $temp_dir_url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . self::BACKUP_DIR_NAME . '/' . self::TEMP_DIR_NAME . '/';
300
-
301
- if ( ! is_dir( $temp_dir ) ) {
302
- $temp_dir = $this->mkdir( $temp_dir );
303
-
304
- if ( is_wp_error( $temp_dir ) ) {
305
- return $temp_dir;
306
- }
307
- }
308
-
309
- $temp_file_id = uniqid();
310
- $file_name = pathinfo( $file_path, PATHINFO_FILENAME );
311
- $file_extension = pathinfo( $file_path, PATHINFO_EXTENSION );
312
- $new_file_name = $temp_file_id . '_' . md5( $file_name ) . '.' . $file_extension;
313
-
314
- $temp_file_path = $temp_dir . $new_file_name;
315
- $temp_file_url = $temp_dir_url . $new_file_name;
316
-
317
- if ( is_file( $file_path ) ) {
318
- if ( ! @copy( $file_path, $temp_file_path ) ) {
319
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap original file %s with %s as copy() failed.', $temp_file_path, $file_path ) );
320
-
321
- return new WP_Error( 'copy_file_to_temp_dir_error', __( 'Could not copy the file to the temporary directory', 'robin-image-optimizer' ) );
322
- }
323
- }
324
-
325
- WRIO_Plugin::app()->logger->info( sprintf( 'Creation of temporary attachment (%s) successfully completed!', $file_path ) );
326
-
327
- return [
328
- 'id' => $temp_file_id,
329
- 'image_path' => $temp_file_path,
330
- 'image_url' => $temp_file_url,
331
- ];
332
- }
333
-
334
- return new WP_Error( 'backup_writable_error', __( 'It is not possible to create a temporary file, the backup folder is not writable.', 'robin-image-optimizer' ) );
335
- }
336
-
337
- /**
338
- * Резервное копирование файла аттачмента.
339
- *
340
- * @param WIO_Attachment $wio_attachment аттачмент
341
- * @param string $image_size Размер(thumbnail, medium ... )
342
- *
343
- * @return bool|WP_Error
344
- */
345
- protected function backupAttachmentSize( WIO_Attachment $wio_attachment, $image_size = '' ) {
346
- if ( $image_size ) {
347
- $original_file = $wio_attachment->getImageSizePath( $image_size );
348
- } else {
349
- $original_file = $wio_attachment->get( 'path' );
350
- }
351
-
352
- $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
353
-
354
- // проверить запись в папку
355
- if ( is_wp_error( $backup_dir ) ) {
356
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to create backup dir, error: %s', $backup_dir->get_error_message() ) );
357
-
358
- return $backup_dir;
359
- }
360
-
361
- if ( ! $original_file ) {
362
- // бывает такое, что размера превьюшки нет в базе данных.
363
- // это не считается ошибкой, поэтому сразу пропускаем
364
- return false;
365
- }
366
-
367
- $backup_file = $backup_dir . wp_basename( $original_file );
368
-
369
- if ( is_file( $original_file ) ) {
370
- if ( ! @copy( $original_file, $backup_file ) ) {
371
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to copy %s to %s as copy() failed', $original_file, $backup_file ) );
372
- }
373
- }
374
-
375
- return true;
376
- }
377
-
378
- /**
379
- * Восстановление файла аттачмента из резервной копии
380
- *
381
- * @param WIO_Attachment $wio_attachment аттачмент
382
- * @param string|null $image_size Размер(thumbnail, medium ... )
383
- *
384
- * @return bool|WP_Error
385
- */
386
- protected function restoreAttachmentSize( WIO_Attachment $wio_attachment, $image_size = null ) {
387
-
388
- if ( ! empty( $image_size ) ) {
389
- $original_file = $wio_attachment->getImageSizePath( $image_size );
390
- } else {
391
- $original_file = $wio_attachment->get( 'path' );
392
- }
393
-
394
- $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
395
-
396
- if ( is_wp_error( $backup_dir ) ) {
397
- return $backup_dir;
398
- }
399
-
400
- if ( empty( $original_file ) ) {
401
- return false;
402
- }
403
-
404
- $backup_file = $backup_dir . wp_basename( $original_file );
405
-
406
- if ( ! is_file( $backup_file ) ) {
407
- WRIO_Plugin::app()->logger->error( sprintf( 'Unable to restore from a backup. There is no file, attachment id: %s, backup file: %s', $wio_attachment->get( 'id' ), $backup_file ) );
408
-
409
- return false;
410
- }
411
-
412
- if ( ! @copy( $backup_file, $original_file ) ) {
413
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap %s with %s as copy() failed', $backup_file, $original_file ) );
414
-
415
- return false;
416
- }
417
-
418
- if ( ! @unlink( $backup_file ) ) {
419
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to delete backup file %s as unlink() failed', $backup_file ) );
420
-
421
- return false;
422
- }
423
-
424
- WRIO_Plugin::app()->logger->info( sprintf( 'Restored file: %s.', $backup_file ) );
425
-
426
- return true;
427
- }
428
-
429
- /**
430
- * Удаляем резервные копии аттачмента
431
- *
432
- * @param int $attachment_id аттачмент id
433
- *
434
- * @return bool|WP_Error
435
- */
436
- public function removeAttachmentBackup( $attachment_id ) {
437
- $attachment_meta = wp_get_attachment_metadata( $attachment_id );
438
- $backup_dir = $this->getAttachmentBackupDir( $attachment_meta );
439
-
440
- if ( is_wp_error( $backup_dir ) ) {
441
- return $backup_dir;
442
- }
443
-
444
- $main_file_path = $backup_dir . wp_basename( $attachment_meta['file'] );
445
-
446
- if ( ! file_exists( $main_file_path ) ) {
447
- WRIO_Plugin::app()->logger->error( sprintf( "Failed to remove an attachment file. File (%s) isn't exists. Attachment #%s", $main_file_path, $attachment_id ) );
448
- }
449
-
450
- if ( ! @unlink( $main_file_path ) ) {
451
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to unlink a main file (%s) for attachment #%s', $main_file_path, $attachment_id ) );
452
- }
453
-
454
- if ( isset( $attachment_meta['sizes'] ) && is_array( $attachment_meta['sizes'] ) ) {
455
- foreach ( $attachment_meta['sizes'] as $size ) {
456
- $thumbnail_file_path = $backup_dir . $size['file'];
457
-
458
- if ( ! file_exists( $thumbnail_file_path ) ) {
459
- WRIO_Plugin::app()->logger->error( sprintf( "Failed to remove a thumbnail file. File (%s) isn't exists. Attachment #%s", $thumbnail_file_path, $attachment_id ) );
460
- }
461
-
462
- if ( ! @unlink( $thumbnail_file_path ) ) {
463
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to unlink thumbnail (%s) for attachment #%s', $thumbnail_file_path, $attachment_id ) );
464
- }
465
- }
466
- }
467
-
468
- return true;
469
- }
470
-
471
- /**
472
- * alternateStorage
473
- *
474
- * @param array $servers
475
- *
476
- * @return array
477
- */
478
- public static function alternateStorage( $servers ) {
479
-
480
- return $servers;
481
- }
482
-
483
- /**
484
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
485
- * @since 1.3.0
486
- *
487
- * @param string $dir
488
- *
489
- * @return string|WP_Error
490
- */
491
- protected function mkdir( $dir ) {
492
- WRIO_Plugin::app()->logger->info( sprintf( 'Try to create backup directory. Backup dir: (%s)', $dir ) );
493
-
494
- if ( ! wp_mkdir_p( $dir ) ) {
495
- WRIO_Plugin::app()->logger->error( sprintf( 'Unable to create backup directory (%s) as mkdir() failed', $dir ) );
496
-
497
- return new WP_Error( 'mkdir_failed', sprintf( "Unable to create backup folder (%s) as mkdir() failed.", $dir ) );
498
- }
499
-
500
- return $dir;
501
- }
502
-
503
- /**
504
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
505
- * @since 1.3.0
506
- *
507
- * @param string $backup_file
508
- * @param string $original_file
509
- *
510
- * @return bool
511
- */
512
- protected function restore_file( $backup_file, $original_file ) {
513
- if ( is_file( $backup_file ) ) {
514
- if ( ! @copy( $backup_file, $original_file ) ) {
515
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap original file (%s) with %s as copy() failed', $backup_file, $original_file ) );
516
-
517
- return false;
518
- }
519
-
520
- if ( ! @unlink( $backup_file ) ) {
521
- WRIO_Plugin::app()->logger->error( sprintf( 'Failed to delete backup file (%s) as unlink() failed', $backup_file ) );
522
-
523
- return false;
524
- }
525
-
526
- WRIO_Plugin::app()->logger->info( sprintf( 'Restored file: %s.', $backup_file ) );
527
-
528
- return true;
529
- }
530
-
531
- WRIO_Plugin::app()->logger->error( sprintf( 'Unable to restore from a backup. There is no file (%s).', $backup_file ) );
532
-
533
- return false;
534
- }
535
- }
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с резервным копированием изображений.
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WIO_Backup {
16
+
17
+ CONST BACKUP_DIR_NAME = 'wio_backup';
18
+ CONST TEMP_DIR_NAME = 'temp';
19
+
20
+ /**
21
+ * The single instance of the class.
22
+ *
23
+ * @since 1.3.0
24
+ * @access protected
25
+ * @var object
26
+ */
27
+ protected static $_instance;
28
+
29
+ /**
30
+ * @var array Данные о папке uploads, возвращаемые функцией wp_upload_dir()
31
+ */
32
+ protected $wp_upload_dir;
33
+
34
+ /**
35
+ * @var string Путь к папке с резервными копиями изображений
36
+ */
37
+ private $backup_dir;
38
+
39
+ /**
40
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
41
+ * @since 1.3.0
42
+ * @var string
43
+ */
44
+ private $blog_backup_dir;
45
+
46
+ /**
47
+ * Инициализация бекапа
48
+ */
49
+ public function __construct() {
50
+ $this->wp_upload_dir = wp_upload_dir();
51
+ }
52
+
53
+ /**
54
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
55
+ * @since 1.3.0
56
+ *
57
+ * @return object|\static object Main instance.
58
+ */
59
+ public static function get_instance() {
60
+ if ( ! isset( static::$_instance ) ) {
61
+ static::$_instance = new static();
62
+ }
63
+
64
+ return static::$_instance;
65
+ }
66
+
67
+ /**
68
+ * Проверка возможности записи в папку uploads.
69
+ *
70
+ * @return bool
71
+ */
72
+ public function isUploadWritable() {
73
+ $upload_dir = $this->wp_upload_dir['basedir'];
74
+
75
+ if ( is_dir( $upload_dir ) && wp_is_writable( $upload_dir ) ) {
76
+ return true;
77
+ }
78
+
79
+ return false;
80
+ }
81
+
82
+ /**
83
+ * Проверка возможности записи в папку бекап.
84
+ *
85
+ * @return bool
86
+ */
87
+ public function isBackupWritable() {
88
+
89
+ $backup_dir = $this->getBackupDir();
90
+
91
+ if ( is_wp_error( $backup_dir ) || ! wp_is_writable( $backup_dir ) ) {
92
+ return false;
93
+ }
94
+
95
+ return true;
96
+ }
97
+
98
+ /**
99
+ * Путь к папке с бекапами
100
+ *
101
+ * @return string|WP_Error
102
+ */
103
+ public function getBackupDir() {
104
+ if ( $this->backup_dir ) {
105
+ return $this->backup_dir;
106
+ }
107
+
108
+ $backup_dir = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . self::BACKUP_DIR_NAME );
109
+
110
+ if ( ! is_dir( $backup_dir ) ) {
111
+ $backup_dir = $this->mkdir( $backup_dir );
112
+
113
+ if ( is_wp_error( $backup_dir ) ) {
114
+ return $backup_dir;
115
+ }
116
+ }
117
+
118
+ $this->backup_dir = apply_filters( 'wbcr/rio/backup/backup_dir', trailingslashit( $backup_dir ) );
119
+
120
+ return $this->backup_dir;
121
+ }
122
+
123
+ /**
124
+ * Путь к папке с бекапами блога.
125
+ *
126
+ * Используется в мультисайт режиме.
127
+ *
128
+ * @return string|WP_Error
129
+ */
130
+ public function getBlogBackupDir() {
131
+ if ( $this->blog_backup_dir ) {
132
+ return $this->blog_backup_dir;
133
+ }
134
+
135
+ $wp_upload_dir = wp_upload_dir();
136
+ $backup_dir = wp_normalize_path( trailingslashit( $wp_upload_dir['basedir'] ) . self::BACKUP_DIR_NAME );
137
+
138
+ if ( ! is_dir( $backup_dir ) ) {
139
+ $backup_dir = $this->mkdir( $backup_dir );
140
+
141
+ if ( is_wp_error( $backup_dir ) ) {
142
+ return $backup_dir;
143
+ }
144
+ }
145
+
146
+ $this->blog_backup_dir = trailingslashit( $backup_dir );
147
+
148
+ return $this->blog_backup_dir;
149
+ }
150
+
151
+ /**
152
+ * Очищает папку с резервными копиями
153
+ *
154
+ * @return bool
155
+ */
156
+ public function removeBackupDir() {
157
+ $backup_dir = $this->getBackupDir();
158
+
159
+ return wrio_rmdir( $backup_dir );
160
+ }
161
+
162
+ /**
163
+ * Очищает папку с резервными копиями блога
164
+ * Используется в мультисайт режиме
165
+ *
166
+ * @return bool
167
+ */
168
+ public function removeBlogBackupDir() {
169
+ $backup_dir = $this->getBlogBackupDir();
170
+
171
+ return wrio_rmdir( $backup_dir );
172
+ }
173
+
174
+ /**
175
+ * Получает путь к папке с резервными копиями
176
+ *
177
+ * @param array $attachment_meta метаданные аттачмента
178
+ *
179
+ * @return string
180
+ */
181
+ public function getAttachmentBackupDir( $attachment_meta ) {
182
+ $backup_dir = $this->getBackupDir();
183
+
184
+ // Get all subfolders in which the image is stored.
185
+ // This is necessary to create an alternate subfolders
186
+ // in directory where they are stored in backups.
187
+ $subfolders = dirname( $attachment_meta['file'] );
188
+
189
+ $backup_dir .= $subfolders;
190
+
191
+ if ( ! is_dir( $backup_dir ) ) {
192
+ $backup_dir = $this->mkdir( $backup_dir );
193
+
194
+ if ( is_wp_error( $backup_dir ) ) {
195
+ return $backup_dir;
196
+ }
197
+ }
198
+
199
+ return trailingslashit( $backup_dir );
200
+ }
201
+
202
+ /**
203
+ * Делаем резервную копию аттачмента
204
+ *
205
+ * @param WIO_Attachment $wio_attachment аттачмент
206
+ *
207
+ * @return bool|WP_Error
208
+ */
209
+ public function backupAttachment( WIO_Attachment $wio_attachment ) {
210
+ $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
211
+
212
+ if ( ! $backup_origin_images ) {
213
+ return false; // если бекап не требуется
214
+ }
215
+
216
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
217
+
218
+ if ( is_wp_error( $backup_dir ) ) {
219
+ return $backup_dir;
220
+ }
221
+
222
+ $full = $this->backupAttachmentSize( $wio_attachment );
223
+
224
+ if ( is_wp_error( $full ) ) {
225
+ return $full;
226
+ }
227
+
228
+ $allowed_sizes = $wio_attachment->getAllowedSizes();
229
+
230
+ if ( ! empty( $allowed_sizes ) ) {
231
+ foreach ( (array) $allowed_sizes as $image_size ) {
232
+ $size_backup = $this->backupAttachmentSize( $wio_attachment, $image_size );
233
+
234
+ if ( is_wp_error( $size_backup ) ) {
235
+ return $size_backup;
236
+ }
237
+ }
238
+ }
239
+
240
+ return true;
241
+ }
242
+
243
+ /**
244
+ * Восстанавливаем аттачмент из резервной копии
245
+ *
246
+ * @param WIO_Attachment $wio_attachment аттачмент
247
+ *
248
+ * @return bool|WP_Error
249
+ */
250
+ public function restoreAttachment( WIO_Attachment $wio_attachment ) {
251
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
252
+
253
+ if ( is_wp_error( $backup_dir ) ) {
254
+ return $backup_dir;
255
+ }
256
+
257
+ $restore_result = $this->restoreAttachmentSize( $wio_attachment );
258
+
259
+ if ( is_wp_error( $restore_result ) ) {
260
+ return $restore_result;
261
+ }
262
+
263
+ $attachment_meta = wp_get_attachment_metadata( $wio_attachment->get( 'id' ) );
264
+
265
+ if ( isset( $attachment_meta['old_width'] ) && isset( $attachment_meta['old_width'] ) ) {
266
+ $attachment_meta['width'] = $attachment_meta['old_width'];
267
+ $attachment_meta['height'] = $attachment_meta['old_height'];
268
+ wp_update_attachment_metadata( $wio_attachment->get( 'id' ), $attachment_meta );
269
+ }
270
+
271
+ $allowed_sizes = $wio_attachment->getAllowedSizes();
272
+
273
+ if ( $allowed_sizes ) {
274
+ foreach ( $allowed_sizes as $image_size ) {
275
+ $this->restoreAttachmentSize( $wio_attachment, $image_size );
276
+ }
277
+ }
278
+
279
+ return true;
280
+ }
281
+
282
+ /**
283
+ * Создает временное изображение с уникальным именем.
284
+ *
285
+ * Необходимо для провайдеров, который кешируют изображения по имени файла,
286
+ * чтобы сбросить кеш, нужно отдать провайдеру изображение с другим именем.
287
+ *
288
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
289
+ * @since 1.1.2
290
+ *
291
+ * @param string $file_path путь к изображению
292
+ *
293
+ * @return array|WP_Error
294
+ */
295
+ public function createTempAttachment( $file_path ) {
296
+ if ( $this->isBackupWritable() ) {
297
+
298
+ $temp_dir = $this->getBackupDir() . self::TEMP_DIR_NAME . '/';
299
+ $temp_dir_url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . self::BACKUP_DIR_NAME . '/' . self::TEMP_DIR_NAME . '/';
300
+
301
+ if ( ! is_dir( $temp_dir ) ) {
302
+ $temp_dir = $this->mkdir( $temp_dir );
303
+
304
+ if ( is_wp_error( $temp_dir ) ) {
305
+ return $temp_dir;
306
+ }
307
+ }
308
+
309
+ $temp_file_id = uniqid();
310
+ $file_name = pathinfo( $file_path, PATHINFO_FILENAME );
311
+ $file_extension = pathinfo( $file_path, PATHINFO_EXTENSION );
312
+ $new_file_name = $temp_file_id . '_' . md5( $file_name ) . '.' . $file_extension;
313
+
314
+ $temp_file_path = $temp_dir . $new_file_name;
315
+ $temp_file_url = $temp_dir_url . $new_file_name;
316
+
317
+ if ( is_file( $file_path ) ) {
318
+ if ( ! @copy( $file_path, $temp_file_path ) ) {
319
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap original file %s with %s as copy() failed.', $temp_file_path, $file_path ) );
320
+
321
+ return new WP_Error( 'copy_file_to_temp_dir_error', __( 'Could not copy the file to the temporary directory', 'robin-image-optimizer' ) );
322
+ }
323
+ }
324
+
325
+ WRIO_Plugin::app()->logger->info( sprintf( 'Creation of temporary attachment (%s) successfully completed!', $file_path ) );
326
+
327
+ return [
328
+ 'id' => $temp_file_id,
329
+ 'image_path' => $temp_file_path,
330
+ 'image_url' => $temp_file_url,
331
+ ];
332
+ }
333
+
334
+ return new WP_Error( 'backup_writable_error', __( 'It is not possible to create a temporary file, the backup folder is not writable.', 'robin-image-optimizer' ) );
335
+ }
336
+
337
+ /**
338
+ * Резервное копирование файла аттачмента.
339
+ *
340
+ * @param WIO_Attachment $wio_attachment аттачмент
341
+ * @param string $image_size Размер(thumbnail, medium ... )
342
+ *
343
+ * @return bool|WP_Error
344
+ */
345
+ protected function backupAttachmentSize( WIO_Attachment $wio_attachment, $image_size = '' ) {
346
+ if ( $image_size ) {
347
+ $original_file = $wio_attachment->getImageSizePath( $image_size );
348
+ } else {
349
+ $original_file = $wio_attachment->get( 'path' );
350
+ }
351
+
352
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
353
+
354
+ // проверить запись в папку
355
+ if ( is_wp_error( $backup_dir ) ) {
356
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to create backup dir, error: %s', $backup_dir->get_error_message() ) );
357
+
358
+ return $backup_dir;
359
+ }
360
+
361
+ if ( ! $original_file ) {
362
+ // бывает такое, что размера превьюшки нет в базе данных.
363
+ // это не считается ошибкой, поэтому сразу пропускаем
364
+ return false;
365
+ }
366
+
367
+ $backup_file = $backup_dir . wp_basename( $original_file );
368
+
369
+ if ( is_file( $original_file ) ) {
370
+ if ( ! @copy( $original_file, $backup_file ) ) {
371
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to copy %s to %s as copy() failed', $original_file, $backup_file ) );
372
+ }
373
+ }
374
+
375
+ return true;
376
+ }
377
+
378
+ /**
379
+ * Восстановление файла аттачмента из резервной копии
380
+ *
381
+ * @param WIO_Attachment $wio_attachment аттачмент
382
+ * @param string|null $image_size Размер(thumbnail, medium ... )
383
+ *
384
+ * @return bool|WP_Error
385
+ */
386
+ protected function restoreAttachmentSize( WIO_Attachment $wio_attachment, $image_size = null ) {
387
+
388
+ if ( ! empty( $image_size ) ) {
389
+ $original_file = $wio_attachment->getImageSizePath( $image_size );
390
+ } else {
391
+ $original_file = $wio_attachment->get( 'path' );
392
+ }
393
+
394
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
395
+
396
+ if ( is_wp_error( $backup_dir ) ) {
397
+ return $backup_dir;
398
+ }
399
+
400
+ if ( empty( $original_file ) ) {
401
+ return false;
402
+ }
403
+
404
+ $backup_file = $backup_dir . wp_basename( $original_file );
405
+
406
+ if ( ! is_file( $backup_file ) ) {
407
+ WRIO_Plugin::app()->logger->error( sprintf( 'Unable to restore from a backup. There is no file, attachment id: %s, backup file: %s', $wio_attachment->get( 'id' ), $backup_file ) );
408
+
409
+ return false;
410
+ }
411
+
412
+ if ( ! @copy( $backup_file, $original_file ) ) {
413
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap %s with %s as copy() failed', $backup_file, $original_file ) );
414
+
415
+ return false;
416
+ }
417
+
418
+ if ( ! @unlink( $backup_file ) ) {
419
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to delete backup file %s as unlink() failed', $backup_file ) );
420
+
421
+ return false;
422
+ }
423
+
424
+ WRIO_Plugin::app()->logger->info( sprintf( 'Restored file: %s.', $backup_file ) );
425
+
426
+ return true;
427
+ }
428
+
429
+ /**
430
+ * Удаляем резервные копии аттачмента
431
+ *
432
+ * @param int $attachment_id аттачмент id
433
+ *
434
+ * @return bool|WP_Error
435
+ */
436
+ public function removeAttachmentBackup( $attachment_id ) {
437
+ $attachment_meta = wp_get_attachment_metadata( $attachment_id );
438
+ $backup_dir = $this->getAttachmentBackupDir( $attachment_meta );
439
+
440
+ if ( is_wp_error( $backup_dir ) ) {
441
+ return $backup_dir;
442
+ }
443
+
444
+ $main_file_path = $backup_dir . wp_basename( $attachment_meta['file'] );
445
+
446
+ if ( ! file_exists( $main_file_path ) ) {
447
+ WRIO_Plugin::app()->logger->error( sprintf( "Failed to remove an attachment file. File (%s) isn't exists. Attachment #%s", $main_file_path, $attachment_id ) );
448
+ }
449
+
450
+ if ( ! @unlink( $main_file_path ) ) {
451
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to unlink a main file (%s) for attachment #%s', $main_file_path, $attachment_id ) );
452
+ }
453
+
454
+ if ( isset( $attachment_meta['sizes'] ) && is_array( $attachment_meta['sizes'] ) ) {
455
+ foreach ( $attachment_meta['sizes'] as $size ) {
456
+ $thumbnail_file_path = $backup_dir . $size['file'];
457
+
458
+ if ( ! file_exists( $thumbnail_file_path ) ) {
459
+ WRIO_Plugin::app()->logger->error( sprintf( "Failed to remove a thumbnail file. File (%s) isn't exists. Attachment #%s", $thumbnail_file_path, $attachment_id ) );
460
+ }
461
+
462
+ if ( ! @unlink( $thumbnail_file_path ) ) {
463
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to unlink thumbnail (%s) for attachment #%s', $thumbnail_file_path, $attachment_id ) );
464
+ }
465
+ }
466
+ }
467
+
468
+ return true;
469
+ }
470
+
471
+ /**
472
+ * alternateStorage
473
+ *
474
+ * @param array $servers
475
+ *
476
+ * @return array
477
+ */
478
+ public static function alternateStorage( $servers ) {
479
+
480
+ return $servers;
481
+ }
482
+
483
+ /**
484
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
485
+ * @since 1.3.0
486
+ *
487
+ * @param string $dir
488
+ *
489
+ * @return string|WP_Error
490
+ */
491
+ protected function mkdir( $dir ) {
492
+ WRIO_Plugin::app()->logger->info( sprintf( 'Try to create backup directory. Backup dir: (%s)', $dir ) );
493
+
494
+ if ( ! wp_mkdir_p( $dir ) ) {
495
+ WRIO_Plugin::app()->logger->error( sprintf( 'Unable to create backup directory (%s) as mkdir() failed', $dir ) );
496
+
497
+ return new WP_Error( 'mkdir_failed', sprintf( "Unable to create backup folder (%s) as mkdir() failed.", $dir ) );
498
+ }
499
+
500
+ return $dir;
501
+ }
502
+
503
+ /**
504
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
505
+ * @since 1.3.0
506
+ *
507
+ * @param string $backup_file
508
+ * @param string $original_file
509
+ *
510
+ * @return bool
511
+ */
512
+ protected function restore_file( $backup_file, $original_file ) {
513
+ if ( is_file( $backup_file ) ) {
514
+ if ( ! @copy( $backup_file, $original_file ) ) {
515
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to swap original file (%s) with %s as copy() failed', $backup_file, $original_file ) );
516
+
517
+ return false;
518
+ }
519
+
520
+ if ( ! @unlink( $backup_file ) ) {
521
+ WRIO_Plugin::app()->logger->error( sprintf( 'Failed to delete backup file (%s) as unlink() failed', $backup_file ) );
522
+
523
+ return false;
524
+ }
525
+
526
+ WRIO_Plugin::app()->logger->info( sprintf( 'Restored file: %s.', $backup_file ) );
527
+
528
+ return true;
529
+ }
530
+
531
+ WRIO_Plugin::app()->logger->error( sprintf( 'Unable to restore from a backup. There is no file (%s).', $backup_file ) );
532
+
533
+ return false;
534
+ }
535
+ }
includes/classes/class-rio-bulk-optimization.php CHANGED
@@ -1,462 +1,665 @@
1
- <?php
2
-
3
- use WBCR\Factory_Processing_100\WP_Background_Process;
4
-
5
- // Exit if accessed directly
6
- if ( ! defined( 'ABSPATH' ) ) {
7
- exit;
8
- }
9
-
10
- /**
11
- * Класс для AJAX массовой оптимизации
12
- *
13
- * @author Artem Prikhodko <webtemyk@yandex.ru>
14
- * @copyright (c) 2021, Webcraftic
15
- * @version 1.0
16
- */
17
- class WRIO_Bulk_Optimization {
18
-
19
- public $processing;
20
-
21
- public function __construct() {
22
- if ( wrio_is_license_activate() ) {
23
- $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
24
- $this->processing = $scope ? wrio_get_processing_class( $scope ) : $scope;
25
-
26
- add_action( 'wp_ajax_wrio-cron-start', [ $this, 'processing_start' ] );
27
- add_action( 'wp_ajax_wrio-cron-stop', [ $this, 'processing_stop' ] );
28
- } else {
29
- add_action( 'wp_ajax_wrio-cron-start', [ $this, 'cron_start' ] );
30
- add_action( 'wp_ajax_wrio-cron-stop', [ $this, 'cron_stop' ] );
31
- }
32
-
33
- add_action( 'wp_ajax_wrio-bulk-optimization-process', [ $this, 'bulk_optimization_process' ] );
34
- add_action( 'wp_ajax_wio_reoptimize_image', [ $this, 'reoptimize_image' ] );
35
- add_action( 'wp_ajax_wio_restore_image', [ $this, 'restore_image' ] );
36
-
37
- add_action( 'wp_ajax_wbcr-rio-check-servers-status', [ $this, 'check_servers_status' ] );
38
- add_action( 'wp_ajax_wbcr-rio-check-user-balance', [ $this, 'check_user_balance' ] );
39
-
40
- add_action( 'wp_ajax_wbcr-rio-calculate-total-images', [ $this, 'calculate_total_images' ] );
41
-
42
- }
43
-
44
- public function cron_start() {
45
- check_ajax_referer( 'bulk_optimization' );
46
-
47
- if ( ! current_user_can( 'manage_options' ) ) {
48
- wp_die( - 1 );
49
- }
50
-
51
- $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
52
-
53
- if ( empty( $scope ) ) {
54
- wp_die( - 1 );
55
- }
56
-
57
- // where was runned cron
58
- $cron_running_place = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
59
-
60
- if ( $scope == $cron_running_place ) {
61
- wp_send_json_success();
62
- }
63
-
64
- WRIO_Plugin::app()->updatePopulateOption( 'cron_running', $scope );
65
- WRIO_Cron::start();
66
-
67
- wp_send_json_success();
68
- }
69
-
70
- public function cron_stop() {
71
- check_ajax_referer( 'bulk_optimization' );
72
-
73
- if ( ! current_user_can( 'manage_options' ) ) {
74
- wp_die( - 1 );
75
- }
76
-
77
- WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false );
78
- WRIO_Cron::stop();
79
-
80
- wp_send_json_success();
81
- }
82
-
83
- public function processing_start() {
84
- check_ajax_referer( 'bulk_optimization' );
85
-
86
- if ( ! current_user_can( 'manage_options' ) ) {
87
- wp_die( - 1 );
88
- }
89
-
90
- $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
91
-
92
- if ( empty( $scope ) ) {
93
- wp_die( - 1 );
94
- }
95
-
96
- // where was runned
97
- $process_running_place = WRIO_Plugin::app()->getPopulateOption( 'process_running', false );
98
-
99
- if ( $scope == $process_running_place ) {
100
- wp_send_json_success();
101
- }
102
-
103
- WRIO_Plugin::app()->updatePopulateOption( 'process_running', $scope );
104
-
105
- $processing = wrio_get_processing_class( $scope );
106
- if ( $processing->push_items() ) {
107
- $processing->save()->dispatch();
108
- } else {
109
- //WRIO_Plugin::app()->updatePopulateOption( 'process_running', false );
110
- wp_send_json_success([
111
- 'stop' => true
112
- ]);
113
- }
114
-
115
- wp_send_json_success();
116
- }
117
-
118
- public function processing_stop() {
119
- check_ajax_referer( 'bulk_optimization' );
120
-
121
- if ( ! current_user_can( 'manage_options' ) ) {
122
- wp_die( - 1 );
123
- }
124
-
125
- $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
126
- if ( empty( $scope ) ) {
127
- wp_die( - 1 );
128
- }
129
-
130
- WRIO_Plugin::app()->updatePopulateOption( 'process_running', false );
131
- $processing = wrio_get_processing_class( $scope );
132
- $processing->cancel_process();
133
-
134
- wp_send_json_success();
135
- }
136
-
137
- public function bulk_optimization_process() {
138
- check_admin_referer( 'bulk_optimization' );
139
-
140
- if ( ! current_user_can( 'manage_options' ) ) {
141
- wp_die( - 1 );
142
- }
143
-
144
- $reset_current_error = (bool) WRIO_Plugin::app()->request->request( 'reset_current_errors' );
145
- $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
146
-
147
- WRIO_Plugin::app()->logger->info( sprintf( 'Start bulk optimization process! Scope: %s', $scope ) );
148
-
149
- if ( empty( $scope ) ) {
150
- wp_die( - 1 );
151
- }
152
-
153
- // Context class name. If plugin expands with add-ons
154
- $class_name = 'WRIO_' . wrio_dashes_to_camel_case( $scope, true );
155
-
156
- if ( ! class_exists( $class_name ) ) {
157
- WRIO_Plugin::app()->logger->error( sprintf( 'Bulk optimization error: Context class (%s) not found.', $class_name ) );
158
-
159
- //todo: Temporary bug fix.
160
- if ( 'media-library' === $scope ) {
161
- $class_name = 'WRIO_Media_Library';
162
- } else if ( 'custom-folders' === $scope ) {
163
- $class_name = 'WRIO_Custom_Folders';
164
- } else if ( 'nextgen-gallery' == $scope ) {
165
- $class_name = 'WRIO_Nextgen_Gallery';
166
- }
167
-
168
- if ( ! class_exists( $class_name ) ) {
169
- wp_send_json_error( [ 'error_message' => 'Context class not found.' ] );
170
- }
171
- }
172
-
173
- /**
174
- * Create an instance of the class depending on the context in which scope user
175
- * has runned optimization.
176
- *
177
- * @see WRIO_Media_Library
178
- * @see WRIO_Custom_Folders
179
- * @see WRIO_Nextgen_Gallery
180
- */
181
- $optimizer = new $class_name();
182
-
183
- // в ajax запросе мы не знаем, получен ли он из мультиадминки или из обычной. Поэтому проверяем параметр, полученный из frontend
184
- /*if ( isset( $_POST['multisite'] ) && (bool) $_POST['multisite'] ) {
185
- $multisite = new WIO_Multisite;
186
- $multisite->initHooks();
187
- }*/
188
-
189
- if ( $reset_current_error ) {
190
- $optimizer->resetCurrentErrors(); // сбрасываем текущие ошибки оптимизации
191
- }
192
-
193
- $result = $optimizer->processUnoptimizedImages( 1 );
194
-
195
- if ( is_wp_error( $result ) ) {
196
- $error_massage = $result->get_error_message();
197
-
198
- if ( empty( $error_massage ) ) {
199
- $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" );
200
- }
201
-
202
- WRIO_Plugin::app()->logger->error( sprintf( 'Bulk optimization error: %s.', $result->get_error_message() ) );
203
-
204
- wp_send_json_error( [ 'error_message' => $error_massage ] );
205
- }
206
-
207
- // если изображения закончились - посылаем команду завершения
208
- if ( $result['remain'] <= 0 ) {
209
- $result['end'] = true;
210
- }
211
-
212
- WRIO_Plugin::app()->logger->info( sprintf( 'End bulk optimization process! Scope: %s. Remain: %d', $scope, $result['remain'] ) );
213
-
214
- wp_send_json_success( $result );
215
- }
216
-
217
- public function reoptimize_image() {
218
- if ( ! current_user_can( 'manage_options' ) ) {
219
- wp_die( - 1 );
220
- }
221
-
222
- $default_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
223
-
224
- $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
225
- $level = WRIO_Plugin::app()->request->post( 'level', $default_level, true );
226
-
227
- $backup = WIO_Backup::get_instance();
228
- $media_library = WRIO_Media_Library::get_instance();
229
- $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
230
-
231
- if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
232
- echo $media_library->getMediaColumnContent( $attachment_id );
233
- die();
234
- }
235
-
236
- $optimized_data = $media_library->optimizeAttachment( $attachment_id, $level );
237
-
238
- if ( $optimized_data && isset( $optimized_data['processing'] ) ) {
239
- echo 'processing';
240
- die();
241
- }
242
-
243
- echo $media_library->getMediaColumnContent( $attachment_id );
244
- die();
245
- }
246
-
247
- public function restore_image() {
248
- if ( ! current_user_can( 'manage_options' ) ) {
249
- wp_die( - 1 );
250
- }
251
-
252
- $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
253
-
254
- $media_library = WRIO_Media_Library::get_instance();
255
- $wio_attachment = $media_library->getAttachment( $attachment_id );
256
-
257
- if ( $wio_attachment->isOptimized() ) {
258
- $media_library->restoreAttachment( $attachment_id );
259
- }
260
-
261
- echo $media_library->getMediaColumnContent( $attachment_id );
262
- die();
263
- }
264
-
265
- public function check_servers_status() {
266
- check_ajax_referer( 'bulk_optimization' );
267
-
268
- if ( ! current_user_can( 'manage_options' ) ) {
269
- wp_die( - 1 );
270
- }
271
-
272
- $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
273
-
274
- if ( empty( $server_name ) || ! in_array( $server_name, [
275
- 'server_1',
276
- 'server_2',
277
- 'server_5'
278
- ] ) ) {
279
- wp_send_json_error( [ 'error' => __( 'Server name is empty!', 'robin-image-optimizer' ) ] );
280
- }
281
-
282
- // Позволяем выбрать сервер, даже если он недоступен.
283
- WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', $server_name );
284
-
285
- // Проверяем доступность сервер
286
- // --------------------------------------------------------------------
287
- $return_data = [ 'server_name' => $server_name ];
288
-
289
- $server_url = wrio_get_server_url( $server_name );
290
- $headers = [];
291
-
292
- $method = 'POST';
293
-
294
- if ( $server_name == 'server_2' ) {
295
- $api_url = "https://dev.robinoptimizer.com/v1/free/license/check";
296
- $method = 'GET';
297
- $host = get_option( 'siteurl' );
298
- $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
299
- } else if ( $server_name == 'server_5' ) {
300
- $api_url = "https://dashboard.robinoptimizer.com/v1/license/check";
301
- $method = 'GET';
302
- $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
303
- $headers['PluginId'] = wrio_get_freemius_plugin_id();
304
- } else {
305
- $api_url = $server_url;
306
- }
307
-
308
- $request = wp_remote_request( $api_url, [
309
- 'method' => $method,
310
- 'headers' => $headers
311
- ] );
312
-
313
- if ( is_wp_error( $request ) ) {
314
- $er_msg = $request->get_error_message();
315
-
316
- $return_data['error'] = $er_msg;
317
- wp_send_json_error( $return_data );
318
- }
319
-
320
- $response_code = wp_remote_retrieve_response_code( $request );
321
-
322
- if ( $response_code != 200 ) {
323
- $return_data['error'] = 'Server response ' . $response_code;
324
- wp_send_json_error( $return_data );
325
- }
326
-
327
- wp_send_json_success( $return_data );
328
- }
329
-
330
- public function check_user_balance() {
331
- check_ajax_referer( 'bulk_optimization' );
332
-
333
- if ( ! current_user_can( 'manage_options' ) ) {
334
- wp_die( - 1 );
335
- }
336
-
337
- $optimization_server = $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
338
- if ( $optimization_server !== 'server_5' && $optimization_server !== 'server_2' ) {
339
- $processor = WIO_OptimizationTools::getImageProcessor();
340
-
341
- $processor->checkLimits( false );
342
-
343
- $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
344
- $remaining = $processor->iamokay() - $usage;
345
- wp_send_json_success( [
346
- 'balance' => $remaining,
347
- ] );
348
- }
349
-
350
- if ( $optimization_server == 'server_2' ) {
351
- $api_url = "https://dev.robinoptimizer.com/v1/free/license/remaining";
352
- $host = get_option( 'siteurl' );
353
- $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
354
- } elseif ( $optimization_server == 'server_5' ) {
355
- $api_url = 'https://dashboard.robinoptimizer.com/v1/license/remaining';
356
- $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
357
- $headers['PluginId'] = wrio_get_freemius_plugin_id();
358
- }
359
-
360
-
361
- $request = wp_remote_request( $api_url, [
362
- 'method' => 'GET',
363
- 'headers' => $headers
364
- ] );
365
-
366
- if ( is_wp_error( $request ) ) {
367
- $error_msg = $request->get_error_message();
368
-
369
- $return_data['error'] = $error_msg;
370
- wp_send_json_error( $return_data );
371
- }
372
-
373
- $response_code = wp_remote_retrieve_response_code( $request );
374
- $response_body = wp_remote_retrieve_body( $request );
375
-
376
- if ( $response_code != 200 ) {
377
- $return_data['error'] = 'Server response ' . $response_code;
378
- if ( $response_code === 401 ) {
379
- $error_data = @json_decode( $response_body );
380
- $return_data['error'] = $error_data->message;
381
- }
382
- wp_send_json_error( $return_data );
383
- }
384
-
385
- if ( empty( $response_body ) ) {
386
- $return_data['error'] = "Server responded an empty request body!";
387
- wp_send_json_error( $return_data );
388
- }
389
-
390
- $data = @json_decode( $response_body );
391
-
392
- if ( ! isset( $data->status ) || $data->status != 'ok' ) {
393
- $return_data['error'] = "Server responded an fail status";
394
- wp_send_json_error( $return_data );
395
- }
396
-
397
- $current_quota = (int) $data->response->quota;
398
- WRIO_Plugin::app()->app()->updateOption( 'current_quota', $current_quota );
399
-
400
- $output = [ 'balance' => $current_quota ];
401
-
402
- if ( $optimization_server == 'server_5' ) {
403
- $reset_at = (int) $data->response->reset_at;
404
- $reset_at += (int) get_option( 'gmt_offset', 0 );
405
- $output['reset_at'] = date( 'd-m-Y H:i', $reset_at );
406
- }
407
-
408
- wp_send_json_success( $output );
409
- }
410
-
411
- public function calculate_total_images() {
412
- check_ajax_referer( 'bulk_optimization' );
413
-
414
- if ( ! current_user_can( 'manage_options' ) ) {
415
- wp_die( - 1 );
416
- }
417
-
418
- global $wpdb;
419
- $allowed_formats_sql = wrio_get_allowed_formats( true );
420
- $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type IN ( {$allowed_formats_sql} );";
421
- $attachments = $wpdb->get_results( $sql );
422
-
423
- $db_table = RIO_Process_Queue::table_name();
424
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
425
- WHERE item_type = 'attachment' AND result_status IN (%s)
426
- ORDER BY id DESC;", RIO_Process_Queue::STATUS_SUCCESS );
427
- $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
428
-
429
- $count = 0;
430
- if ( ! empty( $optimized_images ) ) {
431
- foreach ( $optimized_images as $row ) {
432
- $item = new RIO_Process_Queue( $row );
433
- $count = $count + 1 + (int) $item->get_extra_data()->get_thumbnails_count();
434
- }
435
- }
436
-
437
-
438
- $allowed_sizes = explode( ',', WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', '' ) );
439
- $total_images = 0;
440
- $upload = wp_upload_dir();
441
- $upload = $upload['basedir'];
442
- foreach ( $attachments as $attachment ) {
443
- $meta = wp_get_attachment_metadata( $attachment->ID );
444
- if ( $meta ) {
445
- if ( isset( $meta['file'] ) && file_exists( "{$upload}/{$meta['file']}" ) ) {
446
- $total_images ++;
447
- }
448
-
449
- foreach ( $meta['sizes'] as $k => $value ) {
450
- if ( in_array( $k, $allowed_sizes ) ) {
451
- $total_images ++;
452
- }
453
- }
454
- }
455
- }
456
- $result_total = $total_images - $count;
457
- wp_send_json_success( [
458
- 'total' => $result_total >= 0 ? $result_total : 0,
459
- ] );
460
- }
461
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
1
+ <?php
2
+
3
+ use WBCR\Factory_Processing_101\WP_Background_Process;
4
+
5
+ // Exit if accessed directly
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ /**
11
+ * Класс для AJAX массовой оптимизации
12
+ *
13
+ * @author Artem Prikhodko <webtemyk@yandex.ru>
14
+ * @copyright (c) 2021, Webcraftic
15
+ * @version 1.0
16
+ */
17
+ class WRIO_Bulk_Optimization {
18
+
19
+ public $processing;
20
+
21
+ public function __construct() {
22
+ $image_optimization_type = WRIO_Plugin::app()->getOption( 'image_optimization_type', '' );
23
+ if ( wrio_is_license_activate() && $image_optimization_type === 'background' ) {
24
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
25
+ $this->processing = $scope ? wrio_get_processing_class( $scope ) : $scope;
26
+
27
+ add_action( 'wp_ajax_wrio-cron-start', [ $this, 'processing_start' ] );
28
+ add_action( 'wp_ajax_wrio-cron-stop', [ $this, 'processing_stop' ] );
29
+
30
+ add_action( 'wp_ajax_wrio-webp-cron-start', [ $this, 'webp_processing_start' ] );
31
+ add_action( 'wp_ajax_wrio-webp-cron-stop', [ $this, 'webp_processing_stop' ] );
32
+ } else {
33
+ add_action( 'wp_ajax_wrio-cron-start', [ $this, 'cron_start' ] );
34
+ add_action( 'wp_ajax_wrio-cron-stop', [ $this, 'cron_stop' ] );
35
+
36
+ add_action( 'wp_ajax_wrio-webp-cron-start', [ $this, 'webp_cron_start' ] );
37
+ add_action( 'wp_ajax_wrio-webp-cron-stop', [ $this, 'webp_cron_stop' ] );
38
+ }
39
+
40
+ add_action( 'wp_ajax_wrio-bulk-optimization-process', [ $this, 'bulk_optimization_process' ] );
41
+ add_action( 'wp_ajax_wrio-bulk-conversion-process', [ $this, 'bulk_conversion_process' ] );
42
+ add_action( 'wp_ajax_wio_reoptimize_image', [ $this, 'reoptimize_image' ] );
43
+ add_action( 'wp_ajax_wio_convert_image', [ $this, 'convert_image' ] );
44
+ add_action( 'wp_ajax_wio_restore_image', [ $this, 'restore_image' ] );
45
+
46
+ add_action( 'wp_ajax_wbcr-rio-check-servers-status', [ $this, 'check_servers_status' ] );
47
+ add_action( 'wp_ajax_wbcr-rio-check-user-balance', [ $this, 'check_user_balance' ] );
48
+
49
+ add_action( 'wp_ajax_wbcr-rio-calculate-total-images', [ $this, 'calculate_total_images' ] );
50
+
51
+ }
52
+
53
+ public function cron_start() {
54
+ check_ajax_referer( 'bulk_optimization' );
55
+
56
+ if ( ! current_user_can( 'manage_options' ) ) {
57
+ wp_die( - 1 );
58
+ }
59
+
60
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
61
+
62
+ if ( empty( $scope ) ) {
63
+ wp_die( - 1 );
64
+ }
65
+
66
+ // where was runned cron
67
+ $cron_running_place = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
68
+
69
+ if ( $scope == $cron_running_place ) {
70
+ wp_send_json_success();
71
+ }
72
+
73
+ WRIO_Plugin::app()->updatePopulateOption( 'cron_running', $scope );
74
+ WRIO_Cron::start();
75
+
76
+ wp_send_json_success();
77
+ }
78
+
79
+ public function cron_stop() {
80
+ check_ajax_referer( 'bulk_optimization' );
81
+
82
+ if ( ! current_user_can( 'manage_options' ) ) {
83
+ wp_die( - 1 );
84
+ }
85
+
86
+ WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false );
87
+ WRIO_Cron::stop();
88
+
89
+ wp_send_json_success();
90
+ }
91
+
92
+ public function webp_cron_start() {
93
+ check_ajax_referer( 'bulk_conversion' );
94
+
95
+ if ( ! current_user_can( 'manage_options' ) ) {
96
+ wp_die( - 1 );
97
+ }
98
+
99
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
100
+
101
+ if ( empty( $scope ) ) {
102
+ wp_die( - 1 );
103
+ }
104
+
105
+ $type = 'conversion';
106
+
107
+ // where was runned cron
108
+ $cron_running_place = WRIO_Plugin::app()->getPopulateOption( "{$type}_cron_running", false );
109
+
110
+ if ( $scope == $cron_running_place ) {
111
+ wp_send_json_success();
112
+ }
113
+
114
+ WRIO_Plugin::app()->updatePopulateOption( "{$type}_cron_running", $scope );
115
+ WRIO_Cron::start( $type );
116
+
117
+ wp_send_json_success();
118
+ }
119
+
120
+ public function webp_cron_stop() {
121
+ check_ajax_referer( 'bulk_conversion' );
122
+
123
+ if ( ! current_user_can( 'manage_options' ) ) {
124
+ wp_die( - 1 );
125
+ }
126
+
127
+ $type = 'conversion';
128
+
129
+ WRIO_Plugin::app()->updatePopulateOption( "{$type}_cron_running", false );
130
+ WRIO_Cron::stop( $type );
131
+
132
+ wp_send_json_success();
133
+ }
134
+
135
+ public function processing_start() {
136
+ check_ajax_referer( 'bulk_optimization' );
137
+
138
+ if ( ! current_user_can( 'manage_options' ) ) {
139
+ wp_die( - 1 );
140
+ }
141
+
142
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
143
+
144
+ if ( empty( $scope ) ) {
145
+ wp_die( - 1 );
146
+ }
147
+
148
+ // where was runned
149
+ $process_running_place = WRIO_Plugin::app()->getPopulateOption( 'process_running', false );
150
+
151
+ if ( $scope == $process_running_place ) {
152
+ wp_send_json_success();
153
+ }
154
+
155
+ WRIO_Plugin::app()->updatePopulateOption( 'process_running', $scope );
156
+
157
+ $processing = wrio_get_processing_class( $scope );
158
+ if ( $processing->push_items() ) {
159
+ $processing->save()->dispatch();
160
+ } else {
161
+ //WRIO_Plugin::app()->updatePopulateOption( 'process_running', false );
162
+ wp_send_json_success( [
163
+ 'stop' => true
164
+ ] );
165
+ }
166
+
167
+ wp_send_json_success();
168
+ }
169
+
170
+ public function processing_stop() {
171
+ check_ajax_referer( 'bulk_optimization' );
172
+
173
+ if ( ! current_user_can( 'manage_options' ) ) {
174
+ wp_die( - 1 );
175
+ }
176
+
177
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
178
+ if ( empty( $scope ) ) {
179
+ wp_die( - 1 );
180
+ }
181
+
182
+ WRIO_Plugin::app()->updatePopulateOption( 'process_running', false );
183
+ $processing = wrio_get_processing_class( $scope );
184
+ $processing->cancel_process();
185
+
186
+ wp_send_json_success();
187
+ }
188
+
189
+ public function webp_processing_start() {
190
+ check_ajax_referer( 'bulk_conversion' );
191
+
192
+ if ( ! current_user_can( 'manage_options' ) ) {
193
+ wp_die( - 1 );
194
+ }
195
+
196
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
197
+
198
+ if ( empty( $scope ) ) {
199
+ wp_die( - 1 );
200
+ }
201
+
202
+ $scope = $scope . "_webp";
203
+
204
+ // where was runned
205
+ $process_running_place = WRIO_Plugin::app()->getPopulateOption( "{$scope}_process_running", false );
206
+
207
+ if ( $scope == $process_running_place ) {
208
+ wp_send_json_success();
209
+ }
210
+
211
+ WRIO_Plugin::app()->updatePopulateOption( "{$scope}_process_running", $scope );
212
+
213
+ $processing = wrio_get_processing_class( $scope );
214
+ if ( $processing->push_items() ) {
215
+ $processing->save()->dispatch();
216
+ } else {
217
+ //WRIO_Plugin::app()->updatePopulateOption( 'process_running', false );
218
+ wp_send_json_success( [
219
+ 'stop' => true
220
+ ] );
221
+ }
222
+
223
+ wp_send_json_success();
224
+ }
225
+
226
+ public function webp_processing_stop() {
227
+ check_ajax_referer( 'bulk_conversion' );
228
+
229
+ if ( ! current_user_can( 'manage_options' ) ) {
230
+ wp_die( - 1 );
231
+ }
232
+
233
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
234
+ if ( empty( $scope ) ) {
235
+ wp_die( - 1 );
236
+ }
237
+
238
+ $scope = $scope . "_webp";
239
+
240
+ WRIO_Plugin::app()->updatePopulateOption( "{$scope}_process_running", false );
241
+ $processing = wrio_get_processing_class( $scope );
242
+ $processing->cancel_process();
243
+
244
+ wp_send_json_success();
245
+ }
246
+
247
+ public function bulk_optimization_process() {
248
+ check_admin_referer( 'bulk_optimization' );
249
+
250
+ if ( ! current_user_can( 'manage_options' ) ) {
251
+ wp_die( - 1 );
252
+ }
253
+
254
+ $reset_current_error = (bool) WRIO_Plugin::app()->request->request( 'reset_current_errors' );
255
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
256
+
257
+ WRIO_Plugin::app()->logger->info( sprintf( 'Start bulk optimization process! Scope: %s', $scope ) );
258
+
259
+ if ( empty( $scope ) ) {
260
+ wp_die( - 1 );
261
+ }
262
+
263
+ // Context class name. If plugin expands with add-ons
264
+ $class_name = 'WRIO_' . wrio_dashes_to_camel_case( $scope, true );
265
+
266
+ if ( ! class_exists( $class_name ) ) {
267
+ WRIO_Plugin::app()->logger->error( sprintf( 'Bulk optimization error: Context class (%s) not found.', $class_name ) );
268
+
269
+ //todo: Temporary bug fix.
270
+ if ( 'media-library' === $scope ) {
271
+ $class_name = 'WRIO_Media_Library';
272
+ } else if ( 'custom-folders' === $scope ) {
273
+ $class_name = 'WRIO_Custom_Folders';
274
+ } else if ( 'nextgen-gallery' == $scope ) {
275
+ $class_name = 'WRIO_Nextgen_Gallery';
276
+ }
277
+
278
+ if ( ! class_exists( $class_name ) ) {
279
+ wp_send_json_error( [ 'error_message' => 'Context class not found.' ] );
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Create an instance of the class depending on the context in which scope user
285
+ * has runned optimization.
286
+ *
287
+ * @see WRIO_Media_Library
288
+ * @see WRIO_Custom_Folders
289
+ * @see WRIO_Nextgen_Gallery
290
+ */
291
+ $optimizer = new $class_name();
292
+
293
+ // в ajax запросе мы не знаем, получен ли он из мультиадминки или из обычной. Поэтому проверяем параметр, полученный из frontend
294
+ /*if ( isset( $_POST['multisite'] ) && (bool) $_POST['multisite'] ) {
295
+ $multisite = new WIO_Multisite;
296
+ $multisite->initHooks();
297
+ }*/
298
+
299
+ if ( $reset_current_error ) {
300
+ $optimizer->resetCurrentErrors(); // сбрасываем текущие ошибки оптимизации
301
+ }
302
+
303
+ $result = $optimizer->processUnoptimizedImages( 1 );
304
+
305
+ if ( is_wp_error( $result ) ) {
306
+ $error_massage = $result->get_error_message();
307
+
308
+ if ( empty( $error_massage ) ) {
309
+ $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" );
310
+ }
311
+
312
+ WRIO_Plugin::app()->logger->error( sprintf( 'Bulk optimization error: %s.', $result->get_error_message() ) );
313
+
314
+ wp_send_json_error( [ 'error_message' => $error_massage ] );
315
+ }
316
+
317
+ // если изображения закончились - посылаем команду завершения
318
+ if ( $result['remain'] <= 0 ) {
319
+ $result['end'] = true;
320
+ }
321
+
322
+ WRIO_Plugin::app()->logger->info( sprintf( 'End bulk optimization process! Scope: %s. Remain: %d', $scope, $result['remain'] ) );
323
+
324
+ wp_send_json_success( $result );
325
+ }
326
+
327
+ public function bulk_conversion_process() {
328
+ check_admin_referer( 'bulk_conversion' );
329
+
330
+ if ( ! current_user_can( 'manage_options' ) ) {
331
+ wp_die( - 1 );
332
+ }
333
+
334
+ $reset_current_error = (bool) WRIO_Plugin::app()->request->request( 'reset_current_errors' );
335
+ $scope = WRIO_Plugin::app()->request->request( 'scope', null, true );
336
+
337
+ WRIO_Plugin::app()->logger->info( sprintf( 'Start bulk conversion process! Scope: %s', $scope ) );
338
+
339
+ if ( empty( $scope ) ) {
340
+ wp_die( - 1 );
341
+ }
342
+
343
+ // Context class name. If plugin expands with add-ons
344
+ $class_name = 'WRIO_' . wrio_dashes_to_camel_case( $scope, true );
345
+
346
+ if ( ! class_exists( $class_name ) ) {
347
+ WRIO_Plugin::app()->logger->error( sprintf( 'Bulk conversion error: Context class (%s) not found.', $class_name ) );
348
+
349
+ //todo: Temporary bug fix.
350
+ if ( 'media-library' === $scope ) {
351
+ $class_name = 'WRIO_Media_Library';
352
+ } else if ( 'custom-folders' === $scope ) {
353
+ $class_name = 'WRIO_Custom_Folders';
354
+ } else if ( 'nextgen-gallery' == $scope ) {
355
+ $class_name = 'WRIO_Nextgen_Gallery';
356
+ }
357
+
358
+ if ( ! class_exists( $class_name ) ) {
359
+ wp_send_json_error( [ 'error_message' => 'Context class not found.' ] );
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Create an instance of the class depending on the context in which scope user
365
+ * has runned optimization.
366
+ *
367
+ * @see WRIO_Media_Library
368
+ * @see WRIO_Custom_Folders
369
+ * @see WRIO_Nextgen_Gallery
370
+ */
371
+ $optimizer = new $class_name();
372
+
373
+ if ( $reset_current_error ) {
374
+ $optimizer->resetCurrentErrors(); // сбрасываем текущие ошибки оптимизации
375
+ }
376
+
377
+ $result = $optimizer->webpUnoptimizedImages( 1 );
378
+
379
+ if ( is_wp_error( $result ) ) {
380
+ $error_massage = $result->get_error_message();
381
+
382
+ if ( empty( $error_massage ) ) {
383
+ $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" );
384
+ }
385
+
386
+ WRIO_Plugin::app()->logger->error( sprintf( 'Bulk conversion error: %s.', $result->get_error_message() ) );
387
+
388
+ wp_send_json_error( [ 'error_message' => $error_massage ] );
389
+ }
390
+
391
+ // если изображения закончились - посылаем команду завершения
392
+ if ( $result['remain'] <= 0 ) {
393
+ $result['end'] = true;
394
+ }
395
+
396
+ WRIO_Plugin::app()->logger->info( sprintf( 'End bulk conversion process! Scope: %s. Remain: %d', $scope, $result['remain'] ) );
397
+
398
+ wp_send_json_success( $result );
399
+ }
400
+
401
+ public function reoptimize_image() {
402
+ check_admin_referer( 'reoptimize' );
403
+
404
+ if ( ! current_user_can( 'manage_options' ) ) {
405
+ wp_die( - 1 );
406
+ }
407
+
408
+ $default_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
409
+
410
+ $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
411
+ $level = WRIO_Plugin::app()->request->post( 'level', $default_level, true );
412
+
413
+ $backup = WIO_Backup::get_instance();
414
+ $media_library = WRIO_Media_Library::get_instance();
415
+ $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
416
+
417
+ if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
418
+ echo $media_library->getMediaColumnContent( $attachment_id );
419
+ die();
420
+ }
421
+
422
+ $optimized_data = $media_library->optimizeAttachment( $attachment_id, $level );
423
+
424
+ if ( $optimized_data && isset( $optimized_data['processing'] ) ) {
425
+ echo 'processing';
426
+ die();
427
+ }
428
+
429
+ echo $media_library->getMediaColumnContent( $attachment_id );
430
+ die();
431
+ }
432
+
433
+ public function convert_image() {
434
+ check_admin_referer( 'convert' );
435
+
436
+ if ( ! current_user_can( 'manage_options' ) ) {
437
+ wp_die( - 1 );
438
+ }
439
+
440
+ $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
441
+ $media_library = WRIO_Media_Library::get_instance();
442
+
443
+ $media_library->webpConvertAttachment( $attachment_id );
444
+
445
+ echo $media_library->getMediaColumnContent( $attachment_id );
446
+ die();
447
+ }
448
+
449
+ public function restore_image() {
450
+ check_admin_referer( 'restore' );
451
+
452
+ if ( ! current_user_can( 'manage_options' ) ) {
453
+ wp_die( - 1 );
454
+ }
455
+
456
+ $attachment_id = (int) WRIO_Plugin::app()->request->post( 'id' );
457
+
458
+ $media_library = WRIO_Media_Library::get_instance();
459
+ $wio_attachment = $media_library->getAttachment( $attachment_id );
460
+
461
+ if ( $wio_attachment->isOptimized() ) {
462
+ $media_library->restoreAttachment( $attachment_id );
463
+ }
464
+
465
+ echo $media_library->getMediaColumnContent( $attachment_id );
466
+ die();
467
+ }
468
+
469
+ public function check_servers_status() {
470
+ check_ajax_referer( 'bulk_optimization' );
471
+
472
+ if ( ! current_user_can( 'manage_options' ) ) {
473
+ wp_die( - 1 );
474
+ }
475
+
476
+ $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
477
+
478
+ if ( empty( $server_name ) || ! in_array( $server_name, [
479
+ 'server_1',
480
+ 'server_2',
481
+ 'server_5'
482
+ ] ) ) {
483
+ wp_send_json_error( [ 'error' => __( 'Server name is empty!', 'robin-image-optimizer' ) ] );
484
+ }
485
+
486
+ // Позволяем выбрать сервер, даже если он недоступен.
487
+ WRIO_Plugin::app()->updatePopulateOption( 'image_optimization_server', $server_name );
488
+
489
+ // Проверяем доступность сервер
490
+ // --------------------------------------------------------------------
491
+ $return_data = [ 'server_name' => $server_name ];
492
+
493
+ $server_url = wrio_get_server_url( $server_name );
494
+ $headers = [];
495
+
496
+ $method = 'POST';
497
+
498
+ if ( $server_name == 'server_2' ) {
499
+ $api_url = "https://dev.robinoptimizer.com/v1/free/license/check";
500
+ $method = 'GET';
501
+ $host = get_option( 'siteurl' );
502
+ $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
503
+ } else if ( $server_name == 'server_5' ) {
504
+ $api_url = "https://dashboard.robinoptimizer.com/v1/license/check";
505
+ $method = 'GET';
506
+ $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
507
+ $headers['PluginId'] = wrio_get_freemius_plugin_id();
508
+ } else {
509
+ $api_url = $server_url;
510
+ }
511
+
512
+ $request = wp_remote_request( $api_url, [
513
+ 'method' => $method,
514
+ 'headers' => $headers
515
+ ] );
516
+
517
+ if ( is_wp_error( $request ) ) {
518
+ $er_msg = $request->get_error_message();
519
+
520
+ $return_data['error'] = $er_msg;
521
+ wp_send_json_error( $return_data );
522
+ }
523
+
524
+ $response_code = wp_remote_retrieve_response_code( $request );
525
+
526
+ if ( $response_code != 200 ) {
527
+ $return_data['error'] = 'Server response ' . $response_code;
528
+ wp_send_json_error( $return_data );
529
+ }
530
+
531
+ wp_send_json_success( $return_data );
532
+ }
533
+
534
+ public function check_user_balance() {
535
+ check_ajax_referer( 'bulk_optimization' );
536
+
537
+ if ( ! current_user_can( 'manage_options' ) ) {
538
+ wp_die( - 1 );
539
+ }
540
+
541
+ $optimization_server = $server_name = WRIO_Plugin::app()->request->post( 'server_name' );
542
+ if ( $optimization_server !== 'server_5' && $optimization_server !== 'server_2' ) {
543
+ $processor = WIO_OptimizationTools::getImageProcessor();
544
+
545
+ $processor->checkLimits( false );
546
+
547
+ $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
548
+ $remaining = $processor->iamokay() - $usage;
549
+ wp_send_json_success( [
550
+ 'balance' => $remaining,
551
+ ] );
552
+ }
553
+
554
+ if ( $optimization_server == 'server_2' ) {
555
+ $api_url = "https://dev.robinoptimizer.com/v1/free/license/remaining";
556
+ $host = get_option( 'siteurl' );
557
+ $headers['Authorization'] = 'Bearer ' . base64_encode( $host );
558
+ } elseif ( $optimization_server == 'server_5' ) {
559
+ $api_url = 'https://dashboard.robinoptimizer.com/v1/license/remaining';
560
+ $headers['Authorization'] = 'Bearer ' . base64_encode( wrio_get_license_key() );
561
+ $headers['PluginId'] = wrio_get_freemius_plugin_id();
562
+ }
563
+
564
+
565
+ $request = wp_remote_request( $api_url, [
566
+ 'method' => 'GET',
567
+ 'headers' => $headers
568
+ ] );
569
+
570
+ if ( is_wp_error( $request ) ) {
571
+ $error_msg = $request->get_error_message();
572
+
573
+ $return_data['error'] = $error_msg;
574
+ wp_send_json_error( $return_data );
575
+ }
576
+
577
+ $response_code = wp_remote_retrieve_response_code( $request );
578
+ $response_body = wp_remote_retrieve_body( $request );
579
+
580
+ if ( $response_code != 200 ) {
581
+ $return_data['error'] = 'Server response ' . $response_code;
582
+ if ( $response_code === 401 ) {
583
+ $error_data = @json_decode( $response_body );
584
+ $return_data['error'] = $error_data->message;
585
+ }
586
+ wp_send_json_error( $return_data );
587
+ }
588
+
589
+ if ( empty( $response_body ) ) {
590
+ $return_data['error'] = "Server responded an empty request body!";
591
+ wp_send_json_error( $return_data );
592
+ }
593
+
594
+ $data = @json_decode( $response_body );
595
+
596
+ if ( ! isset( $data->status ) || $data->status != 'ok' ) {
597
+ $return_data['error'] = "Server responded an fail status";
598
+ wp_send_json_error( $return_data );
599
+ }
600
+
601
+ $current_quota = (int) $data->response->quota;
602
+ WRIO_Plugin::app()->app()->updateOption( 'current_quota', $current_quota );
603
+
604
+ $output = [ 'balance' => $current_quota ];
605
+
606
+ if ( $optimization_server == 'server_5' ) {
607
+ $reset_at = (int) $data->response->reset_at;
608
+ $reset_at += (int) get_option( 'gmt_offset', 0 );
609
+ $output['reset_at'] = date( 'd-m-Y H:i', $reset_at );
610
+ }
611
+
612
+ wp_send_json_success( $output );
613
+ }
614
+
615
+ public function calculate_total_images() {
616
+ check_ajax_referer( 'bulk_optimization' );
617
+
618
+ if ( ! current_user_can( 'manage_options' ) ) {
619
+ wp_die( - 1 );
620
+ }
621
+
622
+ global $wpdb;
623
+ $db_table = RIO_Process_Queue::table_name();
624
+ $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
625
+ WHERE item_type = 'attachment' AND result_status IN (%s, %s)
626
+ ORDER BY id DESC;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR );
627
+ $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
628
+
629
+ $count = 0;
630
+ if ( ! empty( $optimized_images ) ) {
631
+ foreach ( $optimized_images as $row ) {
632
+ $item = new RIO_Process_Queue( $row );
633
+ $count = $count + 1 + (int) $item->get_extra_data()->get_thumbnails_count();
634
+ }
635
+ }
636
+
637
+ $allowed_formats_sql = wrio_get_allowed_formats( true );
638
+ $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type IN ( {$allowed_formats_sql} );";
639
+ $attachments = $wpdb->get_results( $sql );
640
+
641
+ $allowed_sizes = explode( ',', WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', '' ) );
642
+ $total_images = 0;
643
+ $upload = wp_upload_dir();
644
+ $upload = $upload['basedir'];
645
+ foreach ( $attachments as $attachment ) {
646
+ $meta = wp_get_attachment_metadata( $attachment->ID );
647
+ if ( $meta ) {
648
+ if ( isset( $meta['file'] ) && file_exists( "{$upload}/{$meta['file']}" ) ) {
649
+ $total_images ++;
650
+ }
651
+
652
+ foreach ( $meta['sizes'] as $k => $value ) {
653
+ if ( in_array( $k, $allowed_sizes ) ) {
654
+ $total_images ++;
655
+ }
656
+ }
657
+ }
658
+ }
659
+ $result_total = $total_images - $count;
660
+ wp_send_json_success( [
661
+ 'total' => $result_total >= 0 ? $result_total : 0,
662
+ ] );
663
+ }
664
+
665
  }
includes/classes/class-rio-cron.php CHANGED
@@ -1,148 +1,190 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы оптимизации по расписанию
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WRIO_Cron {
16
-
17
- /**
18
- * Инициализация оптимизации по расписанию
19
- */
20
- public function __construct() {
21
- $this->initHooks();
22
- }
23
-
24
- /**
25
- * Подключение хуков
26
- */
27
- public function initHooks() {
28
- add_action( 'wrio/cron/optimization_process', [ $this, 'process' ], 10, 1 );
29
- add_filter( 'cron_schedules', [ $this, 'intervals' ], 100, 1 );
30
- }
31
-
32
- /**
33
- * Кастомные интервалы выполнения cron задачи
34
- *
35
- * @param array $intervals Зарегистрированные интервалы
36
- *
37
- * @return array $intervals Новые интервалы
38
- */
39
- public function intervals( $intervals ) {
40
- $intervals['wio_1_min'] = [
41
- 'interval' => 60,
42
- 'display' => __( '1 min', 'robin-image-optimizer' ),
43
- ];
44
- $intervals['wio_2_min'] = [
45
- 'interval' => 60 * 2,
46
- 'display' => __( '2 min', 'robin-image-optimizer' ),
47
- ];
48
- $intervals['wio_5_min'] = [
49
- 'interval' => 60 * 5,
50
- 'display' => __( '5 min', 'robin-image-optimizer' ),
51
- ];
52
- $intervals['wio_10_min'] = [
53
- 'interval' => 60 * 10,
54
- 'display' => __( '10 min', 'robin-image-optimizer' ),
55
- ];
56
- $intervals['wio_30_min'] = [
57
- 'interval' => 60 * 30,
58
- 'display' => __( '30 min', 'robin-image-optimizer' ),
59
- ];
60
- $intervals['wio_hourly'] = [
61
- 'interval' => 60 * 60,
62
- 'display' => __( '60 min', 'robin-image-optimizer' ),
63
- ];
64
- $intervals['wio_daily'] = [
65
- 'interval' => 60 * 60 * 24,
66
- 'display' => __( 'daily', 'robin-image-optimizer' ),
67
- ];
68
-
69
- return $intervals;
70
- }
71
-
72
- /**
73
- * Запуск Cron задачи
74
- */
75
- public static function start_single( $attachment_id ) {
76
- wp_schedule_single_event( time() + 10, 'wrio/cron/optimization_process', [ $attachment_id ] );
77
- }
78
-
79
- /**
80
- * Запуск Cron задачи
81
- */
82
- public static function start() {
83
- $interval = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_shedule_time', 'wio_5_min' );
84
- if ( ! wp_next_scheduled( 'wrio/cron/optimization_process' ) ) {
85
- $intervals = wp_get_schedules();
86
- wp_schedule_event( time(), $interval, 'wrio/cron/optimization_process' );
87
- }
88
- }
89
-
90
- /**
91
- * Остановка Cron задачи
92
- */
93
- public static function stop() {
94
- if ( wp_next_scheduled( 'wrio/cron/optimization_process' ) ) {
95
- wp_clear_scheduled_hook( 'wrio/cron/optimization_process' );
96
- WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false ); // останавливаем крон
97
- }
98
- }
99
-
100
- /**
101
- * Метод оптимизирует изображения при выполнении cron задачи
102
- */
103
- public function process( $attachment_id = 0 ) {
104
- //Optimize single image via cron
105
- if ( $attachment_id ) {
106
- WRIO_Plugin::app()->logger->info( sprintf( "START auto optimize cron job. Attachment: %s", $attachment_id ) );
107
- $media_library = WRIO_Media_Library::get_instance();
108
- $media_library->optimizeAttachment( $attachment_id );
109
- WRIO_Plugin::app()->logger->info( sprintf( "END auto optimize cron job. Attachment: %s", $attachment_id ) );
110
-
111
- return;
112
- }
113
-
114
- $max_process_per_request = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_items_number_per_interation', 3 );
115
- $cron_running_page = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
116
-
117
- if ( ! $cron_running_page ) {
118
- return;
119
- }
120
-
121
- WRIO_Plugin::app()->logger->info( sprintf( "Start cron job. Scope: %s", $cron_running_page ) );
122
-
123
- if ( 'media-library' == $cron_running_page ) {
124
- $media_library = WRIO_Media_Library::get_instance();
125
- $result = $media_library->processUnoptimizedImages( $max_process_per_request );
126
- } else if ( 'nextgen' == $cron_running_page ) {
127
- $nextgen_gallery = WRIO_Nextgen_Gallery::get_instance();
128
- $result = $nextgen_gallery->processUnoptimizedImages( $max_process_per_request );
129
- } else if ( 'custom-folders' == $cron_running_page ) {
130
- $cf = WRIO_Custom_Folders::get_instance();
131
- $result = $cf->processUnoptimizedImages( $max_process_per_request );
132
- }
133
-
134
- if ( is_wp_error( $result ) ) {
135
- WRIO_Plugin::app()->logger->info( sprintf( "Cron job failed. Error: %s", $result->get_error_message() ) );
136
- WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
137
-
138
- return;
139
- }
140
-
141
- if ( $result['remain'] <= 0 ) {
142
- WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
143
- }
144
-
145
- WRIO_Plugin::app()->logger->info( sprintf( "End cron job. Scope: %s", $cron_running_page ) );
146
- }
147
-
148
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы оптимизации по расписанию
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WRIO_Cron {
16
+
17
+ /**
18
+ * Инициализация оптимизации по расписанию
19
+ */
20
+ public function __construct() {
21
+ $this->initHooks();
22
+ }
23
+
24
+ /**
25
+ * Подключение хуков
26
+ */
27
+ public function initHooks() {
28
+ add_action( 'wrio/cron/optimization_process', [ $this, 'optimization_process' ], 10, 1 );
29
+ add_action( 'wrio/cron/conversion_process', [ $this, 'conversion_process' ], 10, 1 );
30
+ add_filter( 'cron_schedules', [ $this, 'intervals' ], 100, 1 );
31
+ }
32
+
33
+ /**
34
+ * Кастомные интервалы выполнения cron задачи
35
+ *
36
+ * @param array $intervals Зарегистрированные интервалы
37
+ *
38
+ * @return array $intervals Новые интервалы
39
+ */
40
+ public function intervals( $intervals ) {
41
+ $intervals['wio_1_min'] = [
42
+ 'interval' => 60,
43
+ 'display' => __( '1 min', 'robin-image-optimizer' ),
44
+ ];
45
+ $intervals['wio_2_min'] = [
46
+ 'interval' => 60 * 2,
47
+ 'display' => __( '2 min', 'robin-image-optimizer' ),
48
+ ];
49
+ $intervals['wio_5_min'] = [
50
+ 'interval' => 60 * 5,
51
+ 'display' => __( '5 min', 'robin-image-optimizer' ),
52
+ ];
53
+ $intervals['wio_10_min'] = [
54
+ 'interval' => 60 * 10,
55
+ 'display' => __( '10 min', 'robin-image-optimizer' ),
56
+ ];
57
+ $intervals['wio_30_min'] = [
58
+ 'interval' => 60 * 30,
59
+ 'display' => __( '30 min', 'robin-image-optimizer' ),
60
+ ];
61
+ $intervals['wio_hourly'] = [
62
+ 'interval' => 60 * 60,
63
+ 'display' => __( '60 min', 'robin-image-optimizer' ),
64
+ ];
65
+ $intervals['wio_daily'] = [
66
+ 'interval' => 60 * 60 * 24,
67
+ 'display' => __( 'daily', 'robin-image-optimizer' ),
68
+ ];
69
+
70
+ return $intervals;
71
+ }
72
+
73
+ /**
74
+ * Запуск Cron задачи
75
+ */
76
+ public static function start_single( $attachment_id ) {
77
+ wp_schedule_single_event( time() + 10, 'wrio/cron/optimization_process', [ $attachment_id ] );
78
+ }
79
+
80
+ /**
81
+ * Запуск Cron задачи
82
+ */
83
+ public static function start( $type = 'optimization' ) {
84
+ $interval = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_shedule_time', 'wio_5_min' );
85
+ if ( ! wp_next_scheduled( "wrio/cron/{$type}_process" ) ) {
86
+ wp_schedule_event( time(), $interval, "wrio/cron/{$type}_process" );
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Остановка Cron задачи
92
+ */
93
+ public static function stop( $type = 'optimization' ) {
94
+ if ( wp_next_scheduled( "wrio/cron/{$type}_process" ) ) {
95
+ wp_clear_scheduled_hook( "wrio/cron/{$type}_process" );
96
+ WRIO_Plugin::app()->updatePopulateOption( "{$type}_cron_running", false ); // останавливаем крон
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Метод оптимизирует изображения при выполнении cron задачи
102
+ */
103
+ public function optimization_process( $attachment_id = 0 ) {
104
+ //Optimize single image via cron
105
+ if ( $attachment_id ) {
106
+ WRIO_Plugin::app()->logger->info( sprintf( "START auto optimize cron job. Attachment: %s", $attachment_id ) );
107
+ $media_library = WRIO_Media_Library::get_instance();
108
+ $media_library->optimizeAttachment( $attachment_id );
109
+ WRIO_Plugin::app()->logger->info( sprintf( "END auto optimize cron job. Attachment: %s", $attachment_id ) );
110
+
111
+ return;
112
+ }
113
+
114
+ $max_process_per_request = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_items_number_per_interation', 3 );
115
+ $cron_running_page = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
116
+
117
+ if ( ! $cron_running_page ) {
118
+ return;
119
+ }
120
+
121
+ WRIO_Plugin::app()->logger->info( sprintf( "Start cron job. Scope: %s", $cron_running_page ) );
122
+
123
+ if ( 'media-library' == $cron_running_page ) {
124
+ $media_library = WRIO_Media_Library::get_instance();
125
+ $result = $media_library->processUnoptimizedImages( $max_process_per_request );
126
+ } else if ( 'nextgen' == $cron_running_page ) {
127
+ $nextgen_gallery = WRIO_Nextgen_Gallery::get_instance();
128
+ $result = $nextgen_gallery->processUnoptimizedImages( $max_process_per_request );
129
+ } else if ( 'custom-folders' == $cron_running_page ) {
130
+ $cf = WRIO_Custom_Folders::get_instance();
131
+ $result = $cf->processUnoptimizedImages( $max_process_per_request );
132
+ }
133
+
134
+ if ( is_wp_error( $result ) ) {
135
+ WRIO_Plugin::app()->logger->info( sprintf( "Cron job failed. Error: %s", $result->get_error_message() ) );
136
+ WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
137
+
138
+ return;
139
+ }
140
+
141
+ if ( $result['remain'] <= 0 ) {
142
+ WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
143
+ }
144
+
145
+ WRIO_Plugin::app()->logger->info( sprintf( "End cron job. Scope: %s", $cron_running_page ) );
146
+ }
147
+
148
+ /**
149
+ * Метод оптимизирует изображения при выполнении cron задачи
150
+ */
151
+ public function conversion_process( $attachment_id = 0 ) {
152
+ //Optimize single image via cron
153
+ if ( $attachment_id ) {
154
+ WRIO_Plugin::app()->logger->info( sprintf( "START auto optimize cron job. Attachment: %s", $attachment_id ) );
155
+ $media_library = WRIO_Media_Library::get_instance();
156
+ $media_library->optimizeAttachment( $attachment_id );
157
+ WRIO_Plugin::app()->logger->info( sprintf( "END auto optimize cron job. Attachment: %s", $attachment_id ) );
158
+
159
+ return;
160
+ }
161
+
162
+ $max_process_per_request = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_items_number_per_interation', 3 );
163
+ $cron_running_page = WRIO_Plugin::app()->getPopulateOption( 'conversion_cron_running', false );
164
+
165
+ if ( ! $cron_running_page ) {
166
+ return;
167
+ }
168
+
169
+ WRIO_Plugin::app()->logger->info( sprintf( "Start cron job. Scope: %s", $cron_running_page ) );
170
+
171
+ if ( 'media-library' == $cron_running_page ) {
172
+ $media_library = WRIO_Media_Library::get_instance();
173
+ $result = $media_library->webpUnoptimizedImages( $max_process_per_request );
174
+ }
175
+
176
+ if ( is_wp_error( $result ) ) {
177
+ WRIO_Plugin::app()->logger->info( sprintf( "Cron job failed. Error: %s", $result->get_error_message() ) );
178
+ WRIO_Plugin::app()->deletePopulateOption( 'conversion_cron_running' );
179
+
180
+ return;
181
+ }
182
+
183
+ if ( $result['remain'] <= 0 ) {
184
+ WRIO_Plugin::app()->deletePopulateOption( 'conversion_cron_running' );
185
+ }
186
+
187
+ WRIO_Plugin::app()->logger->info( sprintf( "End cron job. Scope: %s", $cron_running_page ) );
188
+ }
189
+
190
+ }
includes/classes/class-rio-image-statistic.php CHANGED
@@ -1,411 +1,678 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы со статистическими данными по оптимизации изображений
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WRIO_Image_Statistic {
16
-
17
- /**
18
- * The single instance of the class.
19
- *
20
- * @since 1.3.0
21
- * @access protected
22
- * @var object
23
- */
24
- protected static $_instance;
25
-
26
- /**
27
- * @var array
28
- * @see WRIO_Image_Statistic::load()
29
- */
30
- protected $statistic;
31
-
32
- /**
33
- * Инициализация статистики
34
- *
35
- * @throws Exception
36
- */
37
- public function __construct() {
38
- $this->statistic = $this->load();
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 ) ) {
49
- static::$_instance = new static();
50
- }
51
-
52
- return static::$_instance;
53
- }
54
-
55
- /**
56
- * Возвращает статистические данные
57
- *
58
- * @return array
59
- */
60
- public function get() {
61
- return $this->statistic;
62
- }
63
-
64
- /**
65
- * Добавляет новые данные к текущей статистике
66
- * К текущим числам добавляются новые
67
- *
68
- * @param string $field Поле, к которому добавляем значение
69
- * @param int $value добавляемое значение
70
- */
71
- public function addToField( $field, $value ) {
72
- if ( isset( $this->statistic[ $field ] ) ) {
73
- $this->statistic[ $field ] = $this->statistic[ $field ] + $value;
74
- }
75
- }
76
-
77
- /**
78
- * Вычитает данные из текущей статистики
79
- * Из текущего числа вычитается
80
- *
81
- * @param string $field Поле, из которого вычитается значение
82
- * @param int $value вычитаемое значение
83
- */
84
- public function deductFromField( $field, $value ) {
85
- $value = (int) $value;
86
- if ( isset( $this->statistic[ $field ] ) ) {
87
- $this->statistic[ $field ] = $this->statistic[ $field ] - $value;
88
- if ( $this->statistic[ $field ] < 0 ) {
89
- $this->statistic[ $field ] = 0;
90
- }
91
- }
92
- }
93
-
94
- /**
95
- * Сохранение статистики
96
- */
97
- public function save() {
98
- WRIO_Plugin::app()->updateOption( 'original_size', $this->statistic['original_size'] );
99
- WRIO_Plugin::app()->updateOption( 'optimized_size', $this->statistic['optimized_size'] );
100
- }
101
-
102
- /**
103
- * Загрузка статистики и расчёт некоторых параметров
104
- *
105
- * @return array {
106
- * Параметры
107
- * {type} int $original Всего картинок
108
- * {type} int $optimized Всего оптимизировано картинок
109
- * {type} int $optimized_percent Суммарная оптимизация относительно всех картинок в процентах
110
- * {type} int $percent_line Суммарный КПД оптимизации в процентах. Для вывода линии в интерфейсе.
111
- * {type} int $unoptimized Не оптимизировано
112
- * {type} int $optimized_size Всего оптимизировано. В байтах
113
- * {type} int $original_size Оригинальный размер всех картинок. В байтах
114
- * {type} int $save_size_percent Суммарный КПД оптимизации в процентах
115
- * {type} int $error Кол-во ошибок
116
- * }
117
- */
118
- public function load() {
119
- $original_size = WRIO_Plugin::app()->getOption( 'original_size', 0 );
120
- $optimized_size = WRIO_Plugin::app()->getOption( 'optimized_size', 0 );
121
-
122
- $allowed_formats_sql = wrio_get_allowed_formats( true );
123
-
124
- global $wpdb;
125
- $sql = "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type IN ( {$allowed_formats_sql} );";
126
- $total_images = $wpdb->get_var( $sql );
127
- $error_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'error' );
128
- $optimized_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
129
-
130
- if ( ! $total_images ) {
131
- $total_images = 0;
132
- }
133
- if ( ! $error_count ) {
134
- $error_count = 0;
135
- }
136
- if ( ! $optimized_count ) {
137
- $optimized_count = 0;
138
- }
139
- // unoptimized count: all - optimized - error
140
- $unoptimized_count = static::get_unoptimized_count();
141
- if ( $unoptimized_count < 0 ) {
142
- $unoptimized_count = 0;
143
- }
144
- if ( $optimized_size && $original_size ) {
145
- $percent_diff = round( ( $original_size - $optimized_size ) * 100 / $original_size, 1 );
146
- $percent_diff_line = round( $optimized_size * 100 / $original_size, 0 );
147
- } else {
148
- $percent_diff = 0;
149
- $percent_diff_line = 100;
150
- }
151
- if ( $total_images ) {
152
- $optimized_images_percent = floor( $optimized_count * 100 / $total_images );
153
- } else {
154
- $optimized_images_percent = 0;
155
- }
156
-
157
- $processor = WIO_OptimizationTools::getImageProcessor();
158
- $processor->checkLimits( false );
159
- $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
160
- $remaining = $processor->iamokay() - $usage;
161
-
162
- return [
163
- 'original' => $total_images,
164
- 'optimized' => $optimized_count,
165
- 'optimized_percent' => $optimized_images_percent,
166
- 'percent_line' => $percent_diff_line,
167
- 'unoptimized' => $unoptimized_count,
168
- 'optimized_size' => $optimized_size,
169
- 'original_size' => $original_size,
170
- 'save_size_percent' => $percent_diff,
171
- 'credits' => $remaining,
172
- 'error' => $error_count,
173
- ];
174
- }
175
-
176
- /**
177
- * Count of non-optimized images
178
- *
179
- * @return int
180
- * @since 1.3.6
181
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
182
- */
183
- public static function get_unoptimized_count() {
184
- global $wpdb;
185
- $db_table = RIO_Process_Queue::table_name();
186
-
187
- $allowed_formats_sql = wrio_get_allowed_formats(true);
188
-
189
- $sql_unoptimized = "SELECT COUNT(DISTINCT p.ID)
190
- FROM {$wpdb->posts} p
191
- WHERE NOT EXISTS (SELECT *
192
- FROM {$db_table}
193
- WHERE p.ID = object_id AND p.post_type = item_type)
194
- AND p.post_type = 'attachment' AND p.post_mime_type IN ( {$allowed_formats_sql} )";
195
-
196
- $total_images = $wpdb->get_var( $sql_unoptimized );
197
-
198
- return (int) $total_images;
199
- }
200
-
201
- /**
202
- * Возвращает результат последних оптимизаций изображений
203
- *
204
- * @param int $limit By default - 100. If limit=0, then no limit
205
- *
206
- * @return array {
207
- * Параметры
208
- * @type string $id id
209
- * @type string $file_name Имя файла
210
- * @type string $url URL
211
- * @type string $thumbnail_url URL превьюшки
212
- * @type string $original_size Размер до оптимизации
213
- * @type string $optimized_size Размер после оптимизации
214
- * @type string $webp_size webP размер
215
- * @type string $original_saving На сколько процентов изменился главный файл
216
- * @type string $thumbnails_count Сколько превьюшек оптимизировано
217
- * @type string $total_saving Процент оптимизации главного файла и превьюшек
218
- * }
219
- */
220
- public function get_last_optimized_images( $limit = 100 ) {
221
- global $wpdb;
222
-
223
- $items = [];
224
- $db_table = RIO_Process_Queue::table_name();
225
- if ( $limit ) {
226
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
227
- WHERE item_type = 'attachment' AND result_status IN (%s, %s)
228
- ORDER BY id DESC
229
- LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
230
- } else {
231
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
232
- WHERE item_type = 'attachment' AND result_status IN (%s, %s)
233
- ORDER BY id DESC;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR );
234
-
235
- }
236
- $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
237
-
238
- if ( ! empty( $optimized_images ) ) {
239
- foreach ( $optimized_images as $row ) {
240
- $items[] = $this->format_for_log( new RIO_Process_Queue( $row ) );
241
- }
242
- }
243
-
244
- return $items;
245
- }
246
-
247
- /**
248
- * @param int $object_id
249
- *
250
- * @since 1.3.9
251
- *
252
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
253
- */
254
- public function get_last_optimized_image( $object_id ) {
255
- global $wpdb;
256
-
257
- $items = [];
258
- $db_table = RIO_Process_Queue::table_name();
259
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
260
- WHERE object_id = '%d' AND item_type = 'attachment' AND result_status IN (%s, %s)
261
- ORDER BY id DESC
262
- LIMIT 1;", (int) $object_id, RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR );
263
-
264
- $model = $wpdb->get_row( $sql, ARRAY_A );
265
-
266
- if ( ! empty( $model ) ) {
267
- $items[] = $this->format_for_log( new RIO_Process_Queue( $model ) );
268
- }
269
-
270
- return $items;
271
- }
272
-
273
- /**
274
- * @param RIO_Process_Queue $queue_model
275
- *
276
- * @return array
277
- * @throws \Exception
278
- * @since 1.3.9
279
- *
280
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
281
- */
282
- protected function format_for_log( $queue_model ) {
283
- if ( ! $queue_model instanceof RIO_Process_Queue ) {
284
- throw new Exception( 'Variable $queue_model must be an instance of RIO_Process_Queue!' );
285
- }
286
-
287
- /**
288
- * @var RIO_Attachment_Extra_Data $extra_data
289
- */
290
- $extra_data = $queue_model->get_extra_data();
291
-
292
- $default_formated_data = [
293
- 'id' => $queue_model->get_id(),
294
- 'url' => admin_url( sprintf( "post.php?post=%d&action=edit", $queue_model->get_object_id() ) ),
295
- 'original_url' => null,
296
- 'thumbnail_url' => null,
297
- 'file_name' => null,
298
- 'original_size' => 0,
299
- 'optimized_size' => 0,
300
- 'type' => 'success',
301
- 'webp_size' => null,
302
- 'original_saving' => 0,
303
- 'thumbnails_count' => 0,
304
- 'total_saving' => 0,
305
- ];
306
-
307
- $upload_dir = wp_upload_dir();
308
-
309
- $attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
310
- $formated_data = [];
311
-
312
-
313
- if ( ! empty( $attachment_meta ) ) {
314
- $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
315
- $thumbnail_url = $image_url;
316
-
317
- if ( isset( $attachment_meta['sizes']['thumbnail'] ) ) {
318
- $image_basename = wp_basename( $image_url );
319
- $thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
320
- }
321
-
322
- $formated_data = wp_parse_args( [
323
- 'original_url' => $image_url,
324
- 'thumbnail_url' => $thumbnail_url,
325
- 'file_name' => wp_basename( $attachment_meta['file'] ),
326
- 'original_size' => size_format( $queue_model->get_original_size(), 2 ),
327
- 'optimized_size' => size_format( $queue_model->get_final_size(), 2 )
328
- ], $default_formated_data );
329
-
330
- $main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
331
-
332
- # An extra data may be empty after a failed migration or an unknown error.
333
- if ( ! empty( $extra_data ) ) {
334
- $original_main_size = $extra_data->get_original_main_size();
335
-
336
- if ( $original_main_size && file_exists( $main_file ) ) {
337
- $original_saving = ( $original_main_size - filesize( $main_file ) ) * 100 / $original_main_size;
338
- $formated_data['original_saving'] = round( $original_saving ) . '%';
339
- }
340
-
341
- $webp_size = $extra_data->get_webp_main_size();
342
-
343
- if ( $webp_size ) {
344
- $formated_data['webp_size'] = size_format( $webp_size, 2 );
345
- }
346
-
347
- $formated_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
348
- }
349
-
350
- if ( $queue_model->get_original_size() ) {
351
- $total_saving = ( $queue_model->get_original_size() - $queue_model->get_final_size() ) * 100 / $queue_model->get_original_size();
352
- $formated_data['total_saving'] = round( $total_saving, 2 ) . '%';
353
- }
354
- } else {
355
- $attachment = get_post( $queue_model->get_object_id() );
356
-
357
- if ( ! empty( $attachment ) ) {
358
- $formated_data = [
359
- 'original_url' => $attachment->guid,
360
- 'thumbnail_url' => $attachment->guid,
361
- 'file_name' => wp_basename( $attachment->guid )
362
- ];
363
- }
364
-
365
- $formated_data = wp_parse_args( $formated_data, $default_formated_data );
366
- }
367
-
368
- # We collect information about errors
369
- if ( $queue_model->get_result_status() == RIO_Process_Queue::STATUS_ERROR ) {
370
- $error_message = null;
371
-
372
- if ( ! empty( $extra_data ) ) {
373
- $error_message = $extra_data->get_error_msg();
374
- }
375
-
376
- $formated_data['type'] = 'error';
377
- $formated_data['error_msg'] = ! empty( $error_message ) ? $error_message : __( 'Unknown error', 'robin-image-optimizer' );
378
-
379
- return $formated_data;
380
- }
381
-
382
- return $formated_data;
383
- }
384
-
385
- /**
386
- * Возвращает общий процент оптимизированных изображений
387
- *
388
- * @return int общий процент оптимизации
389
- */
390
- public function getOptimizedPercent() {
391
- if ( isset( $this->statistic['optimized_percent'] ) ) {
392
- return $this->statistic['optimized_percent'];
393
- }
394
-
395
- return 0;
396
- }
397
-
398
- /**
399
- * Пересчёт размера файла в байтах на человекопонятный вид
400
- *
401
- * Пример: вводим 67894 байт, получаем 67.8 KB
402
- * Пример: вводим 6789477 байт, получаем 6.7 MB
403
- *
404
- * @param int $size размер файла в байтах
405
- *
406
- * @return string
407
- */
408
- public function convertToReadableSize( $size ) {
409
- return wrio_convert_bytes( $size );
410
- }
411
- }
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы со статистическими данными по оптимизации изображений
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WRIO_Image_Statistic {
16
+
17
+ /**
18
+ * The single instance of the class.
19
+ *
20
+ * @since 1.3.0
21
+ * @access protected
22
+ * @var object
23
+ */
24
+ protected static $_instance;
25
+
26
+ /**
27
+ * @var array
28
+ * @see WRIO_Image_Statistic::load()
29
+ */
30
+ protected $statistic;
31
+
32
+ /**
33
+ * Инициализация статистики
34
+ *
35
+ * @throws Exception
36
+ */
37
+ public function __construct() {
38
+ $this->statistic = $this->load();
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 ) ) {
49
+ static::$_instance = new static();
50
+ }
51
+
52
+ return static::$_instance;
53
+ }
54
+
55
+ /**
56
+ * Возвращает статистические данные
57
+ *
58
+ * @return array
59
+ */
60
+ public function get() {
61
+ return $this->statistic;
62
+ }
63
+
64
+ /**
65
+ * Добавляет новые данные к текущей статистике
66
+ * К текущим числам добавляются новые
67
+ *
68
+ * @param string $field Поле, к которому добавляем значение
69
+ * @param int $value добавляемое значение
70
+ */
71
+ public function addToField( $field, $value ) {
72
+ if ( isset( $this->statistic[ $field ] ) ) {
73
+ $this->statistic[ $field ] = $this->statistic[ $field ] + $value;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Вычитает данные из текуще�