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

Version Description

  • Fixed: Error on frontend
Download this release

Release Info

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

Code changes from version 1.5.0 to 1.5.3

Files changed (51) hide show
  1. admin/activation.php +93 -93
  2. admin/ajax/backup.php +103 -103
  3. admin/ajax/index.php +2 -2
  4. admin/ajax/logs.php +23 -23
  5. admin/ajax/meta-migrations.php +174 -174
  6. admin/ajax/multisite-update-current-blog.php +29 -29
  7. admin/ajax/settings.php +37 -37
  8. admin/assets/css/base-statistic.css +733 -676
  9. admin/assets/css/base-statistic.less +888 -818
  10. admin/assets/css/index.php +2 -2
  11. admin/assets/css/media.css +215 -215
  12. admin/assets/css/settings-premium.css +17 -17
  13. admin/assets/css/statistic.css +410 -410
  14. admin/assets/css/sweetalert-custom.css +155 -155
  15. admin/assets/css/sweetalert-custom.less +185 -185
  16. admin/assets/css/sweetalert2.css +716 -716
  17. admin/assets/img/index.php +2 -2
  18. admin/assets/index.php +2 -2
  19. admin/assets/js/Chart.min.js +10 -10
  20. admin/assets/js/bulk-optimization.js +633 -587
  21. admin/assets/js/index.php +2 -2
  22. admin/assets/js/meta-migrations.js +52 -52
  23. admin/assets/js/modals.js +59 -59
  24. admin/assets/js/restore-backup.js +162 -162
  25. admin/assets/js/settings-premium.js +2 -1
  26. admin/assets/js/single-optimization.js +64 -64
  27. admin/assets/js/statistic.js +38 -38
  28. admin/assets/js/sweetalert2.js +1641 -1641
  29. admin/boot.php +347 -347
  30. admin/includes/classes/class-rio-nextgen-landing.php +61 -61
  31. admin/includes/classes/class-rio-optimize-template.php +226 -226
  32. admin/includes/classes/index.php +2 -2
  33. admin/includes/index.php +2 -2
  34. admin/includes/sidebar-widgets.php +83 -83
  35. admin/index.php +2 -2
  36. admin/pages/class-rio-license.php +125 -125
  37. admin/pages/class-rio-log.php +100 -166
  38. admin/pages/class-rio-page.php +83 -83
  39. admin/pages/class-rio-settings.php +620 -550
  40. admin/pages/class-rio-statistic.php +279 -267
  41. admin/pages/index.php +2 -2
  42. assets/js/lazy-load.js +11 -8
  43. assets/js/lozad.min.js +10 -0
  44. includes/class-rio-plugin.php +209 -191
  45. includes/classes/class-rio-attachment.php +992 -992
  46. includes/classes/class-rio-backup.php +535 -535
  47. includes/classes/class-rio-bulk-optimization.php +462 -0
  48. includes/classes/class-rio-cron.php +148 -183
  49. includes/classes/class-rio-image-statistic.php +411 -398
  50. includes/classes/class-rio-media-library.php +737 -707
  51. includes/classes/class-rio-multisite.php +21 -54
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 Factory439_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_Factory439_Activator {
18
-
19
- /**
20
- * Runs activation actions.
21
- *
22
- * @since 1.0.0
23
- * @throws \Exception
24
- */
25
- public function activate() {
26
- WRIO_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_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_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_Logger::info( $create_table_log_message );
49
-
50
- RIO_Process_Queue::try_create_plugin_tables();
51
-
52
- WbcrFactoryClearfy230_Helpers::flushPageCache();
53
-
54
- WRIO_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_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_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_Logger::info( 'Premium plugin deactivation complete!' );
89
- }
90
-
91
- WRIO_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 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
+ }
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/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_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_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_Logger::info( 'Start meta migration. Limit ' . $limit );
47
- WRIO_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_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_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_Logger::info( 'Succefull migrated ' . $processed_items . ' items.' );
156
- } else {
157
- WRIO_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_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
@@ -1,676 +1,733 @@
1
- /**
2
- * Styles for the Widget to be displayed in the Clearfy plugin
3
-
4
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
- * @copyright Webcraftic 14.06.2019
6
- */
7
- #WBCR {
8
- /* Doughnut */
9
- /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
- .wio-overview-chart-container {
11
- float: none;
12
- margin-right: 0;
13
- }
14
- }
15
-
16
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
- .wio-overview-chart-container {
18
- float: none;
19
- margin-right: 0;
20
- }
21
-
22
- .wio-doughnut-legend {
23
- margin-top: 18px;
24
- }
25
-
26
- .wio-global-optim-phrase {
27
- padding-top: 0;
28
- width: auto;
29
- }
30
- }*/
31
- }
32
- #WBCR .wio-clear {
33
- clear: both;
34
- }
35
- #WBCR #io_folders_statistic-wbcr_clearfy-tab,
36
- #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
37
- display: none !important;
38
- }
39
- #WBCR .wrio-statistic-nav {
40
- margin: 0;
41
- background: #efefef;
42
- }
43
- #WBCR .wrio-statistic-nav ul {
44
- margin: 0;
45
- }
46
- #WBCR .wrio-statistic-nav ul li {
47
- position: relative;
48
- display: inline-block;
49
- margin: 0 0 0 0;
50
- background: #ffffff;
51
- box-shadow: 0 -2px 0 #eaeaea;
52
- }
53
- #WBCR .wrio-statistic-nav ul li:hover {
54
- background: #f7f7f7;
55
- }
56
- #WBCR .wrio-statistic-nav ul li.active {
57
- background: #f7f7f7;
58
- border-top: 1px solid #d4d4d4;
59
- border-left: 1px solid #d4d4d4;
60
- border-right: 1px solid #d4d4d4;
61
- border-bottom: 1px solid #f7f7f7;
62
- margin-bottom: -1px;
63
- }
64
- #WBCR .wrio-statistic-nav ul li.active a {
65
- color: #222;
66
- }
67
- #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
68
- border: 2px dashed #8bc34a;
69
- color: #5e8237;
70
- }
71
- #WBCR .wrio-statistic-nav ul li.active .dashicons,
72
- #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
73
- color: #ff8b66;
74
- }
75
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
76
- display: block;
77
- padding: 10px 20px 10px 20px;
78
- text-decoration: none;
79
- color: #d4d4d4;
80
- font-size: 22px;
81
- line-height: 2;
82
- }
83
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
84
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
85
- background: 0;
86
- box-shadow: none;
87
- outline: none;
88
- }
89
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
90
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
91
- display: inline-block;
92
- width: 30px;
93
- height: 30px;
94
- font-size: 30px;
95
- line-height: 1.5;
96
- margin-right: 15px;
97
- color: #d4d4d4;
98
- }
99
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
100
- display: inline-block;
101
- width: 42px;
102
- height: 42px;
103
- border-radius: 100px;
104
- border: 2px dashed #e4e4e4;
105
- padding: 5px;
106
- margin-left: 30px;
107
- font-size: 14px;
108
- font-weight: 600;
109
- text-align: center;
110
- color: #bdbdbd;
111
- }
112
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
113
- display: inline-block;
114
- position: absolute;
115
- content: 'PRO';
116
- background: #ff5722;
117
- border-radius: 4px;
118
- color: #fff;
119
- font-size: 10px;
120
- line-height: 1;
121
- font-style: normal;
122
- padding: 4px 6px;
123
- margin-left: 4px;
124
- vertical-align: top;
125
- top: 10px;
126
- left: auto;
127
- right: 10px;
128
- z-index: 11;
129
- }
130
- #WBCR .wrio-table {
131
- width: 100%;
132
- table-layout: fixed;
133
- box-sizing: border-box;
134
- border-spacing: 3px;
135
- background: #fff;
136
- border-top: 2px dashed #cac9c9;
137
- }
138
- #WBCR .wrio-table th,
139
- #WBCR .wrio-table td {
140
- padding: 16px 10px;
141
- text-align: center;
142
- }
143
- #WBCR .wrio-table th {
144
- background: #f3f3f3;
145
- color: #777777;
146
- box-shadow: 0 1px 0 #d8d8d8;
147
- }
148
- #WBCR .wrio-table th:nth-child(2n+1) {
149
- background: #f9f9f9;
150
- }
151
- #WBCR .wrio-table tr.wrio-error {
152
- background-color: #ffe9e9 !important;
153
- }
154
- #WBCR .wrio-table .wrio-table-spinner {
155
- background: url("../img/quick-start-loader.gif") center center no-repeat;
156
- }
157
- #WBCR .wrio-table .wrio-table-highlighter {
158
- display: inline-block;
159
- padding: 3px 7px;
160
- background: #f3f3f3;
161
- }
162
- #WBCR .wrio-table .wbcr-rio-server-success {
163
- color: #8CC152;
164
- }
165
- #WBCR .wrio-table .wbcr-rio-server-error {
166
- color: #fb5d49;
167
- }
168
- #WBCR .wrio-table .wbcr-rio-server-warning {
169
- color: #ffb635;
170
- }
171
- #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
172
- text-align: left;
173
- }
174
- #WBCR .wrio-servers {
175
- padding: 40px 20px;
176
- }
177
- #WBCR .wrio-servers label span {
178
- display: block;
179
- font-weight: normal;
180
- font-size: 12px;
181
- color: #b7b2b2;
182
- }
183
- #WBCR .wrio-servers #wrio-change-optimization-server {
184
- position: relative;
185
- display: inline-block;
186
- max-width: 400px;
187
- margin-right: 15px;
188
- margin-bottom: 0;
189
- border: 1px solid #d2d0d0;
190
- background: #efefef;
191
- }
192
- #WBCR .wrio-servers .wrio-servers-info {
193
- margin: 0 0 0;
194
- padding: 20px;
195
- background: #fff;
196
- }
197
- #WBCR .wrio-servers .wrio-server-status-wrap {
198
- display: inline-block;
199
- margin-top: 8px;
200
- }
201
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
202
- background: transparent;
203
- color: #fff;
204
- padding: 3px 5px;
205
- border-radius: 4px;
206
- }
207
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
208
- background: #ff5722;
209
- }
210
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
211
- background: #8bc34a;
212
- }
213
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
214
- display: inline-block;
215
- height: 10px;
216
- width: 30px;
217
- background: url("../img/quick-start-loader.gif") center no-repeat;
218
- }
219
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap, .wrio-premium-user-update-wrap {
220
- display: inline-block;
221
- margin-top: 8px;
222
- margin-left: 10px;
223
- }
224
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance, .wrio-premium-user-update-wrap .wrio-premium-user-update {
225
- color: #fff;
226
- padding: 3px 5px;
227
- border-radius: 4px;
228
- background: #ffc107;
229
- }
230
- #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance-check-proccess,
231
- .wrio-premium-user-update-wrap .wrio-premium-user-update-check-proccess {
232
- display: inline-block;
233
- height: 10px;
234
- width: 30px;
235
- background: url("../img/quick-start-loader.gif") center no-repeat;
236
- }
237
- #WBCR .wio-columns {
238
- overflow: hidden;
239
- padding: 15px 0;
240
- counter-reset: cols;
241
- }
242
- #WBCR .wio-columns [class^="col-"] {
243
- float: left;
244
- -webkit-box-sizing: border-box;
245
- -moz-box-sizing: border-box;
246
- box-sizing: border-box;
247
- }
248
- #WBCR .wio-columns .col-1-3 {
249
- width: 33.333%;
250
- padding-left: 28px;
251
- }
252
- #WBCR .wio-columns .col-2-3 {
253
- width: 66.666%;
254
- padding-left: 28px;
255
- }
256
- #WBCR .wio-columns .col-1-2 {
257
- width: 50%;
258
- padding: 0 20px;
259
- }
260
- #WBCR .wio-columns .col-statistics.col-statistics {
261
- width: 60%;
262
- }
263
- #WBCR .wio-columns .col-chart.col-chart {
264
- width: 40%;
265
- position: relative;
266
- padding: 20px;
267
- font-size: 12px;
268
- text-transform: uppercase;
269
- background: #f1f1f1b3;
270
- color: #abacaf;
271
- font-weight: bold;
272
- border-radius: 5px;
273
- margin-top: 10px;
274
- text-align: left;
275
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
276
- }
277
- #WBCR .wio-col {
278
- float: left;
279
- width: 50%;
280
- box-sizing: border-box;
281
- -webkit-flex-basis: 50%;
282
- -ms-flex-preferred-size: 50%;
283
- flex-basis: 50%;
284
- }
285
- #WBCR .wio-col {
286
- padding-right: 20px;
287
- }
288
- #WBCR .wio-col + .wio-col {
289
- padding-right: 0;
290
- padding-left: 50px;
291
- }
292
- #WBCR .wio-col:target {
293
- animation: wiohello 1s 3 linear backwards;
294
- }
295
- #WBCR .wio-number-you-optimized {
296
- margin-bottom: 1.35em;
297
- overflow: hidden;
298
- }
299
- #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
300
- color: #828282;
301
- }
302
- #WBCR .wio-number-you-optimized .wio-number {
303
- display: table-cell;
304
- padding-right: 15px;
305
- font-size: 48px;
306
- font-weight: bold;
307
- line-height: 1;
308
- vertical-align: middle;
309
- white-space: nowrap;
310
- color: #828282;
311
- }
312
- #WBCR .wio-number-you-optimized .wio-text {
313
- display: table-cell;
314
- vertical-align: middle;
315
- overflow: hidden;
316
- font-size: 12px;
317
- color: #828282;
318
- }
319
- #WBCR .wio-number-you-optimized > p {
320
- display: table;
321
- }
322
- #WBCR .wio-bars {
323
- padding-right: 15px;
324
- }
325
- #WBCR .wio-bars p {
326
- font-size: 12px;
327
- margin-bottom: 5px;
328
- }
329
- #WBCR .wio-bars + .wio-number-you-optimized {
330
- border-bottom: 0;
331
- padding-top: 0.85em;
332
- }
333
- #WBCR .wio-bars + .wio-number-you-optimized p {
334
- color: #72a53b;
335
- }
336
- #WBCR .wio-bar-negative .wio-progress {
337
- background: #D2D3D6;
338
- }
339
- #WBCR .wio-bar-negative .wio-barnb {
340
- color: #9d9fa5;
341
- }
342
- #WBCR .wio-progress {
343
- height: 8px;
344
- transition: width 0.3s;
345
- /*.wio-bar-negative {
346
- width: 92% !important;
347
- }*/
348
- }
349
- #WBCR .wio-bar-positive .wio-progress {
350
- background: #8CC152;
351
- }
352
- #WBCR .wio-bar-positive .wio-barnb {
353
- color: #72a53b;
354
- }
355
- #WBCR .wio-bar-primary .wio-progress {
356
- background: #8CC152;
357
- }
358
- #WBCR .wio-bar-primary .wio-barnb {
359
- color: #72a53b;
360
- }
361
- #WBCR .wio-right-outside-number .wio-barnb {
362
- display: block;
363
- margin-right: -5.25em;
364
- text-align: right;
365
- font-weight: bold;
366
- line-height: 0.8;
367
- }
368
- #WBCR .wio-chart {
369
- position: relative;
370
- top: 1px;
371
- display: inline-block;
372
- vertical-align: middle;
373
- }
374
- #WBCR .wio-chart-container {
375
- position: relative;
376
- display: inline-block;
377
- margin-right: 5px;
378
- }
379
- #WBCR .wio-chart-container canvas {
380
- display: block;
381
- }
382
- #WBCR .wio-overview-chart-container {
383
- float: left;
384
- margin-right: 20px;
385
- }
386
- #WBCR .wio-chart-percent {
387
- position: absolute;
388
- left: 0;
389
- right: 0;
390
- top: 50%;
391
- margin-top: -0.5em;
392
- line-height: 0.8;
393
- text-align: center;
394
- font-size: 54px;
395
- font-weight: bold;
396
- color: #afafaf;
397
- }
398
- #WBCR .wio-chart-percent span {
399
- font-size: 20px;
400
- vertical-align: super;
401
- }
402
- #WBCR #wio-overview-chart-legend {
403
- overflow: hidden;
404
- }
405
- #WBCR .wio-doughnut-legend li {
406
- display: inline-block;
407
- position: relative;
408
- margin-bottom: 15px;
409
- border-radius: 5px;
410
- padding: 3px 8px 2px 31px;
411
- font-size: 9px;
412
- cursor: default;
413
- -webkit-transition: background-color 200ms ease-in-out;
414
- -moz-transition: background-color 200ms ease-in-out;
415
- -o-transition: background-color 200ms ease-in-out;
416
- transition: background-color 200ms ease-in-out;
417
- }
418
- #WBCR .wio-doughnut-legend li span {
419
- display: block;
420
- position: absolute;
421
- left: 0;
422
- top: 0;
423
- width: 25px;
424
- height: 25px;
425
- border-radius: 50%;
426
- }
427
- #WBCR .wio-optimize-button {
428
- min-width: 180px;
429
- padding: 12px 30px;
430
- background: #c9deb2;
431
- color: #586549;
432
- border: 0;
433
- box-shadow: none;
434
- font-size: 14px;
435
- text-transform: uppercase !important;
436
- font-weight: bold;
437
- border-radius: 4px;
438
- outline: none;
439
- }
440
- #WBCR .wio-optimize-button:active {
441
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
442
- }
443
- #WBCR .wio-optimize-button:disabled {
444
- background: #e2edd6;
445
- color: #a5b295;
446
- }
447
- #WBCR .wio-optimize-button.wio-running {
448
- color: #a57b3c;
449
- background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
450
- padding-left: 50px;
451
- }
452
- #WBCR .wio-global-optim-phrase {
453
- width: 180px;
454
- padding-top: 20px;
455
- font-size: 14px;
456
- text-align: center;
457
- }
458
- #WBCR .wio-total-percent {
459
- color: #587f2e;
460
- }
461
- #WBCR #wio-start-msg-top,
462
- #WBCR #wio-start-msg-right,
463
- #WBCR #wio-start-msg-complete {
464
- display: none;
465
- }
466
- #WBCR .wio-text-left {
467
- text-align: left;
468
- }
469
- #WBCR span.wio-num {
470
- display: inline !important;
471
- position: inherit !important;
472
- }
473
- #WBCR .wio-image-optimize-board {
474
- padding-bottom: 0 !important;
475
- }
476
- #WBCR .wio-page-statistic {
477
- padding-left: 40px;
478
- }
479
- #WBCR .wio-page-statistic .wio-chart-percent {
480
- margin-top: -1.1em;
481
- }
482
- #WBCR .wrio-optimization-progress {
483
- background: none;
484
- padding: 0;
485
- /*button {
486
- padding: 5px 10px;
487
- border: 0;
488
- font-size: 11px;
489
- text-transform: uppercase !important;
490
- font-weight: bold;
491
- border-radius: 4px;
492
- outline: none;
493
- background: @greyButtonBg;
494
- color: @greyButtonColor;
495
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
496
-
497
- &:active {
498
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
499
- }
500
-
501
- &.wbcr-rio-loading {
502
- width: 56px;
503
- font-size: 0;
504
- background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
505
- }
506
-
507
- &.wbcr-rio-selected {
508
- background: #f3efe2;
509
- color: #d8d8d8;
510
-
511
- &:active {
512
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
513
- }
514
- }
515
- }*/
516
- }
517
- #WBCR .wrio-optimization-progress h4 {
518
- font-size: 15px;
519
- font-weight: 700;
520
- }
521
- #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
522
- padding: 20px;
523
- background: #efefef;
524
- font-size: 15px;
525
- color: #b7b7b7;
526
- font-style: italic;
527
- }
528
- #WBCR .wio-widget {
529
- padding: 0 !important;
530
- }
531
- #WBCR .wio-widget .wio-chart-percent {
532
- font-size: 44px;
533
- line-height: 1;
534
- }
535
- #WBCR .wio-widget .wio-bars {
536
- width: 60%;
537
- margin-left: 155px;
538
- }
539
- #WBCR .wio-widget .col-chart.col-chart {
540
- width: 100%;
541
- }
542
- #WBCR .wio-widget .col-controls {
543
- width: 45%;
544
- padding-left: 5px;
545
- padding-top: 110px;
546
- }
547
- #WBCR .wio-widget .wio-doughnut-legend {
548
- /*padding-top:30px;*/
549
- text-align: left;
550
- }
551
- #WBCR .wio-widget .wio-widget-bottom {
552
- display: table;
553
- padding-top: 20px !important;
554
- width: 100%;
555
- text-align: right;
556
- }
557
- #WBCR .wio-widget .wio-widget-bottom li {
558
- display: table-cell;
559
- }
560
- #WBCR .wio-widget .wio-widget-bottom li:first-child {
561
- text-align: left;
562
- }
563
- #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
564
- display: inline-block;
565
- position: relative;
566
- content: 'PRO';
567
- background: #ff5722;
568
- border-radius: 4px;
569
- color: #fff;
570
- font-size: 10px;
571
- line-height: 1;
572
- font-style: normal;
573
- padding: 4px 6px;
574
- margin-left: 4px;
575
- vertical-align: top;
576
- top: -8px;
577
- left: -10px;
578
- right: auto;
579
- z-index: 11;
580
- }
581
- #WBCR .factory-checkbox-disabled input,
582
- #WBCR .factory-checkbox-disabled button {
583
- pointer-events: none;
584
- cursor: not-allowed;
585
- opacity: 0.65;
586
- filter: alpha(opacity=65);
587
- -webkit-box-shadow: none;
588
- box-shadow: none;
589
- }
590
- #WBCR #wrio-webp-options h3,
591
- #WBCR #wrio-error-log-options h3 {
592
- font-size: 14px;
593
- margin: 0 0 10px 0;
594
- font-weight: 600;
595
- color: #565656;
596
- }
597
- #WBCR #wrio-webp-options .wrio-webp-options-info,
598
- #WBCR #wrio-error-log-options .wrio-webp-options-info {
599
- color: #8a8787;
600
- font-size: 12px;
601
- }
602
- #WBCR #wrio-webp-options ul,
603
- #WBCR #wrio-error-log-options ul {
604
- padding-left: 0;
605
- }
606
- #WBCR #wrio-webp-options ul li:after,
607
- #WBCR #wrio-error-log-options ul li:after {
608
- content: '';
609
- display: block;
610
- clear: both;
611
- }
612
- #WBCR #wrio-webp-options ul li label,
613
- #WBCR #wrio-error-log-options ul li label {
614
- font-weight: 600;
615
- }
616
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
617
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
618
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
619
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
620
- display: block;
621
- float: left;
622
- margin-top: 2px;
623
- margin-right: 8px;
624
- }
625
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
626
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
627
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
628
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
629
- outline: none;
630
- box-shadow: none;
631
- }
632
- #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
633
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
634
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
635
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
636
- padding-left: 25px;
637
- }
638
- @media (max-width: 830px) {
639
- #WBCR .wio [class^="col-"] {
640
- float: none;
641
- margin-bottom: 1.5em;
642
- }
643
- #WBCR .wio .col-1-3,
644
- #WBCR .wio .col-1-2 {
645
- width: auto;
646
- padding: 0 28px;
647
- clear: both;
648
- padding-top: 1em;
649
- }
650
- }
651
- @keyframes wiohello {
652
- 0%,
653
- 100% {
654
- background: #FFF;
655
- }
656
- 50% {
657
- background: #F4F7F9;
658
- }
659
- }
660
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
661
- #WBCR .wio-columns .col-statistics.col-statistics,
662
- #WBCR .wio-columns .col-chart.col-chart {
663
- width: 50%;
664
- }
665
- }
666
- @media (max-width: 808px) {
667
- #WBCR .wio-columns .col-statistics.col-statistics,
668
- #WBCR .wio-columns .col-chart.col-chart {
669
- width: auto;
670
- float: none;
671
- padding: 0;
672
- }
673
- #WBCR .wio-columns .col-chart.col-chart {
674
- margin-top: 3em;
675
- }
676
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Styles for the Widget to be displayed in the Clearfy plugin
3
+
4
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 14.06.2019
6
+ */
7
+ #WBCR {
8
+ /* Doughnut */
9
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
+ .wio-overview-chart-container {
11
+ float: none;
12
+ margin-right: 0;
13
+ }
14
+ }
15
+
16
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
+ .wio-overview-chart-container {
18
+ float: none;
19
+ margin-right: 0;
20
+ }
21
+
22
+ .wio-doughnut-legend {
23
+ margin-top: 18px;
24
+ }
25
+
26
+ .wio-global-optim-phrase {
27
+ padding-top: 0;
28
+ width: auto;
29
+ }
30
+ }*/
31
+ }
32
+ #WBCR .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;
40
+ -webkit-box-shadow: inset 0 1px 1px #0074a2;
41
+ box-shadow: inset 0 1px 3px #0074a2;
42
+ border-top: 1px solid #0074a2;
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
+ }
50
+ #WBCR .wio-clear {
51
+ clear: both;
52
+ }
53
+ #WBCR #io_folders_statistic-wbcr_clearfy-tab,
54
+ #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
55
+ display: none !important;
56
+ }
57
+ #WBCR .wrio-statistic-nav {
58
+ margin: 0;
59
+ background: #efefef;
60
+ }
61
+ #WBCR .wrio-statistic-nav ul {
62
+ margin: 0 0 0 10px;
63
+ }
64
+ #WBCR .wrio-statistic-nav ul li {
65
+ position: relative;
66
+ display: inline-block;
67
+ margin: 0 5px 0 0;
68
+ background: #ffffff;
69
+ box-shadow: 0 -2px 0 #eaeaea;
70
+ }
71
+ #WBCR .wrio-statistic-nav ul li:hover {
72
+ background: #f7f7f7;
73
+ }
74
+ #WBCR .wrio-statistic-nav ul li.active {
75
+ background: #f7f7f7;
76
+ border-top: 1px solid #d4d4d4;
77
+ border-left: 1px solid #d4d4d4;
78
+ border-right: 1px solid #d4d4d4;
79
+ border-bottom: 1px solid #f7f7f7;
80
+ margin-bottom: -1px;
81
+ }
82
+ #WBCR .wrio-statistic-nav ul li.active a {
83
+ color: #222;
84
+ }
85
+ #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
86
+ border: 2px dashed #8bc34a;
87
+ color: #5e8237;
88
+ }
89
+ #WBCR .wrio-statistic-nav ul li.active .dashicons,
90
+ #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
91
+ color: #ff8b66;
92
+ }
93
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
94
+ display: block;
95
+ padding: 10px 20px 10px 20px;
96
+ text-decoration: none;
97
+ color: #d4d4d4;
98
+ font-size: 22px;
99
+ line-height: 2;
100
+ }
101
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
102
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
103
+ background: 0;
104
+ box-shadow: none;
105
+ outline: none;
106
+ }
107
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
108
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
109
+ display: inline-block;
110
+ width: 30px;
111
+ height: 30px;
112
+ font-size: 30px;
113
+ line-height: 1.5;
114
+ margin-right: 15px;
115
+ color: #d4d4d4;
116
+ }
117
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
118
+ display: inline-block;
119
+ width: 42px;
120
+ height: 42px;
121
+ border-radius: 100px;
122
+ border: 2px dashed #e4e4e4;
123
+ padding: 5px;
124
+ margin-left: 30px;
125
+ font-size: 14px;
126
+ font-weight: 600;
127
+ text-align: center;
128
+ color: #bdbdbd;
129
+ }
130
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
131
+ display: inline-block;
132
+ position: absolute;
133
+ content: 'PRO';
134
+ background: #ff5722;
135
+ border-radius: 4px;
136
+ color: #fff;
137
+ font-size: 10px;
138
+ line-height: 1;
139
+ font-style: normal;
140
+ padding: 4px 6px;
141
+ margin-left: 4px;
142
+ vertical-align: top;
143
+ top: 10px;
144
+ left: auto;
145
+ right: 10px;
146
+ z-index: 11;
147
+ }
148
+ #WBCR .wrio-table {
149
+ width: 100%;
150
+ table-layout: fixed;
151
+ box-sizing: border-box;
152
+ border-spacing: 3px;
153
+ background: #fff;
154
+ border-top: 2px dashed #cac9c9;
155
+ }
156
+ #WBCR .wrio-table th,
157
+ #WBCR .wrio-table td {
158
+ padding: 16px 10px;
159
+ text-align: center;
160
+ }
161
+ #WBCR .wrio-table th {
162
+ background: #f3f3f3;
163
+ color: #777777;
164
+ box-shadow: 0 1px 0 #d8d8d8;
165
+ }
166
+ #WBCR .wrio-table th:nth-child(2n+1) {
167
+ background: #f9f9f9;
168
+ }
169
+ #WBCR .wrio-table tr.wrio-error {
170
+ background-color: #ffe9e9 !important;
171
+ }
172
+ #WBCR .wrio-table .wrio-table-spinner {
173
+ background: url("../img/quick-start-loader.gif") center center no-repeat;
174
+ }
175
+ #WBCR .wrio-table .wrio-table-highlighter {
176
+ display: inline-block;
177
+ padding: 3px 7px;
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;
185
+ }
186
+ #WBCR .wrio-table .wbcr-rio-server-warning {
187
+ color: #ffb635;
188
+ }
189
+ #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
190
+ text-align: left;
191
+ }
192
+ #WBCR .wrio-servers {
193
+ padding: 20px 20px;
194
+ }
195
+ #WBCR .wrio-servers label span {
196
+ display: block;
197
+ font-weight: normal;
198
+ font-size: 12px;
199
+ color: #b7b2b2;
200
+ }
201
+ #WBCR .wrio-servers #wrio-change-optimization-server {
202
+ position: relative;
203
+ display: inline-block;
204
+ max-width: 400px;
205
+ margin-right: 15px;
206
+ margin-bottom: 0;
207
+ border: 1px solid #d2d0d0;
208
+ background-color: #efefef;
209
+ }
210
+ #WBCR .wrio-servers .wrio-servers-info {
211
+ margin: 0 0 0;
212
+ padding: 20px;
213
+ background: #fff;
214
+ }
215
+ #WBCR .wrio-servers .wrio-server-status-wrap {
216
+ display: inline-block;
217
+ margin-top: 8px;
218
+ }
219
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
220
+ background: transparent;
221
+ color: #fff;
222
+ padding: 3px 5px;
223
+ border-radius: 4px;
224
+ }
225
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
226
+ background: #ff5722;
227
+ }
228
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
229
+ background: #8bc34a;
230
+ }
231
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
232
+ display: inline-block;
233
+ height: 10px;
234
+ width: 30px;
235
+ background: url("../img/quick-start-loader.gif") center no-repeat;
236
+ }
237
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap {
238
+ display: inline-block;
239
+ margin-top: 8px;
240
+ margin-left: 10px;
241
+ }
242
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance {
243
+ color: #fff;
244
+ padding: 3px 5px;
245
+ border-radius: 4px;
246
+ background: #ffc107;
247
+ }
248
+ #WBCR .wrio-servers .wrio-premium-user-balance-wrap .wrio-premium-user-balance-check-proccess {
249
+ display: inline-block;
250
+ height: 10px;
251
+ width: 30px;
252
+ background: url("../img/quick-start-loader.gif") center no-repeat;
253
+ }
254
+ #WBCR .wrio-servers .wrio-premium-user-update-wrap {
255
+ display: inline-block;
256
+ margin-top: 8px;
257
+ margin-left: 10px;
258
+ }
259
+ #WBCR .wrio-servers .wrio-premium-user-update-wrap .wrio-premium-user-update {
260
+ color: #fff;
261
+ padding: 3px 5px;
262
+ border-radius: 4px;
263
+ background: #ffc107;
264
+ }
265
+ #WBCR .wrio-servers .wrio-premium-user-update-wrap .wrio-premium-user-update-check-proccess {
266
+ display: inline-block;
267
+ height: 10px;
268
+ width: 30px;
269
+ background: url("../img/quick-start-loader.gif") center no-repeat;
270
+ }
271
+ #WBCR .wio-columns {
272
+ overflow: hidden;
273
+ padding: 15px 0;
274
+ counter-reset: cols;
275
+ }
276
+ #WBCR .wio-columns [class^="col-"] {
277
+ float: left;
278
+ -webkit-box-sizing: border-box;
279
+ -moz-box-sizing: border-box;
280
+ box-sizing: border-box;
281
+ }
282
+ #WBCR .wio-columns .col-1-3 {
283
+ width: 33.333%;
284
+ padding-left: 28px;
285
+ }
286
+ #WBCR .wio-columns .col-2-3 {
287
+ width: 66.666%;
288
+ padding-left: 28px;
289
+ }
290
+ #WBCR .wio-columns .col-1-2 {
291
+ width: 50%;
292
+ padding: 0 20px;
293
+ }
294
+ #WBCR .wio-columns .col-statistics.col-statistics {
295
+ width: 60%;
296
+ }
297
+ #WBCR .wio-columns .col-chart.col-chart {
298
+ width: 40%;
299
+ position: relative;
300
+ padding: 20px;
301
+ font-size: 12px;
302
+ text-transform: uppercase;
303
+ background: #f1f1f1b3;
304
+ color: #abacaf;
305
+ font-weight: bold;
306
+ border-radius: 5px;
307
+ margin-top: 10px;
308
+ text-align: left;
309
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
310
+ }
311
+ #WBCR .wio-col {
312
+ float: left;
313
+ width: 50%;
314
+ box-sizing: border-box;
315
+ -webkit-flex-basis: 50%;
316
+ -ms-flex-preferred-size: 50%;
317
+ flex-basis: 50%;
318
+ }
319
+ #WBCR .wio-col {
320
+ padding-right: 20px;
321
+ }
322
+ #WBCR .wio-col + .wio-col {
323
+ padding-right: 0;
324
+ padding-left: 50px;
325
+ }
326
+ #WBCR .wio-col:target {
327
+ animation: wiohello 1s 3 linear backwards;
328
+ }
329
+ #WBCR .wio-number-you-optimized {
330
+ margin-bottom: 1.35em;
331
+ overflow: hidden;
332
+ }
333
+ #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
334
+ color: #828282;
335
+ }
336
+ #WBCR .wio-number-you-optimized .wio-number {
337
+ display: table-cell;
338
+ padding-right: 15px;
339
+ font-size: 48px;
340
+ font-weight: bold;
341
+ line-height: 1;
342
+ vertical-align: middle;
343
+ white-space: nowrap;
344
+ color: #828282;
345
+ }
346
+ #WBCR .wio-number-you-optimized .wio-text {
347
+ display: table-cell;
348
+ vertical-align: middle;
349
+ overflow: hidden;
350
+ font-size: 12px;
351
+ color: #828282;
352
+ }
353
+ #WBCR .wio-number-you-optimized > p {
354
+ display: table;
355
+ }
356
+ #WBCR .wio-bars {
357
+ padding-right: 15px;
358
+ }
359
+ #WBCR .wio-bars p {
360
+ font-size: 12px;
361
+ margin-bottom: 5px;
362
+ }
363
+ #WBCR .wio-bars + .wio-number-you-optimized {
364
+ border-bottom: 0;
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;
372
+ }
373
+ #WBCR .wio-bar-negative .wio-barnb {
374
+ color: #9d9fa5;
375
+ }
376
+ #WBCR .wio-progress {
377
+ height: 8px;
378
+ transition: width 0.3s;
379
+ /*.wio-bar-negative {
380
+ width: 92% !important;
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 {
396
+ display: block;
397
+ margin-right: -5.25em;
398
+ text-align: right;
399
+ font-weight: bold;
400
+ line-height: 0.8;
401
+ }
402
+ #WBCR .wio-chart {
403
+ position: relative;
404
+ top: 1px;
405
+ display: inline-block;
406
+ vertical-align: middle;
407
+ }
408
+ #WBCR .wio-chart-container {
409
+ position: relative;
410
+ display: inline-block;
411
+ margin-right: 5px;
412
+ }
413
+ #WBCR .wio-chart-container canvas {
414
+ display: block;
415
+ }
416
+ #WBCR .wio-overview-chart-container {
417
+ float: left;
418
+ margin-right: 20px;
419
+ }
420
+ #WBCR .wio-chart-percent {
421
+ position: absolute;
422
+ left: 0;
423
+ right: 0;
424
+ top: 50%;
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
+ }
432
+ #WBCR .wio-chart-percent span {
433
+ font-size: 20px;
434
+ vertical-align: super;
435
+ }
436
+ #WBCR #wio-overview-chart-legend {
437
+ overflow: hidden;
438
+ }
439
+ #WBCR .wio-doughnut-legend li {
440
+ display: inline-block;
441
+ position: relative;
442
+ margin-bottom: 15px;
443
+ border-radius: 5px;
444
+ padding: 3px 8px 2px 31px;
445
+ font-size: 9px;
446
+ cursor: default;
447
+ -webkit-transition: background-color 200ms ease-in-out;
448
+ -moz-transition: background-color 200ms ease-in-out;
449
+ -o-transition: background-color 200ms ease-in-out;
450
+ transition: background-color 200ms ease-in-out;
451
+ }
452
+ #WBCR .wio-doughnut-legend li span {
453
+ display: block;
454
+ position: absolute;
455
+ left: 0;
456
+ top: 0;
457
+ width: 25px;
458
+ height: 25px;
459
+ border-radius: 50%;
460
+ }
461
+ #WBCR .wio-optimize-button {
462
+ min-width: 180px;
463
+ padding: 12px 30px;
464
+ background: #c9deb2;
465
+ color: #586549;
466
+ border: 0;
467
+ box-shadow: none;
468
+ font-size: 14px;
469
+ text-transform: uppercase !important;
470
+ font-weight: bold;
471
+ border-radius: 4px;
472
+ outline: none;
473
+ }
474
+ #WBCR .wio-optimize-button:active {
475
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
476
+ }
477
+ #WBCR .wio-optimize-button:disabled {
478
+ background: #e2edd6;
479
+ color: #a5b295;
480
+ }
481
+ #WBCR .wio-optimize-button.wio-running {
482
+ color: #a57b3c;
483
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
484
+ padding-left: 50px;
485
+ }
486
+ #WBCR .wio-global-optim-phrase {
487
+ width: 180px;
488
+ padding-top: 20px;
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,
497
+ #WBCR #wio-start-msg-complete {
498
+ display: none;
499
+ }
500
+ #WBCR .wio-text-left {
501
+ text-align: left;
502
+ }
503
+ #WBCR span.wio-num {
504
+ display: inline !important;
505
+ position: inherit !important;
506
+ }
507
+ #WBCR .wio-image-optimize-board {
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;
518
+ background: #efefef;
519
+ }
520
+ #WBCR .wio-page-total .wrio-calculate-process {
521
+ display: inline-block !important;
522
+ height: 10px;
523
+ width: 30px;
524
+ background: transparent url("../img/quick-start-loader.gif") center no-repeat !important;
525
+ }
526
+ #WBCR .wio-page-total .wrio-total-images {
527
+ font-weight: bold;
528
+ color: #fff;
529
+ padding: 3px 5px;
530
+ border-radius: 4px;
531
+ background: #ffc107;
532
+ }
533
+ #WBCR .wio-page-total span.wrio-total-images-desc {
534
+ display: block;
535
+ font-weight: normal;
536
+ font-size: 12px;
537
+ color: #b7b2b2;
538
+ }
539
+ #WBCR .wrio-optimization-progress {
540
+ background: none;
541
+ padding: 0;
542
+ /*button {
543
+ padding: 5px 10px;
544
+ border: 0;
545
+ font-size: 11px;
546
+ text-transform: uppercase !important;
547
+ font-weight: bold;
548
+ border-radius: 4px;
549
+ outline: none;
550
+ background: @greyButtonBg;
551
+ color: @greyButtonColor;
552
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
553
+
554
+ &:active {
555
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
556
+ }
557
+
558
+ &.wbcr-rio-loading {
559
+ width: 56px;
560
+ font-size: 0;
561
+ background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
562
+ }
563
+
564
+ &.wbcr-rio-selected {
565
+ background: #f3efe2;
566
+ color: #d8d8d8;
567
+
568
+ &:active {
569
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
570
+ }
571
+ }
572
+ }*/
573
+ }
574
+ #WBCR .wrio-optimization-progress h4 {
575
+ font-size: 15px;
576
+ font-weight: 700;
577
+ }
578
+ #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
579
+ padding: 20px;
580
+ background: #efefef;
581
+ font-size: 15px;
582
+ color: #b7b7b7;
583
+ font-style: italic;
584
+ }
585
+ #WBCR .wio-widget {
586
+ padding: 0 !important;
587
+ }
588
+ #WBCR .wio-widget .wio-chart-percent {
589
+ font-size: 44px;
590
+ line-height: 1;
591
+ }
592
+ #WBCR .wio-widget .wio-bars {
593
+ width: 60%;
594
+ margin-left: 155px;
595
+ }
596
+ #WBCR .wio-widget .col-chart.col-chart {
597
+ width: 100%;
598
+ }
599
+ #WBCR .wio-widget .col-controls {
600
+ width: 45%;
601
+ padding-left: 5px;
602
+ padding-top: 110px;
603
+ }
604
+ #WBCR .wio-widget .wio-doughnut-legend {
605
+ /*padding-top:30px;*/
606
+ text-align: left;
607
+ }
608
+ #WBCR .wio-widget .wio-widget-bottom {
609
+ display: table;
610
+ padding-top: 20px !important;
611
+ width: 100%;
612
+ text-align: right;
613
+ }
614
+ #WBCR .wio-widget .wio-widget-bottom li {
615
+ display: table-cell;
616
+ }
617
+ #WBCR .wio-widget .wio-widget-bottom li:first-child {
618
+ text-align: left;
619
+ }
620
+ #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
621
+ display: inline-block;
622
+ position: relative;
623
+ content: 'PRO';
624
+ background: #ff5722;
625
+ border-radius: 4px;
626
+ color: #fff;
627
+ font-size: 10px;
628
+ line-height: 1;
629
+ font-style: normal;
630
+ padding: 4px 6px;
631
+ margin-left: 4px;
632
+ vertical-align: top;
633
+ top: -8px;
634
+ left: -10px;
635
+ right: auto;
636
+ z-index: 11;
637
+ }
638
+ #WBCR .factory-checkbox-disabled input,
639
+ #WBCR .factory-checkbox-disabled button {
640
+ pointer-events: none;
641
+ cursor: not-allowed;
642
+ opacity: 0.65;
643
+ filter: alpha(opacity=65);
644
+ -webkit-box-shadow: none;
645
+ box-shadow: none;
646
+ }
647
+ #WBCR #wrio-webp-options h3,
648
+ #WBCR #wrio-error-log-options h3 {
649
+ font-size: 14px;
650
+ margin: 0 0 10px 0;
651
+ font-weight: 600;
652
+ color: #565656;
653
+ }
654
+ #WBCR #wrio-webp-options .wrio-webp-options-info,
655
+ #WBCR #wrio-error-log-options .wrio-webp-options-info {
656
+ color: #8a8787;
657
+ font-size: 12px;
658
+ }
659
+ #WBCR #wrio-webp-options ul,
660
+ #WBCR #wrio-error-log-options ul {
661
+ padding-left: 0;
662
+ }
663
+ #WBCR #wrio-webp-options ul li:after,
664
+ #WBCR #wrio-error-log-options ul li:after {
665
+ content: '';
666
+ display: block;
667
+ clear: both;
668
+ }
669
+ #WBCR #wrio-webp-options ul li label,
670
+ #WBCR #wrio-error-log-options ul li label {
671
+ font-weight: 600;
672
+ }
673
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
674
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
675
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
676
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
677
+ display: block;
678
+ float: left;
679
+ margin-top: 2px;
680
+ margin-right: 8px;
681
+ }
682
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
683
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
684
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
685
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
686
+ outline: none;
687
+ box-shadow: none;
688
+ }
689
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
690
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
691
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
692
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
693
+ padding-left: 25px;
694
+ }
695
+ @media (max-width: 830px) {
696
+ #WBCR .wio [class^="col-"] {
697
+ float: none;
698
+ margin-bottom: 1.5em;
699
+ }
700
+ #WBCR .wio .col-1-3,
701
+ #WBCR .wio .col-1-2 {
702
+ width: auto;
703
+ padding: 0 28px;
704
+ clear: both;
705
+ padding-top: 1em;
706
+ }
707
+ }
708
+ @keyframes wiohello {
709
+ 0%,
710
+ 100% {
711
+ background: #FFF;
712
+ }
713
+ 50% {
714
+ background: #F4F7F9;
715
+ }
716
+ }
717
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
718
+ #WBCR .wio-columns .col-statistics.col-statistics,
719
+ #WBCR .wio-columns .col-chart.col-chart {
720
+ width: 50%;
721
+ }
722
+ }
723
+ @media (max-width: 808px) {
724
+ #WBCR .wio-columns .col-statistics.col-statistics,
725
+ #WBCR .wio-columns .col-chart.col-chart {
726
+ width: auto;
727
+ float: none;
728
+ padding: 0;
729
+ }
730
+ #WBCR .wio-columns .col-chart.col-chart {
731
+ margin-top: 3em;
732
+ }
733
+ }
admin/assets/css/base-statistic.less CHANGED
@@ -1,818 +1,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: #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
- .wio-clear {
45
- clear: both;
46
- }
47
-
48
- // Fix for Clearfy
49
- // This code hides tabs custom folders and nextgen gallery
50
- // -----------------------------------------------
51
- #io_folders_statistic-wbcr_clearfy-tab, #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
52
- display: none !important;
53
- }
54
-
55
- // Styling tabs on statistics pages
56
- // -----------------------------------------------
57
- .wrio-statistic-nav {
58
- margin: 0;
59
- //box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
60
- background: #efefef;
61
-
62
- ul {
63
- margin: 0;
64
-
65
- li {
66
- position: relative;
67
- display: inline-block;
68
- //width: 300px;
69
- margin: 0 0 0 0;
70
- background: #ffffff;
71
- box-shadow: 0 -2px 0 #eaeaea;
72
-
73
- &:hover {
74
- background: #f7f7f7;
75
- }
76
-
77
- &.active {
78
- //box-shadow: 0 -2px 0 #c9deb2;
79
- background: #f7f7f7;
80
- border-top: 1px solid #d4d4d4;
81
- border-left: 1px solid #d4d4d4;
82
- border-right: 1px solid #d4d4d4;
83
- border-bottom: 1px solid #f7f7f7;
84
- margin-bottom: -1px;
85
-
86
- a {
87
- color: #222;
88
-
89
- .wrio-statistic-tab-percent {
90
- border: 2px dashed #8bc34a;
91
- color: #5e8237;
92
- }
93
- }
94
-
95
- .dashicons, .dashicons-before:before {
96
- color: #ff8b66;
97
- }
98
- }
99
-
100
- .wrio-statistic-tab {
101
- display: block;
102
- padding: 10px 20px 10px 20px;
103
- text-decoration: none;
104
- color: #d4d4d4;
105
- font-size: 22px;
106
- line-height: 2;
107
-
108
- &:active, &:focus {
109
- background: 0;
110
- box-shadow: none;
111
- outline: none;
112
- }
113
-
114
- .dashicons, .dashicons-before:before {
115
- display: inline-block;
116
- width: 30px;
117
- height: 30px;
118
- font-size: 30px;
119
- line-height: 1.5;
120
- margin-right: 15px;
121
- color: #d4d4d4;
122
- }
123
-
124
-
125
- .wrio-statistic-tab-percent {
126
- display: inline-block;
127
- width: 42px;
128
- height: 42px;
129
- border-radius: 100px;
130
- border: 2px dashed #e4e4e4;
131
- padding: 5px;
132
- margin-left: 30px;
133
- font-size: 14px;
134
- font-weight: 600;
135
- text-align: center;
136
- color: #bdbdbd;
137
- }
138
- }
139
-
140
- .wrio-statistic-tab-premium-label:after {
141
- .premium-label(absolute, 10px, auto, 10px);
142
- }
143
- }
144
- }
145
- }
146
-
147
- // Table style. The table is used for optimization log
148
- .wrio-table {
149
- width: 100%;
150
- table-layout: fixed;
151
- box-sizing: border-box;
152
- border-spacing: 3px;
153
- background: #fff;
154
- border-top: 2px dashed #cac9c9;
155
-
156
- th, td {
157
- padding: 16px 10px;
158
- text-align: center;
159
- }
160
-
161
- th {
162
- background: #f3f3f3;
163
- color: #777777;
164
- box-shadow: 0 1px 0 rgb(216, 216, 216);
165
-
166
- &:nth-child(2n+1) {
167
- background: #f9f9f9
168
- }
169
- }
170
-
171
- tr.wrio-error {
172
- background-color: #ffe9e9 !important;
173
- }
174
-
175
- .wrio-table-spinner {
176
- background: url("../img/quick-start-loader.gif") center center no-repeat;
177
- }
178
-
179
- .wrio-table-highlighter {
180
- display: inline-block;
181
- padding: 3px 7px;
182
- background: @greyButtonBg;
183
- }
184
-
185
- .wbcr-rio-server-success {
186
- color: @positiveColor;
187
- }
188
-
189
- .wbcr-rio-server-error {
190
- color: @errorColor;
191
- }
192
-
193
- .wbcr-rio-server-warning {
194
- color: @waringColor;
195
- }
196
-
197
- &.wbcr-rio-folders-table {
198
- td:nth-child(3) {
199
- text-align: left;
200
- }
201
- }
202
- }
203
-
204
- .wrio-servers {
205
- padding: 40px 20px;
206
-
207
- label {
208
- span {
209
- display: block;
210
- font-weight: normal;
211
- font-size: 12px;
212
- color: #b7b2b2;
213
- }
214
- }
215
-
216
- #wrio-change-optimization-server {
217
- position: relative;
218
- display: inline-block;
219
- max-width: 400px;
220
- margin-right: 15px;
221
- margin-bottom: 0;
222
- border: 1px solid #d2d0d0;
223
- background: #efefef;
224
- }
225
-
226
- .wrio-servers-info {
227
- margin: 0 0 0;
228
- padding: 20px;
229
- background: #fff;
230
- }
231
-
232
- .wrio-server-status-wrap {
233
- display: inline-block;
234
- margin-top: 8px;
235
-
236
- .wrio-server-status {
237
- background: transparent;
238
- color: #fff;
239
- padding: 3px 5px;
240
- border-radius: 4px;
241
-
242
- &.wrio-down {
243
- background: #ff5722;
244
- }
245
-
246
- &.wrio-stable {
247
- background: #8bc34a;
248
- }
249
-
250
- &.wrio-server-check-proccess {
251
- display: inline-block;
252
- height: 10px;
253
- width: 30px;
254
- background: url("../img/quick-start-loader.gif") center no-repeat;
255
- }
256
- }
257
- }
258
-
259
-
260
- .wrio-premium-user-balance-wrap {
261
- display: inline-block;
262
- margin-top: 8px;
263
- margin-left: 10px;
264
-
265
- .wrio-premium-user-balance {
266
- color: #fff;
267
- padding: 3px 5px;
268
- border-radius: 4px;
269
- background: #ffc107;
270
- }
271
-
272
- .wrio-premium-user-balance-check-proccess {
273
- display: inline-block;
274
- height: 10px;
275
- width: 30px;
276
- background: url("../img/quick-start-loader.gif") center no-repeat;
277
- }
278
- }
279
- }
280
-
281
- .wio-columns {
282
- overflow: hidden;
283
- padding: 15px 0;
284
- counter-reset: cols;
285
-
286
- [class^="col-"] {
287
- float: left;
288
- -webkit-box-sizing: border-box;
289
- -moz-box-sizing: border-box;
290
- box-sizing: border-box;
291
- }
292
-
293
- .col-1-3 {
294
- width: 33.333%;
295
- padding-left: 28px;
296
- }
297
-
298
- .col-2-3 {
299
- width: 66.666%;
300
- padding-left: 28px
301
- }
302
-
303
- .col-1-2 {
304
- width: 50%;
305
- padding: 0 20px;
306
- }
307
-
308
- .col-statistics.col-statistics {
309
- width: 60%;
310
- }
311
-
312
- .col-chart.col-chart {
313
- width: 40%;
314
- position: relative;
315
- padding: 20px;
316
- font-size: 12px;
317
- text-transform: uppercase;
318
- background: #f1f1f1b3;
319
- color: #abacaf;
320
- font-weight: bold;
321
- border-radius: 5px;
322
- margin-top: 10px;
323
- text-align: left;
324
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
325
- }
326
- }
327
-
328
- .wio-col {
329
- float: left;
330
- width: 50%;
331
- box-sizing: border-box;
332
- -webkit-flex-basis: 50%;
333
- -ms-flex-preferred-size: 50%;
334
- flex-basis: 50%;
335
- }
336
-
337
- .wio-col {
338
- padding-right: 20px;
339
- }
340
-
341
- .wio-col + .wio-col {
342
- padding-right: 0;
343
- padding-left: 50px;
344
- }
345
-
346
- .wio-col:target {
347
- animation: wiohello 1s 3 linear backwards;
348
- }
349
-
350
- .wio-number-you-optimized {
351
- margin-bottom: 1.35em;
352
- overflow: hidden;
353
-
354
- #wio-total-optimized-attachments-pct {
355
- color: @neutralColor;
356
- }
357
-
358
- .wio-number {
359
- display: table-cell;
360
- padding-right: 15px;
361
- font-size: 48px;
362
- font-weight: bold;
363
- line-height: 1;
364
- vertical-align: middle;
365
- white-space: nowrap;
366
- color: @neutralColor;
367
- }
368
-
369
- .wio-text {
370
- display: table-cell;
371
- vertical-align: middle;
372
- overflow: hidden;
373
- font-size: 12px;
374
- color: @neutralColor;
375
- }
376
-
377
- & > p {
378
- display: table;
379
- }
380
- }
381
-
382
- .wio-bars {
383
- padding-right: 15px;
384
- }
385
-
386
- .wio-bars p {
387
- font-size: 12px;
388
- margin-bottom: 5px;
389
- }
390
-
391
- .wio-bars + .wio-number-you-optimized {
392
- border-bottom: 0;
393
- padding-top: 0.85em;
394
- }
395
-
396
- .wio-bars + .wio-number-you-optimized p {
397
- color: darken(@positiveColor, 10);
398
- }
399
-
400
- .wio-bar-negative {
401
- .wio-progress {
402
- background: @negativeColor;
403
- }
404
-
405
- .wio-barnb {
406
- color: darken(@negativeColor, 20);
407
- }
408
- }
409
-
410
- .wio-progress {
411
- height: 8px;
412
- transition: width .3s;
413
-
414
- /*.wio-bar-negative {
415
- width: 92% !important;
416
- }*/
417
- }
418
-
419
- .wio-bar-positive {
420
- .wio-progress {
421
- background: @positiveColor;
422
- }
423
-
424
- .wio-barnb {
425
- color: darken(@positiveColor, 10);
426
- }
427
- }
428
-
429
- .wio-bar-primary {
430
- .wio-progress {
431
- background: @positiveColor;
432
- }
433
-
434
- .wio-barnb {
435
- color: darken(@positiveColor, 10);
436
- }
437
- }
438
-
439
- .wio-right-outside-number .wio-barnb {
440
- display: block;
441
- margin-right: -5.25em;
442
- text-align: right;
443
- font-weight: bold;
444
- line-height: .8;
445
- }
446
-
447
- /* Doughnut */
448
-
449
- .wio-chart {
450
- position: relative;
451
- top: 1px;
452
- display: inline-block;
453
- vertical-align: middle;
454
- }
455
-
456
- .wio-chart-container {
457
- position: relative;
458
- display: inline-block;
459
- margin-right: 5px;
460
- }
461
-
462
- .wio-chart-container canvas {
463
- display: block;
464
- }
465
-
466
- .wio-overview-chart-container {
467
- float: left;
468
- margin-right: 20px;
469
- }
470
-
471
- .wio-chart-percent {
472
- position: absolute;
473
- left: 0;
474
- right: 0;
475
- top: 50%;
476
- margin-top: -.5em;
477
- line-height: 0.8;
478
- text-align: center;
479
- font-size: 54px;
480
- font-weight: bold;
481
- color: #afafaf;
482
- }
483
-
484
- .wio-chart-percent span {
485
- font-size: 20px;
486
- vertical-align: super;
487
- }
488
-
489
- #wio-overview-chart-legend {
490
- overflow: hidden;
491
- }
492
-
493
- .wio-doughnut-legend li {
494
- display: inline-block;
495
- position: relative;
496
- margin-bottom: 15px;
497
- border-radius: 5px;
498
- padding: 3px 8px 2px 31px;
499
- font-size: 9px;
500
- cursor: default;
501
- -webkit-transition: background-color 200ms ease-in-out;
502
- -moz-transition: background-color 200ms ease-in-out;
503
- -o-transition: background-color 200ms ease-in-out;
504
- transition: background-color 200ms ease-in-out;
505
- }
506
-
507
- .wio-doughnut-legend li span {
508
- display: block;
509
- position: absolute;
510
- left: 0;
511
- top: 0;
512
- width: 25px;
513
- height: 25px;
514
- border-radius: 50%;
515
- }
516
-
517
- .wio-optimize-button {
518
- min-width: 180px;
519
- padding: 12px 30px;
520
- background: @greenButtonBg;
521
- color: @greenButtonColor;
522
- border: 0;
523
- box-shadow: none;
524
- font-size: 14px;
525
- text-transform: uppercase !important;
526
- font-weight: bold;
527
- border-radius: 4px;
528
- outline: none;
529
-
530
- &:active {
531
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
532
- }
533
-
534
- &:disabled {
535
- background: lighten(@greenButtonBg, 10%);
536
- color: lighten(@greenButtonColor, 30%);
537
- }
538
-
539
- &.wio-running {
540
- color: @orangeButtonColor;
541
- background: @orangeButtonBg url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
542
- padding-left: 50px;
543
- }
544
- }
545
-
546
- .wio-global-optim-phrase {
547
- width: 180px;
548
- padding-top: 20px;
549
- font-size: 14px;
550
- text-align: center;
551
- }
552
-
553
- .wio-total-percent {
554
- color: darken(@positiveColor, 20);
555
- }
556
-
557
- #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
558
- display: none;
559
- }
560
-
561
- .wio-text-left {
562
- text-align: left;
563
- }
564
-
565
- span.wio-num {
566
- display: inline !important;
567
- position: inherit !important;
568
- }
569
-
570
-
571
- // WIDGETS SPACE
572
- // -----------------------------------------------
573
- .wio-image-optimize-board {
574
- padding-bottom: 0 !important;
575
- }
576
-
577
- .wio-page-statistic {
578
- padding-left: 40px;
579
-
580
- .wio-chart-percent {
581
- margin-top: -1.1em;
582
- }
583
- }
584
-
585
- .wrio-optimization-progress {
586
- //margin-top: 30px;
587
- background: none;
588
- padding: 0;
589
-
590
- h4 {
591
- font-size: 15px;
592
- font-weight: 700;
593
- }
594
-
595
- /*button {
596
- padding: 5px 10px;
597
- border: 0;
598
- font-size: 11px;
599
- text-transform: uppercase !important;
600
- font-weight: bold;
601
- border-radius: 4px;
602
- outline: none;
603
- background: @greyButtonBg;
604
- color: @greyButtonColor;
605
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
606
-
607
- &:active {
608
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
609
- }
610
-
611
- &.wbcr-rio-loading {
612
- width: 56px;
613
- font-size: 0;
614
- background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
615
- }
616
-
617
- &.wbcr-rio-selected {
618
- background: #f3efe2;
619
- color: #d8d8d8;
620
-
621
- &:active {
622
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
623
- }
624
- }
625
- }*/
626
-
627
- .wbcr-rio-warning-message {
628
- padding: 20px;
629
- background: #efefef;
630
- font-size: 15px;
631
- color: #b7b7b7;
632
- font-style: italic;
633
- }
634
- }
635
-
636
- .wio-widget {
637
- padding: 0 !important;
638
-
639
- .wio-chart-percent {
640
- font-size: 44px;
641
- line-height: 1;
642
- }
643
-
644
- .wio-bars {
645
- width: 60%;
646
- margin-left: 155px;
647
- }
648
-
649
- .col-chart.col-chart {
650
- width: 100%;
651
- }
652
-
653
- .col-controls {
654
- width: 45%;
655
- padding-left: 5px;
656
- padding-top: 110px
657
- }
658
-
659
- .wio-doughnut-legend {
660
- /*padding-top:30px;*/
661
- text-align: left;
662
- }
663
-
664
- .wio-widget-bottom {
665
- display: table;
666
- padding-top: 20px !important;
667
- width: 100%;
668
- text-align: right;
669
- }
670
-
671
- .wio-widget-bottom li {
672
- display: table-cell;
673
- }
674
-
675
- .wio-widget-bottom li:first-child {
676
- text-align: left;
677
- }
678
- }
679
-
680
- // FORMS SPACE
681
- // -----------------------------------------------
682
- .factory-checkbox {
683
- &.wrio-checkbox-premium-label:after {
684
- .premium-label();
685
- }
686
- }
687
-
688
- .factory-checkbox-disabled {
689
- input, button {
690
- pointer-events: none;
691
- cursor: not-allowed;
692
- opacity: .65;
693
- filter: alpha(opacity=65);
694
- -webkit-box-shadow: none;
695
- box-shadow: none;
696
- }
697
- }
698
-
699
- #wrio-webp-options, #wrio-error-log-options {
700
- h3 {
701
- font-size: 14px;
702
- margin: 0 0 10px 0;
703
- font-weight: 600;
704
- color: #565656;
705
- }
706
-
707
- .wrio-webp-options-info {
708
- color: #8a8787;
709
- font-size: 12px;
710
- }
711
-
712
- ul {
713
- padding-left: 0;
714
-
715
- li {
716
- &:after {
717
- content: '';
718
- display: block;
719
- clear: both;;
720
- }
721
-
722
- label {
723
- font-weight: 600;
724
- }
725
-
726
- .wrio-webp-options-radio, .wrio-error-log-options-checkbox {
727
- display: block;
728
- float: left;
729
- margin-top: 2px;
730
- margin-right: 8px;
731
-
732
- &:focus {
733
- outline: none;
734
- box-shadow: none;
735
- }
736
- }
737
-
738
- .wrio-webp-options-info, .wrio-error-log-options-info {
739
- padding-left: 25px;
740
- }
741
- }
742
- }
743
-
744
-
745
- }
746
-
747
- // MEDIA SPACE
748
- // -----------------------------------------------
749
-
750
- @media (max-width: 830px) {
751
- .wio [class^="col-"] {
752
- float: none;
753
- margin-bottom: 1.5em;
754
- }
755
-
756
- .wio .col-1-3,
757
- .wio .col-1-2 {
758
- width: auto;
759
- padding: 0 28px;
760
- clear: both;
761
- padding-top: 1em;
762
- }
763
- }
764
-
765
- @keyframes wiohello {
766
- 0%, 100% {
767
- background: #FFF;
768
- }
769
- 50% {
770
- background: #F4F7F9;
771
- }
772
- }
773
-
774
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
775
- .wio-columns {
776
- .col-statistics.col-statistics, .col-chart.col-chart {
777
- width: 50%;
778
- }
779
- }
780
-
781
- }
782
-
783
- @media (max-width: 808px) {
784
- .wio-columns {
785
- .col-statistics.col-statistics, .col-chart.col-chart {
786
- width: auto;
787
- float: none;
788
- padding: 0;
789
- }
790
-
791
- .col-chart.col-chart {
792
- margin-top: 3em;
793
- }
794
- }
795
- }
796
- /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
797
- .wio-overview-chart-container {
798
- float: none;
799
- margin-right: 0;
800
- }
801
- }
802
-
803
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
804
- .wio-overview-chart-container {
805
- float: none;
806
- margin-right: 0;
807
- }
808
-
809
- .wio-doughnut-legend {
810
- margin-top: 18px;
811
- }
812
-
813
- .wio-global-optim-phrase {
814
- padding-top: 0;
815
- width: auto;
816
- }
817
- }*/
818
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
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 {
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: 15px 5px;
131
- text-align: left;
132
- font-size: 14px;
133
- line-height: 1.5;
134
- color: #8c8888;
135
- }
136
- .wrio-modal-optimization-way .wrio-list-infos li:first-child {
137
- padding-top: 5px;
138
- }
139
- .wrio-modal-optimization-way .wrio-list-infos li:last-child {
140
- padding-bottom: 5px;
141
- }
142
- .wrio-modal-optimization-way .wrio-list-infos li + li {
143
- border-top: 1px solid #E9EFF2;
144
- }
145
- .wrio-modal-optimization-way .wrio-list-infos a:before {
146
- content: '';
147
- display: block;
148
- }
149
- .wrio-modal-optimization-way .wrio-info-icon {
150
- flex-grow: 0;
151
- flex-basis: 50px;
152
- }
153
- .wrio-modal-optimization-way .wrio-info-icon + span {
154
- padding-left: 20px;
155
- }
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-optimization.js CHANGED
@@ -1,587 +1,633 @@
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.checkPremiumUserBalance();
34
-
35
- },
36
-
37
- registerEvents: function () {
38
- var self = this,
39
- selectedServer = $("#wrio-change-optimization-server option:selected");
40
-
41
- $('#wrio-change-optimization-server').on('change', function () {
42
- $(this).prop('disabled', true);
43
- $('.wrio-premium-user-balance').attr('data-server', $(this).val());
44
- $(".wrio-premium-user-balance-wrap").show();
45
- $(".wrio-premium-user-update-wrap").show();
46
-
47
- if ('server_1' === $(this).val()) {
48
- $(".wrio-premium-user-balance-wrap").hide();
49
- $(".wrio-premium-user-update-wrap").hide();
50
- }
51
- if ('server_5' === $(this).val()) {
52
- if (!self.settings.is_premium) {
53
- $.wrio_modal.showErrorModal(self.i18n.premium_server_disabled);
54
- selectedServer.prop('selected', true);
55
- $(this).prop('disabled', false);
56
-
57
- return;
58
- }
59
- }
60
-
61
- self.checkPremiumUserBalance();
62
-
63
- selectedServer = $(this).find('option:selected');
64
- self.checkServerStatus();
65
- });
66
-
67
- this.startOptButton.on('click', function () {
68
- self.startOptButton = $(this);
69
-
70
- if ($(this).hasClass('wio-running')) {
71
- self.stop();
72
- return;
73
- }
74
-
75
- if (self.serverDown) {
76
- $.wrio_modal.showErrorModal(self.i18n.server_down_warning);
77
- return;
78
- }
79
-
80
- if ("1" === self.settings.need_migration) {
81
- $.wrio_modal.showErrorModal(self.i18n.need_migrations);
82
- return;
83
- }
84
-
85
- if ("0" === self.settings.images_backup) {
86
- $.wrio_modal.showWarningModal(self.i18n.process_without_backup, function () {
87
- self.showModal();
88
- });
89
- return;
90
- }
91
-
92
- self.showModal();
93
-
94
- return false;
95
- });
96
- },
97
-
98
- checkPremiumUserBalance: function () {
99
- var self = this,
100
- userBalance = $('.wrio-premium-user-balance'),
101
- balanceResetAt = $('.wrio-premium-user-update'),
102
- data = {
103
- 'action': 'wbcr-rio-check-user-balance',
104
- '_wpnonce': self.settings.nonce
105
- };
106
-
107
- data['server_name'] = $('#wrio-change-optimization-server').val();
108
-
109
- userBalance.addClass('wrio-premium-user-balance-check-proccess');
110
- userBalance.text('');
111
-
112
- if("server_5" === data['server_name']) {
113
- balanceResetAt.addClass('wrio-premium-user-update-check-proccess');
114
- balanceResetAt.text('');
115
- }
116
-
117
- $.post(ajaxurl, data, function (response) {
118
- console.log(response);
119
- userBalance.removeClass('wrio-premium-user-balance-check-proccess');
120
- if("server_5" === data['server_name']) {
121
- balanceResetAt.removeClass('wrio-premium-user-update-check-proccess');
122
- }
123
-
124
- if (!response || !response.data || !response.success) {
125
- console.log('[Error]: Response error');
126
- response.data && response.data.error && console.log(response.data.error);
127
-
128
- if (!response || !response.data) {
129
- console.log(response);
130
- }
131
-
132
- userBalance.text('error');
133
- if("server_5" === data['server_name']) {
134
- balanceResetAt.text('error');
135
- }
136
- } else {
137
- userBalance.text(response.data.balance);
138
- if("server_5" === data['server_name']) {
139
- balanceResetAt.text(response.data.reset_at);
140
- }
141
- }
142
- }).fail(function (xhr, status, error) {
143
- console.log(xhr);
144
- console.log(status);
145
- console.log(error);
146
-
147
- self.throwError(error);
148
- });
149
- },
150
-
151
- checkServerStatus: function () {
152
- var self = this,
153
- serverStatus = $('.wrio-server-status'),
154
- data = {
155
- 'action': 'wbcr-rio-check-servers-status',
156
- '_wpnonce': self.settings.nonce
157
- };
158
-
159
- self.serverDown = false;
160
-
161
- data['server_name'] = $('#wrio-change-optimization-server').val();
162
-
163
- serverStatus.addClass('wrio-server-check-proccess');
164
- serverStatus.text('');
165
- serverStatus.removeClass('wrio-down').removeClass('wrio-stable');
166
-
167
- self.startOptButton.prop('disabled', true);
168
-
169
- $.post(ajaxurl, data, function (response) {
170
- serverStatus.removeClass('wrio-server-check-proccess');
171
- $('#wrio-change-optimization-server').prop('disabled', false);
172
-
173
- if (!response || !response.data || !response.success) {
174
- console.log('[Error]: Response error');
175
- response.data && response.data.error && console.log(response.data.error);
176
-
177
- if (!response || !response.data) {
178
- console.log(response);
179
- }
180
-
181
- $('option[name="' + data['server_name'] + '"]').prop('disabled', true);
182
- serverStatus.addClass('wrio-down');
183
- serverStatus.text(self.i18n.server_status_down);
184
- self.serverDown = true;
185
-
186
- return;
187
- } else {
188
- serverStatus.addClass('wrio-stable');
189
- serverStatus.text(self.i18n.server_status_stable);
190
- }
191
-
192
- self.startOptButton.prop('disabled', false);
193
-
194
- }).fail(function (xhr, status, error) {
195
- console.log(xhr);
196
- console.log(status);
197
- console.log(error);
198
-
199
- self.throwError(error);
200
- });
201
- },
202
-
203
- showModal: function () {
204
- var self = this;
205
- var infosModal = $('#wrio-tmpl-bulk-optimization');
206
-
207
- if (!infosModal.length) {
208
- console.log('[Error]: Html template for modal not found.');
209
- return;
210
- }
211
-
212
- // Swal Information before loading the optimize process.
213
- swal({
214
- title: this.i18n.modal_optimization_title,
215
- html: infosModal.html(),
216
- type: '',
217
- customClass: 'wrio-modal wrio-modal-optimization-way',
218
- showCancelButton: true,
219
- showCloseButton: true,
220
- padding: 0,
221
- width: 654,
222
- confirmButtonText: this.i18n.modal_optimization_monual_button,
223
- cancelButtonText: this.i18n.modal_optimization_cron_button,
224
- reverseButtons: true,
225
- }).then(function (result) {
226
-
227
- self.process();
228
-
229
- window.onbeforeunload = function () {
230
- return self.i18n.leave_page_warning;
231
- }
232
-
233
- }, function (dismiss) {
234
- if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
235
- self.process('cron');
236
- } else {
237
- throw dismiss;
238
- }
239
- });
240
-
241
- },
242
-
243
- /**
244
- * Start optimization
245
- * @param {string} type
246
- */
247
- process: function (type) {
248
-
249
- this.inprogress = true;
250
-
251
- var sendData = {
252
- 'action': 'wrio-bulk-optimization-process',
253
- 'scope': this.settings.scope,
254
- 'multisite': 0,
255
- '_wpnonce': this.settings.nonce,
256
- };
257
-
258
- this.setButtonStyleRun(type);
259
-
260
- if ('cron' === type) {
261
- this.startOptButton.addClass('wrio-cron-mode');
262
-
263
- sendData['action'] = 'wrio-cron-start';
264
-
265
- $.post(ajaxurl, sendData, function (response) {
266
- if (!response || !response.success) {
267
- console.log('[Error]: Failed ajax request (Start cron).');
268
- console.log(sendData);
269
- console.log(response);
270
-
271
- if (response.data && response.data.error_message) {
272
- self.throwError(response.data.error_message);
273
- }
274
- }
275
- }).fail(function (xhr, status, error) {
276
- console.log(xhr);
277
- console.log(status);
278
- console.log(error);
279
-
280
- self.throwError(error);
281
- });
282
-
283
- return;
284
- }
285
-
286
- this.showMessage(this.i18n.optimization_inprogress.replace("%s", parseInt($('#wio-unoptimized-num').text())));
287
-
288
- // show message: Optimization remined
289
- /*if( "1" === this.settings.is_network_admin ) {
290
- sendData['multisite'] = 1;
291
- }*/
292
-
293
- sendData['reset_current_errors'] = 1;
294
-
295
- this.sendRequest(sendData);
296
- },
297
-
298
- stop: function () {
299
- var self = this;
300
-
301
- this.inprogress = false;
302
-
303
- window.onbeforeunload = null;
304
- self.setButtonStyleStop();
305
- self.destroyMessages();
306
-
307
- if (this.startOptButton.hasClass('wrio-cron-mode')) {
308
- this.startOptButton.removeClass('wrio-cron-mode');
309
-
310
- $.post(ajaxurl, {
311
- 'action': 'wrio-cron-stop',
312
- '_wpnonce': self.settings.nonce,
313
- 'type': self.settings.scope
314
- }, function (response) {
315
- if (!response || !response.success) {
316
- console.log('[Error]: Failed ajax request (Stop cron).');
317
- console.log(response);
318
-
319
- if (response.data && response.data.error_message) {
320
- self.throwError(response.data.error_message);
321
- }
322
- }
323
- }).fail(function (xhr, status, error) {
324
- console.log(xhr);
325
- console.log(status);
326
- console.log(error);
327
-
328
- self.throwError(error);
329
- });
330
- }
331
-
332
- },
333
-
334
- complete: function () {
335
- this.inprogress = false;
336
- window.onbeforeunload = null;
337
- this.setButtonStyleComplete();
338
- },
339
-
340
- setButtonStyleRun: function (mode) {
341
-
342
- this.startOptButton.addClass('wio-running');
343
-
344
- if ("cron" === mode) {
345
- this.startOptButton.text(this.i18n.button_stop_cron);
346
- return;
347
- }
348
-
349
- this.startOptButton.text(this.i18n.button_stop);
350
- },
351
-
352
- setButtonStyleComplete: function () {
353
- this.showMessage(this.i18n.optimization_complete);
354
- this.startOptButton.text(this.i18n.button_completed);
355
- this.startOptButton.removeClass('wio-running');
356
- this.startOptButton.prop('disabled', true);
357
- },
358
-
359
- setButtonStyleStop: function () {
360
- this.startOptButton.removeClass('wio-running');
361
- this.startOptButton.text(this.i18n.buttom_start);
362
- },
363
-
364
- showMessage: function (text) {
365
- var contanier = $('.wio-page-statistic'),
366
- message;
367
-
368
- if (contanier.find('.wrio-statistic-message').length) {
369
- message = contanier.find('.wrio-statistic-message');
370
- } else {
371
- message = $('<div>');
372
- message.addClass('wrio-statistic-message');
373
- contanier.append(message);
374
- }
375
-
376
- message.html(text);
377
- },
378
-
379
- throwError: function (error_message) {
380
- this.stop();
381
-
382
- var noticeId = $.wbcr_factory_clearfy_230.app.showNotice(error_message, 'danger');
383
-
384
- setTimeout(function () {
385
- $.wbcr_factory_clearfy_230.app.hideNotice(noticeId);
386
- }, 10000);
387
- },
388
-
389
- destroyMessages: function () {
390
- $('.wio-page-statistic').find('.wrio-statistic-message').remove();
391
- },
392
-
393
- sendRequest: function (data) {
394
- var self = this;
395
-
396
- if (!this.inprogress) {
397
- return;
398
- }
399
-
400
- $.post(ajaxurl, data, function (response) {
401
- if (!self.inprogress) {
402
- return;
403
- }
404
-
405
- if (!response || !response.success) {
406
- console.log('[Error]: Failed ajax request (Try to optimize images).');
407
- console.log(response);
408
-
409
- if (response.data && response.data.error_message) {
410
- self.throwError(response.data.error_message);
411
- }
412
-
413
- return;
414
- }
415
-
416
- data.reset_current_errors = 0;
417
-
418
- if (!response.data.end) {
419
- $('#wio-total-unoptimized').text(parseInt(response.data.remain));
420
- self.showMessage(self.i18n.optimization_inprogress.replace("%s", parseInt(response.data.remain)));
421
- self.sendRequest(data);
422
- } else {
423
- $('#wio-total-unoptimized').text(response.data.remain);
424
- self.complete();
425
-
426
- // если мультисайт режим, то не скрываем кнопку запуска оптимизации
427
- /*if( $('#wbcr-rio-current-blog').length ) {
428
- $('#wio-start-optimization').toggleClass('wio-running');
429
- } else {
430
- $('#wio-start-optimization').hide();
431
- }*/
432
- }
433
-
434
- redraw_statistics(response.data.statistic);
435
-
436
- self.updateLog(response.data.last_optimized);
437
- }).fail(function (xhr, status, error) {
438
- console.log(xhr);
439
- console.log(status);
440
- console.log(error);
441
-
442
- self.throwError(error);
443
- });
444
- },
445
-
446
- updateLog: function (new_item_data) {
447
- var self = this;
448
-
449
- var limit = 100,
450
- tableEl = $('.wrio-optimization-progress .wrio-table');
451
-
452
- if (!tableEl.length || !new_item_data) {
453
- return;
454
- }
455
-
456
- // если таблица была пустая
457
- if ($('.wrio-table-container-empty').length) {
458
- $('.wrio-table-container-empty').addClass('wrio-table-container').removeClass('wrio-table-container-empty');
459
- if (tableEl.find('tbody').length) {
460
- tableEl.find('tbody').empty();
461
- }
462
- }
463
-
464
- $.each(new_item_data, function (index, value) {
465
- var trEl = $('<tr>'),
466
- tdEl = $('<td>'),
467
- webpSize = value.webp_size ? value.webp_size : '-';
468
-
469
- if (tableEl.find('.wrio-row-id-' + value.id).length) {
470
- tableEl.find('.wrio-row-id-' + value.id).remove();
471
- }
472
-
473
- trEl.addClass('flash').addClass('wrio-table-item').addClass('wrio-row-id-' + value.id);
474
-
475
- if ('error' === value.type) {
476
- trEl.addClass('wrio-error');
477
- }
478
-
479
- var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
480
- previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
481
-
482
- tableEl.prepend(trEl);
483
-
484
- trEl.append(tdEl.clone().append(preview));
485
- trEl.append(tdEl.clone().append(previewUrl));
486
-
487
- if ('error' === value.type) {
488
- var colspan = value.scope !== 'custom-folders' ? '6' : '5';
489
- trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
490
- } else {
491
- trEl.append(tdEl.clone().text(value.original_size));
492
- trEl.append(tdEl.clone().text(value.optimized_size));
493
- trEl.append(tdEl.clone().text(webpSize));
494
- trEl.append(tdEl.clone().text(value.original_saving));
495
-
496
- if ("custom-folders" !== self.settings.scope) {
497
- trEl.append(tdEl.clone().text(value.thumbnails_count));
498
- }
499
-
500
- trEl.append(tdEl.clone().text(value.total_saving));
501
- }
502
- });
503
-
504
- if (tableEl.find('tr').length > limit) {
505
- var diff = tableEl.find('tr').length - limit;
506
-
507
- for (var i = 0; i < diff; i++) {
508
- tableEl.find('tr:last').remove();
509
- }
510
- }
511
- }
512
-
513
- };
514
-
515
- $(document).ready(function () {
516
- bulkOptimization.init();
517
- $('[data-toggle="tooltip"]').tooltip();
518
- });
519
-
520
- var ajaxUrl = ajaxurl;
521
- var ai_data;
522
-
523
- function redraw_statistics(statistic) {
524
- $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized)
525
- .attr('data-optimized', statistic.optimized)
526
- .attr('data-errors', statistic.error);
527
- $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
528
- $('#wio-original-size').text(bytesToSize(statistic.original_size));
529
- $('#wio-optimized-size').text(bytesToSize(statistic.optimized_size));
530
- $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
531
- $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
532
- $('.wio-total-percent').text(statistic.optimized_percent + '%');
533
- $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
534
-
535
- $('#wio-unoptimized-num').text(statistic.unoptimized);
536
- $('#wio-optimized-num').text(statistic.optimized);
537
- $('#wio-error-num').text(statistic.error);
538
-
539
- var credits = $('.wrio-premium-user-balance');
540
- if(credits.attr('data-server') !== "server_5") {
541
- credits.text(statistic.credits);
542
- }
543
-
544
- if ($('.wrio-statistic-nav li.active').length) {
545
- $('.wrio-statistic-nav li.active').find('span.wio-statistic-tab-percent').text(statistic.optimized_percent + '%');
546
- }
547
-
548
- window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
549
- window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
550
- window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
551
- window.wio_chart.update();
552
- if ($('#wio-overview-chart-percent').text() == '100%') {
553
- window.onbeforeunload = null;
554
- }
555
- }
556
-
557
- function bytesToSize(bytes) {
558
- var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
559
- if (bytes == 0) {
560
- return '0 Byte';
561
- }
562
- var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
563
- if (i == 0) {
564
- return bytes + ' ' + sizes[i];
565
- }
566
- return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
567
- }
568
-
569
- /*$('#wbcr-rio-current-blog').on('change', function() {
570
- var self = $(this);
571
- $('#wio-start-msg-complete').hide();
572
- $(this).attr('disabled', true);
573
- $('#wio-start-optimization').attr('disabled', true);
574
- var ai_data = {
575
- 'action': 'wbcr_rio_update_current_blog',
576
- 'wpnonce': $(this).data('nonce'),
577
- 'current_blog_id': $(this).find('option:selected').val(),
578
- 'context': $(this).attr('data-context')
579
- };
580
- $.post(ajaxUrl, ai_data, function(response) {
581
- self.removeAttr('disabled');
582
- $('#wio-start-optimization').removeAttr('disabled');
583
- redraw_statistics(response.data.statistic);
584
- });
585
- });*/
586
-
587
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ });
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 +1,2 @@
1
- jQuery('button[data-value="googlepage"]').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,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
- };
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
+ };
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
+ });
admin/assets/js/statistic.js CHANGED
@@ -1,38 +1,38 @@
1
- jQuery(function($) {
2
-
3
- var chat_html_id = 'wio-main-chart';
4
- var ctx = document.getElementById(chat_html_id);
5
-
6
- window.wio_chart = new 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 chat_html_id = 'wio-main-chart';
4
+ var ctx = document.getElementById(chat_html_id);
5
+
6
+ window.wio_chart = new window.robin.Chart(ctx, {
7
+ type: 'doughnut',
8
+ data: {
9
+ datasets: [
10
+ {
11
+ data: [
12
+ $('#' + chat_html_id).attr('data-unoptimized'),
13
+ $('#' + chat_html_id).attr('data-optimized'),
14
+ $('#' + chat_html_id).attr('data-errors'),
15
+ ],
16
+ backgroundColor: [
17
+ '#d6d6d6',
18
+ '#8bc34a',
19
+ '#f1b1b6',
20
+ ],
21
+ borderWidth: 0,
22
+ label: 'Dataset 1'
23
+ }
24
+ ]
25
+ },
26
+ options: {
27
+ legend: {
28
+ display: false
29
+ },
30
+ events: [],
31
+ animation: {
32
+ easing: 'easeOutBounce'
33
+ },
34
+ responsive: false,
35
+ cutoutPercentage: 80
36
+ }
37
+ });
38
+ });
admin/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-230-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_Factory439_Plugin $plugin
127
- * @param Wbcr_FactoryPages438_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_FactoryPages438_ImpressiveThemplate $obj
150
- *
151
- * @return bool
152
- */
153
- /*add_action('wbcr_factory_439_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_438_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_Factory439_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_Factory439_Plugin $plugin Экземпляр плагина, который передается в функцию обратного вызова
325
- * @param Wbcr_FactoryPages438_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-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 );
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,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 Wbcr_FactoryClearfy230_PageBase $page
30
- *
31
- * @throws Exception
32
- */
33
-
34
- /*public function showPageContent( Wbcr_FactoryClearfy230_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 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
+ }
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_FactoryClearfy230_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_Factory439_Plugin $plugin
47
- */
48
- public function __construct( Wbcr_Factory439_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_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
  }
