PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.7.4
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.7.4
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.7.4, at static/code-profiler.js

863 lines 21.8 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://nintechnet.com/codeprofiler/ |
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 var exclusions = jQuery('#exclusions').val();
269
270 // Change buttons status and add animated image with status message
271 jQuery('#start-profile').prop('disabled', true);
272 jQuery('#cp-progress-div').slideDown();
273 jQuery('#progress-gif').slideDown();
274 jQuery('#progress-text').slideDown();
275 jQuery('#code-profiler-error').slideUp();
276 jQuery('#cp-span-progress').css('width', '30%');
277
278 var data = {
279 'action': 'codeprofiler_start_profiler',
280 'cp_nonce': cp_nonce,
281 'where': where,
282 'post': post,
283 'content_type': ct,
284 'profile': profile,
285 'user': user,
286 'username': username,
287 'cookies': cookies,
288 'custom_headers': headers,
289 'exclusions': exclusions,
290 'method': method,
291 'payload': payload,
292 'ua': ua,
293 'theme': theme
294 };
295 // Send the request via AJAX
296 jQuery.ajax( {
297 type: 'POST',
298 url: ajaxurl,
299 data: data,
300 dataType: 'json',
301 success: function( response ) {
302
303 if (typeof response === 'undefined') {
304 cpjs_start_error('<p>'+ cpi18n.unknown_error +'</p>');
305 return;
306 }
307
308 if ( response.status != 'success') {
309 cpjs_start_error('<p>'+ response.message +'</p>');
310 return;
311 }
312
313 // ------------------------------------------------------------
314 // Inform the user we're moving to step 2
315 jQuery('#cp-span-progress').css('width', '70%');
316 jQuery('#progress-text').html( cpi18n.preparing_report );
317
318 data['action'] = 'codeprofiler_prepare_report';
319 data['microtime'] = response.microtime;
320 jQuery.ajax( {
321 type: 'POST',
322 url: ajaxurl,
323 data: data,
324 dataType: 'json',
325 success: function( response ) {
326
327 if (typeof response === 'undefined') {
328 cpjs_start_error('<p>'+ cpi18n.unknown_error +'</p>');
329 return;
330 }
331
332 if ( response.status != 'success') {
333 cpjs_start_error('<p>'+ response.message +'</p>');
334 return;
335 }
336 var cp_uri;
337 if (response.cp_profile !== 'undefined' && response.cp_profile != '') {
338 cp_uri = '&cptab=profiles_list&action=view_profile&id=' + response.cp_profile + '&section=1';
339 } else {
340 cp_uri = '&cptab=profiles_list';
341 }
342
343 // All good, redirect to the Profiles List tab
344 jQuery('#cp-span-progress').css('width', '100%');
345 window.location.href = window.location.href + cp_uri;
346 return;
347
348 },
349
350 // Display non-200 HTTP response
351 error: function( xhr, status, err ) {
352 if ( err != '') {
353 if ( xhr.status != 0 ) {
354 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
355 // Timeout
356 if ( xhr.status == 503 || xhr.status == 504 ) {
357 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.timeout_error +'.</p>');
358 // Redirections, not found
359 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
360 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.notfound_error +'.</p>');
361 // Forbidden
362 } else if ( xhr.status == 403 ) {
363 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.forbidden_error +'.</p>');
364 // Internal error
365 } else if ( xhr.status == 500 ) {
366 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error +'.</p>');
367 } else {
368 cpjs_start_error('<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>');
369 }
370 return;
371
372 } else {
373 cpjs_start_error('<p>'+ cpi18n.unknown_error +' '+ err +'.</p>');
374 return;
375 }
376 }
377 return;
378 }
379 });
380 // ------------------------------------------------------------
381 },
382
383 // Display non-200 HTTP response
384 error: function( xhr, status, err ) {
385 if ( err != '') {
386 if ( xhr.status != 0 ) {
387 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
388 // Timeout
389 if ( xhr.status == 503 || xhr.status == 504 ) {
390 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.timeout_error +'.</p>');
391 // Redirections, not found
392 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
393 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.notfound_error +'.</p>');
394 // Forbidden
395 } else if ( xhr.status == 403 ) {
396 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.forbidden_error +'.</p>');
397 // Internal error
398 } else if ( xhr.status == 500 ) {
399 cpjs_start_error('<p>'+ message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error +'.</p>');
400 } else {
401 cpjs_start_error('<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>');
402 }
403 return;
404
405 } else {
406 cpjs_start_error('<p>'+ cpi18n.unknown_error +' '+ err +'.</p>');
407 return;
408 }
409 }
410 return;
411 }
412 });
413 }
414
415 // Display error
416 function cpjs_start_error( error ) {
417 'use strict';
418 jQuery('#start-profile').prop('disabled', false);
419 jQuery('#progress-gif').slideUp();
420 jQuery('#progress-text').slideUp();
421 jQuery('#cp-span-progress').css('width', '0%');
422 jQuery('#code-profiler-error').html( error );
423 jQuery('#code-profiler-error').slideDown();
424 jQuery('#cp-progress-div').slideUp();
425
426 }
427
428 // =====================================================================
429 // Profiles List page.
430
431 function cpjs_delete_profile() {
432 'use strict';
433 if ( confirm( cpi18n.delete_profile ) ) {
434 return true;
435 }
436 return false;
437 }
438
439 // Hide/show the edit box and buttons when renaming a profile.
440 function cpjs_toggle_name( row ) {
441 if ( jQuery('#profile_div_'+ row).css('display') == 'none') {
442 jQuery('#profile_name_'+ row).hide();
443 jQuery('#profile_div_'+ row).show();
444 jQuery('#edit-'+ row).val( jQuery('#profile_name_'+ row).html() );
445 jQuery('#edit-'+ row).focus();
446 } else {
447 jQuery('#profile_div_'+ row).hide();
448 jQuery('#profile_name_'+ row).show();
449 }
450 }
451
452 // Edit the profile name via AJAX endpoint.
453 function cpjs_edit_name( profile, id, cp_nonce, row ) {
454
455 'use strict';
456
457 if ( cp_nonce == '') {
458 alert( cpi18n.missing_nonce );
459 return;
460 }
461 if ( profile == '') {
462 alert( cpi18n.missing_profileid );
463 return;
464 }
465
466 var new_name = jQuery('#edit-'+ id).val().trim();
467 if ( new_name == '') {
468 alert( cpi18n.missing_profilename );
469 return;
470 }
471
472 jQuery('#profile_spinner_'+ row).addClass('is-active');
473
474 var data = {
475 'action': 'codeprofiler_rename',
476 'cp_nonce': cp_nonce,
477 'new_name': new_name,
478 'profile': profile,
479 };
480
481 // Send the request via AJAX
482 jQuery.ajax( {
483 type: 'POST',
484 url: ajaxurl,
485 data: data,
486 dataType: 'json',
487 success: function( response ) {
488 jQuery('#profile_spinner_'+ row ).removeClass('is-active');
489
490 if (typeof response === 'undefined') {
491 alert( cpi18n.unknown_error );
492 return;
493 }
494
495 if ( response.status != 'success') {
496 alert( response.message );
497 return;
498 }
499
500 // Success: update the name in the table
501 jQuery('#profile_name_'+ id).html( response.newname );
502 cpjs_toggle_name(row);
503 },
504 // Display non-200 HTTP response
505 error: function( xhr, status, err ) {
506 jQuery('#profile_spinner_'+ row ).removeClass('is-active');
507 if ( err != '') {
508 if ( xhr.status != 0 ) {
509 var message = cpi18n.http_error +' '+ xhr.status +' '+ err;
510 // Timeout
511 if ( xhr.status == 503 || xhr.status == 504 ) {
512 alert( message +'<br />'+ cpi18n.timeout_error );
513 // Redirections, not found
514 } else if ( xhr.status == 301 || xhr.status == 302 || xhr.status == 404 ) {
515 alert( message +'<br />'+ cpi18n.notfound_error );
516 // Forbidden
517 } else if ( xhr.status == 403 ) {
518 alert( message +'<br />'+ cpi18n.forbidden_error );
519 // Internal error
520 } else if ( xhr.status == 500 ) {
521 alert( message +'<br />'+ cpi18n.internal_error +'.<br />'+ cpi18n.timeout_error );
522 } else {
523 alert( cpi18n.http_error +' '+ xhr.status +' '+ err );
524 }
525 return;
526
527 } else {
528 alert( cpi18n.unknown_error +' '+ err );
529 return;
530 }
531 }
532 return;
533 }
534 });
535 }
536
537 // =====================================================================
538 // Plugins/Theme chart.
539
540 function cpjs_plugins_chart( caxis, clabel, cdata, ctotal_time ) {
541 'use strict';
542 // Switch between vertical and horizontal bars
543 var _indexAxis = caxis;
544 document.getElementById('htov').onclick = function() {
545 if ( _indexAxis == 'x') {
546 _indexAxis = 'y';
547 } else {
548 _indexAxis = 'x';
549 }
550 myChart.destroy();
551 myChart = new Chart(ctx, {
552 type: 'bar',
553 options: {
554 animation: {
555 duration: 1000,
556 onComplete: function() {
557 document.getElementById('download-png-img').href = myChart.toBase64Image();
558 }
559 },
560 indexAxis: _indexAxis,
561 plugins: chartPlugins
562 },
563 plugins:[ plugin],
564 data: chartData
565 });
566 };
567
568 var ctx = document.getElementById('myChart').getContext('2d');
569
570 var chartData = {
571 labels: clabel,
572 datasets: [{
573 label: cpi18n.exec_sec_plugins,
574 backgroundColor: 'rgba(204, 0, 0, .5)',
575 borderColor: '#c00',
576 borderWidth: 2,
577 hoverBackgroundColor: '#B45252',
578 data: cdata
579 }]
580 };
581
582 const total_time = ctotal_time;
583 const footer = (tooltipItems) => {
584 var sum;
585 tooltipItems.forEach(function(tooltipItem) {
586 if ( _indexAxis == 'x') {
587 sum = Math.round( ( tooltipItem.parsed.y / total_time ) * 100 );
588 } else {
589 sum = Math.round( ( tooltipItem.parsed.x / total_time ) * 100 );
590 }
591 });
592 return sum + cpi18n.pc_plugins;
593 };
594
595 var chartPlugins = {
596 title: {
597 display: true,
598 text: cpi18n.exec_tot_plugins_1 +' (' + cpi18n.chart_total +' '+ ctotal_time +')'
599 },
600 legend: {
601 display: false
602 },
603 tooltip: {
604 borderWidth: 1,
605 borderColor: '#666',
606 displayColors: false,
607 backgroundColor: '#F5F5B5',
608 titleColor:'#666',
609 padding: 8,
610 footerColor: '#666',
611 callbacks: {
612 footer: footer,
613 labelTextColor: function(context) {
614 return '#543453';
615 }
616 }
617 }
618 }
619
620 // We want a background colour for the downloaded PNG file
621 const plugin = {
622 id: 'custom_canvas_background_color',
623 beforeDraw: (chart) => {
624 const ctx = chart.canvas.getContext('2d');
625 ctx.save();
626 ctx.globalCompositeOperation = 'destination-over';
627 ctx.fillStyle = '#f0f0f1',
628 ctx.fillRect(0, 0, chart.width, chart.height);
629 ctx.restore();
630 }
631 }
632
633 var myChart = new Chart(ctx, {
634 type: 'bar',
635 data: chartData,
636 options: {
637 animation: {
638 duration: 700,
639 onComplete: function() {
640 jQuery('#cp-footer-buttons').slideDown(200);
641 document.getElementById('download-png-img').href = myChart.toBase64Image();
642 }
643 },
644 indexAxis: _indexAxis,
645 plugins: chartPlugins
646 },
647 plugins:[plugin]
648 });
649 }
650
651 // =====================================================================
652 // File I/O chart.
653
654 function cpjs_iostats_chart( caxis, clabel, cdata, ctotal_calls ) {
655 'use strict';
656 // Switch between vertical and horizontal bars
657 var _indexAxis = caxis;
658 document.getElementById('htov').onclick = function() {
659 if ( _indexAxis == 'x') {
660 _indexAxis = 'y';
661 } else {
662 _indexAxis = 'x';
663 }
664 myChart.destroy();
665 myChart = new Chart(ctx, {
666 type: 'line',
667 options: {
668 animation: {
669 duration: 1000,
670 onComplete: function() {
671 document.getElementById('download-png-img').href = myChart.toBase64Image();
672 }
673 },
674 indexAxis: _indexAxis,
675 plugins: chartPlugins
676 },
677 plugins:[ plugin],
678 data: chartData
679 });
680 };
681
682 var ctx = document.getElementById('myChart').getContext('2d');
683
684 var chartData = {
685 labels: clabel,
686 datasets: [{
687 label: cpi18n.iolist_total_calls,
688 backgroundColor: 'rgba(34, 113, 177, .5)',
689 borderColor: '#2271B1',
690 borderWidth: 2,
691 hoverBackgroundColor: '#FF0000',
692 data: cdata,
693 fill: 'origin',
694 radius: 6,
695 pointBackgroundColor: '#B45252'
696 }]
697 };
698 var chartPlugins = {
699 title: {
700 display: true,
701 text: cpi18n.io_calls +' (' + cpi18n.chart_total +' '+ ctotal_calls +')'
702 },
703 legend: {
704 display: false
705 },
706 tooltip: {
707 borderWidth: 1,
708 borderColor: '#666',
709 displayColors: false,
710 backgroundColor: '#F5F5B5',
711 titleColor:'#666',
712 padding: 8,
713 footerColor: '#666',
714 callbacks: {
715 labelTextColor: function(context) {
716 return '#543453';
717 }
718 }
719 }
720 }
721 // We want a background colour for the downloaded PNG file
722 const plugin = {
723 id: 'custom_canvas_background_color',
724 beforeDraw: (chart) => {
725 const ctx = chart.canvas.getContext('2d');
726 ctx.save();
727 ctx.globalCompositeOperation = 'destination-over';
728 ctx.fillStyle = '#f0f0f1',
729 ctx.fillRect(0, 0, chart.width, chart.height);
730 ctx.restore();
731 }
732 }
733
734 var myChart = new Chart(ctx, {
735 type: 'line',
736 data: chartData,
737 options: {
738 animation: {
739 duration: 700,
740 onComplete: function() {
741 jQuery('#cp-footer-buttons').slideDown(200);
742 document.getElementById('download-png-img').href = myChart.toBase64Image();
743 }
744 },
745 indexAxis: _indexAxis,
746 plugins: chartPlugins
747 },
748 plugins:[plugin]
749 });
750
751 }
752 // =====================================================================
753 // Disk I/O chart.
754
755 function cpjs_diskio_chart( caxis, clabel, cdata ) {
756 'use strict';
757 // Switch between vertical and horizontal bars
758 var _indexAxis = caxis;
759 document.getElementById('htov').onclick = function() {
760 if ( _indexAxis == 'x') {
761 _indexAxis = 'y';
762 } else {
763 _indexAxis = 'x';
764 }
765 myChart.destroy();
766 myChart = new Chart(ctx, {
767 type: 'line',
768 options: {
769 animation: {
770 duration: 1000,
771 onComplete: function() {
772 document.getElementById('download-png-img').href = myChart.toBase64Image();
773 }
774 },
775 indexAxis: _indexAxis,
776 plugins: chartPlugins
777 },
778 plugins:[ plugin],
779 data: chartData
780 });
781 };
782 var ctx = document.getElementById('myChart').getContext('2d');
783
784 var chartData = {
785 labels: clabel,
786 datasets: [{
787 label: cpi18n.disk_io_bytes,
788 backgroundColor: 'rgba(143, 240, 164, .5)',
789 borderColor: '#41B141',
790 borderWidth: 2,
791 hoverBackgroundColor: '#FF0000',
792 data: cdata,
793 fill: 'origin',
794 radius: 6,
795 pointBackgroundColor: '#B45252'
796 }]
797 };
798 var chartPlugins = {
799 title: {
800 display: true,
801 text: cpi18n.disk_io_title,
802 },
803 legend: {
804 display: false
805 },
806 tooltip: {
807 borderWidth: 1,
808 borderColor: '#666',
809 displayColors: false,
810 backgroundColor: '#F5F5B5',
811 titleColor:'#666',
812 padding: 8,
813 footerColor: '#666',
814 callbacks: {
815 labelTextColor: function(context) {
816 return '#543453';
817 }
818 }
819 }
820 }
821 // We want a background colour for the downloaded PNG file
822 const plugin = {
823 id: 'custom_canvas_background_color',
824 beforeDraw: (chart) => {
825 const ctx = chart.canvas.getContext('2d');
826 ctx.save();
827 ctx.globalCompositeOperation = 'destination-over';
828 ctx.fillStyle = '#f0f0f1',
829 ctx.fillRect(0, 0, chart.width, chart.height);
830 ctx.restore();
831 }
832 }
833
834 var myChart = new Chart(ctx, {
835 type: 'line',
836 data: chartData,
837 options: {
838 animation: {
839 duration: 700,
840 onComplete: function() {
841 jQuery('#cp-footer-buttons').slideDown(200);
842 document.getElementById('download-png-img').href = myChart.toBase64Image();
843 }
844 },
845 indexAxis: _indexAxis,
846 plugins: chartPlugins
847 },
848 plugins:[plugin]
849 });
850 }
851
852 // =====================================================================
853 // Settings page
854
855 function cpjs_copy_textarea( id ) {
856 document.getElementById(id).select();
857 document.execCommand('copy');
858 alert( cpi18n.text_copied );
859 }
860
861 // =====================================================================
862 // EOF
863