PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.6.7
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.6.7
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
code-profiler / static / code-profiler.js

code-profiler.js in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.6.7, at static/code-profiler.js

861 lines 21.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 +=====================================================================+
3 | ____ _ ____ __ _ _ |
4 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
5 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
6 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
7 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
8 | |
9 | (c) Jerome Bruandet ~ https://code-profiler.com/ |
10 +=====================================================================+
11 */
12
13 // =====================================================================
14 // Generic stuff
15
16 // TipTip tooltip
17 jQuery( document ).ready(function( $ ) {
18 'use strict';
19 $('.code-profiler-tip').tipTip( {
20 'attribute': 'data-tip',
21 'fadeIn': 50,
22 'fadeOut': 50,
23 'delay': 100,
24 'maxWidth' : '350px'
25 });
26
27 // We remove the '&action=delete_profiles...' query string because
28 // if the user reloaded the page that would throw an error:
29 var url = window.location.href;
30 window.history.replaceState({},
31 document.title,
32 url.replace( /&action=delete_profiles&.+/, '')
33 );
34
35 });
36
37 // Append/clear the search query to/from the query string
38 function cpjs_search_query() {
39
40 'use strict';
41 var query;
42 if ( jQuery('#search_id-search-input').val().length > 0 ) {
43 query = '&s=' + jQuery('#search_id-search-input').val();
44 // Case sensitivity
45 if ( jQuery('#case-search-input').is(':checked') === true ) {
46 query += '&c=1';
47 }
48 jQuery('#profile-form').attr('action', jQuery('#profile-form').attr('action')+ query );
49
50 } else {
51 jQuery('#profile-form').attr('action','');
52 var url = window.location.href;
53 window.history.replaceState({},
54 document.title,
55 url.replace( /&s=[^&$]+/, '')
56 );
57 var url = window.location.href;
58 window.history.replaceState({},
59 document.title,
60 url.replace( /&c=1/, '')
61 );
62 }
63 }
64
65 // =====================================================================
66 // Summary page
67
68 function cpjs_front_or_backend( item ) {
69 'use strict';
70 // Enable/disable frontend/backend select box
71 // depending on user's choice
72 if ( item == 1 ) {
73 jQuery('#p-frontend').show();
74 jQuery('#p-backend').hide();
75 jQuery('#p-custom').hide();
76 jQuery('#id-frontend').focus();
77 jQuery('#user-unauthenticated').prop('disabled', false);
78 } else if ( item == 2 ) {
79 jQuery('#p-backend').show();
80 jQuery('#p-frontend').hide();
81 jQuery('#p-custom').hide();
82 jQuery('#id-backend').focus();
83 jQuery('#user-unauthenticated').prop('disabled', true);
84 jQuery('#user-authenticated').prop('checked', true);
85 jQuery('#user-name').prop('disabled', false);
86 } else {
87 jQuery('#p-custom').show();
88 jQuery('#p-frontend').hide();
89 jQuery('#p-backend').hide();
90 jQuery('#id-custom').focus();
91 jQuery('#user-unauthenticated').prop('disabled', false);
92 }
93 }
94
95 function cpjs_authenticated( id ) {
96 if ( id == 1 ) {
97 jQuery('#user-name').prop('disabled', false);
98 jQuery('#user-name').focus();
99 } else {
100 jQuery('#user-name').prop('disabled', true);
101 }
102 }
103
104 function cpjs_show_adv_settings() {
105 jQuery('#cp-advanced-settings').slideDown();
106 jQuery('#button-adv-settings').prop('disabled', true);
107 }
108
109 function cpjs_get_post( id ) {
110 if ( id == 1 ) {
111 jQuery('#post-value').prop('disabled', false);
112 jQuery('#id-content-type').prop('disabled', false);
113 jQuery('#post-value').focus();
114 } else {
115 jQuery('#post-value').prop('disabled', true);
116 jQuery('#id-content-type').prop('disabled', true);
117 }
118 }
119
120 function cpjs_content_type( value ) {
121 if ( value == 1 ) {
122 jQuery('#ct-1').slideDown();
123 jQuery('#ct-2').slideUp();
124 } else {
125 jQuery('#ct-2').slideDown();
126 jQuery('#ct-1').slideUp();
127 }
128 }
129
130 function cpjs_isJSON( data ) {
131
132 if ( jQuery('#id-content-type').val() == 1 || jQuery('#get-method').prop('checked') == true ) {
133 // Ignore
134 return 1;
135 }
136 try {
137 return JSON.parse( data );
138 } catch (e) {
139 // Not a JSON-encoded string
140 return null;
141 }
142 }
143
144 // =====================================================================
145 // Log page: filter and delete the log.
146
147 function cpjs_filter_log() {
148 'use strict';
149 // Create bitmask
150 var bitmask = 0;
151 if ( document.cplogform.info.checked == true ) { bitmask += 1; }
152 if ( document.cplogform.warn.checked == true ) { bitmask += 2; }
153 if ( document.cplogform.error.checked == true ) { bitmask += 4; }
154 if ( document.cplogform.debug.checked == true ) { bitmask += 8; }
155
156 // Clear the textarea
157 document.cplogform.cptxtlog.value = '';
158
159 // Browser through our array and return only selected verbosity
160 var cp_count = 0;
161 var i = 0;
162 for ( i = 0; i < cplog_array.length; ++i ) {
163 var line = decodeURIComponent( cplog_array[i] );
164 var line_array = line.split('~~', 2 );
165 if ( line_array[0] & bitmask ) {
166 document.cplogform.cptxtlog.value += line_array[1];
167 ++cp_count;
168 }
169 }
170 if ( cp_count == 0 ) {
171 document.cplogform.cptxtlog.value = '\n > ' + cpi18n.empty_log;
172 }
173 }
174
175 function cpjs_delete_log() {
176 'use strict';
177 if ( confirm( cpi18n.delete_log ) ) {
178 return true;
179 }
180 return false;
181 }
182 // =====================================================================
183 // AJAX call to start the profiler.
184
185 function cpjs_start_profiler() {
186 'use strict';
187 // Get the nonce
188 var cp_nonce = jQuery('#cp_nonce').val();
189 if ( cp_nonce == '') {
190 alert( cpi18n.missing_nonce );
191 return;
192 }
193
194 // Get the scan type (frontend/backend)
195 var post;
196 var where = jQuery('input[name="where"]:checked').val();
197 if ( where == 'frontend') {
198 post = jQuery('#id-frontend').val();
199
200 } else if ( where == 'backend') {
201 post = jQuery('#id-backend').val();
202
203 } else if ( where == 'custom') {
204 post = jQuery('#id-custom').val().trim(); // Trim user input
205
206 } else {
207 alert( cpi18n.missing_frontbackend );
208 return;
209 }
210 if ( post == '') {
211 alert( cpi18n.missing_post );
212 return;
213 }
214
215 // Get the profile's name
216 var profile = jQuery('input[name="profile"]').val();
217 if ( profile == '') {
218 alert( cpi18n.missing_profilename );
219 jQuery('input[name="profile"]').focus();
220 return;
221 }
222
223 var user = jQuery('input[name="user"]:checked').val();
224 if ( user == '') {
225 alert( cpi18n.missing_userauth );
226 return;
227 }
228
229 var username = jQuery('#user-name').val().trim(); // Trim user input
230 if ( user == 'authenticated') {
231 if ( username == '') {
232 alert( cpi18n.missing_username );
233 jQuery('#user-name').focus();
234 return;
235 }
236 }
237
238 var ua = jQuery('#ua-id').val();
239 if ( ua == 'undefined') {
240 ua = 'FireFox';
241 }
242
243 var theme = jQuery('#id-theme').val();
244
245 // GET or POST
246 var method = jQuery('input[name="method"]:checked').val();
247 var payload = '';
248 if ( method == 'post') {
249 // Payload
250 payload = jQuery('#post-value').val();
251 } else {
252 method = 'get';
253 }
254
255 //Content type
256 var ct = jQuery('#id-content-type').val();
257 // application/json
258 if ( ct == 2 ) {
259 if ( cpjs_isJSON( payload ) == null ) {
260 alert( cpi18n.missing_ajax );
261 jQuery('#user-name').focus();
262 return;
263 }
264 }
265
266 var cookies = jQuery('#cp-cookies').val();
267 var headers = jQuery('#custom-headers').val();
268
269 // Change buttons status and add animated image with status message
270 jQuery('#start-profile').prop('disabled', true);
271 jQuery('#cp-progress-div').slideDown();
272 jQuery('#progress-gif').slideDown();
273 jQuery('#progress-text').slideDown();
274 jQuery('#code-profiler-error').slideUp();
275 jQuery('#cp-span-progress').css('width', '30%');
276
277 var data = {
278 'action': 'codeprofiler_start_profiler',
279 'cp_nonce': cp_nonce,
280 'where': where,
281 'post': post,
282 'content_type': ct,
283 'profile': profile,
284 'user': user,
285 'username': username,
286 'cookies': cookies,
287 'custom_headers': headers,
288 'method': method,
289 'payload': payload,
290 'ua': ua,
291 'theme': theme
292 };
293 // Send the request via AJAX
294 jQuery.ajax( {
295 type: 'POST',
296 url: ajaxurl,
297 data: data,
298 dataType: 'json',
299 success: function( response ) {
300
301 if (typeof response === 'undefined') {
302 cpjs_start_error('<p>'+ cpi18n.unknown_error +'</p>');
303 return;
304 }
305
306 if ( response.status != 'success') {
307 cpjs_start_error('<p>'+ response.message +'</p>');
308 return;
309 }
310
311 // ------------------------------------------------------------
312 // Inform the user we're moving to step 2
313 jQuery('#cp-span-progress').css('width', '70%');
314 jQuery('#progress-text').html( cpi18n.preparing_report );
315
316 data['action'] = 'codeprofiler_prepare_report';
317 data['microtime'] = response.microtime;
318 jQuery.ajax( {
319 type: 'POST',
320 url: ajaxurl,
321 data: data,
322 dataType: 'json',
323 success: function( response ) {
324
325 if (typeof response === 'undefined') {
326 cpjs_start_error('<p>'+ cpi18n.unknown_error +'</p>');
327 return;
328 }
329
330 if ( response.status != 'success') {
331 cpjs_start_error('<p>'+ response.message +'</p>');
332 return;
333 }
334 var cp_uri;
335 if (response.cp_profile !== 'undefined' && response.cp_profile != '') {
336 cp_uri = '&cptab=profiles_list&action=view_profile&id=' + response.cp_profile + '&section=1';
337 } else {
338 cp_uri = '&cptab=profiles_list';
339 }
340
341 // All good, redirect to the Profiles List tab
342 jQuery('#cp-span-progress').css('width', '100%');
343 window.location.href = window.location.href + cp_uri;
344 return;
345
346 },
347
348 // Display non-200 HTTP response
349 error: function( xhr, status, err ) {
350 if ( err != '') {
351 if ( xhr.status != 0 ) {
352 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
353 // Timeout
354 if ( xhr.status == 503 || xhr.status == 504 ) {
355 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.timeout_error +'.</p>');
356 // Redirections, not found
357 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
358 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.notfound_error +'.</p>');
359 // Forbidden
360 } else if ( xhr.status == 403 ) {
361 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.forbidden_error +'.</p>');
362 // Internal error
363 } else if ( xhr.status == 500 ) {
364 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error +'.</p>');
365 } else {
366 cpjs_start_error('<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>');
367 }
368 return;
369
370 } else {
371 cpjs_start_error('<p>'+ cpi18n.unknown_error +' '+ err +'.</p>');
372 return;
373 }
374 }
375 return;
376 }
377 });
378 // ------------------------------------------------------------
379 },
380
381 // Display non-200 HTTP response
382 error: function( xhr, status, err ) {
383 if ( err != '') {
384 if ( xhr.status != 0 ) {
385 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
386 // Timeout
387 if ( xhr.status == 503 || xhr.status == 504 ) {
388 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.timeout_error +'.</p>');
389 // Redirections, not found
390 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
391 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.notfound_error +'.</p>');
392 // Forbidden
393 } else if ( xhr.status == 403 ) {
394 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.forbidden_error +'.</p>');
395 // Internal error
396 } else if ( xhr.status == 500 ) {
397 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error +'.</p>');
398 } else {
399 cpjs_start_error('<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>');
400 }
401 return;
402
403 } else {
404 cpjs_start_error('<p>'+ cpi18n.unknown_error +' '+ err +'.</p>');
405 return;
406 }
407 }
408 return;
409 }
410 });
411 }
412
413 // Display error
414 function cpjs_start_error( error ) {
415 'use strict';
416 jQuery('#start-profile').prop('disabled', false);
417 jQuery('#progress-gif').slideUp();
418 jQuery('#progress-text').slideUp();
419 jQuery('#cp-span-progress').css('width', '0%');
420 jQuery('#code-profiler-error').html( error );
421 jQuery('#code-profiler-error').slideDown();
422 jQuery('#cp-progress-div').slideUp();
423
424 }
425
426 // =====================================================================
427 // Profiles List page.
428
429 function cpjs_delete_profile() {
430 'use strict';
431 if ( confirm( cpi18n.delete_profile ) ) {
432 return true;
433 }
434 return false;
435 }
436
437 // Hide/show the edit box and buttons when renaming a profile.
438 function cpjs_toggle_name( row ) {
439 if ( jQuery('#profile_div_'+ row).css('display') == 'none') {
440 jQuery('#profile_name_'+ row).hide();
441 jQuery('#profile_div_'+ row).show();
442 jQuery('#edit-'+ row).val( jQuery('#profile_name_'+ row).html() );
443 jQuery('#edit-'+ row).focus();
444 } else {
445 jQuery('#profile_div_'+ row).hide();
446 jQuery('#profile_name_'+ row).show();
447 }
448 }
449
450 // Edit the profile name via AJAX endpoint.
451 function cpjs_edit_name( profile, id, cp_nonce, row ) {
452
453 'use strict';
454
455 if ( cp_nonce == '') {
456 alert( cpi18n.missing_nonce );
457 return;
458 }
459 if ( profile == '') {
460 alert( cpi18n.missing_profileid );
461 return;
462 }
463
464 var new_name = jQuery('#edit-'+ id).val().trim();
465 if ( new_name == '') {
466 alert( cpi18n.missing_profilename );
467 return;
468 }
469
470 jQuery('#profile_spinner_'+ row).addClass('is-active');
471
472 var data = {
473 'action': 'codeprofiler_rename',
474 'cp_nonce': cp_nonce,
475 'new_name': new_name,
476 'profile': profile,
477 };
478
479 // Send the request via AJAX
480 jQuery.ajax( {
481 type: 'POST',
482 url: ajaxurl,
483 data: data,
484 dataType: 'json',
485 success: function( response ) {
486 jQuery('#profile_spinner_'+ row ).removeClass('is-active');
487
488 if (typeof response === 'undefined') {
489 alert( cpi18n.unknown_error );
490 return;
491 }
492
493 if ( response.status != 'success') {
494 alert( response.message );
495 return;
496 }
497
498 // Success: update the name in the table
499 jQuery('#profile_name_'+ id).html( response.newname );
500 cpjs_toggle_name(row);
501 },
502 // Display non-200 HTTP response
503 error: function( xhr, status, err ) {
504 jQuery('#profile_spinner_'+ row ).removeClass('is-active');
505 if ( err != '') {
506 if ( xhr.status != 0 ) {
507 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
508 // Timeout
509 if ( xhr.status == 503 || xhr.status == 504 ) {
510 alert( message +'<br />'+ cpi18n.timeout_error );
511 // Redirections, not found
512 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
513 alert( message +'<br />'+ cpi18n.notfound_error );
514 // Forbidden
515 } else if ( xhr.status == 403 ) {
516 alert( message +'<br />'+ cpi18n.forbidden_error );
517 // Internal error
518 } else if ( xhr.status == 500 ) {
519 alert( message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error );
520 } else {
521 alert( cpi18n.http_error +' '+ xhr.status +' '+ err );
522 }
523 return;
524
525 } else {
526 alert( cpi18n.unknown_error +' '+ err );
527 return;
528 }
529 }
530 return;
531 }
532 });
533 }
534
535 // =====================================================================
536 // Plugins/Theme chart.
537
538 function cpjs_plugins_chart( caxis, clabel, cdata, ctotal_time ) {
539 'use strict';
540 // Switch between vertical and horizontal bars
541 var _indexAxis = caxis;
542 document.getElementById('htov').onclick = function() {
543 if ( _indexAxis == 'x') {
544 _indexAxis = 'y';
545 } else {
546 _indexAxis = 'x';
547 }
548 myChart.destroy();
549 myChart = new Chart(ctx, {
550 type: 'bar',
551 options: {
552 animation: {
553 duration: 1000,
554 onComplete: function() {
555 document.getElementById('download-png-img').href = myChart.toBase64Image();
556 }
557 },
558 indexAxis: _indexAxis,
559 plugins: chartPlugins
560 },
561 plugins:[ plugin],
562 data: chartData
563 });
564 };
565
566 var ctx = document.getElementById('myChart').getContext('2d');
567
568 var chartData = {
569 labels: clabel,
570 datasets: [{
571 label: cpi18n.exec_sec_plugins,
572 backgroundColor: 'rgba(204, 0, 0, .5)',
573 borderColor: '#c00',
574 borderWidth: 2,
575 hoverBackgroundColor: '#B45252',
576 data: cdata
577 }]
578 };
579
580 const total_time = ctotal_time;
581 const footer = (tooltipItems) => {
582 var sum;
583 tooltipItems.forEach(function(tooltipItem) {
584 if ( _indexAxis == 'x') {
585 sum = Math.round( ( tooltipItem.parsed.y / total_time ) * 100 );
586 } else {
587 sum = Math.round( ( tooltipItem.parsed.x / total_time ) * 100 );
588 }
589 });
590 return sum + cpi18n.pc_plugins;
591 };
592
593 var chartPlugins = {
594 title: {
595 display: true,
596 text: cpi18n.exec_tot_plugins_1 +' (' + cpi18n.chart_total +' '+ ctotal_time +')'
597 },
598 legend: {
599 display: false
600 },
601 tooltip: {
602 borderWidth: 1,
603 borderColor: '#666',
604 displayColors: false,
605 backgroundColor: '#F5F5B5',
606 titleColor:'#666',
607 padding: 8,
608 footerColor: '#666',
609 callbacks: {
610 footer: footer,
611 labelTextColor: function(context) {
612 return '#543453';
613 }
614 }
615 }
616 }
617
618 // We want a background colour for the downloaded PNG file
619 const plugin = {
620 id: 'custom_canvas_background_color',
621 beforeDraw: (chart) => {
622 const ctx = chart.canvas.getContext('2d');
623 ctx.save();
624 ctx.globalCompositeOperation = 'destination-over';
625 ctx.fillStyle = '#f0f0f1',
626 ctx.fillRect(0, 0, chart.width, chart.height);
627 ctx.restore();
628 }
629 }
630
631 var myChart = new Chart(ctx, {
632 type: 'bar',
633 data: chartData,
634 options: {
635 animation: {
636 duration: 700,
637 onComplete: function() {
638 jQuery('#cp-footer-buttons').slideDown(200);
639 document.getElementById('download-png-img').href = myChart.toBase64Image();
640 }
641 },
642 indexAxis: _indexAxis,
643 plugins: chartPlugins
644 },
645 plugins:[plugin]
646 });
647 }
648
649 // =====================================================================
650 // File I/O chart.
651
652 function cpjs_iostats_chart( caxis, clabel, cdata, ctotal_calls ) {
653 'use strict';
654 // Switch between vertical and horizontal bars
655 var _indexAxis = caxis;
656 document.getElementById('htov').onclick = function() {
657 if ( _indexAxis == 'x') {
658 _indexAxis = 'y';
659 } else {
660 _indexAxis = 'x';
661 }
662 myChart.destroy();
663 myChart = new Chart(ctx, {
664 type: 'line',
665 options: {
666 animation: {
667 duration: 1000,
668 onComplete: function() {
669 document.getElementById('download-png-img').href = myChart.toBase64Image();
670 }
671 },
672 indexAxis: _indexAxis,
673 plugins: chartPlugins
674 },
675 plugins:[ plugin],
676 data: chartData
677 });
678 };
679
680 var ctx = document.getElementById('myChart').getContext('2d');
681
682 var chartData = {
683 labels: clabel,
684 datasets: [{
685 label: cpi18n.iolist_total_calls,
686 backgroundColor: 'rgba(34, 113, 177, .5)',
687 borderColor: '#2271B1',
688 borderWidth: 2,
689 hoverBackgroundColor: '#FF0000',
690 data: cdata,
691 fill: 'origin',
692 radius: 6,
693 pointBackgroundColor: '#B45252'
694 }]
695 };
696 var chartPlugins = {
697 title: {
698 display: true,
699 text: cpi18n.io_calls +' (' + cpi18n.chart_total +' '+ ctotal_calls +')'
700 },
701 legend: {
702 display: false
703 },
704 tooltip: {
705 borderWidth: 1,
706 borderColor: '#666',
707 displayColors: false,
708 backgroundColor: '#F5F5B5',
709 titleColor:'#666',
710 padding: 8,
711 footerColor: '#666',
712 callbacks: {
713 labelTextColor: function(context) {
714 return '#543453';
715 }
716 }
717 }
718 }
719 // We want a background colour for the downloaded PNG file
720 const plugin = {
721 id: 'custom_canvas_background_color',
722 beforeDraw: (chart) => {
723 const ctx = chart.canvas.getContext('2d');
724 ctx.save();
725 ctx.globalCompositeOperation = 'destination-over';
726 ctx.fillStyle = '#f0f0f1',
727 ctx.fillRect(0, 0, chart.width, chart.height);
728 ctx.restore();
729 }
730 }
731
732 var myChart = new Chart(ctx, {
733 type: 'line',
734 data: chartData,
735 options: {
736 animation: {
737 duration: 700,
738 onComplete: function() {
739 jQuery('#cp-footer-buttons').slideDown(200);
740 document.getElementById('download-png-img').href = myChart.toBase64Image();
741 }
742 },
743 indexAxis: _indexAxis,
744 plugins: chartPlugins
745 },
746 plugins:[plugin]
747 });
748
749 }
750 // =====================================================================
751 // Disk I/O chart.
752
753 function cpjs_diskio_chart( caxis, clabel, cdata ) {
754 'use strict';
755 // Switch between vertical and horizontal bars
756 var _indexAxis = caxis;
757 document.getElementById('htov').onclick = function() {
758 if ( _indexAxis == 'x') {
759 _indexAxis = 'y';
760 } else {
761 _indexAxis = 'x';
762 }
763 myChart.destroy();
764 myChart = new Chart(ctx, {
765 type: 'line',
766 options: {
767 animation: {
768 duration: 1000,
769 onComplete: function() {
770 document.getElementById('download-png-img').href = myChart.toBase64Image();
771 }
772 },
773 indexAxis: _indexAxis,
774 plugins: chartPlugins
775 },
776 plugins:[ plugin],
777 data: chartData
778 });
779 };
780 var ctx = document.getElementById('myChart').getContext('2d');
781
782 var chartData = {
783 labels: clabel,
784 datasets: [{
785 label: cpi18n.disk_io_bytes,
786 backgroundColor: 'rgba(143, 240, 164, .5)',
787 borderColor: '#41B141',
788 borderWidth: 2,
789 hoverBackgroundColor: '#FF0000',
790 data: cdata,
791 fill: 'origin',
792 radius: 6,
793 pointBackgroundColor: '#B45252'
794 }]
795 };
796 var chartPlugins = {
797 title: {
798 display: true,
799 text: cpi18n.disk_io_title,
800 },
801 legend: {
802 display: false
803 },
804 tooltip: {
805 borderWidth: 1,
806 borderColor: '#666',
807 displayColors: false,
808 backgroundColor: '#F5F5B5',
809 titleColor:'#666',
810 padding: 8,
811 footerColor: '#666',
812 callbacks: {
813 labelTextColor: function(context) {
814 return '#543453';
815 }
816 }
817 }
818 }
819 // We want a background colour for the downloaded PNG file
820 const plugin = {
821 id: 'custom_canvas_background_color',
822 beforeDraw: (chart) => {
823 const ctx = chart.canvas.getContext('2d');
824 ctx.save();
825 ctx.globalCompositeOperation = 'destination-over';
826 ctx.fillStyle = '#f0f0f1',
827 ctx.fillRect(0, 0, chart.width, chart.height);
828 ctx.restore();
829 }
830 }
831
832 var myChart = new Chart(ctx, {
833 type: 'line',
834 data: chartData,
835 options: {
836 animation: {
837 duration: 700,
838 onComplete: function() {
839 jQuery('#cp-footer-buttons').slideDown(200);
840 document.getElementById('download-png-img').href = myChart.toBase64Image();
841 }
842 },
843 indexAxis: _indexAxis,
844 plugins: chartPlugins
845 },
846 plugins:[plugin]
847 });
848 }
849
850 // =====================================================================
851 // Settings page
852
853 function cpjs_copy_textarea( id ) {
854 document.getElementById(id).select();
855 document.execCommand('copy');
856 alert( cpi18n.text_copied );
857 }
858
859 // =====================================================================
860 // EOF
861