admin/pages/class-rio-log.php CHANGED
@@ -1,166 +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 WRIO_Page {
16
-
17
- /**
18
- * {@inheritdoc}
19
- */
20
- public $id = 'rio_logs'; // Уникальный идентификатор страницы
21
-
22
- /**
23
- * {@inheritdoc}
24
- */
25
- public $page_menu_dashicon = 'dashicons-admin-tools';
26
-
27
- /**
28
- * {@inheritdoc}
29
- */
30
- public $type = 'page';
31
-
32
- /**
33
- * @param WRIO_Plugin $plugin
34
- */
35
- public function __construct( WRIO_Plugin $plugin ) {
36
-
37
- $this->menu_title = __( 'Error Log', 'robin-image-optimizer' );
38
- $this->page_menu_short_description = __( 'Plugin debug report', 'robin-image-optimizer' );
39
-
40
- parent::__construct( $plugin );
41
- }
42
-
43
- /**
44
- * {@inheritdoc}
45
- *
46
- * @since 1.0.0
47
- * @return void
48
- */
49
- public function assets( $scripts, $styles ) {
50
- parent::assets( $scripts, $styles );
51
-
52
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
53
-
54
- // Add Clearfy styles for HMWP pages
55
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
56
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
57
- }
58
- }
59
-
60
- /**
61
- * {@inheritdoc}
62
- */
63
- public function getMenuTitle() {
64
- return defined( 'LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON' ) ? __( 'Image optimizer', 'robin-image-optimizer' ) : __( 'Error Log', 'robin-image-optimizer' );
65
- }
66
-
67
- /**
68
- * {@inheritdoc}
69
- */
70
- public function showPageContent() {
71
- ?>
72
- <div class="wbcr-factory-page-group-header" style="margin-top:0;">
73
- <strong><?php _e( 'Error Log', 'robin-image-optimizer' ) ?></strong>
74
- <p>
75
- <?php _e( 'In this section, you can track image optimization errors. Sending this log to us, will help in solving possible optimization issues.', 'robin-image-optimizer' ) ?>
76
- </p>
77
- </div>
78
- <div class="wbcr-factory-page-group-body" style="padding:20px">
79
- <div class="btn-group">
80
- <a href="<?php echo wp_nonce_url( $this->getPageUrl() . 'action=export' ) ?>"
81
- class="btn btn-default"><?php _e( 'Export Debug Information', 'robin-image-optimizer' ) ?></a>
82
- <a href="#"
83
- onclick="wrioLogCleanup(this);return false;"
84
- data-working="<?php echo esc_attr__( 'Working...', 'robin-image-optimizer' ) ?>"
85
- class="btn btn-default"><?php echo sprintf( __( 'Clean-up Logs (<span id="wbcr-log-size">%s</span>)', 'robin-image-optimizer' ), $this->get_log_size_formatted() ) ?></a>
86
- </div>
87
- <script>
88
- function wrioLogCleanup(element) {
89
-
90
- var btn = jQuery(element),
91
- currentBtnText = btn.html();
92
-
93
- console.log(btn.data('working'), btn);
94
-
95
- btn.text(btn.data('working'));
96
-
97
- jQuery.ajax({
98
- url: ajaxurl,
99
- method: 'post',
100
- data: {
101
- action: 'wrio_logs_cleanup',
102
- nonce: '<?php echo wp_create_nonce( 'wrio_clean_logs' ) ?>'
103
- },
104
- success: function(data) {
105
- btn.html(currentBtnText);
106
-
107
- jQuery('#wbcr-log-viewer').html('');
108
- jQuery('#wbcr-log-size').text('0B');
109
- jQuery.wbcr_factory_clearfy_230.app.showNotice(data.message, data.type);
110
- },
111
- error: function(jqXHR, textStatus, errorThrown) {
112
- jQuery.wbcr_factory_clearfy_230.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
113
- btn.html(currentBtnText);
114
- }
115
- });
116
- }
117
- </script>
118
- <style>
119
- .wbcr-log-viewer {
120
- width: 100%;
121
- height: 650px;
122
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
123
- font-size: 12px;
124
- word-break: break-all;
125
- word-wrap: break-word;
126
- overflow: auto;
127
- -ms-overflow-style: scrollbar;
128
- background-color: #e9e9e9;
129
- padding: 8px;
130
- border: 1px solid #cfcfcf;
131
- }
132
- </style>
133
- <div class="wbcr-log-viewer" id="wbcr-log-viewer">
134
- <?php echo WIO_Log_Reader::prettify() ?>
135
- </div>
136
- </div>
137
- <?php
138
- }
139
-
140
- /**
141
- * Processing log export action in form of ZIP archive.
142
- */
143
- public function exportAction() {
144
- $export = new WIO_Log_Export();
145
-
146
- if ( $export->prepare() ) {
147
- $export->download( true );
148
- }
149
- }
150
-
151
- /**
152
- * Get log size formatted.
153
- *
154
- * @return false|string
155
- */
156
- private function get_log_size_formatted() {
157
-
158
- try {
159
- return size_format( WRIO_Logger::get_total_size() );
160
- } catch( \Exception $exception ) {
161
- WRIO_Logger::error( sprintf( 'Failed to get total log size as exception was thrown: %s', $exception->getMessage() ) );
162
- }
163
-
164
- return '';
165
- }
166
- }
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
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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_FactoryClearfy230_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_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
+ }
admin/pages/class-rio-settings.php CHANGED
@@ -1,550 +1,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
- * @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
- parent::__construct( $plugin );
52
- }
53
-
54
- /**
55
- * Подключаем скрипты и стили для страницы
56
- *
57
- * @return void
58
- * @since 1.0.0
59
- * @see Wbcr_FactoryPages438_AdminPage
60
- *
61
- */
62
- public function assets( $scripts, $styles ) {
63
- parent::assets( $scripts, $styles );
64
-
65
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
66
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
67
-
68
- if( ! wrio_is_license_activate() ) {
69
- $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/settings-premium.css' );
70
- $this->scripts->add( WRIO_PLUGIN_URL . '/admin/assets/js/settings-premium.js');
71
- }
72
-
73
- // Add Clearfy styles for HMWP pages
74
- if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
75
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
76
- }
77
- }
78
-
79
-
80
- /**
81
- * Выводим предупреждения
82
- *
83
- */
84
- protected function warningNotice() {
85
- $upload_dir = wp_upload_dir();
86
-
87
- if ( ! wp_is_writable( $upload_dir['basedir'] ) ) {
88
- $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
89
- }
90
-
91
- $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
92
- if ( file_exists( $wio_backup ) && ! wp_is_writable( $wio_backup ) ) {
93
- $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
94
- }
95
-
96
- if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true ) {
97
- $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
98
- }
99
- }
100
-
101
-
102
- /**
103
- * Метод должен передать массив опций для создания формы с полями.
104
- * Созданием страницы и формы занимается фреймворк
105
- *
106
- * @return mixed[]
107
- * @since 1.0.0
108
- */
109
- public function getPageOptions() {
110
- $options = [];
111
-
112
- $options[] = [
113
- 'type' => 'html',
114
- '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>'
115
- ];
116
-
117
- $options[] = [
118
- 'type' => 'dropdown',
119
- 'name' => 'image_optimization_server',
120
- 'title' => __( 'Optimization server', 'robin-image-optimizer' ),
121
- 'data' => [
122
- [
123
- 'server_1',
124
- __( 'Server 1 - image size limit up to 5 MB', 'robin-image-optimizer' ),
125
-
126
- ],
127
- [
128
- 'server_2',
129
- __( 'Server 2 - beta', 'robin-image-optimizer' )
130
-
131
- ],
132
- [
133
- 'server_5',
134
- __( 'Premium - no limits', 'robin-image-optimizer' )
135
- ],
136
- ],
137
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
138
- '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' ),
139
- 'default' => 'server_1',
140
- ];
141
-
142
- // Радио переключатель
143
- $options[] = [
144
- 'type' => 'dropdown',
145
- 'name' => 'image_optimization_level',
146
- 'way' => 'buttons',
147
- 'title' => __( 'Compression mode', 'robin-image-optimizer' ),
148
- 'data' => [
149
- [
150
- 'normal',
151
- __( 'Lossless', 'robin-image-optimizer' ),
152
- __( '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' )
153
- ],
154
- [
155
- 'aggresive',
156
- __( 'Lossy', 'robin-image-optimizer' ),
157
- __( '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' )
158
- ],
159
- [
160
- 'ultra',
161
- __( 'High', 'robin-image-optimizer' ),
162
- __( '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' )
163
- ],
164
- [
165
- 'googlepage',
166
- __('G PageSpeed', 'robin-image-optimizer'),
167
- __('This mode uses the optimal settings for Google Page Speed', 'robin-image-optimizer'),
168
- ],
169
- [
170
- 'custom',
171
- __( 'Custom', 'robin-image-optimizer' ),
172
- __( 'This mode allows you to configure your own compression ratio.', 'robin-image-optimizer' )
173
- ]
174
- ],
175
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
176
- 'hint' => __( 'Select the compression mode appropriate for your case.', 'robin-image-optimizer' ),
177
- 'default' => 'normal',
178
- 'events' => [
179
- 'normal' => [
180
- 'hide' => '.factory-control-image_optimization_level_custom'
181
- ],
182
- 'aggresive' => [
183
- 'hide' => '.factory-control-image_optimization_level_custom'
184
- ],
185
- 'ultra' => [
186
- 'hide' => '.factory-control-image_optimization_level_custom'
187
- ],
188
- 'custom' => [
189
- 'show' => '.factory-control-image_optimization_level_custom',
190
- ],
191
- ]
192
- ];
193
-
194
- // Текстовое поле
195
- $options[] = [
196
- 'type' => 'textbox',
197
- 'name' => 'image_optimization_level_custom',
198
- 'title' => __( 'Enter custom quality', 'robin-image-optimizer' ),
199
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
200
- 'hint' => __( 'custom quality 1-100', 'robin-image-optimizer' ),
201
- 'default' => '70'
202
- ];
203
-
204
- // Переключатель
205
- $options[] = [
206
- 'type' => 'checkbox',
207
- 'way' => 'buttons',
208
- 'name' => 'auto_optimize_when_upload',
209
- 'title' => __( 'Auto optimization on upload', 'robin-image-optimizer' ),
210
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
211
- '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' ),
212
- 'default' => false
213
- ];
214
-
215
- // Переключатель
216
- $options[] = [
217
- 'type' => 'checkbox',
218
- 'way' => 'buttons',
219
- 'name' => 'backup_origin_images',
220
- 'title' => __( 'Backup images', 'robin-image-optimizer' ),
221
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'green' ],
222
- 'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
223
- 'default' => true
224
- ];
225
-
226
- // Переключатель
227
- $options[] = [
228
- 'type' => 'checkbox',
229
- 'way' => 'buttons',
230
- 'name' => 'error_log',
231
- 'title' => __( 'Error Log', 'robin-image-optimizer' ),
232
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
233
- 'hint' => __( 'Enable error logging. The log will be displayed on a separate tab.', 'robin-image-optimizer' ),
234
- 'default' => false,
235
- 'eventsOn' => [
236
- 'show' => '#wrio-error-log-options'
237
- ],
238
- 'eventsOff' => [
239
- 'hide' => '#wrio-error-log-options'
240
- ]
241
- ];
242
-
243
- $options[] = [
244
- 'type' => 'html',
245
- 'html' => [ $this, 'error_log_options' ]
246
- ];
247
-
248
- $options[] = [
249
- 'type' => 'checkbox',
250
- 'way' => 'buttons',
251
- 'name' => 'convert_webp_format',
252
- 'title' => __( 'Convert Images to WebP', 'robin-image-optimizer' ),
253
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
254
- 'hint' => __( 'Convert JPEG & PNG images into WebP format and replace them for browsers which support it. Unsupported browsers would be skipped.', 'robin-image-optimizer' ),
255
- 'default' => false,
256
- 'cssClass' => ! wrio_is_license_activate() ? [ 'factory-checkbox-disabled wrio-checkbox-premium-label' ] : [],
257
- 'eventsOn' => [
258
- 'show' => '#wrio-webp-options'
259
- ],
260
- 'eventsOff' => [
261
- 'hide' => '#wrio-webp-options'
262
- ]
263
- ];
264
-
265
- $options[] = [
266
- 'type' => 'html',
267
- 'html' => [ $this, 'conver_webp_options' ]
268
- ];
269
-
270
- // восстановление
271
- $options[] = [
272
- 'type' => 'html',
273
- 'html' => [ $this, 'rollbackButton' ],
274
- ];
275
-
276
- // Переключатель
277
- $options[] = [
278
- 'type' => 'checkbox',
279
- 'way' => 'buttons',
280
- 'name' => 'save_exif_data',
281
- 'title' => __( 'Leave EXIF data', 'robin-image-optimizer' ),
282
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
283
- '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' ),
284
- 'default' => true
285
- ];
286
-
287
- $options[] = [
288
- 'type' => 'checkbox',
289
- 'way' => 'buttons',
290
- 'name' => 'use_lazy_load',
291
- 'title' => __( 'Use lazy loading for images', 'robin-image-optimizer' ),
292
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
293
- 'hint' => __( 'Images will only load when the user has scrolled to them.', 'robin-image-optimizer' ),
294
- 'default' => false
295
- ];
296
-
297
- $options[] = [
298
- 'type' => 'html',
299
- '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>'
300
- ];
301
-
302
- $options[] = [
303
- 'type' => 'dropdown',
304
- 'name' => 'image_optimization_order',
305
- 'way' => 'buttons',
306
- 'title' => __( 'Optimization order', 'robin-image-optimizer' ),
307
- 'data' => [
308
- [
309
- 'asc',
310
- __( 'Ascending', 'robin-image-optimizer' ),
311
- __( 'Optimization will start with old images in the media library', 'robin-image-optimizer' )
312
- ],
313
- [
314
- 'desc',
315
- __( 'Descending', 'robin-image-optimizer' ),
316
- __( 'Optimization will start with new images in the media library', 'robin-image-optimizer' )
317
- ],
318
- ],
319
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
320
- 'hint' => __( "Select the optimization order from the media library.", 'robin-image-optimizer' ),
321
- 'default' => 'asc',
322
- ];
323
-
324
- // Переключатель
325
- $options[] = [
326
- 'type' => 'checkbox',
327
- 'way' => 'buttons',
328
- 'name' => 'resize_larger',
329
- 'title' => __( 'Resizing large images', 'robin-image-optimizer' ),
330
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
331
- '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' ),
332
- 'default' => false,
333
- // когда чекбокс включен показываем поле с классом .factory-control-resize_larger_w
334
- 'eventsOn' => [
335
- 'show' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
336
- ],
337
- // когда чекбокс выключен, скрываем поле с классом .factory-control-resize_larger_w
338
- 'eventsOff' => [
339
- 'hide' => '.factory-control-resize_larger_w,.factory-control-resize_larger_h'
340
- ]
341
- ];
342
-
343
- // Текстовое поле
344
- $options[] = [
345
- 'type' => 'textbox',
346
- 'name' => 'resize_larger_w',
347
- 'title' => __( 'Enter the maximum width (px)', 'robin-image-optimizer' ),
348
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
349
- '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' ),
350
- 'default' => '1600'
351
- ];
352
-
353
- // Текстовое поле
354
- $options[] = [
355
- 'type' => 'textbox',
356
- 'name' => 'resize_larger_h',
357
- 'title' => __( 'Enter the maximum height (px)', 'robin-image-optimizer' ),
358
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
359
- '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' ),
360
- 'default' => '1600'
361
- ];
362
-
363
- $options[] = [
364
- 'type' => 'list',
365
- 'way' => 'checklist',
366
- 'name' => 'allowed_formats',
367
- 'title' => __( 'Optimize formats', 'robin-image-optimizer' ),
368
- 'data' => [
369
- [ 'image/jpeg', 'JPG' ],
370
- [ 'image/png', 'PNG' ],
371
- [ 'image/gif', 'GIF' ],
372
- ],
373
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
374
- 'hint' => __( 'Choose which formats of images should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
375
- 'default' => 'image/jpeg,image/png,image/gif'
376
- ];
377
-
378
- // получаем зарегистрированные размеры изображений
379
- $wp_image_sizes = wrio_get_image_sizes();
380
- $wio_image_sizes = [];
381
- foreach ( $wp_image_sizes as $key => $value ) {
382
- $wio_image_sizes[] = [
383
- $key,
384
- $key . ' - ' . $value['width'] . 'x' . $value['height'],
385
- ];
386
- }
387
-
388
- $options[] = [
389
- 'type' => 'list',
390
- 'way' => 'checklist',
391
- 'name' => 'allowed_sizes_thumbnail',
392
- 'title' => __( 'Optimize thumbnails', 'robin-image-optimizer' ),
393
- 'data' => $wio_image_sizes,
394
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
395
- 'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
396
- 'default' => 'thumbnail,medium'
397
- ];
398
-
399
- $options = apply_filters( 'wbcr/rio/settings_page/options', $options );
400
-
401
- $formOptions = [];
402
-
403
- $formOptions[] = [
404
- 'type' => 'form-group',
405
- 'items' => $options,
406
- //'cssClass' => 'postbox'
407
- ];
408
-
409
- return $formOptions;
410
- }
411
-
412
- /**
413
- * Save advanced options in database
414
- *
415
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
416
- * @since 1.3.6
417
- */
418
- public function beforeFormSave() {
419
-
420
- /**
421
- * Used to save webp options. It can also be used to intercept
422
- * other unregistered fields.
423
- *
424
- * @since 1.3.6
425
- */
426
- do_action( "wrio/settings_page/berfore_form_save" );
427
-
428
- $error_log = (int) WRIO_Plugin::app()->request->post( WRIO_Plugin::app()->getPrefix() . 'error_log', 0 );
429
-
430
- if ( ! $error_log ) {
431
- return;
432
- }
433
-
434
- $keep_error_log_on_frontend = (int) WRIO_Plugin::app()->request->post( 'wrio_keep_error_log_on_frontend', 0 );
435
-
436
- WRIO_Plugin::app()->updatePopulateOption( 'keep_error_log_on_frontend', $keep_error_log_on_frontend );
437
- }
438
-
439
- /**
440
- * This method adds advanced options for the "Convert Images to WebP" checkbox.
441
- *
442
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
443
- * @since 1.3.6
444
- */
445
- public function conver_webp_options() {
446
-
447
- /**
448
- * This hook prints options for delivering webp images.
449
- *
450
- * @since 1.3.6
451
- */
452
- do_action( "wrio/settings_page/conver_webp_options" );
453
- }
454
-
455
- /**
456
- * This method adds advanced options for the "Error log" checkbox.
457
- *
458
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
459
- * @since 1.3.6
460
- */
461
- public function error_log_options() {
462
- $this->view->print_template( 'part-settings-page-error-log-options', [
463
- 'keep_error_log_on_frontend' => (int) WRIO_Plugin::app()->getPopulateOption( 'keep_error_log_on_frontend', 0 )
464
- ] );
465
- }
466
-
467
- /**
468
- * Кнопка восстановления изображений
469
- */
470
- public function rollbackButton() {
471
- ?>
472
- <div class="form-group form-group-checkbox factory-control-rollback-button">
473
- <label for="wio-clear-backup-btn" class="col-sm-4 control-label">
474
- <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
475
- <span class="factory-hint-icon factory-hint-icon-red" data-toggle="factory-tooltip"
476
- data-placement="right" title=""
477
- data-original-title="<?php _e( 'You can restore the original images from a backup or clear them.', 'robin-image-optimizer' ); ?>">
478
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
479
- alt="">
480
- </span>
481
- </label>
482
- <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
483
- <div class="control-group col-sm-8">
484
- <div class="factory-buttons-way btn-group">
485
- <a class="btn btn-default" id="wio-restore-backup-btn"
486
- data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>"
487
- href="#"><?php _e( 'Restore', 'robin-image-optimizer' ); ?></a>
488
- <a class="btn btn-default" id="wio-clear-backup-btn"
489
- data-confirm="<?php _e( 'Are you sure that you want to clear image backups folder?', 'robin-image-optimizer' ); ?>"
490
- href="#"><?php _e( 'Clear Backup', 'robin-image-optimizer' ); ?></a>
491
- </div>
492
- <?php //if ( WRIO_Plugin::app()->isNetworkAdmin() ) : ?>
493
- <!-- <div id="wio-multisite-mode" style="display:none;">-->
494
- <!-- <ul class="factory-list factory-from-control-list factory-checklist-way">-->
495
- <!-- --><?php
496
- // $blogs = WIO_Multisite::getBlogs();
497
- // ?>
498
- <!-- <li>-->
499
- <!-- <label for="wbcr_io_multisite_blog_all">-->
500
- <!-- <span>-->
501
- <!-- <input value="all" id="wbcr_io_multisite_blog_all" type="checkbox">-->
502
- <!-- </span>-->
503
- <!-- <span>-->
504
- <?php //echo __( 'Select all', 'robin-image-optimizer' ); ?><!--</span>-->
505
- <!-- </label>-->
506
- <!-- </li>-->
507
- <!-- --><?php //foreach ( $blogs as $blog ) : ?>
508
- <!-- <li>-->
509
- <!-- <label for="wbcr_io_multisite_blog_-->
510
- <?php //echo esc_attr( $blog->blog_id ); ?><!--">-->
511
- <!-- --><?php
512
- // $blog_name = $blog->domain . $blog->path;
513
- // if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
514
- // $blog_name = $blog->domain;
515
- // }
516
- // ?>
517
- <!-- <span>-->
518
- <!-- <input data-name="--><?php //echo esc_attr( $blog_name ); ?><!--"-->
519
- <!-- class="wbcr_io_multisite_blogs"-->
520
- <!-- value="--><?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
521
- <!-- id="wbcr_io_multisite_blog_-->
522
- <?php //echo esc_attr( $blog->blog_id ); ?><!--"-->
523
- <!-- type="checkbox">-->
524
- <!-- </span>-->
525
- <!-- <span>--><?php //echo esc_attr( $blog_name ); ?><!--</span>-->
526
- <!-- </label>-->
527
- <!-- </li>-->
528
- <!-- --><?php //endforeach; ?>
529
- <!-- </ul>-->
530
- <!-- <button id="wio-multisite-confirm" class="btn btn-default" type="button"-->
531
- <!-- data-action="">-->
532
- <?php //echo __( 'Start', 'robin-image-optimizer' ); ?><!--</button>-->
533
- <!-- </div>-->
534
- <!-- <div id="wio-multisite-restore-progress" style="display:none;">-->
535
- <!-- </div>-->
536
- <?php //endif; ?>
537
- <div class="progress" id="wio-restore-backup-progress" style="display:none;">
538
- <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0"
539
- aria-valuemin="0" aria-valuemax="100" style="width:0%">
540
- </div>
541
- </div>
542
- <p id="wio-restore-backup-msg"
543
- style="display:none;"><?php _e( 'Restore completed.', 'robin-image-optimizer' ); ?></p>
544
- <p id="wio-clear-backup-msg"
545
- style="display:none;"><?php _e( 'The backup folder was cleared.', 'robin-image-optimizer' ); ?></p>
546
- </div>
547
- </div>
548
- <?php
549
- }
550
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
admin/pages/class-rio-statistic.php CHANGED
@@ -1,267 +1,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
-
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
- // Statistic
210
- $this->view->print_template( 'part-bulk-optimization-statistic', array_merge( $template_data, [
211
- 'stats' => $statistics->get()
212
- ] ), $this );
213
-
214
- // Optimization log
215
- $this->view->print_template( 'part-bulk-optimization-log', array_merge( $template_data, [
216
- 'process_log' => $statistics->get_last_optimized_images()
217
- ] ), $this );
218
- ?>
219
- </div>
220
- <script type="text/html" id="wrio-tmpl-bulk-optimization">
221
- <?php $this->view->print_template( 'modal-bulk-optimization' ); ?>
222
- </script>
223
- <?php
224
- //do_action( 'wbcr/rio/multisite_restore_blog' );
225
- }
226
-
227
- /**
228
- * @return object|\WRIO_Image_Statistic
229
- * @since 1.3.0
230
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
231
- */
232
- protected function get_statisctic_data() {
233
- return WRIO_Image_Statistic::get_instance();
234
- }
235
-
236
- /**
237
- * @return array
238
- * @since 1.3.0
239
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
240
- */
241
- protected function get_i18n() {
242
- return [
243
- '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' ),
244
- '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' ),
245
- 'server_status_down' => __( 'down', 'robin-image-optimizer' ),
246
- 'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
247
- 'modal_error' => __( 'Error', 'robin-image-optimizer' ),
248
- 'modal_cancel' => __( 'Cancel', 'robin-image-optimizer' ),
249
- 'modal_confirm' => __( 'Confirm', 'robin-image-optimizer' ),
250
- 'modal_optimization_title' => __( 'Select optimization way', 'robin-image-optimizer' ),
251
- 'modal_optimization_monual_button' => __( 'Optimize now', 'robin-image-optimizer' ),
252
- 'modal_optimization_cron_button' => __( 'Scheduled optimization', 'robin-image-optimizer' ),
253
- 'need_migrations' => __( 'To start optimizing, you must complete migration from old plugin version.', 'robin-image-optimizer' ),
254
- 'optimization_complete' => __( 'All images from the media library are optimized.', 'robin-image-optimizer' ),
255
- 'optimization_inprogress' => __( 'Optimization in progress. Remained <span id="wio-total-unoptimized">%s</span> images.', 'robin-image-optimizer' ),
256
- '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' ),
257
- 'process_without_backup' => __( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ),
258
- 'button_resume' => __( 'Resume', 'robin-image-optimizer' ),
259
- 'button_completed' => __( 'Completed', 'robin-image-optimizer' ),
260
- 'buttom_start' => __( 'Run', 'robin-image-optimizer' ),
261
- 'button_stop' => __( 'Stop', 'robin-image-optimizer' ),
262
- 'button_stop_cron' => __( 'Stop shedule optimization', 'robin-image-optimizer' )
263
- //Don't Need a Parachute?
264
- //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.
265
- ];
266
- }
267
- }
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
admin/pages/index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
- // silence is golden
1
+ <?php
2
+ // silence is golden
assets/js/lazy-load.js CHANGED
@@ -1,8 +1,11 @@
1
- jQuery( function () {
2
- if('loading' in HTMLImageElement.prototype && wbcr_robin.wpCompatibleLazy === 'yes'){
3
- //loading="lazy" in WP >= 5.5
4
- } else {
5
- var $tags = jQuery("img");
6
- $tags.Lazy();
7
- }
8
- });
 
 
 
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 ADDED
@@ -0,0 +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}}});
includes/class-rio-plugin.php CHANGED
@@ -1,191 +1,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_Factory439_Plugin {
15
-
16
- /**
17
- * @see self::app()
18
- * @var Wbcr_Factory439_Plugin
19
- */
20
- private static $app;
21
-
22
- /**
23
- * @since 3.1.0
24
- * @var array
25
- */
26
- private $plugin_data;
27
-
28
- /**
29
- * Конструктор
30
- *
31
- * Применяет конструктор родительского класса и записывает экземпляр текущего класса в свойство $app.
32
- * Подробнее о свойстве $app см. self::app()
33
- *
34
- * @param string $plugin_path
35
- * @param array $data
36
- *
37
- * @throws \Exception
38
- */
39
- public function __construct( $plugin_path, $data ) {
40
- parent::__construct( $plugin_path, $data );
41
-
42
- self::$app = $this;
43
- $this->plugin_data = $data;
44
-
45
- $this->includes();
46
-
47
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
48
- // Ajax files
49
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/backup.php' );
50
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/bulk-optimization.php' );
51
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/logs.php' );
52
- // Not under AJAX logical operator above on purpose to have helpers available to find out whether
53
- // metas were migrated or not
54
- require_once( WRIO_PLUGIN_DIR . '/admin/ajax/meta-migrations.php' );
55
- }
56
-
57
- if ( is_admin() ) {
58
- $this->initActivation();
59
-
60
- // completely disable image size threshold
61
- add_filter( 'big_image_size_threshold', '__return_false' );
62
-
63
- if ( wrio_is_license_activate() ) {
64
- if ( ! defined( 'FACTORY_ADVERTS_BLOCK' ) ) {
65
- define( 'FACTORY_ADVERTS_BLOCK', true );
66
- }
67
- }
68
- }
69
-
70
- add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
71
- }
72
-
73
- /**
74
- * Статический метод для быстрого доступа к интерфейсу плагина.
75
- *
76
- * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
77
- * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
78
- *
79
- * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
80
- * классам.
81
- *
82
- * @return \Wbcr_Factory439_Plugin|\WRIO_Plugin
83
- */
84
- public static function app() {
85
- return self::$app;
86
- }
87
-
88
- /**
89
- * Подключаем функции бекенда
90
- *
91
- * @throws Exception
92
- */
93
- public function pluginsLoaded() {
94
- if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
95
- $media_library = WRIO_Media_Library::get_instance();
96
- $media_library->initHooks();
97
- }
98
-
99
- if ( is_admin() ) {
100
- require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
101
- //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
102
-
103
- $this->registerPages();
104
- } else {
105
- $lazy_load = WRIO_Lazy_Load::get_instance();
106
- $lazy_load->init();
107
- }
108
-
109
- if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
110
- $media_library = WRIO_Media_Library::get_instance();
111
- $media_library->initHooks();
112
- }
113
-
114
- if ( wrio_is_license_activate() ) {
115
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
116
- wrio_premium_load();
117
- }
118
- }
119
-
120
- /**
121
- * Подключаем модули классы и функции
122
- */
123
- protected function includes() {
124
-
125
- require_once( WRIO_PLUGIN_DIR . '/includes/functions.php' );
126
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-views.php' );
127
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-attachment.php' );
128
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-media-library.php' );
129
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-lazy-load.php' );
130
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/processors/class-rio-server-abstract.php' );
131
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-image-statistic.php' );
132
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-backup.php' );
133
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-optimization-tools.php' );
134
-
135
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-helper.php' );
136
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-object.php' ); // Base object
137
-
138
- // Database related models
139
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-active-record.php' );
140
- // Base class
141
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-base-extra-data.php' );
142
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-attachment-extra-data.php' );
143
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-server-smushit-extra-data.php' );
144
-
145
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/models/class-rio-process-queue-table.php' ); // Processing queue model
146
-
147
- // Cron
148
- // ----------------
149
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/class-rio-cron.php' );
150
- new WRIO_Cron();
151
-
152
- // Logger
153
- // ----------------
154
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-logger.php' );
155
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-export.php' );
156
- require_once( WRIO_PLUGIN_DIR . '/includes/classes/logger/class-rio-log-reader.php' );
157
- new WRIO_Logger();
158
- }
159
-
160
- /**
161
- * Инициализируем активацию плагина
162
- */
163
- protected function initActivation() {
164
- include_once( WRIO_PLUGIN_DIR . '/admin/activation.php' );
165
- self::app()->registerActivation( 'WIO_Activation' );
166
- }
167
-
168
- /**
169
- * Регистрируем страницы плагина
170
- *
171
- * @throws Exception
172
- */
173
- private function registerPages() {
174
- $admin_path = WRIO_PLUGIN_DIR . '/admin/pages/';
175
-
176
- // Parent page class
177
- require_once( $admin_path . '/class-rio-page.php' );
178
-
179
- if ( ! wrio_is_clearfy_license_activate() ) {
180
- self::app()->registerPage( 'WRIO_License_Page', $admin_path . '/class-rio-license.php' );
181
- }
182
-
183
- self::app()->registerPage( 'WRIO_SettingsPage', $admin_path . '/class-rio-settings.php' );
184
- self::app()->registerPage( 'WRIO_StatisticPage', $admin_path . '/class-rio-statistic.php' );
185
-
186
- if ( self::app()->getPopulateOption( 'error_log', false ) ) {
187
- self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
188
- }
189
- }
190
- }
191
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
includes/classes/class-rio-attachment.php CHANGED
@@ -1,992 +1,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_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_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_Logger::error( sprintf( 'Failed regenerate meta data for attachment file (%s).', $file_path ) );
146
-
147
- return false;
148
- }
149
-
150
- WRIO_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_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_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_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_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_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_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_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_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_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_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_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_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
+ $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
+ }
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_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_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_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_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_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_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_Logger::error( sprintf( 'Failed to delete backup file %s as unlink() failed', $backup_file ) );
420
-
421
- return false;
422
- }
423
-
424
- WRIO_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_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_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_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_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_Logger::info( sprintf( 'Try to create backup directory. Backup dir: (%s)', $dir ) );
493
-
494
- if ( ! wp_mkdir_p( $dir ) ) {
495
- WRIO_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_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_Logger::error( sprintf( 'Failed to delete backup file (%s) as unlink() failed', $backup_file ) );
522
-
523
- return false;
524
- }
525
-
526
- WRIO_Logger::info( sprintf( 'Restored file: %s.', $backup_file ) );
527
-
528
- return true;
529
- }
530
-
531
- WRIO_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 ADDED
@@ -0,0 +1,462 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
includes/classes/class-rio-cron.php CHANGED
@@ -1,183 +1,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_filter( 'wbcr/rio/settings_page/options', [ $this, 'settings_form' ], 10, 1 );
29
- add_action( 'wrio/cron/optimization_process', [ $this, 'process' ] );
30
- add_filter( 'cron_schedules', [ $this, 'intervals' ], 100, 1 );
31
- }
32
-
33
- /**
34
- * Хук на фильтр wbcr/rio/settings_page/options
35
- *
36
- * Добавляет в настройки плагина элементы управления cron
37
- *
38
- * @param array $options настройки
39
- *
40
- * @return array $options настройки
41
- */
42
- public function settings_form( $options ) {
43
- // cron
44
- $options[] = [
45
- 'type' => 'html',
46
- 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Scheduled optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Schedule your images optimization.', 'robin-image-optimizer' ) . '</p></div>'
47
- ];
48
- $group_items[] = [
49
- 'type' => 'dropdown',
50
- 'way' => 'buttons',
51
- 'name' => 'image_autooptimize_shedule_time',
52
- 'data' => [
53
- [ 'wio_1_min', __( '1 min', 'robin-image-optimizer' ) ],
54
- [ 'wio_2_min', __( '2 min', 'robin-image-optimizer' ) ],
55
- [ 'wio_5_min', __( '5 min', 'robin-image-optimizer' ) ],
56
- [ 'wio_10_min', __( '10 min', 'robin-image-optimizer' ) ],
57
- [ 'wio_30_min', __( '30 min', 'robin-image-optimizer' ) ],
58
- [ 'wio_hourly', __( 'Hour', 'robin-image-optimizer' ) ],
59
- [ 'wio_daily', __( 'Day', 'robin-image-optimizer' ) ],
60
- ],
61
- 'default' => 'wio_5_min',
62
- 'title' => __( 'Run every', 'robin-image-optimizer' ),
63
- 'hint' => __( 'Select time at which the task will be repeated.', 'robin-image-optimizer' )
64
- ];
65
-
66
- $group_items[] = [
67
- 'type' => 'textbox',
68
- 'name' => 'image_autooptimize_items_number_per_interation',
69
- 'title' => __( 'Images per iteration', 'robin-image-optimizer' ),
70
- 'layout' => [ 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ],
71
- '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' ),
72
- 'default' => '3'
73
- ];
74
-
75
- $options[] = [
76
- 'type' => 'div',
77
- 'id' => 'wbcr-io-shedule-options',
78
- 'items' => $group_items
79
- ];
80
-
81
- return $options;
82
- }
83
-
84
- /**
85
- * Кастомные интервалы выполнения cron задачи
86
- *
87
- * @param array $intervals Зарегистророванные интервалы
88
- *
89
- * @return array $intervals Новые интервалы
90
- */
91
- public function intervals( $intervals ) {
92
- $intervals['wio_1_min'] = [
93
- 'interval' => 60,
94
- 'display' => __( '1 min', 'robin-image-optimizer' ),
95
- ];
96
- $intervals['wio_2_min'] = [
97
- 'interval' => 60 * 2,
98
- 'display' => __( '2 min', 'robin-image-optimizer' ),
99
- ];
100
- $intervals['wio_5_min'] = [
101
- 'interval' => 60 * 5,
102
- 'display' => __( '5 min', 'robin-image-optimizer' ),
103
- ];
104
- $intervals['wio_10_min'] = [
105
- 'interval' => 60 * 10,
106
- 'display' => __( '10 min', 'robin-image-optimizer' ),
107
- ];
108
- $intervals['wio_30_min'] = [
109
- 'interval' => 60 * 30,
110
- 'display' => __( '30 min', 'robin-image-optimizer' ),
111
- ];
112
- $intervals['wio_hourly'] = [
113
- 'interval' => 60 * 60,
114
- 'display' => __( '60 min', 'robin-image-optimizer' ),
115
- ];
116
- $intervals['wio_daily'] = [
117
- 'interval' => 60 * 60 * 24,
118
- 'display' => __( 'daily', 'robin-image-optimizer' ),
119
- ];
120
-
121
- return $intervals;
122
- }
123
-
124
- /**
125
- * Запуск Cron задачи
126
- */
127
- public static function start() {
128
- $interval = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_shedule_time', 'wio_5_min' );
129
- if ( ! wp_next_scheduled( 'wrio/cron/optimization_process' ) ) {
130
- $intervals = wp_get_schedules();
131
- wp_schedule_event( time(), $interval, 'wrio/cron/optimization_process' );
132
- }
133
- }
134
-
135
- /**
136
- * Остановка Cron задачи
137
- */
138
- public static function stop() {
139
- if ( wp_next_scheduled( 'wrio/cron/optimization_process' ) ) {
140
- wp_clear_scheduled_hook( 'wrio/cron/optimization_process' );
141
- WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false ); // останавливаем крон
142
- }
143
- }
144
-
145
- /**
146
- * Метод оптимизирует изображения при выполнении cron задачи
147
- */
148
- public function process() {
149
- $max_process_per_request = WRIO_Plugin::app()->getPopulateOption( 'image_autooptimize_items_number_per_interation', 3 );
150
- $cron_running_page = WRIO_Plugin::app()->getPopulateOption( 'cron_running', false );
151
-
152
- if ( ! $cron_running_page ) {
153
- return;
154
- }
155
-
156
- WRIO_Logger::info( sprintf( "Start cron job. Scope: %s", $cron_running_page ) );
157
-
158
- if ( 'media-library' == $cron_running_page ) {
159
- $media_library = WRIO_Media_Library::get_instance();
160
- $result = $media_library->processUnoptimizedImages( $max_process_per_request );
161
- } else if ( 'nextgen' == $cron_running_page ) {
162
- $nextgen_gallery = WRIO_Nextgen_Gallery::get_instance();
163
- $result = $nextgen_gallery->processUnoptimizedImages( $max_process_per_request );
164
- } else if ( 'custom-folders' == $cron_running_page ) {
165
- $cf = WRIO_Custom_Folders::get_instance();
166
- $result = $cf->processUnoptimizedImages( $max_process_per_request );
167
- }
168
-
169
- if ( is_wp_error( $result ) ) {
170
- WRIO_Logger::info( sprintf( "Cron job failed. Error: %s", $result->get_error_message() ) );
171
- WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
172
-
173
- return;
174
- }
175
-
176
- if ( $result['remain'] <= 0 ) {
177
- WRIO_Plugin::app()->deletePopulateOption( 'cron_running' );
178
- }
179
-
180
- WRIO_Logger::info( sprintf( "End cron job. Scope: %s", $cron_running_page ) );
181
- }
182
-
183
- }
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
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/classes/class-rio-image-statistic.php CHANGED
@@ -1,398 +1,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
- * Вычитает данные из текущей статистики
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
- global $wpdb;
123
- $sql = "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' );";
124
- $total_images = $wpdb->get_var( $sql );
125
- $error_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'error' );
126
- $optimized_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
127
-
128
- if ( ! $total_images ) {
129
- $total_images = 0;
130
- }
131
- if ( ! $error_count ) {
132
- $error_count = 0;
133
- }
134
- if ( ! $optimized_count ) {
135
- $optimized_count = 0;
136
- }
137
- // unoptimized count: all - optimized - error
138
- $unoptimized_count = static::get_unoptimized_count();
139
- if ( $unoptimized_count < 0 ) {
140
- $unoptimized_count = 0;
141
- }
142
- if ( $optimized_size && $original_size ) {
143
- $percent_diff = round( ( $original_size - $optimized_size ) * 100 / $original_size, 1 );
144
- $percent_diff_line = round( $optimized_size * 100 / $original_size, 0 );
145
- } else {
146
- $percent_diff = 0;
147
- $percent_diff_line = 100;
148
- }
149
- if ( $total_images ) {
150
- $optimized_images_percent = floor( $optimized_count * 100 / $total_images );
151
- } else {
152
- $optimized_images_percent = 0;
153
- }
154
-
155
- $processor = WIO_OptimizationTools::getImageProcessor();
156
- $processor->checkLimits( false );
157
- $usage = (int) WRIO_Plugin::app()->getPopulateOption( $processor->getUsageOptionName(), 0 );
158
- $remaining = $processor->iamokay() - $usage;
159
-
160
- return [
161
- 'original' => $total_images,
162
- 'optimized' => $optimized_count,
163
- 'optimized_percent' => $optimized_images_percent,
164
- 'percent_line' => $percent_diff_line,
165
- 'unoptimized' => $unoptimized_count,
166
- 'optimized_size' => $optimized_size,
167
- 'original_size' => $original_size,
168
- 'save_size_percent' => $percent_diff,
169
- 'credits' => $remaining,
170
- 'error' => $error_count,
171
- ];
172
- }
173
-
174
- /**
175
- * Count of non-optimized images
176
- *
177
- * @return int
178
- * @since 1.3.6
179
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
180
- */
181
- public static function get_unoptimized_count() {
182
- global $wpdb;
183
- $db_table = RIO_Process_Queue::table_name();
184
-
185
- $sql_unoptimized = "SELECT COUNT(DISTINCT p.ID)
186
- FROM {$wpdb->posts} p
187
- WHERE NOT EXISTS (SELECT *
188
- FROM {$db_table}
189
- WHERE p.ID = object_id AND p.post_type = item_type)
190
- AND p.post_type = 'attachment' AND p.post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' )";
191
-
192
- $total_images = $wpdb->get_var( $sql_unoptimized );
193
-
194
- return (int) $total_images;
195
- }
196
-
197
- /**
198
- * Возвращает результат последних оптимизаций изображений
199
- *
200
- * @param int $limit лимит
201
- *
202
- * @return array {
203
- * Параметры
204
- * @type string $id id
205
- * @type string $file_name Имя файла
206
- * @type string $url URL
207
- * @type string $thumbnail_url URL превьюшки
208
- * @type string $original_size Размер до оптимизации
209
- * @type string $optimized_size Размер после оптимизации
210
- * @type string $webp_size webP размер
211
- * @type string $original_saving На сколько процентов изменился главный файл
212
- * @type string $thumbnails_count Сколько превьюшек оптимизировано
213
- * @type string $total_saving Процент оптимизации главного файла и превьюшек
214
- * }
215
- */
216
- public function get_last_optimized_images( $limit = 100 ) {
217
- global $wpdb;
218
-
219
- $items = [];
220
- $db_table = RIO_Process_Queue::table_name();
221
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
222
- WHERE item_type = 'attachment' AND result_status IN (%s, %s)
223
- ORDER BY id DESC
224
- LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
225
-
226
- $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
227
-
228
- if ( ! empty( $optimized_images ) ) {
229
- foreach ( $optimized_images as $row ) {
230
- $items[] = $this->format_for_log( new RIO_Process_Queue( $row ) );
231
- }
232
- }
233
-
234
- return $items;
235
- }
236
-
237
- /**
238
- * @param int $object_id
239
- *
240
- * @since 1.3.9
241
- *
242
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
243
- */
244
- public function get_last_optimized_image( $object_id ) {
245
- global $wpdb;
246
-
247
- $items = [];
248
- $db_table = RIO_Process_Queue::table_name();
249
- $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
250
- WHERE object_id = '%d' AND item_type = 'attachment' AND result_status IN (%s, %s)
251
- ORDER BY id DESC
252
- LIMIT 1;", (int) $object_id, RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR );
253
-
254
- $model = $wpdb->get_row( $sql, ARRAY_A );
255
-
256
- if ( ! empty( $model ) ) {
257
- $items[] = $this->format_for_log( new RIO_Process_Queue( $model ) );
258
- }
259
-
260
- return $items;
261
- }
262
-
263
- /**
264
- * @param RIO_Process_Queue $queue_model
265
- *
266
- * @return array
267
- * @throws \Exception
268
- * @since 1.3.9
269
- *
270
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
271
- */
272
- protected function format_for_log( $queue_model ) {
273
- if ( ! $queue_model instanceof RIO_Process_Queue ) {
274
- throw new Exception( 'Variable $queue_model must be an instance of RIO_Process_Queue!' );
275
- }
276
-
277
- /**
278
- * @var RIO_Attachment_Extra_Data $extra_data
279
- */
280
- $extra_data = $queue_model->get_extra_data();
281
-
282
- $default_formated_data = [
283
- 'id' => $queue_model->get_id(),
284
- 'url' => admin_url( sprintf( "post.php?post=%d&action=edit", $queue_model->get_object_id() ) ),
285
- 'thumbnail_url' => null,
286
- 'file_name' => null,
287
- 'original_size' => 0,
288
- 'optimized_size' => 0,
289
- 'type' => 'success',
290
- 'webp_size' => null,
291
- 'original_saving' => 0,
292
- 'thumbnails_count' => 0,
293
- 'total_saving' => 0,
294
- ];
295
-
296
- $upload_dir = wp_upload_dir();
297
-
298
- $attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
299
- $formated_data = [];
300
-
301
-
302
- if ( ! empty( $attachment_meta ) ) {
303
- $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
304
- $thumbnail_url = $image_url;
305
-
306
- if ( isset( $attachment_meta['sizes']['thumbnail'] ) ) {
307
- $image_basename = wp_basename( $image_url );
308
- $thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
309
- }
310
-
311
- $formated_data = wp_parse_args( [
312
- 'thumbnail_url' => $thumbnail_url,
313
- 'file_name' => wp_basename( $attachment_meta['file'] ),
314
- 'original_size' => size_format( $queue_model->get_original_size(), 2 ),
315
- 'optimized_size' => size_format( $queue_model->get_final_size(), 2 )
316
- ], $default_formated_data );
317
-
318
- $main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
319
-
320
- # An extra data may be empty after a failed migration or an unknown error.
321
- if ( ! empty( $extra_data ) ) {
322
- $original_main_size = $extra_data->get_original_main_size();
323
-
324
- if ( $original_main_size && file_exists( $main_file ) ) {
325
- $original_saving = ( $original_main_size - filesize( $main_file ) ) * 100 / $original_main_size;
326
- $formated_data['original_saving'] = round( $original_saving ) . '%';
327
- }
328
-
329
- $webp_size = $extra_data->get_webp_main_size();
330
-
331
- if ( $webp_size ) {
332
- $formated_data['webp_size'] = size_format( $webp_size, 2 );
333
- }
334
-
335
- $formated_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
336
- }
337
-
338
- if ( $queue_model->get_original_size() ) {
339
- $total_saving = ( $queue_model->get_original_size() - $queue_model->get_final_size() ) * 100 / $queue_model->get_original_size();
340
- $formated_data['total_saving'] = round( $total_saving, 2 ) . '%';
341
- }
342
- } else {
343
- $attachment = get_post( $queue_model->get_object_id() );
344
-
345
- if ( ! empty( $attachment ) ) {
346
- $formated_data = [
347
- 'thumbnail_url' => $attachment->guid,
348
- 'file_name' => wp_basename( $attachment->guid )
349
- ];
350
- }
351
-
352
- $formated_data = wp_parse_args( $formated_data, $default_formated_data );
353
- }
354
-
355
- # We collect information about errors
356
- if ( $queue_model->get_result_status() == RIO_Process_Queue::STATUS_ERROR ) {
357
- $error_message = null;
358
-
359
- if ( ! empty( $extra_data ) ) {
360
- $error_message = $extra_data->get_error_msg();
361
- }
362
-
363
- $formated_data['type'] = 'error';
364
- $formated_data['error_msg'] = ! empty( $error_message ) ? $error_message : __( 'Unknown error', 'robin-image-optimizer' );
365
-
366
- return $formated_data;
367
- }
368
-
369
- return $formated_data;
370
- }
371
-
372
- /**
373
- * Возвращает общий процент оптимизированных изображений
374
- *
375
- * @return int общий процент оптимизации
376
- */
377
- public function getOptimizedPercent() {
378
- if ( isset( $this->statistic['optimized_percent'] ) ) {
379
- return $this->statistic['optimized_percent'];
380
- }
381
-
382
- return 0;
383
- }
384
-
385
- /**
386
- * Пересчёт размера файла в байтах на человекопонятный вид
387
- *
388
- * Пример: вводим 67894 байт, получаем 67.8 KB
389
- * Пример: вводим 6789477 байт, получаем 6.7 MB
390
- *
391
- * @param int $size размер файла в байтах
392
- *
393
- * @return string
394
- */
395
- public function convertToReadableSize( $size ) {
396
- return wrio_convert_bytes( $size );
397
- }
398
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
includes/classes/class-rio-media-library.php CHANGED
@@ -1,707 +1,737 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы с wordpress media library.
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WRIO_Media_Library {
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 Массив для хранения объектов WIO_Attachment
28
- */
29
- private $attachments = [];
30
-
31
- /**
32
- * @return object|\WRIO_Media_Library object Main instance.
33
- * @since 1.3.0
34
- *
35
- * @author Alexander Kovalev <alex.kovalevv@gmail.com>
36
- */
37
- public static function get_instance() {
38
- if ( ! isset( static::$_instance ) ) {
39
- static::$_instance = new static();
40
- }
41
-
42
- return static::$_instance;
43
- }
44
-
45
- /**
46
- * Установка хуков
47
- */
48
- public function initHooks() {
49
- // оптимизация при загрузке в медиабиблиотеку
50
- if ( WRIO_Plugin::app()->getPopulateOption( 'auto_optimize_when_upload', false ) ) {
51
- add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
52
- add_action( 'wr2x_retina_file_added', 'WRIO_Media_Library::optimize_after_retina_2x_add', 10, 2 );
53
- }
54
-
55
- // соло оптимизация
56
- add_filter( 'attachment_fields_to_edit', [ $this, 'attachmentEditorFields' ], 1000, 2 );
57
- add_filter( 'manage_media_columns', [ $this, 'addMediaColumn' ] );
58
- add_action( 'manage_media_custom_column', [ $this, 'manageMediaColumn' ], 10, 2 );
59
- add_action( 'admin_enqueue_scripts', [ $this, 'enqueueMeadiaScripts' ], 10 );
60
- add_action( 'delete_attachment', [ $this, 'deleteAttachmentHook' ], 10 );
61
- add_action( 'wbcr/rio/optimize_template/optimized_percent', [ $this, 'optimizedPercent' ], 10, 2 );
62
- add_action( 'wbcr/riop/queue_item_saved', [ $this, 'webpSuccess' ] );
63
- }
64
-
65
- /**
66
- * @param int $attachment_id
67
- * @param string $retina_file
68
- */
69
- public static function optimize_after_retina_2x_add( $attachment_id, $retina_file ) {
70
- $metadata = get_post_meta( $attachment_id );
71
- self::optimize_after_upload( $metadata, $attachment_id );
72
- }
73
-
74
- /**
75
- * Оптимизация при загрузке в медиабиблилтеку
76
- *
77
- * @param array $metadata метаданные аттачмента
78
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
79
- *
80
- * @return array $metadata Метаданные аттачмента
81
- */
82
- public static function optimize_after_upload( $metadata, $attachment_id ) {
83
- // todo: There is a bug in this method! The filter is executed when meta data is not saved yet.
84
- // todo: So you need to generate the meta data of the image again in the process of optimizing the image.
85
- // todo: The best solution would be to add images to the queue for optimization. And do not optimize them from the current moment.
86
-
87
- $backup = WIO_Backup::get_instance();
88
- $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
89
-
90
- if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
91
- return $metadata;
92
- }
93
-
94
- $media_library = static::get_instance();
95
-
96
- $attachment = $media_library->getAttachment( $attachment_id, $metadata );
97
- $media_library->optimizeAttachment( $attachment_id );
98
- $metadata = $attachment->getMetaData();
99
- $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
100
-
101
- /*// если отложенная оптимизация
102
- if ( in_array( $server, [ 'server_4' ] ) ) {
103
- sleep( 2 );
104
- $media_library->processDeferredOptimization();
105
- }
106
- */
107
-
108
- return $metadata;
109
- }
110
-
111
- /**
112
- * Возвращает объект аттачмента
113
- *
114
- * @param int $attachment_id
115
- * @param mixed $attachment_meta
116
- *
117
- * @return WIO_Attachment
118
- */
119
- public function getAttachment( $attachment_id, $attachment_meta = false ) {
120
- if ( ! isset( $this->attachments[ $attachment_id ] ) ) {
121
- $this->attachments[ $attachment_id ] = new WIO_Attachment( $attachment_id, $attachment_meta );
122
- }
123
-
124
- return $this->attachments[ $attachment_id ];
125
- }
126
-
127
- /**
128
- * Оптимизирует аттачмент и сохраняет статистику
129
- *
130
- * @param int $attachment_id
131
- * @param string $level уровень оптимизации
132
- *
133
- * @return array
134
- */
135
- public function optimizeAttachment( $attachment_id, $level = '' ) {
136
- $wio_attachment = $this->getAttachment( $attachment_id );
137
- $optimization_data = $wio_attachment->getOptimizationData();
138
-
139
- if ( 'processing' == $optimization_data->get_result_status() ) {
140
- return $this->deferredOptimizeAttachment( $attachment_id );
141
- }
142
-
143
- $image_statistics = WRIO_Image_Statistic::get_instance();
144
- wp_suspend_cache_addition( true ); // останавливаем кеширование
145
-
146
- if ( $wio_attachment->isOptimized() ) {
147
- $this->restoreAttachment( $attachment_id );
148
- $wio_attachment->reload();
149
- }
150
-
151
- $attachment_optimized_data = $wio_attachment->optimize( $level );
152
- $original_size = $attachment_optimized_data['original_size'];
153
- $optimized_size = $attachment_optimized_data['optimized_size'];
154
- $image_statistics->addToField( 'optimized_size', $optimized_size );
155
- $image_statistics->addToField( 'original_size', $original_size );
156
- $image_statistics->save();
157
- wp_suspend_cache_addition(); // возобновляем кеширование
158
-
159
- return $attachment_optimized_data;
160
- }
161
-
162
- /**
163
- * Отложенная оптимизация
164
- *
165
- * @param int $attachment_id
166
- *
167
- * @return bool|array
168
- */
169
- protected function deferredOptimizeAttachment( $attachment_id ) {
170
- $wio_attachment = $this->getAttachment( $attachment_id );
171
- $optimization_data = $wio_attachment->getOptimizationData();
172
- $image_processor = WIO_OptimizationTools::getImageProcessor();
173
-
174
- // если текущий сервер оптимизации не поддерживает отложенную оптимизацию, а в очереди есть аттачменты - ставим им ошибку
175
- if ( ! $image_processor->isDeferred() ) {
176
- $optimization_data->set_result_status( 'error' );
177
-
178
- /**
179
- * @var $extra_data RIO_Attachment_Extra_Data
180
- */
181
- $extra_data = $optimization_data->get_extra_data();
182
- $extra_data->set_error( 'deferred' );
183
- $extra_data->set_error_msg( 'server not support deferred optimization' );
184
- $optimization_data->set_extra_data( $extra_data );
185
- $optimization_data->save();
186
-
187
- return false;
188
- }
189
-
190
- $optimized_data = $wio_attachment->deferredOptimization();
191
- if ( $optimized_data ) {
192
- $image_statistics = WRIO_Image_Statistic::get_instance();
193
- $image_statistics->addToField( 'optimized_size', $optimized_data['optimized_size'] );
194
- $image_statistics->addToField( 'original_size', $optimized_data['original_size'] );
195
- $image_statistics->save();
196
- }
197
-
198
- return $optimized_data;
199
- }
200
-
201
- /**
202
- * Восстанавливает аттачмент из резервной копии и сохраняет статистику
203
- *
204
- * @param int $attachment_id
205
- *
206
- * @return bool|WP_Error
207
- */
208
- public function restoreAttachment( $attachment_id ) {
209
- $image_statistics = WRIO_Image_Statistic::get_instance();
210
- $wio_attachment = $this->getAttachment( $attachment_id );
211
- $restored = $wio_attachment->restore();
212
-
213
- if ( is_wp_error( $restored ) ) {
214
- return $restored;
215
- }
216
-
217
- $optimization_data = $wio_attachment->getOptimizationData();
218
- $optimized_size = $optimization_data->get_final_size();
219
- $original_size = $optimization_data->get_original_size();
220
- $image_statistics->deductFromField( 'optimized_size', $optimized_size );
221
- $image_statistics->deductFromField( 'original_size', $original_size );
222
- $image_statistics->save();
223
- $optimization_data->delete();
224
-
225
- /**
226
- * Хук срабатывает после восстановления аттачмента
227
- *
228
- * @param RIO_Process_Queue $optimization_data
229
- *
230
- * @since 1.2.0
231
- *
232
- */
233
- do_action( 'wbcr/rio/attachment_restored', $optimization_data );
234
-
235
- return true;
236
- }
237
-
238
- /**
239
- * Обработка неоптимизированных изображений
240
- *
241
- * @param int $max_process_per_request кол-во аттачментов за 1 запуск
242
- *
243
- * @return array|\WP_Error
244
- */
245
- public function processUnoptimizedImages( $max_process_per_request ) {
246
- global $wpdb;
247
-
248
- $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
249
-
250
- $backup = WIO_Backup::get_instance();
251
-
252
- if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
253
- return new WP_Error( 'unwritable_backup_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
254
- }
255
-
256
- if ( ! $backup->isUploadWritable() ) {
257
- return new WP_Error( 'unwritable_upload_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
258
- }
259
-
260
- $db_table = RIO_Process_Queue::table_name();
261
- $max_process_per_request = intval( $max_process_per_request );
262
- $allowed_formats = explode( ',', WRIO_Plugin::app()->getOption( 'allowed_formats', "image/jpeg,image/png,image/gif" ) );
263
- $allowed_formats_sql = [];
264
- foreach ( $allowed_formats as $k => $format ) {
265
- $allowed_formats_sql[ $k ] = "'{$format}'";
266
- }
267
- $allowed_formats_sql = implode( ',', $allowed_formats_sql );
268
-
269
- $optimize_order = WRIO_Plugin::app()->getOption( 'image_optimization_order', "asc" );
270
-
271
- $sql = "SELECT DISTINCT posts.ID
272
- FROM {$wpdb->posts} AS posts
273
- LEFT JOIN {$db_table} AS rio ON posts.ID = rio.object_id AND rio.item_type = 'attachment'
274
- WHERE rio.object_id IS NULL
275
- AND posts.post_type = 'attachment'
276
- AND posts.post_status = 'inherit'
277
- AND posts.post_mime_type IN ( {$allowed_formats_sql} )
278
- ORDER BY posts.ID {$optimize_order}
279
- LIMIT {$max_process_per_request}";
280
-
281
- //выборка неоптимизированных изображений
282
- $unoptimized_attachments_ids = $wpdb->get_col( $sql );
283
-
284
- // временно
285
- $optimized_count = (int) RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
286
- $attachments_count = ! empty( $unoptimized_attachments_ids ) ? sizeof( $unoptimized_attachments_ids ) : 0;
287
- $total_unoptimized = WRIO_Image_Statistic::get_unoptimized_count();
288
-
289
- $original_size = 0;
290
- $optimized_size = 0;
291
- $optimized_items = [];
292
-
293
- // обработка
294
- if ( ! empty( $attachments_count ) ) {
295
-
296
- foreach ( $unoptimized_attachments_ids as $attachment_id ) {
297
- $wio_attachment = $this->getAttachment( $attachment_id );
298
-
299
- if ( $wio_attachment->isOptimized() ) {
300
- $this->restoreAttachment( $attachment_id );
301
- $wio_attachment->reload();
302
- }
303
- $attachment_optimized_data = $wio_attachment->optimize();
304
- $original_size = $original_size + $attachment_optimized_data['original_size'];
305
- $optimized_size = $optimized_size + $attachment_optimized_data['optimized_size'];
306
- $optimized_items[] = $attachment_id;
307
- }
308
- }
309
-
310
- $image_statistics = WRIO_Image_Statistic::get_instance();
311
-
312
- if ( $original_size > 0 || $optimized_size > 0 ) {
313
- $image_statistics->addToField( 'optimized_size', $optimized_size );
314
- $image_statistics->addToField( 'original_size', $original_size );
315
- $image_statistics->save();
316
- }
317
-
318
- $remain = $total_unoptimized - $attachments_count;
319
-
320
- // проверяем, есть ли аттачменты в очереди на отложенную оптимизацию
321
- $optimized_data = $this->processDeferredOptimization();
322
-
323
- if ( $optimized_data ) {
324
- $optimized_count = $optimized_data['optimized_count'];
325
- $remain = $total_unoptimized - $optimized_count;
326
- }
327
-
328
- if ( $remain <= 0 ) {
329
- $remain = 0;
330
- }
331
-
332
- # Take the last optimized image ID. Used to log 100 optimized images.
333
- $last_optimized_id = end( $optimized_items );
334
-
335
- $response = [
336
- 'remain' => $remain,
337
- 'end' => false,
338
- 'statistic' => $image_statistics->load(),
339
- 'last_optimized' => $image_statistics->get_last_optimized_image( $last_optimized_id ),
340
- 'optimized_count' => $optimized_count,
341
- ];
342
-
343
- return $response;
344
- }
345
-
346
- /**
347
- * Отложенная оптимизация
348
- *
349
- * @return bool|array
350
- */
351
- protected function processDeferredOptimization() {
352
- global $wpdb;
353
- $db_table = RIO_Process_Queue::table_name();
354
- $attachment_id = $wpdb->get_var( "SELECT object_id FROM {$db_table} WHERE item_type = 'attachment' and result_status = 'processing' LIMIT 1;" );
355
- if ( ! $attachment_id ) {
356
- return false;
357
- }
358
-
359
- return $this->optimizeAttachment( $attachment_id );
360
- }
361
-
362
- /**
363
- * Сбрасывает текущие ошибки оптимизации
364
- * Позволяет изображениям, которые оптимизированы с ошибкой, заново пройти оптимизацию.
365
- *
366
- * @return void
367
- */
368
- public function resetCurrentErrors() {
369
- //do_action( 'wbcr/rio/multisite_current_blog' );
370
- global $wpdb;
371
- $db_table = RIO_Process_Queue::table_name();
372
- $wpdb->delete( $db_table, [
373
- 'item_type' => 'attachment',
374
- 'result_status' => 'error',
375
- ], [ '%s', '%s' ] );
376
- //do_action( 'wbcr/rio/multisite_restore_blog' );
377
- }
378
-
379
- /**
380
- * Восстановление из резервной копии.
381
- *
382
- * @param int $max_process_per_request кол-во аттачментов за 1 запуск
383
- *
384
- * @return array
385
- */
386
- public function restoreAllFromBackup( $max_process_per_request ) {
387
- if ( class_exists( 'WRIO_Cron' ) ) {
388
- WRIO_Cron::stop();
389
- }
390
-
391
- WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false ); // останавливаем крон
392
-
393
- global $wpdb;
394
-
395
- $db_table = RIO_Process_Queue::table_name();
396
- $optimized_count = $wpdb->get_var( "SELECT COUNT(*) FROM {$db_table} WHERE item_type = 'attachment' AND result_status = 'success' LIMIT 1;" );
397
- $optimized_attachments = $wpdb->get_results( "SELECT * FROM {$db_table} WHERE item_type = 'attachment' AND result_status = 'success' LIMIT " . intval( $max_process_per_request ) );
398
-
399
- $attachments_count = 0;
400
- if ( $optimized_attachments ) {
401
- $attachments_count = count( $optimized_attachments );
402
- }
403
-
404
- $restored_count = 0;
405
-
406
- // обработка
407
- if ( $attachments_count ) {
408
- foreach ( $optimized_attachments as $row ) {
409
- $attachment_id = intval( $row->object_id );
410
-
411
- $restored = $this->restoreAttachment( $attachment_id );
412
- $restored_count ++;
413
-
414
- if ( is_wp_error( $restored ) ) {
415
- return [
416
- 'remain' => 0,
417
- ];
418
- }
419
- }
420
- }
421
-
422
- $remane = $optimized_count - $restored_count;
423
-
424
- if ( $remane === 0 ) {
425
- // Should empty original/optimized size once all backups are empty
426
- WRIO_Plugin::app()->updateOption( 'original_size', 0 );
427
- WRIO_Plugin::app()->updateOption( 'optimized_size', 0 );
428
- }
429
-
430
- return [
431
- 'remain' => $remane,
432
- ];
433
- }
434
-
435
- /**
436
- * Кол-во оптимизированных изображений
437
- *
438
- * @return int
439
- */
440
- public function getOptimizedCount() {
441
- $optimized_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
442
- if ( ! $optimized_count ) {
443
- $optimized_count = 0;
444
- }
445
-
446
- return $optimized_count;
447
- }
448
-
449
- /**
450
- * Add "Image Optimizer" column in the Media Uploader
451
- *
452
- * @param array $form_fields An array of attachment form fields.
453
- * @param object $post The WP_Post attachment object.
454
- *
455
- * @return array
456
- */
457
- public function attachmentEditorFields( $form_fields, $post ) {
458
- global $pagenow;
459
-
460
- if ( 'post.php' === $pagenow ) {
461
- return $form_fields;
462
- }
463
-
464
- $form_fields['wio'] = [
465
- 'label' => 'Image Optimizer',
466
- 'input' => 'html',
467
- 'html' => $this->getMediaColumnContent( $post->ID ),
468
- 'show_in_edit' => true,
469
- 'show_in_modal' => true,
470
- ];
471
-
472
- return $form_fields;
473
- }
474
-
475
- /**
476
- * Add "wio" column in upload.php.
477
- *
478
- * @param array $columns An array of columns displayed in the Media list table.
479
- *
480
- * @return array
481
- */
482
- public function addMediaColumn( $columns ) {
483
- $columns['wio_optimized_file'] = __( 'Robin Image Optimizer', 'image optimizer' );
484
-
485
- return $columns;
486
- }
487
-
488
- /**
489
- * Add content to the "wio" columns in upload.php.
490
- *
491
- * @param string $column_name Name of the custom column.
492
- * @param int $attachment_id Attachment ID.
493
- */
494
- public function manageMediaColumn( $column_name, $attachment_id ) {
495
- if ( 'wio_optimized_file' !== $column_name ) {
496
- return;
497
- }
498
- echo $this->getMediaColumnContent( $attachment_id );
499
- }
500
-
501
- /**
502
- * Возвращает шаблон для вывода блока кнопок на странице ручной оптимизации
503
- *
504
- * @param array $params @see calculateMediaLibraryParams()
505
- * @param string $type Тип страницы
506
- *
507
- * @return string
508
- */
509
- public function getMediaColumnTemplate( $params, $type = 'media-library' ) {
510
- require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-optimize-template.php' );
511
- $template = new WIO_OptimizePageTemplate( $type );
512
-
513
- return $template->getMediaColumnTemplate( $params );
514
- }
515
-
516
- /**
517
- * Выводит блок статистики для аттачмента в медиабиблиотеке
518
- *
519
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
520
- *
521
- * @return string
522
- */
523
- public function getMediaColumnContent( $attachment_id ) {
524
- $params = $this->calculateMediaLibraryParams( $attachment_id );
525
-
526
- return $this->getMediaColumnTemplate( $params );
527
- }
528
-
529
- /**
530
- * Расчитывает параметры для блока статистики в медиабиблиотеке
531
- *
532
- * @param int $attachment_id
533
- *
534
- * @return array @see WIO_OptimizePageTemplate::getMediaColumnTemplate()
535
- */
536
- public function calculateMediaLibraryParams( $attachment_id ) {
537
- $wio_attachment = $this->getAttachment( $attachment_id );
538
- $optimization_data = $wio_attachment->getOptimizationData();
539
- $is_optimized = $optimization_data->is_optimized();
540
- $is_skipped = $optimization_data->is_skipped();
541
- $attach_meta = wp_get_attachment_metadata( $attachment_id );
542
- $attach_dimensions = '0 x 0';
543
-
544
- if ( isset( $attach_meta['width'] ) && isset( $attach_meta['height'] ) ) {
545
- $attach_dimensions = $attach_meta['width'] . ' × ' . $attach_meta['height'];
546
- }
547
-
548
- clearstatcache();
549
- $attachment_file = get_attached_file( $attachment_id );
550
- $attachment_file_size = 0;
551
-
552
- if ( $attachment_file && file_exists( $attachment_file ) ) {
553
- $attachment_file_size = filesize( get_attached_file( $attachment_id ) );
554
- }
555
-
556
- if ( $is_optimized ) {
557
- $optimized_size = $optimization_data->get_final_size();
558
- $original_size = $optimization_data->get_original_size();
559
-
560
- /**
561
- * @var $extra_data RIO_Attachment_Extra_Data
562
- */
563
- $extra_data = $optimization_data->get_extra_data();
564
- $original_main_size = $extra_data->get_original_main_size();
565
- $thumbnails_optimized = $extra_data->get_thumbnails_count();
566
-
567
- if ( empty( $original_main_size ) ) {
568
- $original_main_size = $original_size;
569
- }
570
-
571
- $optimization_level = $optimization_data->get_processing_level();
572
- $error_msg = $extra_data->get_error_msg();
573
- $backuped = $optimization_data->get_is_backed_up();
574
- $diff_percent = 0;
575
- $diff_percent_all = 0;
576
-
577
- if ( $attachment_file_size && $original_main_size ) {
578
- $diff_percent = round( ( $original_main_size - $attachment_file_size ) * 100 / $original_main_size );
579
- }
580
-
581
- if ( $optimized_size && $original_size ) {
582
- $diff_percent_all = round( ( $original_size - $optimized_size ) * 100 / $original_size );
583
- }
584
- } else {
585
- $optimized_size = $optimized_size = $original_size = $original_main_size = false;
586
- $thumbnails_optimized = $optimization_level = $error_msg = $backuped = $diff_percent = $diff_percent_all = false;
587
- }
588
-
589
- $params = [
590
- 'attachment_id' => $attachment_id,
591
- 'is_optimized' => $is_optimized,
592
- 'attach_dimensions' => $attach_dimensions,
593
- 'attachment_file_size' => $attachment_file_size,
594
- 'optimized_size' => $optimized_size,
595
- 'original_size' => $original_size,
596
- 'original_main_size' => $original_main_size,
597
- 'thumbnails_optimized' => $thumbnails_optimized,
598
- 'optimization_level' => $optimization_level,
599
- 'error_msg' => $error_msg,
600
- 'backuped' => $backuped,
601
- 'diff_percent' => $diff_percent,
602
- 'diff_percent_all' => $diff_percent_all,
603
- 'is_skipped' => $is_skipped,
604
- ];
605
-
606
- return $params;
607
- }
608
-
609
- /**
610
- * Добавляем стили и скрипты в медиабиблиотеку
611
- */
612
- public function enqueueMeadiaScripts( $hook ) {
613
- if ( $hook != 'upload.php' ) {
614
- return;
615
- }
616
- wp_enqueue_style( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/css/media.css', [], WRIO_Plugin::app()->getPluginVersion() );
617
- wp_enqueue_script( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/js/single-optimization.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
618
- }
619
-
620
- /**
621
- * Выполняется при удалении аттачмента из медиабиблиотеки
622
- */
623
- public function deleteAttachmentHook( $attachment_id ) {
624
- $wio_attachment = new WIO_Attachment( $attachment_id );
625
- if ( $wio_attachment->isOptimized() ) {
626
- $this->restoreAttachment( $attachment_id );
627
- }
628
- }
629
-
630
- /**
631
- * Возвращает процент оптимизации
632
- * Фильтр wbcr/rio/optimize_template/optimized_percent
633
- *
634
- * @param int $percent процент оптимизации
635
- * @param string $type тип страницы
636
- *
637
- * @return int процент оптимизации
638
- */
639
- public function optimizedPercent( $percent, $type ) {
640
- if ( 'media-library' == $type ) {
641
- $image_statistics = WRIO_Image_Statistic::get_instance();
642
-
643
- return $image_statistics->getOptimizedPercent();
644
- }
645
-
646
- return $percent;
647
- }
648
-
649
- /**
650
- * Сохраняет WebP размер
651
- *
652
- * @param RIO_Process_Queue $queue_model
653
- *
654
- * @return bool
655
- */
656
- public function webpSuccess( $queue_model ) {
657
- if ( ! class_exists( 'WRIO\WEBP\Listener' ) ) {
658
- return false; // если не установлена премиум версия, то WebP не активен
659
- }
660
-
661
- if ( $queue_model->get_item_type() !== WRIO\WEBP\Listener::DEFAULT_TYPE ) {
662
- return false;
663
- }
664
-
665
- if ( $queue_model->get_result_status() !== RIO_Process_Queue::STATUS_SUCCESS ) {
666
- return false;
667
- }
668
-
669
- /**
670
- * @var $extra_data RIO_Attachment_Extra_Data
671
- */
672
- $extra_data = $queue_model->get_extra_data();
673
- $item_type = $extra_data->get_convert_from();
674
- if ( 'attachment' != $item_type ) {
675
- return false;
676
- }
677
-
678
- $object_id = $queue_model->get_object_id();
679
- if ( ! $object_id ) {
680
- return false;
681
- }
682
- $src = wp_get_attachment_image_src( $object_id, 'full' );
683
-
684
- if ( false !== $src ) {
685
- $src = $src[0];
686
- }
687
-
688
- $url_hash = hash( 'sha256', $src );
689
- if ( $queue_model->get_item_hash() == $url_hash ) {
690
- $optimization_data = new RIO_Process_Queue( [
691
- 'object_id' => $object_id,
692
- 'item_type' => 'attachment',
693
- ] );
694
- $optimization_data->load();
695
- $extra_data = $optimization_data->get_extra_data();
696
- $extra_data->set_webp_main_size( $queue_model->get_final_size() );
697
- $optimization_data->set_extra_data( $extra_data );
698
- add_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
699
- $optimization_data->save();
700
- remove_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
701
- }
702
-
703
- return true;
704
- }
705
- }
706
-
707
- add_filter( str_rot13( 'jope/evb/nyybj_freiref' ), 'WIO_Backup::alternateStorage' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с wordpress media library.
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WRIO_Media_Library {
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 Массив для хранения объектов WIO_Attachment
28
+ */
29
+ private $attachments = [];
30
+
31
+ /**
32
+ * @return object|\WRIO_Media_Library object Main instance.
33
+ * @since 1.3.0
34
+ *
35
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
36
+ */
37
+ public static function get_instance() {
38
+ if ( ! isset( static::$_instance ) ) {
39
+ static::$_instance = new static();
40
+ }
41
+
42
+ return static::$_instance;
43
+ }
44
+
45
+ /**
46
+ * Установка хуков
47
+ */
48
+ public function initHooks() {
49
+ // оптимизация при загрузке в медиабиблиотеку
50
+ if ( WRIO_Plugin::app()->getPopulateOption( 'auto_optimize_when_upload', false ) ) {
51
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
52
+ add_action( 'wr2x_retina_file_added', 'WRIO_Media_Library::optimize_after_retina_2x_add', 10, 2 );
53
+ }
54
+
55
+ // соло оптимизация
56
+ add_filter( 'attachment_fields_to_edit', [ $this, 'attachmentEditorFields' ], 1000, 2 );
57
+ add_filter( 'manage_media_columns', [ $this, 'addMediaColumn' ] );
58
+ add_action( 'manage_media_custom_column', [ $this, 'manageMediaColumn' ], 10, 2 );
59
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueueMeadiaScripts' ], 10 );
60
+ add_action( 'delete_attachment', [ $this, 'deleteAttachmentHook' ], 10 );
61
+ add_action( 'wbcr/rio/optimize_template/optimized_percent', [ $this, 'optimizedPercent' ], 10, 2 );
62
+ add_action( 'wbcr/riop/queue_item_saved', [ $this, 'webpSuccess' ] );
63
+ }
64
+
65
+ /**
66
+ * @param int $attachment_id
67
+ * @param string $retina_file
68
+ */
69
+ public static function optimize_after_retina_2x_add( $attachment_id, $retina_file ) {
70
+ $metadata = get_post_meta( $attachment_id );
71
+ self::optimize_after_upload( $metadata, $attachment_id );
72
+ }
73
+
74
+ /**
75
+ * Оптимизация при загрузке в медиабиблиотеку
76
+ *
77
+ * @param array $metadata метаданные аттачмента
78
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
79
+ *
80
+ * @return array $metadata Метаданные аттачмента
81
+ */
82
+ public static function optimize_after_upload( $metadata, $attachment_id ) {
83
+
84
+ $backup = WIO_Backup::get_instance();
85
+ $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
86
+
87
+ if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
88
+ return $metadata;
89
+ }
90
+
91
+ WRIO_Cron::start_single( $attachment_id );
92
+
93
+ /*// если отложенная оптимизация
94
+ $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
95
+ if ( in_array( $server, [ 'server_4' ] ) ) {
96
+ sleep( 2 );
97
+ $media_library->processDeferredOptimization();
98
+ }
99
+ */
100
+
101
+ return $metadata;
102
+ }
103
+
104
+ /**
105
+ * Возвращает объект аттачмента
106
+ *
107
+ * @param int $attachment_id
108
+ * @param mixed $attachment_meta
109
+ *
110
+ * @return WIO_Attachment
111
+ */
112
+ public function getAttachment( $attachment_id, $attachment_meta = false ) {
113
+ if ( ! isset( $this->attachments[ $attachment_id ] ) ) {
114
+ $this->attachments[ $attachment_id ] = new WIO_Attachment( $attachment_id, $attachment_meta );
115
+ }
116
+
117
+ return $this->attachments[ $attachment_id ];
118
+ }
119
+
120
+ /**
121
+ * Оптимизирует аттачмент и сохраняет статистику
122
+ *
123
+ * @param int $attachment_id
124
+ * @param string $level уровень оптимизации
125
+ *
126
+ * @return array
127
+ */
128
+ public function optimizeAttachment( $attachment_id, $level = '' ) {
129
+ $wio_attachment = $this->getAttachment( $attachment_id );
130
+ $optimization_data = $wio_attachment->getOptimizationData();
131
+
132
+ if ( 'processing' == $optimization_data->get_result_status() ) {
133
+ return $this->deferredOptimizeAttachment( $attachment_id );
134
+ }
135
+
136
+ $image_statistics = WRIO_Image_Statistic::get_instance();
137
+ wp_suspend_cache_addition( true ); // останавливаем кеширование
138
+
139
+ if ( $wio_attachment->isOptimized() ) {
140
+ $this->restoreAttachment( $attachment_id );
141
+ $wio_attachment->reload();
142
+ }
143
+
144
+ $attachment_optimized_data = $wio_attachment->optimize( $level );
145
+ $original_size = $attachment_optimized_data['original_size'];
146
+ $optimized_size = $attachment_optimized_data['optimized_size'];
147
+ $image_statistics->addToField( 'optimized_size', $optimized_size );
148
+ $image_statistics->addToField( 'original_size', $original_size );
149
+ $image_statistics->save();
150
+ wp_suspend_cache_addition(); // возобновляем кеширование
151
+
152
+ return $attachment_optimized_data;
153
+ }
154
+
155
+ /**
156
+ * Отложенная оптимизация
157
+ *
158
+ * @param int $attachment_id
159
+ *
160
+ * @return bool|array
161
+ */
162
+ protected function deferredOptimizeAttachment( $attachment_id ) {
163
+ $wio_attachment = $this->getAttachment( $attachment_id );
164
+ $optimization_data = $wio_attachment->getOptimizationData();
165
+ $image_processor = WIO_OptimizationTools::getImageProcessor();
166
+
167
+ // если текущий сервер оптимизации не поддерживает отложенную оптимизацию, а в очереди есть аттачменты - ставим им ошибку
168
+ if ( ! $image_processor->isDeferred() ) {
169
+ $optimization_data->set_result_status( 'error' );
170
+
171
+ /**
172
+ * @var $extra_data RIO_Attachment_Extra_Data
173
+ */
174
+ $extra_data = $optimization_data->get_extra_data();
175
+ $extra_data->set_error( 'deferred' );
176
+ $extra_data->set_error_msg( 'server not support deferred optimization' );
177
+ $optimization_data->set_extra_data( $extra_data );
178
+ $optimization_data->save();
179
+
180
+ return false;
181
+ }
182
+
183
+ $optimized_data = $wio_attachment->deferredOptimization();
184
+ if ( $optimized_data ) {
185
+ $image_statistics = WRIO_Image_Statistic::get_instance();
186
+ $image_statistics->addToField( 'optimized_size', $optimized_data['optimized_size'] );
187
+ $image_statistics->addToField( 'original_size', $optimized_data['original_size'] );
188
+ $image_statistics->save();
189
+ }
190
+
191
+ return $optimized_data;
192
+ }
193
+
194
+ /**
195
+ * Восстанавливает аттачмент из резервной копии и сохраняет статистику
196
+ *
197
+ * @param int $attachment_id
198
+ *
199
+ * @return bool|WP_Error
200
+ */
201
+ public function restoreAttachment( $attachment_id ) {
202
+ $image_statistics = WRIO_Image_Statistic::get_instance();
203
+ $wio_attachment = $this->getAttachment( $attachment_id );
204
+ $restored = $wio_attachment->restore();
205
+
206
+ if ( is_wp_error( $restored ) ) {
207
+ return $restored;
208
+ }
209
+
210
+ $optimization_data = $wio_attachment->getOptimizationData();
211
+ $optimized_size = $optimization_data->get_final_size();
212
+ $original_size = $optimization_data->get_original_size();
213
+ $image_statistics->deductFromField( 'optimized_size', $optimized_size );
214
+ $image_statistics->deductFromField( 'original_size', $original_size );
215
+ $image_statistics->save();
216
+ $optimization_data->delete();
217
+
218
+ /**
219
+ * Хук срабатывает после восстановления аттачмента
220
+ *
221
+ * @param RIO_Process_Queue $optimization_data
222
+ *
223
+ * @since 1.2.0
224
+ *
225
+ */
226
+ do_action( 'wbcr/rio/attachment_restored', $optimization_data );
227
+
228
+ return true;
229
+ }
230
+
231
+ /**
232
+ * Get ID's of unoptimized attachments
233
+ *
234
+ * @return array
235
+ */
236
+ public function getUnoptimizedImages() {
237
+ global $wpdb;
238
+ $db_table = RIO_Process_Queue::table_name();
239
+
240
+ $allowed_formats_sql = wrio_get_allowed_formats( true );
241
+
242
+ $optimize_order = WRIO_Plugin::app()->getOption( 'image_optimization_order', "asc" );
243
+
244
+ $sql = "SELECT DISTINCT posts.ID
245
+ FROM {$wpdb->posts} AS posts
246
+ LEFT JOIN {$db_table} AS rio ON posts.ID = rio.object_id AND rio.item_type = 'attachment'
247
+ WHERE rio.object_id IS NULL
248
+ AND posts.post_type = 'attachment'
249
+ AND posts.post_status = 'inherit'
250
+ AND posts.post_mime_type IN ( {$allowed_formats_sql} )
251
+ ORDER BY posts.ID {$optimize_order}";
252
+
253
+ //выборка не оптимизированных изображений
254
+ $unoptimized_attachments_ids = $wpdb->get_col( $sql );
255
+
256
+ return is_array( $unoptimized_attachments_ids ) ? $unoptimized_attachments_ids : [];
257
+ }
258
+
259
+ /**
260
+ * Обработка не оптимизированных изображений
261
+ *
262
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
263
+ *
264
+ * @return array|\WP_Error
265
+ */
266
+ public function processUnoptimizedImages( $max_process_per_request ) {
267
+ global $wpdb;
268
+
269
+ $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
270
+
271
+ $backup = WIO_Backup::get_instance();
272
+
273
+ if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
274
+ return new WP_Error( 'unwritable_backup_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
275
+ }
276
+
277
+ if ( ! $backup->isUploadWritable() ) {
278
+ return new WP_Error( 'unwritable_upload_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
279
+ }
280
+
281
+ $db_table = RIO_Process_Queue::table_name();
282
+ $max_process_per_request = intval( $max_process_per_request );
283
+ $allowed_formats = explode( ',', WRIO_Plugin::app()->getOption( 'allowed_formats', "image/jpeg,image/png,image/gif" ) );
284
+ $allowed_formats_sql = [];
285
+ foreach ( $allowed_formats as $k => $format ) {
286
+ $allowed_formats_sql[ $k ] = "'{$format}'";
287
+ }
288
+ $allowed_formats_sql = implode( ',', $allowed_formats_sql );
289
+
290
+ $optimize_order = WRIO_Plugin::app()->getOption( 'image_optimization_order', "asc" );
291
+
292
+ $sql = "SELECT DISTINCT posts.ID
293
+ FROM {$wpdb->posts} AS posts
294
+ LEFT JOIN {$db_table} AS rio ON posts.ID = rio.object_id AND rio.item_type = 'attachment'
295
+ WHERE rio.object_id IS NULL
296
+ AND posts.post_type = 'attachment'
297
+ AND posts.post_status = 'inherit'
298
+ AND posts.post_mime_type IN ( {$allowed_formats_sql} )
299
+ ORDER BY posts.ID {$optimize_order}
300
+ LIMIT {$max_process_per_request}";
301
+
302
+ //выборка неоптимизированных изображений
303
+ $unoptimized_attachments_ids = $wpdb->get_col( $sql );
304
+
305
+ // временно
306
+ $optimized_count = (int) RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
307
+ $attachments_count = ! empty( $unoptimized_attachments_ids ) ? sizeof( $unoptimized_attachments_ids ) : 0;
308
+ $total_unoptimized = WRIO_Image_Statistic::get_unoptimized_count();
309
+
310
+ $original_size = 0;
311
+ $optimized_size = 0;
312
+ $optimized_items = [];
313
+
314
+ // обработка
315
+ if ( ! empty( $attachments_count ) ) {
316
+
317
+ foreach ( $unoptimized_attachments_ids as $attachment_id ) {
318
+ $wio_attachment = $this->getAttachment( $attachment_id );
319
+
320
+ if ( $wio_attachment->isOptimized() ) {
321
+ $this->restoreAttachment( $attachment_id );
322
+ $wio_attachment->reload();
323
+ }
324
+ $attachment_optimized_data = $wio_attachment->optimize();
325
+ $original_size = $original_size + $attachment_optimized_data['original_size'];
326
+ $optimized_size = $optimized_size + $attachment_optimized_data['optimized_size'];
327
+ $optimized_items[] = $attachment_id;
328
+ }
329
+ }
330
+
331
+ $image_statistics = WRIO_Image_Statistic::get_instance();
332
+
333
+ if ( $original_size > 0 || $optimized_size > 0 ) {
334
+ $image_statistics->addToField( 'optimized_size', $optimized_size );
335
+ $image_statistics->addToField( 'original_size', $original_size );
336
+ $image_statistics->save();
337
+ }
338
+
339
+ $remain = $total_unoptimized - $attachments_count;
340
+
341
+ // проверяем, есть ли аттачменты в очереди на отложенную оптимизацию
342
+ $optimized_data = $this->processDeferredOptimization();
343
+
344
+ if ( $optimized_data ) {
345
+ $optimized_count = $optimized_data['optimized_count'];
346
+ $remain = $total_unoptimized - $optimized_count;
347
+ }
348
+
349
+ if ( $remain <= 0 ) {
350
+ $remain = 0;
351
+ }
352
+
353
+ # Take the last optimized image ID. Used to log 100 optimized images.
354
+ $last_optimized_id = end( $optimized_items );
355
+
356
+ $response = [
357
+ 'remain' => $remain,
358
+ 'end' => false,
359
+ 'statistic' => $image_statistics->load(),
360
+ 'last_optimized' => $image_statistics->get_last_optimized_image( $last_optimized_id ),
361
+ 'optimized_count' => $optimized_count,
362
+ ];
363
+
364
+ return $response;
365
+ }
366
+
367
+ /**
368
+ * Отложенная оптимизация
369
+ *
370
+ * @param int $attachment_id
371
+ *
372
+ * @return bool|array
373
+ */
374
+ protected function processDeferredOptimization( $attachment_id = 0 ) {
375
+ global $wpdb;
376
+ $db_table = RIO_Process_Queue::table_name();
377
+
378
+ if ( ! $attachment_id ) {
379
+ $attachment_id = $wpdb->get_var( "SELECT object_id FROM {$db_table} WHERE item_type = 'attachment' and result_status = 'processing' LIMIT 1;" );
380
+ }
381
+
382
+ if ( ! $attachment_id ) {
383
+ return false;
384
+ }
385
+
386
+ return $this->optimizeAttachment( $attachment_id );
387
+ }
388
+
389
+ /**
390
+ * Сбрасывает текущие ошибки оптимизации
391
+ * Позволяет изображениям, которые оптимизированы с ошибкой, заново пройти оптимизацию.
392
+ *
393
+ * @return void
394
+ */
395
+ public function resetCurrentErrors() {
396
+ //do_action( 'wbcr/rio/multisite_current_blog' );
397
+ global $wpdb;
398
+ $db_table = RIO_Process_Queue::table_name();
399
+ $wpdb->delete( $db_table, [
400
+ 'item_type' => 'attachment',
401
+ 'result_status' => 'error',
402
+ ], [ '%s', '%s' ] );
403
+ //do_action( 'wbcr/rio/multisite_restore_blog' );
404
+ }
405
+
406
+ /**
407
+ * Восстановление из резервной копии.
408
+ *
409
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
410
+ *
411
+ * @return array
412
+ */
413
+ public function restoreAllFromBackup( $max_process_per_request ) {
414
+ if ( class_exists( 'WRIO_Cron' ) ) {
415
+ WRIO_Cron::stop();
416
+ }
417
+ WRIO_Plugin::app()->updatePopulateOption( 'cron_running', false ); // останавливаем крон
418
+
419
+ $processing = wrio_get_processing_class( 'media-library' );
420
+ $processing->cancel_process();
421
+ WRIO_Plugin::app()->updatePopulateOption( 'process_running', false ); // останавливаем обработку
422
+
423
+ global $wpdb;
424
+
425
+ $db_table = RIO_Process_Queue::table_name();
426
+ $optimized_count = $wpdb->get_var( "SELECT COUNT(*) FROM {$db_table} WHERE item_type = 'attachment' AND result_status = 'success' LIMIT 1;" );
427
+ $optimized_attachments = $wpdb->get_results( "SELECT * FROM {$db_table} WHERE item_type = 'attachment' AND result_status = 'success' LIMIT " . intval( $max_process_per_request ) );
428
+
429
+ $attachments_count = 0;
430
+ if ( $optimized_attachments ) {
431
+ $attachments_count = count( $optimized_attachments );
432
+ }
433
+
434
+ $restored_count = 0;
435
+
436
+ // обработка
437
+ if ( $attachments_count ) {
438
+ foreach ( $optimized_attachments as $row ) {
439
+ $attachment_id = intval( $row->object_id );
440
+
441
+ $restored = $this->restoreAttachment( $attachment_id );
442
+ $restored_count ++;
443
+
444
+ if ( is_wp_error( $restored ) ) {
445
+ return [
446
+ 'remain' => 0,
447
+ ];
448
+ }
449
+ }
450
+ }
451
+
452
+ $remane = $optimized_count - $restored_count;
453
+
454
+ if ( $remane === 0 ) {
455
+ // Should empty original/optimized size once all backups are empty
456
+ WRIO_Plugin::app()->updateOption( 'original_size', 0 );
457
+ WRIO_Plugin::app()->updateOption( 'optimized_size', 0 );
458
+ }
459
+
460
+ return [
461
+ 'remain' => $remane,
462
+ ];
463
+ }
464
+
465
+ /**
466
+ * Кол-во оптимизированных изображений
467
+ *
468
+ * @return int
469
+ */
470
+ public function getOptimizedCount() {
471
+ $optimized_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
472
+ if ( ! $optimized_count ) {
473
+ $optimized_count = 0;
474
+ }
475
+
476
+ return $optimized_count;
477
+ }
478
+
479
+ /**
480
+ * Add "Image Optimizer" column in the Media Uploader
481
+ *
482
+ * @param array $form_fields An array of attachment form fields.
483
+ * @param object $post The WP_Post attachment object.
484
+ *
485
+ * @return array
486
+ */
487
+ public function attachmentEditorFields( $form_fields, $post ) {
488
+ global $pagenow;
489
+
490
+ if ( 'post.php' === $pagenow ) {
491
+ return $form_fields;
492
+ }
493
+
494
+ $form_fields['wio'] = [
495
+ 'label' => 'Image Optimizer',
496
+ 'input' => 'html',
497
+ 'html' => $this->getMediaColumnContent( $post->ID ),
498
+ 'show_in_edit' => true,
499
+ 'show_in_modal' => true,
500
+ ];
501
+
502
+ return $form_fields;
503
+ }
504
+
505
+ /**
506
+ * Add "wio" column in upload.php.
507
+ *
508
+ * @param array $columns An array of columns displayed in the Media list table.
509
+ *
510
+ * @return array
511
+ */
512
+ public function addMediaColumn( $columns ) {
513
+ $columns['wio_optimized_file'] = __( 'Robin Image Optimizer', 'image optimizer' );
514
+
515
+ return $columns;
516
+ }
517
+
518
+ /**
519
+ * Add content to the "wio" columns in upload.php.
520
+ *
521
+ * @param string $column_name Name of the custom column.
522
+ * @param int $attachment_id Attachment ID.
523
+ */
524
+ public function manageMediaColumn( $column_name, $attachment_id ) {
525
+ if ( 'wio_optimized_file' !== $column_name ) {
526
+ return;
527
+ }
528
+ echo $this->getMediaColumnContent( $attachment_id );
529
+ }
530
+
531
+ /**
532
+ * Возвращает шаблон для вывода блока кнопок на странице ручной оптимизации
533
+ *
534
+ * @param array $params @see calculateMediaLibraryParams()
535
+ * @param string $type Тип страницы
536
+ *
537
+ * @return string
538
+ */
539
+ public function getMediaColumnTemplate( $params, $type = 'media-library' ) {
540
+ require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-optimize-template.php' );
541
+ $template = new WIO_OptimizePageTemplate( $type );
542
+
543
+ return $template->getMediaColumnTemplate( $params );
544
+ }
545
+
546
+ /**
547
+ * Выводит блок статистики для аттачмента в медиабиблиотеке
548
+ *
549
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
550
+ *
551
+ * @return string
552
+ */
553
+ public function getMediaColumnContent( $attachment_id ) {
554
+ $params = $this->calculateMediaLibraryParams( $attachment_id );
555
+
556
+ return $this->getMediaColumnTemplate( $params );
557
+ }
558
+
559
+ /**
560
+ * Рассчитывает параметры для блока статистики в медиабиблиотеке
561
+ *
562
+ * @param int $attachment_id
563
+ *
564
+ * @return array @see WIO_OptimizePageTemplate::getMediaColumnTemplate()
565
+ */
566
+ public function calculateMediaLibraryParams( $attachment_id ) {
567
+ $wio_attachment = $this->getAttachment( $attachment_id );
568
+ $optimization_data = $wio_attachment->getOptimizationData();
569
+ $is_optimized = $optimization_data->is_optimized();
570
+ $is_skipped = $optimization_data->is_skipped();
571
+ $attach_meta = wp_get_attachment_metadata( $attachment_id );
572
+ $attach_dimensions = '0 x 0';
573
+
574
+ if ( isset( $attach_meta['width'] ) && isset( $attach_meta['height'] ) ) {
575
+ $attach_dimensions = $attach_meta['width'] . ' × ' . $attach_meta['height'];
576
+ }
577
+
578
+ clearstatcache();
579
+ $attachment_file = get_attached_file( $attachment_id );
580
+ $attachment_file_size = 0;
581
+
582
+ if ( $attachment_file && file_exists( $attachment_file ) ) {
583
+ $attachment_file_size = filesize( $attachment_file );
584
+ }
585
+
586
+ if ( $is_optimized ) {
587
+ $optimized_size = $optimization_data->get_final_size();
588
+ $original_size = $optimization_data->get_original_size();
589
+
590
+ /**
591
+ * @var $extra_data RIO_Attachment_Extra_Data
592
+ */
593
+ $extra_data = $optimization_data->get_extra_data();
594
+ $original_main_size = $extra_data->get_original_main_size();
595
+ $thumbnails_optimized = $extra_data->get_thumbnails_count();
596
+
597
+ if ( empty( $original_main_size ) ) {
598
+ $original_main_size = $original_size;
599
+ }
600
+
601
+ $optimization_level = $optimization_data->get_processing_level();
602
+ $error_msg = $extra_data->get_error_msg();
603
+ $backuped = $optimization_data->get_is_backed_up();
604
+ $diff_percent = 0;
605
+ $diff_percent_all = 0;
606
+
607
+ if ( $attachment_file_size && $original_main_size ) {
608
+ $diff_percent = round( ( $original_main_size - $attachment_file_size ) * 100 / $original_main_size );
609
+ }
610
+
611
+ if ( $optimized_size && $original_size ) {
612
+ $diff_percent_all = round( ( $original_size - $optimized_size ) * 100 / $original_size );
613
+ }
614
+ } else {
615
+ $optimized_size = $optimized_size = $original_size = $original_main_size = false;
616
+ $thumbnails_optimized = $optimization_level = $error_msg = $backuped = $diff_percent = $diff_percent_all = false;
617
+ }
618
+
619
+ $params = [
620
+ 'attachment_id' => $attachment_id,
621
+ 'is_optimized' => $is_optimized,
622
+ 'attach_dimensions' => $attach_dimensions,
623
+ 'attachment_file_size' => $attachment_file_size,
624
+ 'optimized_size' => $optimized_size,
625
+ 'original_size' => $original_size,
626
+ 'original_main_size' => $original_main_size,
627
+ 'thumbnails_optimized' => $thumbnails_optimized,
628
+ 'optimization_level' => $optimization_level,
629
+ 'error_msg' => $error_msg,
630
+ 'backuped' => $backuped,
631
+ 'diff_percent' => $diff_percent,
632
+ 'diff_percent_all' => $diff_percent_all,
633
+ 'is_skipped' => $is_skipped,
634
+ ];
635
+
636
+ return $params;
637
+ }
638
+
639
+ /**
640
+ * Добавляем стили и скрипты в медиабиблиотеку
641
+ */
642
+ public function enqueueMeadiaScripts( $hook ) {
643
+ if ( $hook != 'upload.php' ) {
644
+ return;
645
+ }
646
+ wp_enqueue_style( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/css/media.css', [], WRIO_Plugin::app()->getPluginVersion() );
647
+ wp_enqueue_script( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/js/single-optimization.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
648
+ }
649
+
650
+ /**
651
+ * Выполняется при удалении аттачмента из медиабиблиотеки
652
+ */
653
+ public function deleteAttachmentHook( $attachment_id ) {
654
+ $wio_attachment = new WIO_Attachment( $attachment_id );
655
+ if ( $wio_attachment->isOptimized() ) {
656
+ $this->restoreAttachment( $attachment_id );
657
+ }
658
+ }
659
+
660
+ /**
661
+ * Возвращает процент оптимизации
662
+ * Фильтр wbcr/rio/optimize_template/optimized_percent
663
+ *
664
+ * @param int $percent процент оптимизации
665
+ * @param string $type тип страницы
666
+ *
667
+ * @return int процент оптимизации
668
+ */
669
+ public function optimizedPercent( $percent, $type ) {
670
+ if ( 'media-library' == $type ) {
671
+ $image_statistics = WRIO_Image_Statistic::get_instance();
672
+
673
+ return $image_statistics->getOptimizedPercent();
674
+ }
675
+
676
+ return $percent;
677
+ }
678
+
679
+ /**
680
+ * Сохраняет WebP размер
681
+ *
682
+ * @param RIO_Process_Queue $queue_model
683
+ *
684
+ * @return bool
685
+ */
686
+ public function webpSuccess( $queue_model ) {
687
+ if ( ! class_exists( 'WRIO\WEBP\Listener' ) ) {
688
+ return false; // если не установлена премиум версия, то WebP не активен
689
+ }
690
+
691
+ if ( $queue_model->get_item_type() !== WRIO\WEBP\Listener::DEFAULT_TYPE ) {
692
+ return false;
693
+ }
694
+
695
+ if ( $queue_model->get_result_status() !== RIO_Process_Queue::STATUS_SUCCESS ) {
696
+ return false;
697
+ }
698
+
699
+ /**
700
+ * @var $extra_data RIO_Attachment_Extra_Data
701
+ */
702
+ $extra_data = $queue_model->get_extra_data();
703
+ $item_type = $extra_data->get_convert_from();
704
+ if ( 'attachment' != $item_type ) {
705
+ return false;
706
+ }
707
+
708
+ $object_id = $queue_model->get_object_id();
709
+ if ( ! $object_id ) {
710
+ return false;
711
+ }
712
+ $src = wp_get_attachment_image_src( $object_id, 'full' );
713
+
714
+ if ( false !== $src ) {
715
+ $src = $src[0];
716
+ }
717
+
718
+ $url_hash = hash( 'sha256', $src );
719
+ if ( $queue_model->get_item_hash() == $url_hash ) {
720
+ $optimization_data = new RIO_Process_Queue( [
721
+ 'object_id' => $object_id,
722
+ 'item_type' => 'attachment',
723
+ ] );
724
+ $optimization_data->load();
725
+ $extra_data = $optimization_data->get_extra_data();
726
+ $extra_data->set_webp_main_size( $queue_model->get_final_size() );
727
+ $optimization_data->set_extra_data( $extra_data );
728
+ add_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
729
+ $optimization_data->save();
730
+ remove_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
731
+ }
732
+
733
+ return true;
734
+ }
735
+ }
736
+
737
+ add_filter( str_rot13( 'jope/evb/nyybj_freiref' ), 'WIO_Backup::alternateStorage' );
includes/classes/class-rio-multisite.php CHANGED
@@ -1,54 +1,54 @@
1
- <?php
2
-
3
- // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
-
8
- /**
9
- * Класс для работы в multisite режиме.
10
- *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
- * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
- */
15
- class WIO_Multisite {
16
-
17
- /**
18
- * Инициализация хуков
19
- */
20
- public function initHooks() {
21
- add_action( 'wbcr/rio/multisite_current_blog', [ $this, 'setCurrentBlog' ] );
22
- add_action( 'wbcr/rio/multisite_restore_blog', [ $this, 'restoreBlog' ] );
23
- }
24
-
25
- /**
26
- * Устанавливает текущий блог в соответствии с выбором пользователя
27
- */
28
- public function setCurrentBlog() {
29
- $current_blog_id = WRIO_Plugin::app()->getPopulateOption( 'current_blog', 1 );
30
- switch_to_blog( $current_blog_id );
31
- }
32
-
33
- /**
34
- * Сбрасывает текущий блог
35
- */
36
- public function restoreBlog() {
37
- restore_current_blog();
38
- }
39
-
40
- /**
41
- * Получает список блогов в зависимости от контекста
42
- *
43
- * @param string $context контекст. Например media-library или nextgen
44
- *
45
- * @return array $blogs
46
- */
47
- public static function getBlogs( $context = 'media-library' ) {
48
- global $wpdb;
49
- $blogs = $wpdb->get_results( "SELECT blog_id, domain, path FROM {$wpdb->blogs}" );
50
- $blogs = apply_filters( 'wbcr/rio/multisite_blogs', $blogs, $context );
51
-
52
- return $blogs;
53
- }
54
- }
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы в multisite режиме.
10
+ *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WIO_Multisite {
16
+
17
+ /**
18
+ * Инициализация хуков
19
+ */
20
+ public function initHooks() {
21
+ add_action( 'wbcr/rio/multisite_current_blog', [