From 367388fbe39d69466c9b3606d78eedfa8afa3caf Mon Sep 17 00:00:00 2001 From: Andrew Collington Date: Tue, 23 Feb 2016 15:46:34 +0000 Subject: [PATCH 1/2] Optimisations for the file list and filtering (added a debounce function, streamlined some jquery, updates to jsx to facilitate). --- README.md | 2 ++ index.php | 81 ++++++++++++++++++++++++++++++++------------------ src/status.jsx | 4 +-- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 548c180..f8ecdd1 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ A clean and responsive interface for Zend OPcache information, showing statistic ## What's new +Version 2.2.2 brings in optimisations for the file listing when filtering + Version 2.2.1 has the gauges now updating with the real-time pulse and a couple rounding issues fixed Version 2.2.0 provides the ability to turn on/off the file list (default is on) diff --git a/index.php b/index.php index b74698c..3e5ab97 100644 --- a/index.php +++ b/index.php @@ -6,7 +6,7 @@ * A simple but effective single-file GUI for the OPcache PHP extension. * * @author Andrew Collington, andy@amnuts.com - * @version 2.2.1 + * @version 2.2.2 * @link https://github.com/amnuts/opcache-gui * @license MIT, http://acollington.mit-license.org/ */ @@ -248,6 +248,8 @@ $opcache = OpCacheService::init($options); table td { padding: 4px 6px; line-height: 1.4em; vertical-align: top; border-color: #fff; } table tr:nth-child(odd) { background-color: #EFFEFF; } table tr:nth-child(even) { background-color: #E0ECEF; } + #filelist table tr { background-color: #EFFEFF; } + #filelist table tr.alternate { background-color: #E0ECEF; } td.pathname { width: 70%; } footer { border-top: 1px solid #ccc; padding: 1em 2em; } footer a { padding: 2em; text-decoration: none; opacity: 0.7; } @@ -371,6 +373,36 @@ $opcache = OpCacheService::init($options); var canInvalidate = canInvalidate()); ?>; var useCharts = getOption('charts')); ?>; var allowFiles = getOption('allow_filelist')); ?>; + var debounce = function(func, wait, immediate) { + var timeout; + wait = wait || 250; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) { + func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func.apply(context, args); + } + }; + }; + function keyUp(event){ + var compare = $('#frmFilter').val().toLowerCase(); + $('#filelist').find('table tbody tr').each(function(index){ + if ($(this).data('path').indexOf(compare) == -1) { + $(this).addClass('hide'); + } else { + $(this).removeClass('hide'); + } + }); + $('#filelist table tbody').trigger('paint'); + }; getOption('charts')): ?> var Gauge = function(el, colour) { @@ -449,7 +481,7 @@ $opcache = OpCacheService::init($options); count_formatted : opstate.overview.readable.num_cached_scripts, count : opstate.overview.num_cached_scripts }); - $('#frmFilter').trigger('keyup'); + keyUp(); } }); } @@ -472,24 +504,15 @@ $opcache = OpCacheService::init($options); return false; }); $(document).on('paint', '#filelist table tbody', function(event, params) { - var trs = $('tr', $(this)).not('.hide'); - trs.filter(':odd').css({backgroundColor:'#E0ECEF'}) - .end().filter(':even').css({backgroundColor:'#EFFEFF'}); - filesObj.setState({showing: trs.length}); - }); - $('#frmFilter').bind('keyup', function(event){ - $('span.pathname').each(function(index){ - if ($(this).text().toLowerCase().indexOf($('#frmFilter').val().toLowerCase()) == -1) { - $(this).closest('tr').addClass('hide'); - } else { - $(this).closest('tr').removeClass('hide'); - } - }); - $('#filelist table tbody').trigger('paint'); + var trs = $('#filelist').find('tbody tr'); + trs.removeClass('alternate'); + trs.filter(':not(.hide):odd').addClass('alternate'); + filesObj.setState({showing: trs.filter(':not(.hide)').length}); }); + $('#frmFilter').bind('keyup', debounce(keyUp)); }); - var MemoryUsage = React.createClass({displayName: 'MemoryUsage', + var MemoryUsage = React.createClass({displayName: "MemoryUsage", getInitialState: function() { return { memoryUsageGauge : null @@ -508,13 +531,13 @@ $opcache = OpCacheService::init($options); }, render: function() { if (this.props.chart == true) { - return(React.createElement("canvas", {id: "memoryUsageCanvas", width: "250", height: "250", 'data-value': this.props.value})); + return(React.createElement("canvas", {id: "memoryUsageCanvas", width: "250", height: "250", "data-value": this.props.value})); } return(React.createElement("p", null, React.createElement("span", {className: "large"}, this.props.value), React.createElement("span", null, "%"))); } }); - var HitRate = React.createClass({displayName: 'HitRate', + var HitRate = React.createClass({displayName: "HitRate", getInitialState: function() { return { hitRateGauge : null @@ -533,13 +556,13 @@ $opcache = OpCacheService::init($options); }, render: function() { if (this.props.chart == true) { - return(React.createElement("canvas", {id: "hitRateCanvas", width: "250", height: "250", 'data-value': this.props.value})); + return(React.createElement("canvas", {id: "hitRateCanvas", width: "250", height: "250", "data-value": this.props.value})); } return(React.createElement("p", null, React.createElement("span", {className: "large"}, this.props.value), React.createElement("span", null, "%"))); } }); - var OverviewCounts = React.createClass({displayName: 'OverviewCounts', + var OverviewCounts = React.createClass({displayName: "OverviewCounts", getInitialState: function() { return { data : opstate.overview, @@ -574,7 +597,7 @@ $opcache = OpCacheService::init($options); } }); - var GeneralInfo = React.createClass({displayName: 'GeneralInfo', + var GeneralInfo = React.createClass({displayName: "GeneralInfo", getInitialState: function() { return { version : opstate.version, @@ -601,7 +624,7 @@ $opcache = OpCacheService::init($options); } }); - var Directives = React.createClass({displayName: 'Directives', + var Directives = React.createClass({displayName: "Directives", getInitialState: function() { return { data : opstate.directives }; }, @@ -638,7 +661,7 @@ $opcache = OpCacheService::init($options); } }); - var Files = React.createClass({displayName: 'Files', + var Files = React.createClass({displayName: "Files", getInitialState: function() { return { data : opstate.files, @@ -658,17 +681,17 @@ $opcache = OpCacheService::init($options); }, render: function() { if (this.state.allowFiles) { - var fileNodes = this.state.data.map(function(file) { + var fileNodes = this.state.data.map(function(file, i) { var invalidate, invalidated; if (file.timestamp == 0) { invalidated = React.createElement("span", null, React.createElement("i", {className: "invalid metainfo"}, " - has been invalidated")); } if (canInvalidate) { invalidate = React.createElement("span", null, ", ", React.createElement("a", {className: "metainfo", href: '?invalidate=' - + file.full_path, 'data-file': file.full_path, onClick: this.handleInvalidate}, "force file invalidation")); + + file.full_path, "data-file": file.full_path, onClick: this.handleInvalidate}, "force file invalidation")); } return ( - React.createElement("tr", {key: file.full_path}, + React.createElement("tr", {key: file.full_path, "data-path": file.full_path.toLowerCase(), className: i%2?'alternate':''}, React.createElement("td", null, React.createElement("div", null, React.createElement("span", {className: "pathname"}, file.full_path), React.createElement("br", null), @@ -699,7 +722,7 @@ $opcache = OpCacheService::init($options); } }); - var FilesMeta = React.createClass({displayName: 'FilesMeta', + var FilesMeta = React.createClass({displayName: "FilesMeta", render: function() { return ( React.createElement("span", {className: "metainfo"}, @@ -711,7 +734,7 @@ $opcache = OpCacheService::init($options); } }); - var FilesListed = React.createClass({displayName: 'FilesListed', + var FilesListed = React.createClass({displayName: "FilesListed", getInitialState: function() { return { formatted : opstate.overview.readable.num_cached_scripts, diff --git a/src/status.jsx b/src/status.jsx index 6edbdb1..b3b7410 100644 --- a/src/status.jsx +++ b/src/status.jsx @@ -167,7 +167,7 @@ var Files = React.createClass({ }, render: function() { if (this.state.allowFiles) { - var fileNodes = this.state.data.map(function(file) { + var fileNodes = this.state.data.map(function(file, i) { var invalidate, invalidated; if (file.timestamp == 0) { invalidated = - has been invalidated; @@ -177,7 +177,7 @@ var Files = React.createClass({ + file.full_path} data-file={file.full_path} onClick={this.handleInvalidate}>force file invalidation; } return ( - +
{file.full_path}
From 109dcc32d2f81963b95a8b403ff147aecb213d63 Mon Sep 17 00:00:00 2001 From: Andrew Collington Date: Wed, 24 Feb 2016 00:26:43 +0000 Subject: [PATCH 2/2] Added option to configure debounce rate. --- README.md | 3 ++- index.php | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f8ecdd1..a18871e 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,8 @@ $options = [ 'refresh_time' => 5, // how often the data will refresh, in seconds 'size_precision' => 2, // Digits after decimal point 'size_space' => false, // have '1MB' or '1 MB' when showing sizes - 'charts' => true // show gauge chart or just big numbers + 'charts' => true, // show gauge chart or just big numbers + 'debounce_rate' => 250 // milliseconds after key press to send keyup event when filtering ]; ``` diff --git a/index.php b/index.php index 3e5ab97..36d82c2 100644 --- a/index.php +++ b/index.php @@ -24,7 +24,8 @@ $options = [ 'refresh_time' => 5, // how often the data will refresh, in seconds 'size_precision' => 2, // Digits after decimal point 'size_space' => false, // have '1MB' or '1 MB' when showing sizes - 'charts' => true // show gauge chart or just big numbers + 'charts' => true, // show gauge chart or just big numbers + 'debounce_rate' => 250 // milliseconds after key press to send keyup event when filtering ]; /* @@ -47,7 +48,8 @@ class OpCacheService 'refresh_time' => 5, 'size_precision' => 2, 'size_space' => false, - 'charts' => true + 'charts' => true, + 'debounce_rate' => 250 ]; private function __construct($options = []) @@ -509,7 +511,7 @@ $opcache = OpCacheService::init($options); trs.filter(':not(.hide):odd').addClass('alternate'); filesObj.setState({showing: trs.filter(':not(.hide)').length}); }); - $('#frmFilter').bind('keyup', debounce(keyUp)); + $('#frmFilter').bind('keyup', debounce(keyUp, getOption('debounce_rate'); ?>)); }); var MemoryUsage = React.createClass({displayName: "MemoryUsage",