Version Description
Initial release.
=
Download this release
Release Info
Developer | StarfieldTech |
Plugin | P3 (Plugin Performance Profiler) |
Version | 1.0 |
Comparing to | |
See all releases |
Version 1.0
- .htaccess +1 -0
- .profiling_enabled +1 -0
- class.p3-profile-reader.php +271 -0
- class.p3-profile-table-sorter.php +57 -0
- class.p3-profile-table.php +293 -0
- class.p3-profiler.php +634 -0
- css/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- css/custom-theme/images/ui-bg_flat_100_ffffff_40x100.png +0 -0
- css/custom-theme/images/ui-bg_highlight-hard_100_206d92_1x100.png +0 -0
- css/custom-theme/images/ui-bg_highlight-hard_100_f1f1f1_1x100.png +0 -0
- css/custom-theme/images/ui-bg_highlight-hard_100_f8f8f8_1x100.png +0 -0
- css/custom-theme/images/ui-bg_highlight-hard_100_fbfbfb_1x100.png +0 -0
- css/custom-theme/images/ui-bg_highlight-soft_50_206d92_1x100.png +0 -0
- css/custom-theme/images/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
- css/custom-theme/images/ui-icons_000000_256x240.png +0 -0
- css/custom-theme/images/ui-icons_222222_256x240.png +0 -0
- css/custom-theme/images/ui-icons_464646_256x240.png +0 -0
- css/custom-theme/images/ui-icons_cd0a0a_256x240.png +0 -0
- css/custom-theme/images/ui-icons_ffffff_256x240.png +0 -0
- css/custom-theme/jquery-ui-1.8.16.custom.css +568 -0
- css/icon_mail.gif +0 -0
- css/jquery.qtip.min.css +1 -0
- css/p3.css +345 -0
- css/wordwrap.xml +22 -0
- index.php +2 -0
- js/jquery.corner.js +22 -0
- js/jquery.flot.min.js +5 -0
- js/jquery.flot.navigate.js +6 -0
- js/jquery.flot.pie.min.js +5 -0
- js/jquery.qtip.min.js +13 -0
- license.txt +339 -0
- logo.gif +0 -0
- p3-profiler.php +798 -0
- readme.txt +67 -0
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
- screenshot-3.png +0 -0
- screenshot-4.png +0 -0
- screenshot-5.png +0 -0
- screenshot-6.png +0 -0
- screenshot-7.png +0 -0
- screenshot-8.png +0 -0
- start-profile.php +8 -0
- templates/.htaccess +1 -0
- templates/callouts.php +624 -0
- templates/fix-flag-file.php +11 -0
- templates/help.php +471 -0
- templates/index.php +2 -0
- templates/list-scans.php +39 -0
- templates/template.php +117 -0
- templates/view-scan.php +993 -0
.htaccess
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
Options -Indexes
|
.profiling_enabled
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
[]
|
class.p3-profile-reader.php
ADDED
@@ -0,0 +1,271 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Performance Profile Reader
|
4 |
+
*
|
5 |
+
* @author GoDaddy.com
|
6 |
+
* @version 1.0
|
7 |
+
* @package P3_Profiler
|
8 |
+
*/
|
9 |
+
class P3_Profile_Reader {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Total site load time (profile + theme + core + plugins)
|
13 |
+
* @var float
|
14 |
+
*/
|
15 |
+
public $total_time = 0;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Total site load time (theme + core + plugins - profile)
|
19 |
+
* @var float
|
20 |
+
*/
|
21 |
+
public $site_time = 0;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Time spent in themes
|
25 |
+
* Calls which spend time in multiple areas are prioritized prioritized
|
26 |
+
* first as plugins, second as themes, lastly as core.
|
27 |
+
* @var float
|
28 |
+
*/
|
29 |
+
public $theme_time = 0;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Time spent in plugins.
|
33 |
+
* Calls which spend time in multiple areas are prioritized prioritized
|
34 |
+
* first as plugins, second as themes, lastly as core.
|
35 |
+
* @var float
|
36 |
+
*/
|
37 |
+
public $plugin_time = 0;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Time spent in the profiler code.
|
41 |
+
* @var float
|
42 |
+
*/
|
43 |
+
public $profile_time = 0;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Time spent in themes
|
47 |
+
* Calls which spend time in multiple areas are prioritized prioritized
|
48 |
+
* first as plugins, second as themes, lastly as core.
|
49 |
+
* @var float
|
50 |
+
*/
|
51 |
+
public $core_time = 0;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Memory usage per visit as reported by memory_get_peak_usage(true)
|
55 |
+
* @var float
|
56 |
+
*/
|
57 |
+
public $memory = 0;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Number of plugin related function calls (does not include php internal
|
61 |
+
* calls due to a limitation of how the tick handler works)
|
62 |
+
* @var int
|
63 |
+
*/
|
64 |
+
public $plugin_calls = 0;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Extracted URL from the profile
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
public $report_url = '';
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Extracted date from the first visit in the profile
|
74 |
+
* @var int
|
75 |
+
*/
|
76 |
+
public $report_date = '';
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Total number of mysql queries as reported by get_num_queries()
|
80 |
+
* @var int
|
81 |
+
*/
|
82 |
+
public $queries = 0;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Total number of visits recorded in the profile
|
86 |
+
* @var int
|
87 |
+
*/
|
88 |
+
public $visits = 0;
|
89 |
+
|
90 |
+
/**
|
91 |
+
* List of detected plugins
|
92 |
+
* @var array
|
93 |
+
*/
|
94 |
+
public $detected_plugins = array();
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Array of total time spent in each plugin
|
98 |
+
* key = plugin name
|
99 |
+
* value = seconds (float)
|
100 |
+
* @var array
|
101 |
+
*/
|
102 |
+
public $plugin_times = array();
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Averaged values for the report
|
106 |
+
* @var array
|
107 |
+
*/
|
108 |
+
public $averages = array(
|
109 |
+
'total' => 0,
|
110 |
+
'site' => 0,
|
111 |
+
'core' => 0,
|
112 |
+
'plugins' => 0,
|
113 |
+
'profile' => 0,
|
114 |
+
'theme' => 0,
|
115 |
+
'memory' => 0,
|
116 |
+
'plugin_calls' => 0,
|
117 |
+
'queries' => 0,
|
118 |
+
'observed' => 0,
|
119 |
+
'expected' => 0,
|
120 |
+
'drift' => 0,
|
121 |
+
'plugin_impact' => 0,
|
122 |
+
);
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Internal profile data
|
126 |
+
* @var array
|
127 |
+
*/
|
128 |
+
private $_data = array();
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Constructor
|
132 |
+
* @param string $file Full path to the profile json file
|
133 |
+
* @return P3_Profile_Reader
|
134 |
+
*/
|
135 |
+
public function __construct( $file ) {
|
136 |
+
|
137 |
+
// Open the file
|
138 |
+
$fp = fopen( $file, 'r' );
|
139 |
+
if ( FALSE === $fp ) {
|
140 |
+
throw new Exception( 'Cannot open ' . $file );
|
141 |
+
}
|
142 |
+
|
143 |
+
// Decode each line. Each line is a separate json object. Whenever a
|
144 |
+
// a visit is recorded, a new line is added to the file.
|
145 |
+
while ( !feof( $fp ) ) {
|
146 |
+
$line = fgets( $fp );
|
147 |
+
if ( empty( $line) ) {
|
148 |
+
continue;
|
149 |
+
}
|
150 |
+
$tmp = json_decode( $line );
|
151 |
+
if ( null === $tmp ) {
|
152 |
+
throw new Exception( 'Cannot parse ' . $file );
|
153 |
+
fclose( $fp );
|
154 |
+
}
|
155 |
+
$this->_data[] = $tmp;
|
156 |
+
}
|
157 |
+
|
158 |
+
// Close the file
|
159 |
+
fclose( $fp );
|
160 |
+
|
161 |
+
// Parse the data
|
162 |
+
$this->_parse();
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Parse from $this->_data and fill in the rest of the member vars
|
167 |
+
* @return void
|
168 |
+
*/
|
169 |
+
private function _parse() {
|
170 |
+
foreach ( $this->_data as $o ) {
|
171 |
+
// Set report meta-data
|
172 |
+
if ( empty( $this->report_date ) ) {
|
173 |
+
$this->report_date = strtotime( $o->date );
|
174 |
+
$scheme = parse_url( $o->url, PHP_URL_SCHEME );
|
175 |
+
$host = parse_url( $o->url, PHP_URL_HOST );
|
176 |
+
$path = parse_url( $o->url, PHP_URL_PATH );
|
177 |
+
$this->report_url = sprintf( '%s://%s%s', $scheme, $host, $path );
|
178 |
+
$this->visits = count( $this->_data );
|
179 |
+
}
|
180 |
+
|
181 |
+
// Set total times / queries / function calls
|
182 |
+
$this->total_time += $o->runtime->total;
|
183 |
+
$this->site_time += ( $o->runtime->total - $o->runtime->profile );
|
184 |
+
$this->theme_time += $o->runtime->theme;
|
185 |
+
$this->plugin_time += $o->runtime->plugins;
|
186 |
+
$this->profile_time += $o->runtime->profile;
|
187 |
+
$this->core_time += $o->runtime->wordpress;
|
188 |
+
$this->memory += $o->memory;
|
189 |
+
$this->plugin_calls += $o->stacksize;
|
190 |
+
$this->queries += $o->queries;
|
191 |
+
|
192 |
+
// Loop through the plugin data
|
193 |
+
foreach ( $o->runtime->breakdown as $k => $v ) {
|
194 |
+
if ( !array_key_exists( $k, $this->plugin_times ) ) {
|
195 |
+
$this->plugin_times[$k] = 0;
|
196 |
+
}
|
197 |
+
$this->plugin_times[$k] += $v;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
// Fix plugin names and average out plugin times
|
202 |
+
$tmp = $this->plugin_times;
|
203 |
+
$this->plugin_times = array();
|
204 |
+
foreach ( $tmp as $k => $v ) {
|
205 |
+
$k = ucwords( str_replace( array( '-', '_' ), ' ', $k ) );
|
206 |
+
$this->plugin_times[$k] = $v / $this->visits;
|
207 |
+
}
|
208 |
+
|
209 |
+
// Get a list of the plugins we detected
|
210 |
+
$this->detected_plugins = array_keys( $this->plugin_times );
|
211 |
+
sort( $this->detected_plugins );
|
212 |
+
|
213 |
+
// Calculate the averages
|
214 |
+
$this->_get_averages();
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Calculate the average values
|
219 |
+
* @return void
|
220 |
+
*/
|
221 |
+
private function _get_averages() {
|
222 |
+
if ( $this->visits <= 0 ) {
|
223 |
+
return;
|
224 |
+
}
|
225 |
+
$this->averages = array(
|
226 |
+
'total' => $this->total_time / $this->visits,
|
227 |
+
'site' => ( $this->total_time - $this->profile_time) / $this->visits,
|
228 |
+
'core' => $this->core_time / $this->visits,
|
229 |
+
'plugins' => $this->plugin_time / $this->visits,
|
230 |
+
'profile' => $this->profile_time / $this->visits,
|
231 |
+
'theme' => $this->theme_time / $this->visits,
|
232 |
+
'memory' => $this->memory / $this->visits,
|
233 |
+
'plugin_calls' => $this->plugin_calls / $this->visits,
|
234 |
+
'queries' => $this->queries / $this->visits,
|
235 |
+
'observed' => $this->total_time / $this->visits,
|
236 |
+
'expected' => ( $this->theme_time + $this->core_time + $this->profile_time + $this->plugin_time) / $this->visits,
|
237 |
+
);
|
238 |
+
$this->averages['drift'] = $this->averages['observed'] - $this->averages['expected'];
|
239 |
+
$this->averages['plugin_impact'] = $this->averages['plugins'] / $this->averages['site'] * 100;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Return a list of runtimes times by url
|
244 |
+
* Where the key is the url and the value is an array of runtime values
|
245 |
+
* in seconds (float)
|
246 |
+
* @return array
|
247 |
+
*/
|
248 |
+
public function get_stats_by_url() {
|
249 |
+
$ret = array();
|
250 |
+
foreach ( $this->_data as $o ) {
|
251 |
+
$tmp = array(
|
252 |
+
'url' => $o->url,
|
253 |
+
'core' => $o->runtime->wordpress,
|
254 |
+
'plugins' => $o->runtime->plugins,
|
255 |
+
'profile' => $o->runtime->profile,
|
256 |
+
'theme' => $o->runtime->theme,
|
257 |
+
'queries' => $o->queries,
|
258 |
+
'breakdown' => array()
|
259 |
+
);
|
260 |
+
foreach ( $o->runtime->breakdown as $k => $v ) {
|
261 |
+
$name = ucwords( str_replace( array( '-', '_' ), ' ', $k ) );
|
262 |
+
if ( !array_key_exists( $name, $tmp['breakdown'] ) ) {
|
263 |
+
$tmp['breakdown'][$name] = 0;
|
264 |
+
}
|
265 |
+
$tmp['breakdown'][$name] += $v;
|
266 |
+
}
|
267 |
+
$ret[] = $tmp;
|
268 |
+
}
|
269 |
+
return $ret;
|
270 |
+
}
|
271 |
+
}
|
class.p3-profile-table-sorter.php
ADDED
@@ -0,0 +1,57 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Profile table sorter
|
4 |
+
*
|
5 |
+
* @author GoDaddy.com
|
6 |
+
* @version 1.0
|
7 |
+
* @package P3_Profiler
|
8 |
+
*/
|
9 |
+
class P3_Profile_Table_Sorter {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* The field name to sort by
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
private $field = null;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The data to sort
|
19 |
+
* @var array
|
20 |
+
*/
|
21 |
+
private $data = null;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Constructor.
|
25 |
+
* @param array $data
|
26 |
+
* @param string $field Default is 'name'
|
27 |
+
*/
|
28 |
+
public function __construct( array $data, $field = 'name' ) {
|
29 |
+
$this->data = $data;
|
30 |
+
$this->field = $field;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Sort the data in 'asc' or 'desc' directions
|
35 |
+
* @param string $direction Default is 'asc'
|
36 |
+
* @return array
|
37 |
+
*/
|
38 |
+
public function sort( $direction = 'asc' ) {
|
39 |
+
usort( &$this->data, array( $this, '_compare' ) );
|
40 |
+
return ( 'asc' == $direction ) ? $this->data : array_reverse( $this->data );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Compare the data
|
45 |
+
* @link http://us.php.net/usort
|
46 |
+
* @param type $a
|
47 |
+
* @param type $b
|
48 |
+
* @return bool
|
49 |
+
*/
|
50 |
+
private function _compare( $a, $b ) {
|
51 |
+
if ( in_array( $this->field, array( '_filesize', '_count', '_date' ) ) ) {
|
52 |
+
return $a[$this->field] < $b[$this->field];
|
53 |
+
} else {
|
54 |
+
return strcmp( $a[$this->field], $b[$this->field] );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
class.p3-profile-table.php
ADDED
@@ -0,0 +1,293 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Lists the performance profiles
|
4 |
+
*
|
5 |
+
* @author GoDaddy.com
|
6 |
+
* @version 1.0
|
7 |
+
* @package P3_Profiler
|
8 |
+
*/
|
9 |
+
class P3_Profile_Table extends WP_List_Table {
|
10 |
+
|
11 |
+
/**************************************************************************/
|
12 |
+
/** SETUP **/
|
13 |
+
/**************************************************************************/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Constructor
|
17 |
+
* @return P3_Profile_Table
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
parent::__construct(
|
21 |
+
array(
|
22 |
+
'singular' => 'scan',
|
23 |
+
'plural' => 'scans',
|
24 |
+
)
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Set up the columns, dataset, paginator
|
30 |
+
* @return void
|
31 |
+
*/
|
32 |
+
public function prepare_items() {
|
33 |
+
|
34 |
+
// Set up columns
|
35 |
+
$columns = $this->get_columns();
|
36 |
+
$hidden = array();
|
37 |
+
$sortable = $this->get_sortable_columns();
|
38 |
+
$this->_column_headers = array( $columns, $hidden, $sortable );
|
39 |
+
|
40 |
+
// Perform bulk actions
|
41 |
+
$this->do_bulk_action();
|
42 |
+
$data = $this->_get_profiles();
|
43 |
+
|
44 |
+
// Sort data
|
45 |
+
$orderby = ( !empty( $_REQUEST['orderby']) ) ? $_REQUEST['orderby'] : 'name';
|
46 |
+
$order = ( !empty( $_REQUEST['order']) ) ? $_REQUEST['order'] : 'asc';
|
47 |
+
$data = $this->_sort( $data, $orderby, $order );
|
48 |
+
|
49 |
+
// 20 items per page
|
50 |
+
$per_page = 20;
|
51 |
+
|
52 |
+
// Get page number
|
53 |
+
$current_page = $this->get_pagenum();
|
54 |
+
|
55 |
+
// Get total items
|
56 |
+
$total_items = count( $data );
|
57 |
+
|
58 |
+
// Carve out only the visible dataset
|
59 |
+
$data = array_slice( $data, $current_page - 1 * $per_page, $per_page );
|
60 |
+
$this->items = $data;
|
61 |
+
|
62 |
+
// Set up the paginator
|
63 |
+
$this->set_pagination_args(
|
64 |
+
array(
|
65 |
+
'total_items' => $total_items,
|
66 |
+
'per_page' => $per_page,
|
67 |
+
'total_pages' => ceil( $total_items / $per_page ),
|
68 |
+
)
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**************************************************************************/
|
73 |
+
/** COLUMN PREP **/
|
74 |
+
/**************************************************************************/
|
75 |
+
|
76 |
+
/**
|
77 |
+
* If there's no column_[whatever] method available, use this to render
|
78 |
+
* the column
|
79 |
+
* @param array $item
|
80 |
+
* @param string $column_name
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function column_default( $item, $column_name ) {
|
84 |
+
switch ( $column_name ) {
|
85 |
+
case 'name' :
|
86 |
+
case 'date' :
|
87 |
+
case 'count' :
|
88 |
+
case 'filesize' :
|
89 |
+
return $item[$column_name];
|
90 |
+
break;
|
91 |
+
default:
|
92 |
+
return '';
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Render the "title" column
|
98 |
+
* @param array $item
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function column_title( $item ) {
|
102 |
+
$actions = array(
|
103 |
+
'delete' => sprintf( '<a href="?page=%s&action=%s&name=%s">Delete</a>', $_REQUEST['name'], 'delete', $item['name'] ),
|
104 |
+
);
|
105 |
+
|
106 |
+
//Return the title contents
|
107 |
+
return sprintf(
|
108 |
+
'%1$s <span style="color:silver">(id:%2$s )</span>%3$s',
|
109 |
+
$item['name'],
|
110 |
+
$item['name'],
|
111 |
+
$this->row_actions( $actions )
|
112 |
+
);
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Render the checkbox column
|
117 |
+
* @param type $item
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public function column_cb( $item ) {
|
121 |
+
return sprintf(
|
122 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
123 |
+
$this->_args['singular'],
|
124 |
+
$item['filename']
|
125 |
+
);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Get a list of columns
|
130 |
+
* @return array
|
131 |
+
*/
|
132 |
+
public function get_columns() {
|
133 |
+
$columns = array(
|
134 |
+
'cb' => '<input type="checkbox" />',
|
135 |
+
'name' => 'Name',
|
136 |
+
'date' => 'Date',
|
137 |
+
'count' => 'Visits',
|
138 |
+
'filesize' => 'Size',
|
139 |
+
);
|
140 |
+
return $columns;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Get a list of sortable columns (note, do not return the checkbox column )
|
145 |
+
* @return array
|
146 |
+
*/
|
147 |
+
public function get_sortable_columns() {
|
148 |
+
$sortable_columns = array(
|
149 |
+
'name' => array( 'name', true ),
|
150 |
+
'date' => array( 'date', true ),
|
151 |
+
'count' => array( 'count', true ),
|
152 |
+
'filesize' => array( 'filesize', true ),
|
153 |
+
);
|
154 |
+
return $sortable_columns;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Add some the "view" and "delete" links to the scan
|
159 |
+
* @param string $key Internal key (scan filename )
|
160 |
+
* @param string $display Display key (scan filename )
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
private function _action_links( $key, $display ) {
|
164 |
+
$url = add_query_arg(
|
165 |
+
array(
|
166 |
+
'p3_action' => 'view-scan',
|
167 |
+
'name' => $key,
|
168 |
+
)
|
169 |
+
);
|
170 |
+
return <<<EOD
|
171 |
+
<a href="$url"><strong>$display</strong></a>
|
172 |
+
<div class="row-actions-visible">
|
173 |
+
<span class="view">
|
174 |
+
<a href="$url" data-name="$key" title="View the results of this scan" class="view-results">View</a> |
|
175 |
+
</span>
|
176 |
+
<span>
|
177 |
+
<a href="javascript:;" data-name="$key" title="Continue this scan" class="p3-continue-scan">Continue</a> |
|
178 |
+
</span>
|
179 |
+
<span class="delete">
|
180 |
+
<a href="javascript:;" data-name="$key" title="Delete this scan" class="delete-scan delete">Delete</a>
|
181 |
+
</span>
|
182 |
+
</div>
|
183 |
+
EOD;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**************************************************************************/
|
187 |
+
/** BULK ACTIONS **/
|
188 |
+
/**************************************************************************/
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Get a list of which actions are available in the bulk actions dropdown
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
+
public function get_bulk_actions() {
|
195 |
+
$actions = array( 'delete' => 'Delete' );
|
196 |
+
return $actions;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Performan any bulk actions
|
201 |
+
* @return void
|
202 |
+
*/
|
203 |
+
public function do_bulk_action() {
|
204 |
+
global $p3_profiler_plugin;
|
205 |
+
if ( 'delete' === $this->current_action() && !empty( $_REQUEST['scan'] ) ) {
|
206 |
+
if ( !wp_verify_nonce( $_REQUEST['p3_nonce'], 'delete_scans' ) ) {
|
207 |
+
wp_die( 'Invalid nonce' );
|
208 |
+
}
|
209 |
+
foreach ( $_REQUEST['scan'] as $scan ) {
|
210 |
+
$file = P3_PROFILES_PATH . DIRECTORY_SEPARATOR . basename( $scan );
|
211 |
+
if ( !file_exists( $file ) || !is_writable( $file ) || !unlink( $file ) ) {
|
212 |
+
wp_die( 'Error removing file ' . $file );
|
213 |
+
}
|
214 |
+
}
|
215 |
+
$count = count( $_REQUEST['scan'] );
|
216 |
+
if ( $count == 1 ) {
|
217 |
+
$p3_profiler_plugin->add_notice( "Deleted $count scan." );
|
218 |
+
} else {
|
219 |
+
$p3_profiler_plugin->add_notice( "Deleted $count scans." );
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**************************************************************************/
|
225 |
+
/** DATA PREP **/
|
226 |
+
/**************************************************************************/
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Sort the data
|
230 |
+
* @param array $data
|
231 |
+
* @param string $field Field name (e.g. 'name' or 'count')
|
232 |
+
* @param string $direction asc / desc
|
233 |
+
* @return array
|
234 |
+
*/
|
235 |
+
private function _sort( $data, $field, $direction ) {
|
236 |
+
|
237 |
+
// Override the count / date fields as they've had some display markup
|
238 |
+
// applied to them and need to be sorted on the original values
|
239 |
+
switch ( $field ) {
|
240 |
+
case 'count' :
|
241 |
+
$field = '_count';
|
242 |
+
break;
|
243 |
+
case 'date' :
|
244 |
+
$field = '_date';
|
245 |
+
break;
|
246 |
+
case 'filesize' :
|
247 |
+
$field = '_filesize';
|
248 |
+
break;
|
249 |
+
}
|
250 |
+
$sorter = new P3_Profile_Table_Sorter( $data, $field );
|
251 |
+
return $sorter->sort( $direction );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Get a list of the profiles in the profiles folder
|
256 |
+
* Profiles are named as "*.json". Add additional info, too, like
|
257 |
+
* date and number of visits in the file
|
258 |
+
* @uses list_files
|
259 |
+
* @return type
|
260 |
+
*/
|
261 |
+
private function _get_profiles() {
|
262 |
+
$p3_profile_dir = P3_PROFILES_PATH;
|
263 |
+
$files = list_files( $p3_profile_dir );
|
264 |
+
$files = array_filter( $files, array( &$this, '_filter_json_files' ) );
|
265 |
+
$ret = array();
|
266 |
+
foreach ( $files as $file ) {
|
267 |
+
$time = filemtime( $file );
|
268 |
+
$count = count( file( $file ) );
|
269 |
+
$key = basename( $file );
|
270 |
+
$name = substr( $key, 0, -5 ); // strip off .json
|
271 |
+
$ret[] = array(
|
272 |
+
'filename' => basename( $file ),
|
273 |
+
'name' => $this->_action_links( $key, $name ),
|
274 |
+
'date' => date( 'D, M jS', $time ) . ' at ' . date( 'g:i a', $time ),
|
275 |
+
'count' => number_format( $count ),
|
276 |
+
'filesize' => $GLOBALS['p3_profiler_plugin']->readable_size( filesize( $file ) ),
|
277 |
+
'_filesize' => filesize( $file ),
|
278 |
+
'_date' => $time,
|
279 |
+
'_count' => $count,
|
280 |
+
);
|
281 |
+
}
|
282 |
+
return $ret;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Only let "*.json" files pass through
|
287 |
+
* @param type $file
|
288 |
+
* @return type
|
289 |
+
*/
|
290 |
+
private function _filter_json_files( $file ) {
|
291 |
+
return ( '.json' == substr( strtolower( $file ), -5 ) );
|
292 |
+
}
|
293 |
+
}
|
class.p3-profiler.php
ADDED
@@ -0,0 +1,634 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Profiles a WordPress site
|
4 |
+
*
|
5 |
+
* @author GoDaddy.com
|
6 |
+
* @version 1.0
|
7 |
+
* @package P3_Profiler
|
8 |
+
*/
|
9 |
+
class P3_Profiler {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Time spent in WordPress Core
|
13 |
+
* @var float
|
14 |
+
*/
|
15 |
+
private $_core = 0;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Time spent in theme
|
19 |
+
* @var float
|
20 |
+
*/
|
21 |
+
private $_theme = 0;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Time spent in the profiler code
|
25 |
+
* @var float
|
26 |
+
*/
|
27 |
+
private $_runtime = 0;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Time spent in plugins
|
31 |
+
* @var float
|
32 |
+
*/
|
33 |
+
private $_plugin_runtime = 0;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Profile information, built up during the application's execution
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
private $_profile = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Stack trace of the last function call. The stack is held here until
|
43 |
+
* it's recorded. It's not recorded until it's been timed. It won't be
|
44 |
+
* timed until after it's complete and the next function is in being
|
45 |
+
* examined, so the $_last_stack will be moved to $_profile and the current
|
46 |
+
* function will be moved to $_last_stack.
|
47 |
+
* @var array
|
48 |
+
*/
|
49 |
+
private $_last_stack = array();
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Time spent in last function call
|
53 |
+
* @var float
|
54 |
+
*/
|
55 |
+
private $_last_call_time = 0;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Timestamp when the last function call was started
|
59 |
+
* @var float
|
60 |
+
*/
|
61 |
+
private $_last_call_start = 0;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* How to categorize the last call ( core, theme, plugin )
|
65 |
+
* @var int
|
66 |
+
*/
|
67 |
+
private $_last_call_category = '';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Where to save the profile when it's done
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
private $_profile_filename = '';
|
74 |
+
|
75 |
+
/**
|
76 |
+
* App start time ( as close as we can measure )
|
77 |
+
* @var float
|
78 |
+
*/
|
79 |
+
private $_start_time = 0;
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Path to ourselves
|
83 |
+
* @var string
|
84 |
+
*/
|
85 |
+
private $_P3_PATH = ''; // Cannot rely on P3_PATH, may be instantiated before the plugin
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Path to the ".profiling_enabled" flag file
|
89 |
+
* @var string
|
90 |
+
*/
|
91 |
+
private $_P3_FLAG_FILE = '';
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Last stack should be marked as plugin time
|
95 |
+
* @const
|
96 |
+
*/
|
97 |
+
const CATEGORY_PLUGIN = 1;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Last stack should be marked as theme time
|
101 |
+
* @const
|
102 |
+
*/
|
103 |
+
const CATEGORY_THEME = 2;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Last stack should be marked as core time
|
107 |
+
* @const
|
108 |
+
*/
|
109 |
+
const CATEGORY_CORE = 3;
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Constructor
|
113 |
+
* Initialize the object, figure out if profiling is enabled, and if so,
|
114 |
+
* start the profile.
|
115 |
+
* @return p3_profiler
|
116 |
+
*/
|
117 |
+
public function __construct() {
|
118 |
+
|
119 |
+
// Set up paths
|
120 |
+
$this->_P3_PATH = realpath( dirname( __FILE__ ) );
|
121 |
+
$this->_P3_FLAG_FILE = $this->_P3_PATH . DIRECTORY_SEPARATOR . '.profiling_enabled';
|
122 |
+
|
123 |
+
// Check to see if we should profile
|
124 |
+
$p3_json = ( file_exists( $this->_P3_FLAG_FILE ) ? json_decode( file_get_contents( $this->_P3_FLAG_FILE ) ) : null );
|
125 |
+
if ( empty( $p3_json ) ) {
|
126 |
+
return $this;
|
127 |
+
}
|
128 |
+
$found = false;
|
129 |
+
foreach ( (array) $p3_json as $k => $v ) {
|
130 |
+
if ( 0 === strpos( $_SERVER['REQUEST_URI'], $v->site_url ) && preg_match( '/' . preg_quote( $v->ip ) . '/', $this->get_ip() ) ) {
|
131 |
+
$found = true;
|
132 |
+
break;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
if ( !$found ) {
|
136 |
+
return $this;
|
137 |
+
}
|
138 |
+
|
139 |
+
// Kludge memory limit / time limit
|
140 |
+
ini_set( 'memory_limit', '128M' );
|
141 |
+
set_time_limit( 90 );
|
142 |
+
|
143 |
+
// Set the profile file
|
144 |
+
$this->_profile_filename = $v->name . '.json';
|
145 |
+
|
146 |
+
// Start timing
|
147 |
+
$this->_start_time = microtime( true );
|
148 |
+
$this->_last_call_start = microtime( true );
|
149 |
+
|
150 |
+
// Reset state
|
151 |
+
$this->_last_call_time = 0;
|
152 |
+
$this->_runtime = 0;
|
153 |
+
$this->_plugin_runtime = 0;
|
154 |
+
$this->_core = 0;
|
155 |
+
$this->_theme = 0;
|
156 |
+
$this->_last_call_category = self::CATEGORY_CORE;
|
157 |
+
$this->_last_stack = array();
|
158 |
+
|
159 |
+
// Add a global flag to let everyone know we're profiling
|
160 |
+
define( 'WPP_PROFILING_STARTED', true );
|
161 |
+
|
162 |
+
// Add some startup information
|
163 |
+
$this->_profile = array(
|
164 |
+
'url' => $this->_get_url(),
|
165 |
+
'ip' => ( array_key_exists( 'HTTP_X_FORWARDED_FOR', $_SERVER ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'] ),
|
166 |
+
'pid' => getmypid(),
|
167 |
+
'date' => @date( 'c' ),
|
168 |
+
'stack' => array()
|
169 |
+
);
|
170 |
+
|
171 |
+
// Clear any opcode caches, the optimization / caching from these can
|
172 |
+
// hide calls from the tick handler and backtraces
|
173 |
+
if ( $v->disable_opcode_cache ) {
|
174 |
+
if ( extension_loaded( 'xcache' ) && function_exists( 'xcache_clear_cache' ) && !ini_get( 'xcache.admin.enable_auth' ) ) {
|
175 |
+
for ( $i = 0 ; $i < xcache_count( XC_TYPE_PHP ); $i++ ) {
|
176 |
+
xcache_clear_cache( XC_TYPE_PHP, 0 );
|
177 |
+
}
|
178 |
+
} elseif ( extension_loaded( 'apc' ) && function_exists( 'apc_clear_cache' ) ) {
|
179 |
+
apc_clear_cache();
|
180 |
+
} elseif ( extension_loaded( 'eaccelerator' ) && function_exists( 'eaccelerator_clean' ) ) {
|
181 |
+
@eaccelerator_clean();
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
// Monitor all function-calls
|
186 |
+
declare( ticks = 1 );
|
187 |
+
register_tick_function( array( $this, 'tick_handler' ) );
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* In between every call, examine the stack trace time the calls, and record
|
192 |
+
* the calls if the operations went through a plugin
|
193 |
+
* @return void
|
194 |
+
*/
|
195 |
+
public function tick_handler() {
|
196 |
+
static $theme_files_cache = array(); // Cache for theme files
|
197 |
+
static $actions_hooked = false;
|
198 |
+
static $themes_folder = 'themes';
|
199 |
+
static $content_folder = 'wp-content'; // Guess, if it's not defined
|
200 |
+
static $folder_flag = false;
|
201 |
+
static $in_wp = false;
|
202 |
+
|
203 |
+
// See if we're in WP
|
204 |
+
$in_wp = ($in_wp || defined( 'WP_USE_THEMES' ) || defined( 'DOING_CRON' ) || defined( 'WP_ADMIN' ));
|
205 |
+
|
206 |
+
// Set the content folder
|
207 |
+
if ( !$folder_flag && defined( 'WP_CONTENT_DIR' ) ) {
|
208 |
+
$content_folder = basename( WP_CONTENT_DIR );
|
209 |
+
$folder_flag = true;
|
210 |
+
}
|
211 |
+
|
212 |
+
// Start timing time spent in the profiler
|
213 |
+
$start = microtime( true );
|
214 |
+
|
215 |
+
// Calculate the last call time
|
216 |
+
$this->_last_call_time = ( $start - $this->_last_call_start );
|
217 |
+
|
218 |
+
// Don't profile in non-WP scripts
|
219 |
+
if ( !$in_wp && !$this->_is_a_plugin_file( $_SERVER['SCRIPT_FILENAME'] ) ) {
|
220 |
+
$tmp = microtime( true );
|
221 |
+
$this->_runtime += ( $tmp - $start );
|
222 |
+
$this->_last_call_start = $tmp;
|
223 |
+
return;
|
224 |
+
}
|
225 |
+
|
226 |
+
// Hook actions
|
227 |
+
if ( !$actions_hooked && function_exists( 'add_action' ) ) {
|
228 |
+
// Hook the shutdown action to save the profile when we're done
|
229 |
+
add_action( 'shutdown', array( $this, 'shutdown_handler' ) );
|
230 |
+
|
231 |
+
// Don't re-hook again
|
232 |
+
$actions_hooked = true;
|
233 |
+
}
|
234 |
+
|
235 |
+
// If we had a stack in the queue, track the runtime, and write it to the log
|
236 |
+
// array() !== $this->_last_stack is slightly faster than !empty( $this->_last_stack )
|
237 |
+
// which is important since this is called on every tick
|
238 |
+
if ( self::CATEGORY_PLUGIN == $this->_last_call_category && array() !== $this->_last_stack ) {
|
239 |
+
// Write the stack to the profile
|
240 |
+
$this->_plugin_runtime += $this->_last_call_time;
|
241 |
+
|
242 |
+
// Add this stack to the profile
|
243 |
+
$this->_profile['stack'][] = array(
|
244 |
+
'plugin' => $this->_last_stack['plugin'],
|
245 |
+
'runtime' => $this->_last_call_time,
|
246 |
+
);
|
247 |
+
|
248 |
+
// Reset the stack
|
249 |
+
$this->_last_stack = array();
|
250 |
+
} elseif ( self::CATEGORY_THEME == $this->_last_call_category ) {
|
251 |
+
$this->_theme += $this->_last_call_time;
|
252 |
+
} elseif ( self::CATEGORY_CORE == $this->_last_call_category ) {
|
253 |
+
$this->_core += $this->_last_call_time;
|
254 |
+
}
|
255 |
+
|
256 |
+
// Examine the current stack, see if we should track it. It should be
|
257 |
+
// related to a plugin file if we're going to track it
|
258 |
+
if ( defined( 'DEBUG_BACKTRACE_IGNORE_ARGS' ) ) {
|
259 |
+
$bt = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT );
|
260 |
+
} else {
|
261 |
+
$bt = debug_backtrace( true );
|
262 |
+
}
|
263 |
+
|
264 |
+
// Find our function
|
265 |
+
$frame = $bt[0];
|
266 |
+
if ( count( $bt ) >= 2 ) {
|
267 |
+
$frame = $bt[1];
|
268 |
+
}
|
269 |
+
|
270 |
+
// Include/require
|
271 |
+
if ( in_array( strtolower( $frame['function'] ), array( 'include', 'require', 'include_once', 'require_once' ) ) ) {
|
272 |
+
$file = $frame['args'][0];
|
273 |
+
|
274 |
+
// Object instances
|
275 |
+
} elseif ( isset( $frame['object'] ) && method_exists( $frame['object'], $frame['function'] ) ) {
|
276 |
+
try {
|
277 |
+
$reflector = new ReflectionMethod( $frame['object'], $frame['function'] );
|
278 |
+
$file = $reflector->getFileName();
|
279 |
+
} catch ( Exception $e ) {
|
280 |
+
}
|
281 |
+
|
282 |
+
// Static object calls
|
283 |
+
} elseif ( isset( $frame['class'] ) && method_exists( $frame['class'], $frame['function'] ) ) {
|
284 |
+
try {
|
285 |
+
$reflector = new ReflectionMethod( $frame['class'], $frame['function'] );
|
286 |
+
$file = $reflector->getFileName();
|
287 |
+
} catch ( Exception $e ) {
|
288 |
+
}
|
289 |
+
|
290 |
+
// Functions
|
291 |
+
} elseif ( !empty( $frame['function'] ) && function_exists( $frame['function'] ) ) {
|
292 |
+
try {
|
293 |
+
$reflector = new ReflectionFunction( $frame['function'] );
|
294 |
+
$file = $reflector->getFileName();
|
295 |
+
} catch ( Exception $e ) {
|
296 |
+
}
|
297 |
+
|
298 |
+
// Lambdas / closures
|
299 |
+
} elseif ( '__lambda_func' == $frame['function'] || '{closure}' == $frame['function'] ) {
|
300 |
+
$file = preg_replace( '/\(\d+\)\s+:\s+runtime-created function/', '', $bt[0]['file'] );
|
301 |
+
|
302 |
+
// Files, no other hints
|
303 |
+
} elseif ( isset( $frame['file'] ) ) {
|
304 |
+
$file = $frame['file'];
|
305 |
+
|
306 |
+
// No idea
|
307 |
+
} else {
|
308 |
+
$file = $_SERVER['SCRIPT_FILENAME'];
|
309 |
+
}
|
310 |
+
unset( $bt );
|
311 |
+
|
312 |
+
// Is it a plugin?
|
313 |
+
$plugin = $this->_is_a_plugin_file( $file );
|
314 |
+
if ( $plugin ) {
|
315 |
+
$plugin_name = $this->_get_plugin_name( $file );
|
316 |
+
}
|
317 |
+
|
318 |
+
// Is it a theme?
|
319 |
+
$is_a_theme = false;
|
320 |
+
if ( FALSE === $plugin ) {
|
321 |
+
if ( !$is_a_theme && isset( $theme_files_cache[$file] ) ) {
|
322 |
+
$is_a_theme = $theme_files_cache[$file];
|
323 |
+
}
|
324 |
+
|
325 |
+
$theme_files_cache[$file] = (
|
326 |
+
( FALSE !== strpos( $file, '/' . $themes_folder . '/' ) || FALSE !== strpos( $file, '\\'. $themes_folder . '\\' ) ) &&
|
327 |
+
( FALSE !== strpos( $file, '/' . $content_folder . '/' ) || FALSE !== strpos( $file, '\\' . $content_folder . '\\' ) )
|
328 |
+
);
|
329 |
+
$theme_files_cache[$file];
|
330 |
+
|
331 |
+
if ( $theme_files_cache[$file] ) {
|
332 |
+
$is_a_theme = true;
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
// If we're in a plugin, queue up the stack to be timed and logged during the next tick
|
337 |
+
if ( FALSE !== $plugin ) {
|
338 |
+
$this->_last_stack = array( 'plugin' => $plugin_name );
|
339 |
+
$this->_last_call_category = self::CATEGORY_PLUGIN;
|
340 |
+
|
341 |
+
// Track theme times - code can travel from core -> theme -> plugin, and the whole trace
|
342 |
+
// will show up in the stack, but we can only categorize it as one time, so we prioritize
|
343 |
+
// timing plugins over themes, and thems over the core.
|
344 |
+
} elseif ( FALSE !== $is_a_theme ) {
|
345 |
+
$this->_last_call_category = self::CATEGORY_THEME;
|
346 |
+
// We must be in the core
|
347 |
+
} else {
|
348 |
+
$this->_last_call_category = self::CATEGORY_CORE;
|
349 |
+
}
|
350 |
+
|
351 |
+
// Count the time spent in here as profiler runtime
|
352 |
+
$tmp = microtime( true );
|
353 |
+
$this->_runtime += ( $tmp - $start );
|
354 |
+
|
355 |
+
// Reset the timer for the next tick
|
356 |
+
$this->_last_call_start = microtime( true );
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Check if the given file is in the plugins folder
|
361 |
+
* @param string $file
|
362 |
+
* @return bool
|
363 |
+
*/
|
364 |
+
private function _is_a_plugin_file( $file ) {
|
365 |
+
static $plugin_files_cache = array();
|
366 |
+
static $plugins_folder = 'plugins'; // Guess, if it's not defined
|
367 |
+
static $muplugins_folder = 'mu-plugins';
|
368 |
+
static $content_folder = 'wp-content';
|
369 |
+
static $folder_flag = false;
|
370 |
+
|
371 |
+
// Set the plugins folder
|
372 |
+
if ( !$folder_flag && defined( 'WPMU_PLUGIN_DIR' ) ) {
|
373 |
+
$plugins_folder = basename( WP_PLUGIN_DIR );
|
374 |
+
$muplugins_folder = basename( WPMU_PLUGIN_DIR );
|
375 |
+
$content_folder = basename( WP_CONTENT_DIR );
|
376 |
+
$folder_flag = true;
|
377 |
+
}
|
378 |
+
|
379 |
+
if ( isset( $plugin_files_cache[$file] ) ) {
|
380 |
+
return $plugin_files_cache[$file];
|
381 |
+
}
|
382 |
+
|
383 |
+
$plugin_files_cache[$file] = (
|
384 |
+
(
|
385 |
+
( FALSE !== strpos( $file, '/' . $plugins_folder . '/' ) || FALSE !== stripos( $file, '\\' . $plugins_folder . '\\' ) ) ||
|
386 |
+
( FALSE !== strpos( $file, '/' . $muplugins_folder . '/' ) || FALSE !== stripos( $file, '\\' . $muplugins_folder . '\\' ) )
|
387 |
+
) &&
|
388 |
+
( FALSE !== strpos( $file, '/' . $content_folder . '/' ) || FALSE !== stripos( $file, '\\' . $content_folder . '\\' ) )
|
389 |
+
);
|
390 |
+
|
391 |
+
return $plugin_files_cache[$file];
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Guess a plugin's name from the file path
|
396 |
+
* @param string $path
|
397 |
+
* @return string
|
398 |
+
*/
|
399 |
+
private function _get_plugin_name( $path ) {
|
400 |
+
static $seen_files_cache = array();
|
401 |
+
static $plugins_folder = 'plugins'; // Guess, if it's not defined
|
402 |
+
static $muplugins_folder = 'mu-plugins';
|
403 |
+
static $content_folder = 'wp-content';
|
404 |
+
static $folder_flag = false;
|
405 |
+
|
406 |
+
// Set the plugins folder
|
407 |
+
if ( !$folder_flag && defined( 'WP_PLUGIN_DIR' ) ) {
|
408 |
+
$plugins_folder = basename( WP_PLUGIN_DIR );
|
409 |
+
$muplugins_folder = basename( WPMU_PLUGIN_DIR );
|
410 |
+
$content_folder = basename( WP_CONTENT_DIR );
|
411 |
+
$folder_flag = true;
|
412 |
+
}
|
413 |
+
|
414 |
+
// Check the cache
|
415 |
+
if ( isset( $seen_files_cache[$path] ) ) {
|
416 |
+
return $seen_files_cache[$path];
|
417 |
+
}
|
418 |
+
|
419 |
+
// Trim off the base path
|
420 |
+
$_path = realpath( $path );
|
421 |
+
if ( FALSE !== strpos( $_path, '/' . $content_folder . '/' . $plugins_folder . '/' ) ) {
|
422 |
+
$_path = substr(
|
423 |
+
$_path,
|
424 |
+
strpos( $_path, '/' . $content_folder . '/' . $plugins_folder . '/' ) +
|
425 |
+
strlen( '/' . $content_folder . '/' . $plugins_folder . '/' )
|
426 |
+
);
|
427 |
+
} elseif ( FALSE !== stripos( $_path, '\\' . $content_folder . '\\' . $plugins_folder . '\\' ) ) {
|
428 |
+
$_path = substr(
|
429 |
+
$_path,
|
430 |
+
stripos( $_path, '\\' . $content_folder . '\\' . $plugins_folder . '\\' ) +
|
431 |
+
strlen( '\\' . $content_folder . '\\' . $plugins_folder . '\\' )
|
432 |
+
);
|
433 |
+
} elseif ( FALSE !== strpos( $_path, '/' . $content_folder . '/' . $muplugins_folder . '/' ) ) {
|
434 |
+
$_path = substr(
|
435 |
+
$_path,
|
436 |
+
strpos( $_path, '/' . $content_folder . '/' . $muplugins_folder . '/' ) +
|
437 |
+
strlen( '/' . $content_folder . '/' . $muplugins_folder . '/' )
|
438 |
+
);
|
439 |
+
} elseif ( FALSE !== stripos( $_path, '\\' . $content_folder . '\\' . $muplugins_folder . '\\' ) ) {
|
440 |
+
$_path = substr(
|
441 |
+
$_path, stripos( $_path, '\\' . $content_folder . '\\' . $muplugins_folder . '\\' ) +
|
442 |
+
strlen( '\\' . $content_folder . '\\' . $muplugins_folder . '\\' )
|
443 |
+
);
|
444 |
+
}
|
445 |
+
|
446 |
+
// Grab the plugin name as a folder or a file
|
447 |
+
if ( FALSE !== strpos( $_path, DIRECTORY_SEPARATOR ) ) {
|
448 |
+
$plugin = substr( $_path, 0, strpos( $_path, DIRECTORY_SEPARATOR ) );
|
449 |
+
} else {
|
450 |
+
$plugin = substr( $_path, 0, stripos( $_path, '.php' ) );
|
451 |
+
}
|
452 |
+
|
453 |
+
// Save it to the cache
|
454 |
+
$seen_files_cache[$path] = $plugin;
|
455 |
+
|
456 |
+
// Return
|
457 |
+
return $plugin;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* Shutdown handler function
|
462 |
+
* @return void
|
463 |
+
*/
|
464 |
+
public function shutdown_handler() {
|
465 |
+
|
466 |
+
// Make sure we've actually started ( wp-cron??)
|
467 |
+
if ( !defined( 'WPP_PROFILING_STARTED' ) || !WPP_PROFILING_STARTED ) {
|
468 |
+
return;
|
469 |
+
}
|
470 |
+
|
471 |
+
// Last call time
|
472 |
+
$this->_last_call_time = ( microtime( true ) - $this->_last_call_start );
|
473 |
+
|
474 |
+
// Account for the last stack we measured
|
475 |
+
if ( self::CATEGORY_PLUGIN == $this->_last_call_category && array() !== $this->_last_stack ) {
|
476 |
+
// Write the stack to the profile
|
477 |
+
$this->_plugin_runtime += $this->_last_call_time;
|
478 |
+
|
479 |
+
// Add this stack to the profile
|
480 |
+
$this->_profile['stack'][] = array(
|
481 |
+
'plugin' => $this->_last_stack['plugin'],
|
482 |
+
'runtime' => $this->_last_call_time,
|
483 |
+
);
|
484 |
+
|
485 |
+
// Reset the stack
|
486 |
+
$this->_last_stack = array();
|
487 |
+
} elseif ( self::CATEGORY_THEME == $this->_last_call_category ) {
|
488 |
+
$this->_theme += $this->_last_call_time;
|
489 |
+
} elseif ( self::CATEGORY_CORE == $this->_last_call_category ) {
|
490 |
+
$this->_core += $this->_last_call_time;
|
491 |
+
}
|
492 |
+
|
493 |
+
// Total runtime by plugin
|
494 |
+
$plugin_totals = array();
|
495 |
+
if ( !empty( $this->_profile['stack'] ) ) {
|
496 |
+
foreach ( $this->_profile['stack'] as $stack ) {
|
497 |
+
if ( empty( $plugin_totals[$stack['plugin']] ) ) {
|
498 |
+
$plugin_totals[$stack['plugin']] = 0;
|
499 |
+
}
|
500 |
+
$plugin_totals[$stack['plugin']] += $stack['runtime'];
|
501 |
+
}
|
502 |
+
}
|
503 |
+
foreach ( $plugin_totals as $k => $v ) {
|
504 |
+
$plugin_totals[$k] = $v;
|
505 |
+
}
|
506 |
+
|
507 |
+
// Stop timing total run
|
508 |
+
$tmp = microtime( true );
|
509 |
+
$runtime = ( $tmp - $this->_start_time );
|
510 |
+
|
511 |
+
// Count the time spent in here as profiler runtime
|
512 |
+
$this->_runtime += ( $tmp - $this->_last_call_start );
|
513 |
+
|
514 |
+
// Is the whole script a plugin? ( e.g. http://mysite.com/wp-content/plugins/somescript.php )
|
515 |
+
if ( $this->_is_a_plugin_file( $_SERVER['SCRIPT_FILENAME'] ) ) {
|
516 |
+
$this->_profile['runtime'] = array(
|
517 |
+
'total' => $runtime,
|
518 |
+
'wordpress' => 0,
|
519 |
+
'theme' => 0,
|
520 |
+
'plugins' => ( $runtime - $this->_runtime ),
|
521 |
+
'profile' => $this->_runtime,
|
522 |
+
'breakdown' => array(
|
523 |
+
$this->_get_plugin_name( $_SERVER['SCRIPT_FILENAME'] ) => ( $runtime - $this->_runtime ),
|
524 |
+
)
|
525 |
+
);
|
526 |
+
} elseif (
|
527 |
+
( FALSE !== strpos( $_SERVER['SCRIPT_FILENAME'], '/themes/' ) || FALSE !== stripos( $_SERVER['SCRIPT_FILENAME'], '\\themes\\' ) ) &&
|
528 |
+
(
|
529 |
+
FALSE !== strpos( $_SERVER['SCRIPT_FILENAME'], '/' . basename( WP_CONTENT_DIR ) . '/' ) ||
|
530 |
+
FALSE !== stripos( $file, '\\' . basename( WP_CONTENT_DIR ) . '\\' )
|
531 |
+
)
|
532 |
+
) {
|
533 |
+
$this->_profile['runtime'] = array(
|
534 |
+
'total' => $runtime,
|
535 |
+
'wordpress' => 0.0,
|
536 |
+
'theme' => ( $runtime - $this->_runtime ),
|
537 |
+
'plugins' => 0.0,
|
538 |
+
'profile' => $this->_runtime,
|
539 |
+
'breakdown' => array()
|
540 |
+
);
|
541 |
+
} else {
|
542 |
+
// Add runtime information
|
543 |
+
$this->_profile['runtime'] = array(
|
544 |
+
'total' => $runtime,
|
545 |
+
'wordpress' => $this->_core,
|
546 |
+
'theme' => $this->_theme,
|
547 |
+
'plugins' => $this->_plugin_runtime,
|
548 |
+
'profile' => $this->_runtime,
|
549 |
+
'breakdown' => $plugin_totals,
|
550 |
+
);
|
551 |
+
}
|
552 |
+
|
553 |
+
// Additional metrics
|
554 |
+
$this->_profile['memory'] = memory_get_peak_usage( true );
|
555 |
+
$this->_profile['stacksize'] = count( $this->_profile['stack'] );
|
556 |
+
$this->_profile['queries'] = get_num_queries();
|
557 |
+
|
558 |
+
// Throw away unneeded information to make the profiles smaller
|
559 |
+
unset( $this->_profile['stack'] );
|
560 |
+
|
561 |
+
// Open the file and acquire an exclusive lock ( prevent multiple hits from stomping on our
|
562 |
+
// previous profiles
|
563 |
+
$uploads_dir = wp_upload_dir();
|
564 |
+
$path = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' . DIRECTORY_SEPARATOR . $this->_profile_filename;
|
565 |
+
$fp = fopen( $path, 'a+' );
|
566 |
+
$wait = 30; // Wait 30 iterations ( 3 seconds )
|
567 |
+
while ( !flock( $fp, LOCK_EX ) && $wait-- ) {
|
568 |
+
usleep( 100 * 1000 );
|
569 |
+
}
|
570 |
+
|
571 |
+
// If we've waited too long, bail, don't add this profile, there's too
|
572 |
+
// much traffic
|
573 |
+
if ( $wait <= 0 ) {
|
574 |
+
return;
|
575 |
+
}
|
576 |
+
|
577 |
+
fwrite( $fp, json_encode( $this->_profile ) . PHP_EOL );
|
578 |
+
|
579 |
+
// Release the lock and close the file
|
580 |
+
flock( $fp, LOCK_UN );
|
581 |
+
fclose( $fp );
|
582 |
+
}
|
583 |
+
|
584 |
+
/**
|
585 |
+
* Get the current URL
|
586 |
+
* @return string
|
587 |
+
*/
|
588 |
+
private function _get_url() {
|
589 |
+
$protocol = 'http://';
|
590 |
+
if ( ( !empty( $_SERVER['HTTPS'] ) && 'on' == strtolower( $_SERVER['HTTPS'] ) ) || 443 == $_SERVER['SERVER_PORT'] ) {
|
591 |
+
$protocol = 'https://';
|
592 |
+
}
|
593 |
+
$domain = $_SERVER['HTTP_HOST'];
|
594 |
+
if ( !empty( $_SERVER['REQUEST_URI'] ) ) {
|
595 |
+
$file = '';
|
596 |
+
$query_string = '';
|
597 |
+
$path = $_SERVER['REQUEST_URI'];
|
598 |
+
} else {
|
599 |
+
$file = '';
|
600 |
+
if ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
|
601 |
+
$file = $_SERVER['SCRIPT_NAME'];
|
602 |
+
}
|
603 |
+
$path = '';
|
604 |
+
if ( !empty( $_SERVER['PATH_INFO'] ) ) {
|
605 |
+
$path = $_SERVER['PATH_INFO'];
|
606 |
+
} elseif ( !empty( $_SERVER['REDIRECT_URL'] ) ) {
|
607 |
+
$path = $_SERVER['REDIRECT_URL'];
|
608 |
+
}
|
609 |
+
$query_string = '';
|
610 |
+
if ( !empty( $_SERVER['QUERY_STRING'] ) ) {
|
611 |
+
$query_string = '?' . $_SERVER['QUERY_STRING'];
|
612 |
+
}
|
613 |
+
}
|
614 |
+
return $protocol.$domain.$file.$path.$query_string;
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get the user's IP
|
619 |
+
* @return string
|
620 |
+
*/
|
621 |
+
public function get_ip() {
|
622 |
+
static $ip = '';
|
623 |
+
if ( !empty( $ip ) ) {
|
624 |
+
return $ip;
|
625 |
+
} else {
|
626 |
+
if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
627 |
+
$ip = filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_SANITIZE_STRING );
|
628 |
+
} else {
|
629 |
+
$ip = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_SANITIZE_STRING );
|
630 |
+
}
|
631 |
+
return $ip;
|
632 |
+
}
|
633 |
+
}
|
634 |
+
}
|
css/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_flat_100_ffffff_40x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_highlight-hard_100_206d92_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_highlight-hard_100_f1f1f1_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_highlight-hard_100_f8f8f8_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_highlight-hard_100_fbfbfb_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_highlight-soft_50_206d92_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-bg_inset-soft_95_fef1ec_1x100.png
ADDED
Binary file
|
css/custom-theme/images/ui-icons_000000_256x240.png
ADDED
Binary file
|
css/custom-theme/images/ui-icons_222222_256x240.png
ADDED
Binary file
|
css/custom-theme/images/ui-icons_464646_256x240.png
ADDED
Binary file
|
css/custom-theme/images/ui-icons_cd0a0a_256x240.png
ADDED
Binary file
|
css/custom-theme/images/ui-icons_ffffff_256x240.png
ADDED
Binary file
|
css/custom-theme/jquery-ui-1.8.16.custom.css
ADDED
@@ -0,0 +1,568 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* jQuery UI CSS Framework 1.8.16
|
3 |
+
*
|
4 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
6 |
+
* http://jquery.org/license
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI/Theming/API
|
9 |
+
*/
|
10 |
+
|
11 |
+
/* Layout helpers
|
12 |
+
----------------------------------*/
|
13 |
+
.ui-helper-hidden { display: none; }
|
14 |
+
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
15 |
+
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
16 |
+
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
17 |
+
.ui-helper-clearfix { display: inline-block; }
|
18 |
+
/* required comment for clearfix to work in Opera \*/
|
19 |
+
* html .ui-helper-clearfix { height:1%; }
|
20 |
+
.ui-helper-clearfix { display:block; }
|
21 |
+
/* end clearfix */
|
22 |
+
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
23 |
+
|
24 |
+
|
25 |
+
/* Interaction Cues
|
26 |
+
----------------------------------*/
|
27 |
+
.ui-state-disabled { cursor: default !important; }
|
28 |
+
|
29 |
+
|
30 |
+
/* Icons
|
31 |
+
----------------------------------*/
|
32 |
+
|
33 |
+
/* states and images */
|
34 |
+
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
35 |
+
|
36 |
+
|
37 |
+
/* Misc visuals
|
38 |
+
----------------------------------*/
|
39 |
+
|
40 |
+
/* Overlays */
|
41 |
+
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
42 |
+
|
43 |
+
|
44 |
+
/*
|
45 |
+
* jQuery UI CSS Framework 1.8.16
|
46 |
+
*
|
47 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
48 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
49 |
+
* http://jquery.org/license
|
50 |
+
*
|
51 |
+
* http://docs.jquery.com/UI/Theming/API
|
52 |
+
*
|
53 |
+
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=8px&bgColorHeader=f8f8f8&bgTextureHeader=04_highlight_hard.png&bgImgOpacityHeader=100&borderColorHeader=dfdfdf&fcHeader=464646&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=100&borderColorContent=dfdfdf&fcContent=333333&iconColorContent=222222&bgColorDefault=f1f1f1&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=100&borderColorDefault=bbbbbb&fcDefault=464646&iconColorDefault=464646&bgColorHover=f1f1f1&bgTextureHover=04_highlight_hard.png&bgImgOpacityHover=100&borderColorHover=666666&fcHover=464646&iconColorHover=464646&bgColorActive=206d92&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=100&borderColorActive=298cba&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=206d92&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=50&borderColorHighlight=298cba&fcHighlight=ffffff&iconColorHighlight=ffffff&bgColorError=fef1ec&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
54 |
+
*/
|
55 |
+
|
56 |
+
|
57 |
+
/* Component containers
|
58 |
+
----------------------------------*/
|
59 |
+
.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
|
60 |
+
.ui-widget .ui-widget { font-size: 1em; }
|
61 |
+
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
|
62 |
+
.ui-widget-content { border: 1px solid #dfdfdf; background: #ffffff url(images/ui-bg_flat_100_ffffff_40x100.png) 50% 50% repeat-x; color: #333333; }
|
63 |
+
.ui-widget-content a { color: #333333; }
|
64 |
+
.ui-widget-header { border: 1px solid #dfdfdf; background: #f8f8f8 url(images/ui-bg_highlight-hard_100_f8f8f8_1x100.png) 50% 50% repeat-x; color: #464646; font-weight: bold; }
|
65 |
+
.ui-widget-header a { color: #464646; }
|
66 |
+
|
67 |
+
/* Interaction states
|
68 |
+
----------------------------------*/
|
69 |
+
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #bbbbbb; background: #f1f1f1 url(images/ui-bg_highlight-hard_100_f1f1f1_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #464646; }
|
70 |
+
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #464646; text-decoration: none; }
|
71 |
+
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #666666; background: #f1f1f1 url(images/ui-bg_highlight-hard_100_f1f1f1_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #464646; }
|
72 |
+
.ui-state-hover a, .ui-state-hover a:hover { color: #464646; text-decoration: none; }
|
73 |
+
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #298cba; background: #206d92 url(images/ui-bg_highlight-hard_100_206d92_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
|
74 |
+
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
|
75 |
+
.ui-widget :active { outline: none; }
|
76 |
+
|
77 |
+
/* Interaction Cues
|
78 |
+
----------------------------------*/
|
79 |
+
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #298cba; background: #206d92 url(images/ui-bg_highlight-soft_50_206d92_1x100.png) 50% top repeat-x; color: #ffffff; }
|
80 |
+
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #ffffff; }
|
81 |
+
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_inset-soft_95_fef1ec_1x100.png) 50% bottom repeat-x; color: #cd0a0a; }
|
82 |
+
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
|
83 |
+
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
|
84 |
+
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
85 |
+
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
86 |
+
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
87 |
+
|
88 |
+
/* Icons
|
89 |
+
----------------------------------*/
|
90 |
+
|
91 |
+
/* states and images */
|
92 |
+
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
|
93 |
+
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
|
94 |
+
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
|
95 |
+
.ui-state-default .ui-icon { background-image: url(images/ui-icons_464646_256x240.png); }
|
96 |
+
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_464646_256x240.png); }
|
97 |
+
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
|
98 |
+
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
|
99 |
+
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
|
100 |
+
|
101 |
+
/* positioning */
|
102 |
+
.ui-icon-carat-1-n { background-position: 0 0; }
|
103 |
+
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
104 |
+
.ui-icon-carat-1-e { background-position: -32px 0; }
|
105 |
+
.ui-icon-carat-1-se { background-position: -48px 0; }
|
106 |
+
.ui-icon-carat-1-s { background-position: -64px 0; }
|
107 |
+
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
108 |
+
.ui-icon-carat-1-w { background-position: -96px 0; }
|
109 |
+
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
110 |
+
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
111 |
+
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
112 |
+
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
113 |
+
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
114 |
+
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
115 |
+
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
116 |
+
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
117 |
+
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
118 |
+
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
119 |
+
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
120 |
+
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
121 |
+
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
122 |
+
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
123 |
+
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
124 |
+
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
125 |
+
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
126 |
+
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
127 |
+
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
128 |
+
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
129 |
+
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
130 |
+
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
131 |
+
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
132 |
+
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
133 |
+
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
134 |
+
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
135 |
+
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
136 |
+
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
137 |
+
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
138 |
+
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
139 |
+
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
140 |
+
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
141 |
+
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
142 |
+
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
143 |
+
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
144 |
+
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
145 |
+
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
146 |
+
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
147 |
+
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
148 |
+
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
149 |
+
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
150 |
+
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
151 |
+
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
152 |
+
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
153 |
+
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
154 |
+
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
155 |
+
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
156 |
+
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
157 |
+
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
158 |
+
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
159 |
+
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
160 |
+
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
161 |
+
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
162 |
+
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
163 |
+
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
164 |
+
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
165 |
+
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
166 |
+
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
167 |
+
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
168 |
+
.ui-icon-extlink { background-position: -32px -80px; }
|
169 |
+
.ui-icon-newwin { background-position: -48px -80px; }
|
170 |
+
.ui-icon-refresh { background-position: -64px -80px; }
|
171 |
+
.ui-icon-shuffle { background-position: -80px -80px; }
|
172 |
+
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
173 |
+
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
174 |
+
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
175 |
+
.ui-icon-folder-open { background-position: -16px -96px; }
|
176 |
+
.ui-icon-document { background-position: -32px -96px; }
|
177 |
+
.ui-icon-document-b { background-position: -48px -96px; }
|
178 |
+
.ui-icon-note { background-position: -64px -96px; }
|
179 |
+
.ui-icon-mail-closed { background-position: -80px -96px; }
|
180 |
+
.ui-icon-mail-open { background-position: -96px -96px; }
|
181 |
+
.ui-icon-suitcase { background-position: -112px -96px; }
|
182 |
+
.ui-icon-comment { background-position: -128px -96px; }
|
183 |
+
.ui-icon-person { background-position: -144px -96px; }
|
184 |
+
.ui-icon-print { background-position: -160px -96px; }
|
185 |
+
.ui-icon-trash { background-position: -176px -96px; }
|
186 |
+
.ui-icon-locked { background-position: -192px -96px; }
|
187 |
+
.ui-icon-unlocked { background-position: -208px -96px; }
|
188 |
+
.ui-icon-bookmark { background-position: -224px -96px; }
|
189 |
+
.ui-icon-tag { background-position: -240px -96px; }
|
190 |
+
.ui-icon-home { background-position: 0 -112px; }
|
191 |
+
.ui-icon-flag { background-position: -16px -112px; }
|
192 |
+
.ui-icon-calendar { background-position: -32px -112px; }
|
193 |
+
.ui-icon-cart { background-position: -48px -112px; }
|
194 |
+
.ui-icon-pencil { background-position: -64px -112px; }
|
195 |
+
.ui-icon-clock { background-position: -80px -112px; }
|
196 |
+
.ui-icon-disk { background-position: -96px -112px; }
|
197 |
+
.ui-icon-calculator { background-position: -112px -112px; }
|
198 |
+
.ui-icon-zoomin { background-position: -128px -112px; }
|
199 |
+
.ui-icon-zoomout { background-position: -144px -112px; }
|
200 |
+
.ui-icon-search { background-position: -160px -112px; }
|
201 |
+
.ui-icon-wrench { background-position: -176px -112px; }
|
202 |
+
.ui-icon-gear { background-position: -192px -112px; }
|
203 |
+
.ui-icon-heart { background-position: -208px -112px; }
|
204 |
+
.ui-icon-star { background-position: -224px -112px; }
|
205 |
+
.ui-icon-link { background-position: -240px -112px; }
|
206 |
+
.ui-icon-cancel { background-position: 0 -128px; }
|
207 |
+
.ui-icon-plus { background-position: -16px -128px; }
|
208 |
+
.ui-icon-plusthick { background-position: -32px -128px; }
|
209 |
+
.ui-icon-minus { background-position: -48px -128px; }
|
210 |
+
.ui-icon-minusthick { background-position: -64px -128px; }
|
211 |
+
.ui-icon-close { background-position: -80px -128px; }
|
212 |
+
.ui-icon-closethick { background-position: -96px -128px; }
|
213 |
+
.ui-icon-key { background-position: -112px -128px; }
|
214 |
+
.ui-icon-lightbulb { background-position: -128px -128px; }
|
215 |
+
.ui-icon-scissors { background-position: -144px -128px; }
|
216 |
+
.ui-icon-clipboard { background-position: -160px -128px; }
|
217 |
+
.ui-icon-copy { background-position: -176px -128px; }
|
218 |
+
.ui-icon-contact { background-position: -192px -128px; }
|
219 |
+
.ui-icon-image { background-position: -208px -128px; }
|
220 |
+
.ui-icon-video { background-position: -224px -128px; }
|
221 |
+
.ui-icon-script { background-position: -240px -128px; }
|
222 |
+
.ui-icon-alert { background-position: 0 -144px; }
|
223 |
+
.ui-icon-info { background-position: -16px -144px; }
|
224 |
+
.ui-icon-notice { background-position: -32px -144px; }
|
225 |
+
.ui-icon-help { background-position: -48px -144px; }
|
226 |
+
.ui-icon-check { background-position: -64px -144px; }
|
227 |
+
.ui-icon-bullet { background-position: -80px -144px; }
|
228 |
+
.ui-icon-radio-off { background-position: -96px -144px; }
|
229 |
+
.ui-icon-radio-on { background-position: -112px -144px; }
|
230 |
+
.ui-icon-pin-w { background-position: -128px -144px; }
|
231 |
+
.ui-icon-pin-s { background-position: -144px -144px; }
|
232 |
+
.ui-icon-play { background-position: 0 -160px; }
|
233 |
+
.ui-icon-pause { background-position: -16px -160px; }
|
234 |
+
.ui-icon-seek-next { background-position: -32px -160px; }
|
235 |
+
.ui-icon-seek-prev { background-position: -48px -160px; }
|
236 |
+
.ui-icon-seek-end { background-position: -64px -160px; }
|
237 |
+
.ui-icon-seek-start { background-position: -80px -160px; }
|
238 |
+
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
239 |
+
.ui-icon-seek-first { background-position: -80px -160px; }
|
240 |
+
.ui-icon-stop { background-position: -96px -160px; }
|
241 |
+
.ui-icon-eject { background-position: -112px -160px; }
|
242 |
+
.ui-icon-volume-off { background-position: -128px -160px; }
|
243 |
+
.ui-icon-volume-on { background-position: -144px -160px; }
|
244 |
+
.ui-icon-power { background-position: 0 -176px; }
|
245 |
+
.ui-icon-signal-diag { background-position: -16px -176px; }
|
246 |
+
.ui-icon-signal { background-position: -32px -176px; }
|
247 |
+
.ui-icon-battery-0 { background-position: -48px -176px; }
|
248 |
+
.ui-icon-battery-1 { background-position: -64px -176px; }
|
249 |
+
.ui-icon-battery-2 { background-position: -80px -176px; }
|
250 |
+
.ui-icon-battery-3 { background-position: -96px -176px; }
|
251 |
+
.ui-icon-circle-plus { background-position: 0 -192px; }
|
252 |
+
.ui-icon-circle-minus { background-position: -16px -192px; }
|
253 |
+
.ui-icon-circle-close { background-position: -32px -192px; }
|
254 |
+
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
255 |
+
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
256 |
+
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
257 |
+
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
258 |
+
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
259 |
+
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
260 |
+
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
261 |
+
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
262 |
+
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
263 |
+
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
264 |
+
.ui-icon-circle-check { background-position: -208px -192px; }
|
265 |
+
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
266 |
+
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
267 |
+
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
268 |
+
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
269 |
+
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
270 |
+
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
271 |
+
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
272 |
+
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
273 |
+
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
274 |
+
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
275 |
+
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
276 |
+
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
277 |
+
|
278 |
+
|
279 |
+
/* Misc visuals
|
280 |
+
----------------------------------*/
|
281 |
+
|
282 |
+
/* Corner radius */
|
283 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 8px; -webkit-border-top-left-radius: 8px; -khtml-border-top-left-radius: 8px; border-top-left-radius: 8px; }
|
284 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 8px; -webkit-border-top-right-radius: 8px; -khtml-border-top-right-radius: 8px; border-top-right-radius: 8px; }
|
285 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 8px; -webkit-border-bottom-left-radius: 8px; -khtml-border-bottom-left-radius: 8px; border-bottom-left-radius: 8px; }
|
286 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 8px; -webkit-border-bottom-right-radius: 8px; -khtml-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; }
|
287 |
+
|
288 |
+
/* Overlays */
|
289 |
+
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
290 |
+
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
|
291 |
+
* jQuery UI Resizable 1.8.16
|
292 |
+
*
|
293 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
294 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
295 |
+
* http://jquery.org/license
|
296 |
+
*
|
297 |
+
* http://docs.jquery.com/UI/Resizable#theming
|
298 |
+
*/
|
299 |
+
.ui-resizable { position: relative;}
|
300 |
+
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
|
301 |
+
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
302 |
+
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
303 |
+
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
304 |
+
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
305 |
+
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
306 |
+
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
307 |
+
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
308 |
+
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
309 |
+
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
310 |
+
* jQuery UI Selectable 1.8.16
|
311 |
+
*
|
312 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
313 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
314 |
+
* http://jquery.org/license
|
315 |
+
*
|
316 |
+
* http://docs.jquery.com/UI/Selectable#theming
|
317 |
+
*/
|
318 |
+
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
319 |
+
/*
|
320 |
+
* jQuery UI Accordion 1.8.16
|
321 |
+
*
|
322 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
323 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
324 |
+
* http://jquery.org/license
|
325 |
+
*
|
326 |
+
* http://docs.jquery.com/UI/Accordion#theming
|
327 |
+
*/
|
328 |
+
/* IE/Win - Fix animation bug - #4615 */
|
329 |
+
.ui-accordion { width: 100%; }
|
330 |
+
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
331 |
+
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
332 |
+
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
333 |
+
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
334 |
+
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
335 |
+
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
336 |
+
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
337 |
+
.ui-accordion .ui-accordion-content-active { display: block; }
|
338 |
+
/*
|
339 |
+
* jQuery UI Autocomplete 1.8.16
|
340 |
+
*
|
341 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
342 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
343 |
+
* http://jquery.org/license
|
344 |
+
*
|
345 |
+
* http://docs.jquery.com/UI/Autocomplete#theming
|
346 |
+
*/
|
347 |
+
.ui-autocomplete { position: absolute; cursor: default; }
|
348 |
+
|
349 |
+
/* workarounds */
|
350 |
+
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
351 |
+
|
352 |
+
/*
|
353 |
+
* jQuery UI Menu 1.8.16
|
354 |
+
*
|
355 |
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
356 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
357 |
+
* http://jquery.org/license
|
358 |
+
*
|
359 |
+
* http://docs.jquery.com/UI/Menu#theming
|
360 |
+
*/
|
361 |
+
.ui-menu {
|
362 |
+
list-style:none;
|
363 |
+
padding: 2px;
|
364 |
+
margin: 0;
|
365 |
+
display:block;
|
366 |
+
float: left;
|
367 |
+
}
|
368 |
+
.ui-menu .ui-menu {
|
369 |
+
margin-top: -3px;
|
370 |
+
}
|
371 |
+
.ui-menu .ui-menu-item {
|
372 |
+
margin:0;
|
373 |
+
padding: 0;
|
374 |
+
zoom: 1;
|
375 |
+
float: left;
|
376 |
+
clear: left;
|
377 |
+
width: 100%;
|
378 |
+
}
|
379 |
+
.ui-menu .ui-menu-item a {
|
380 |
+
text-decoration:none;
|
381 |
+
display:block;
|
382 |
+
padding:.2em .4em;
|
383 |
+
line-height:1.5;
|
384 |
+
zoom:1;
|
385 |
+
}
|
386 |
+
.ui-menu .ui-menu-item a.ui-state-hover,
|
387 |
+
.ui-menu .ui-menu-item a.ui-state-active {
|
388 |
+
font-weight: normal;
|
389 |
+
margin: -1px;
|
390 |
+
}
|
391 |
+
/*
|
392 |
+
* jQuery UI Button 1.8.16
|
393 |
+
*
|
394 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
395 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
396 |
+
* http://jquery.org/license
|
397 |
+
*
|
398 |
+
* http://docs.jquery.com/UI/Button#theming
|
399 |
+
*/
|
400 |
+
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
401 |
+
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
402 |
+
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
403 |
+
.ui-button-icons-only { width: 3.4em; }
|
404 |
+
button.ui-button-icons-only { width: 3.7em; }
|
405 |
+
|
406 |
+
/*button text element */
|
407 |
+
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
408 |
+
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
409 |
+
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
410 |
+
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
411 |
+
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
412 |
+
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
413 |
+
/* no icon support for input elements, provide padding by default */
|
414 |
+
input.ui-button { padding: .4em 1em; }
|
415 |
+
|
416 |
+
/*button icon element(s) */
|
417 |
+
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
418 |
+
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
419 |
+
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
420 |
+
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
421 |
+
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
422 |
+
|
423 |
+
/*button sets*/
|
424 |
+
.ui-buttonset { margin-right: 7px; }
|
425 |
+
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
426 |
+
|
427 |
+
/* workarounds */
|
428 |
+
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
429 |
+
/*
|
430 |
+
* jQuery UI Dialog 1.8.16
|
431 |
+
*
|
432 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
433 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
434 |
+
* http://jquery.org/license
|
435 |
+
*
|
436 |
+
* http://docs.jquery.com/UI/Dialog#theming
|
437 |
+
*/
|
438 |
+
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
439 |
+
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
440 |
+
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
441 |
+
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
442 |
+
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
443 |
+
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
444 |
+
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
445 |
+
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
446 |
+
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
447 |
+
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
448 |
+
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
449 |
+
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
450 |
+
/*
|
451 |
+
* jQuery UI Slider 1.8.16
|
452 |
+
*
|
453 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
454 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
455 |
+
* http://jquery.org/license
|
456 |
+
*
|
457 |
+
* http://docs.jquery.com/UI/Slider#theming
|
458 |
+
*/
|
459 |
+
.ui-slider { position: relative; text-align: left; }
|
460 |
+
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
461 |
+
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
462 |
+
|
463 |
+
.ui-slider-horizontal { height: .8em; }
|
464 |
+
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
465 |
+
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
466 |
+
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
467 |
+
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
468 |
+
|
469 |
+
.ui-slider-vertical { width: .8em; height: 100px; }
|
470 |
+
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
471 |
+
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
472 |
+
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
473 |
+
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
|
474 |
+
* jQuery UI Tabs 1.8.16
|
475 |
+
*
|
476 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
477 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
478 |
+
* http://jquery.org/license
|
479 |
+
*
|
480 |
+
* http://docs.jquery.com/UI/Tabs#theming
|
481 |
+
*/
|
482 |
+
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
483 |
+
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
484 |
+
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
485 |
+
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
486 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
487 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
488 |
+
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
489 |
+
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
490 |
+
.ui-tabs .ui-tabs-hide { display: none !important; }
|
491 |
+
/*
|
492 |
+
* jQuery UI Datepicker 1.8.16
|
493 |
+
*
|
494 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
495 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
496 |
+
* http://jquery.org/license
|
497 |
+
*
|
498 |
+
* http://docs.jquery.com/UI/Datepicker#theming
|
499 |
+
*/
|
500 |
+
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
501 |
+
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
502 |
+
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
503 |
+
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
504 |
+
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
505 |
+
.ui-datepicker .ui-datepicker-next { right:2px; }
|
506 |
+
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
507 |
+
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
508 |
+
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
509 |
+
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
510 |
+
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
511 |
+
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
512 |
+
.ui-datepicker select.ui-datepicker-month,
|
513 |
+
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
514 |
+
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
515 |
+
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
516 |
+
.ui-datepicker td { border: 0; padding: 1px; }
|
517 |
+
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
518 |
+
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
519 |
+
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
520 |
+
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
521 |
+
|
522 |
+
/* with multiple calendars */
|
523 |
+
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
524 |
+
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
525 |
+
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
526 |
+
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
527 |
+
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
528 |
+
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
529 |
+
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
530 |
+
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
531 |
+
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
532 |
+
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
533 |
+
|
534 |
+
/* RTL support */
|
535 |
+
.ui-datepicker-rtl { direction: rtl; }
|
536 |
+
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
537 |
+
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
538 |
+
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
539 |
+
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
540 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
541 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
542 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
543 |
+
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
544 |
+
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
545 |
+
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
546 |
+
|
547 |
+
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
548 |
+
.ui-datepicker-cover {
|
549 |
+
display: none; /*sorry for IE5*/
|
550 |
+
display/**/: block; /*sorry for IE5*/
|
551 |
+
position: absolute; /*must have*/
|
552 |
+
z-index: -1; /*must have*/
|
553 |
+
filter: mask(); /*must have*/
|
554 |
+
top: -4px; /*must have*/
|
555 |
+
left: -4px; /*must have*/
|
556 |
+
width: 200px; /*must have*/
|
557 |
+
height: 200px; /*must have*/
|
558 |
+
}/*
|
559 |
+
* jQuery UI Progressbar 1.8.16
|
560 |
+
*
|
561 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
562 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
563 |
+
* http://jquery.org/license
|
564 |
+
*
|
565 |
+
* http://docs.jquery.com/UI/Progressbar#theming
|
566 |
+
*/
|
567 |
+
.ui-progressbar { height:2em; text-align: left; }
|
568 |
+
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
css/icon_mail.gif
ADDED
Binary file
|
css/jquery.qtip.min.css
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
.ui-tooltip,.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;z-index:15000;}.ui-tooltip-fluid{display:block;visibility:hidden;position:static!important;float:left!important;}.ui-tooltip-content{position:relative;padding:5px 9px;overflow:hidden;border-width:1px;border-style:solid;text-align:left;word-wrap:break-word;overflow:hidden;}.ui-tooltip-titlebar{position:relative;min-height:14px;padding:5px 35px 5px 10px;overflow:hidden;border-width:1px 1px 0;border-style:solid;font-weight:bold;}.ui-tooltip-titlebar+.ui-tooltip-content{border-top-width:0!important;}/*!Default close button class */ .ui-tooltip-titlebar .ui-state-default{position:absolute;right:4px;top:50%;margin-top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;}* html .ui-tooltip-titlebar .ui-state-default{top:16px;}.ui-tooltip-titlebar .ui-icon,.ui-tooltip-icon .ui-icon{display:block;text-indent:-1000em;}.ui-tooltip-icon,.ui-tooltip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;}.ui-tooltip-icon .ui-icon{width:18px;height:14px;text-align:center;text-indent:0;font:normal bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em;}/*!Default tooltip style */ .ui-tooltip-default .ui-tooltip-titlebar,.ui-tooltip-default .ui-tooltip-content{border-color:#F1D031;background-color:#FFFFA3;color:#555;}.ui-tooltip-default .ui-tooltip-titlebar{background-color:#FFEF93;}.ui-tooltip-default .ui-tooltip-icon{border-color:#CCC;background:#F1F1F1;color:#777;}.ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{border-color:#AAA;color:#111;}.ui-tooltip .ui-tooltip-tip{margin:0 auto;overflow:hidden;background:transparent!important;border:0 dashed transparent!important;z-index:10;}.ui-tooltip .ui-tooltip-tip,.ui-tooltip .ui-tooltip-tip *{position:absolute;line-height:.1px!important;font-size:.1px!important;color:#123456;background:transparent;border:0 dashed transparent;}.ui-tooltip .ui-tooltip-tip canvas{top:0;left:0;}/*!Light tooltip style */ .ui-tooltip-light .ui-tooltip-titlebar,.ui-tooltip-light .ui-tooltip-content{border-color:#E2E2E2;color:#454545;}.ui-tooltip-light .ui-tooltip-content{background-color:white;}.ui-tooltip-light .ui-tooltip-titlebar{background-color:#f1f1f1;}/*!Dark tooltip style */ .ui-tooltip-dark .ui-tooltip-titlebar,.ui-tooltip-dark .ui-tooltip-content{border-color:#303030;color:#f3f3f3;}.ui-tooltip-dark .ui-tooltip-content{background-color:#505050;}.ui-tooltip-dark .ui-tooltip-titlebar{background-color:#404040;}.ui-tooltip-dark .ui-tooltip-icon{border-color:#444;}.ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}/*!Cream tooltip style */ .ui-tooltip-cream .ui-tooltip-titlebar,.ui-tooltip-cream .ui-tooltip-content{border-color:#F9E98E;color:#A27D35;}.ui-tooltip-cream .ui-tooltip-content{background-color:#FBF7AA;}.ui-tooltip-cream .ui-tooltip-titlebar{background-color:#F0DE7D;}.ui-tooltip-cream .ui-state-default .ui-tooltip-icon{background-position:-82px 0;}/*!Red tooltip style */ .ui-tooltip-red .ui-tooltip-titlebar,.ui-tooltip-red .ui-tooltip-content{border-color:#D95252;color:#912323;}.ui-tooltip-red .ui-tooltip-content{background-color:#F78B83;}.ui-tooltip-red .ui-tooltip-titlebar{background-color:#F06D65;}.ui-tooltip-red .ui-state-default .ui-tooltip-icon{background-position:-102px 0;}.ui-tooltip-red .ui-tooltip-icon{border-color:#D95252;}.ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{border-color:#D95252;}/*!Green tooltip style */ .ui-tooltip-green .ui-tooltip-titlebar,.ui-tooltip-green .ui-tooltip-content{border-color:#90D93F;color:#3F6219;}.ui-tooltip-green .ui-tooltip-content{background-color:#CAED9E;}.ui-tooltip-green .ui-tooltip-titlebar{background-color:#B0DE78;}.ui-tooltip-green .ui-state-default .ui-tooltip-icon{background-position:-42px 0;}/*!Blue tooltip style */ .ui-tooltip-blue .ui-tooltip-titlebar,.ui-tooltip-blue .ui-tooltip-content{border-color:#ADD9ED;color:#5E99BD;}.ui-tooltip-blue .ui-tooltip-content{background-color:#E5F6FE;}.ui-tooltip-blue .ui-tooltip-titlebar{background-color:#D0E9F5;}.ui-tooltip-blue .ui-state-default .ui-tooltip-icon{background-position:-2px 0;}/*!Add shadows to your tooltips in:FF3+,Chrome 2+,Opera 10.6+,IE6+,Safari 2+*/ .ui-tooltip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);}.ui-tooltip-shadow .ui-tooltip-titlebar,.ui-tooltip-shadow .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.Shadow(Color='gray',Direction=135,Strength=3);-ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray',Direction=135,Strength=3)";_margin-bottom:-3px;.margin-bottom:-3px;}/*!Add rounded corners to your tooltips in:FF3+,Chrome 2+,Opera 10.6+,IE9+,Safari 2+*/ .ui-tooltip-rounded,.ui-tooltip-rounded .ui-tooltip-content,.ui-tooltip-tipsy,.ui-tooltip-tipsy .ui-tooltip-content,.ui-tooltip-youtube,.ui-tooltip-youtube .ui-tooltip-content{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;}.ui-tooltip-rounded .ui-tooltip-titlebar,.ui-tooltip-tipsy .ui-tooltip-titlebar,.ui-tooltip-youtube .ui-tooltip-titlebar{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}.ui-tooltip-rounded .ui-tooltip-titlebar+.ui-tooltip-content,.ui-tooltip-tipsy .ui-tooltip-titlebar+.ui-tooltip-content,.ui-tooltip-youtube .ui-tooltip-titlebar+.ui-tooltip-content{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;}/*!Youtube tooltip style */ .ui-tooltip-youtube{-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;}.ui-tooltip-youtube .ui-tooltip-titlebar,.ui-tooltip-youtube .ui-tooltip-content{_margin-bottom:0;.margin-bottom:0;background:transparent;background:rgba(0,0,0,0.85);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";color:white;border-color:#CCC;}.ui-tooltip-youtube .ui-tooltip-icon{border-color:#222;}.ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}.ui-tooltip-jtools{background:#232323;background:rgba(0,0,0,0.7);background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333;}.ui-tooltip-jtools .ui-tooltip-titlebar{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";}.ui-tooltip-jtools .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";}.ui-tooltip-jtools .ui-tooltip-titlebar,.ui-tooltip-jtools .ui-tooltip-content{background:transparent;color:white;border:0 dashed transparent;}.ui-tooltip-jtools .ui-tooltip-icon{border-color:#555;}.ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{border-color:#333;}.ui-tooltip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,0.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,0.4);box-shadow:4px 4px 5px rgba(0,0,0,0.4);}.ui-tooltip-cluetip .ui-tooltip-titlebar{background-color:#87876A;color:white;border:0 dashed transparent;}.ui-tooltip-cluetip .ui-tooltip-content{background-color:#D9D9C2;color:#111;border:0 dashed transparent;}.ui-tooltip-cluetip .ui-tooltip-icon{border-color:#808064;}.ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{border-color:#696952;color:#696952;}.ui-tooltip-tipsy{border:0;}.ui-tooltip-tipsy .ui-tooltip-titlebar,.ui-tooltip-tipsy .ui-tooltip-content{_margin-bottom:0;.margin-bottom:0;background:transparent;background:rgba(0,0,0,.87);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";color:white;border:0 transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:bold;line-height:16px;text-shadow:0 1px black;}.ui-tooltip-tipsy .ui-tooltip-titlebar{padding:6px 35px 0 10;}.ui-tooltip-tipsy .ui-tooltip-content{padding:6px 10;}.ui-tooltip-tipsy .ui-tooltip-icon{border-color:#222;text-shadow:none;}.ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}.ui-tooltip-tipped .ui-tooltip-titlebar,.ui-tooltip-tipped .ui-tooltip-content{border:3px solid #959FA9;filter:none;-ms-filter:none;}.ui-tooltip-tipped .ui-tooltip-titlebar{background:#3A79B8;background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";color:white;font-weight:normal;font-family:serif;border-bottom-width:0;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}.ui-tooltip-tipped .ui-tooltip-content{background-color:#F9F9F9;color:#454545;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;}.ui-tooltip-tipped .ui-tooltip-icon{border:2px solid #285589;background:#285589;}.ui-tooltip-tipped .ui-tooltip-icon .ui-icon{background-color:#FBFBFB;color:#555;}.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{filter:none;-ms-filter:none;}
|
css/p3.css
ADDED
@@ -0,0 +1,345 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
|
2 |
+
/** Top grey nav bar **/
|
3 |
+
#p3-navbar {
|
4 |
+
margin-top: 10px;
|
5 |
+
padding: 4px;
|
6 |
+
cursor: default;
|
7 |
+
}
|
8 |
+
|
9 |
+
|
10 |
+
/** The grey box behind the big buttons **/
|
11 |
+
#p3-scan-form-wrapper {
|
12 |
+
cursor: default;
|
13 |
+
padding: 10px;
|
14 |
+
width: 170px;
|
15 |
+
height: 80px;
|
16 |
+
text-align: center;
|
17 |
+
margin-top: 10px;
|
18 |
+
}
|
19 |
+
|
20 |
+
/** Big buttons **/
|
21 |
+
.p3-big-button {
|
22 |
+
margin: auto;
|
23 |
+
text-align: center;
|
24 |
+
}
|
25 |
+
.p3-big-button label {
|
26 |
+
margin: 5px;
|
27 |
+
}
|
28 |
+
.p3-big-button label span {
|
29 |
+
font-size: 110%;
|
30 |
+
font-weight: bold;
|
31 |
+
width: 110px;
|
32 |
+
margin: 2px;
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
/** Light grey italic captions **/
|
37 |
+
em.p3-em {
|
38 |
+
color: #999999;
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
/** Auto scanner frame **/
|
43 |
+
#p3-scan-frame {
|
44 |
+
border-width: 0px;
|
45 |
+
height: 500px;
|
46 |
+
width: 100%;
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
/** jQuery UI Dialog overrides **/
|
51 |
+
.noPadding.ui-dialog .ui-dialog-content {
|
52 |
+
padding: 0;
|
53 |
+
}
|
54 |
+
.noTitle .ui-dialog-titlebar {
|
55 |
+
display: none;
|
56 |
+
}
|
57 |
+
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
|
58 |
+
float: none;
|
59 |
+
text-align: center;
|
60 |
+
}
|
61 |
+
.p3-dialog {
|
62 |
+
display: none;
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
|
67 |
+
/** Turn "Cancel" button into link **/
|
68 |
+
button.p3-cancel-button{
|
69 |
+
border-width: 0px !important;
|
70 |
+
background-image: none !important;
|
71 |
+
background-color: transparent !important;
|
72 |
+
}
|
73 |
+
.ui-dialog .ui-dialog-buttonpane button.p3-cancel-button span {
|
74 |
+
text-decoration: underline;
|
75 |
+
padding-left: 0;
|
76 |
+
padding-right: 0;
|
77 |
+
margin-left: 1px;
|
78 |
+
margin-right: 0;
|
79 |
+
color: #21759b;
|
80 |
+
}
|
81 |
+
#p3-manual-scan-cancel {
|
82 |
+
color: #21759b;
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
/** Captions for the scan "This will take several minutes ..." **/
|
87 |
+
#p3-scan-caption {
|
88 |
+
margin: 8px auto 0 auto;
|
89 |
+
width: 85%;
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
/** Auto scanner display status **/
|
94 |
+
#p3-scanning-caption {
|
95 |
+
text-overflow: ellipsis;
|
96 |
+
white-space: nowrap;
|
97 |
+
-moz-binding: url('wordwrap.xml#wordwrap');
|
98 |
+
word-wrap: break-word;
|
99 |
+
overflow: hidden;
|
100 |
+
width: 100%;
|
101 |
+
padding-left: 4px;
|
102 |
+
height: 18px;
|
103 |
+
color: #999999;
|
104 |
+
font-style: italic;
|
105 |
+
}
|
106 |
+
|
107 |
+
|
108 |
+
/** Progress bar **/
|
109 |
+
#p3-progress {
|
110 |
+
margin: 5px auto 5px auto;
|
111 |
+
}
|
112 |
+
|
113 |
+
|
114 |
+
/** Charts and graphs **/
|
115 |
+
div.p3-plugin-graph {
|
116 |
+
margin: 10px auto 20px auto;
|
117 |
+
width: 620px;
|
118 |
+
height: 320px;
|
119 |
+
}
|
120 |
+
div.p3-graph-holder {
|
121 |
+
width: 500px;
|
122 |
+
height: 300px;
|
123 |
+
margin: auto;
|
124 |
+
}
|
125 |
+
div.p3-custom-legend {
|
126 |
+
float: left;
|
127 |
+
width: 120px;
|
128 |
+
height: 280px;
|
129 |
+
overflow: auto;
|
130 |
+
}
|
131 |
+
#p3-tabs h2 {
|
132 |
+
margin: auto;
|
133 |
+
text-align: center;
|
134 |
+
}
|
135 |
+
div.p3-plugin-graph td {
|
136 |
+
vertical-align: top;
|
137 |
+
}
|
138 |
+
div.p3-plugin-graph td h3{
|
139 |
+
text-align: center;
|
140 |
+
margin: auto;
|
141 |
+
}
|
142 |
+
div.p3-plugin-graph div.yAxis div.tickLabel {
|
143 |
+
margin-right: 25px;
|
144 |
+
margin-top: -10px;
|
145 |
+
}
|
146 |
+
|
147 |
+
|
148 |
+
/** Advanced metrics table and glossary table **/
|
149 |
+
table.p3-results-table td {
|
150 |
+
background-color: #ffffff;
|
151 |
+
padding: 6px;
|
152 |
+
}
|
153 |
+
table.p3-results-table td {
|
154 |
+
border-style: solid;
|
155 |
+
border-color: #eaeaea;
|
156 |
+
border-width: 0px 1px 1px 1px;
|
157 |
+
vertical-align: top;
|
158 |
+
}
|
159 |
+
table.p3-results-table th:last-child {
|
160 |
+
border-left-width: 0px;
|
161 |
+
}
|
162 |
+
table.p3-results-table tr.even td {
|
163 |
+
background-color: #fcfcfc;
|
164 |
+
}
|
165 |
+
table.p3-results-table {
|
166 |
+
width: 100%;
|
167 |
+
border-collapse: collapse;
|
168 |
+
margin: 0 auto 20px auto;
|
169 |
+
}
|
170 |
+
p3-metrics-header {
|
171 |
+
width: 100%;
|
172 |
+
}
|
173 |
+
p3-metrics-container {
|
174 |
+
min-width: 650px;
|
175 |
+
max-width: 800px;
|
176 |
+
width: 80%;
|
177 |
+
}
|
178 |
+
p3-glossary-header {
|
179 |
+
width: 100%;
|
180 |
+
}
|
181 |
+
p3-glossary-container {
|
182 |
+
min-width: 650px;
|
183 |
+
max-width: 800px;
|
184 |
+
width: 80%;
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
|
189 |
+
/** Glossary **/
|
190 |
+
#p3-glossary-term-display {
|
191 |
+
vertical-align: text-top;
|
192 |
+
border-width: 1px !important;
|
193 |
+
font-size: 14px;
|
194 |
+
}
|
195 |
+
#p3-glossary-table td.term {
|
196 |
+
border-width: 1px !important;
|
197 |
+
border-color: transparent !important;
|
198 |
+
cursor: pointer;
|
199 |
+
}
|
200 |
+
#p3-glossary-table td.term.hover {
|
201 |
+
background-color: #206d92;
|
202 |
+
border-width: 1px 0px 1px 1px !important;
|
203 |
+
border-color: #298cba !important;
|
204 |
+
background-image: url(custom-theme/images/ui-bg_highlight-hard_100_206d92_1x100.png);
|
205 |
+
background-position: 50% 50%;
|
206 |
+
background-repeat: repeat-x;
|
207 |
+
color: white;
|
208 |
+
}
|
209 |
+
|
210 |
+
/** Quick report table **/
|
211 |
+
#p3-quick-report {
|
212 |
+
width: 100%;
|
213 |
+
}
|
214 |
+
#p3-quick-report td {
|
215 |
+
width: 20%;
|
216 |
+
vertical-align: top;
|
217 |
+
padding: 0px;
|
218 |
+
}
|
219 |
+
#p3-quick-report td.p3-callout {
|
220 |
+
text-align: center;
|
221 |
+
}
|
222 |
+
#p3-quick-report div.p3-callout-outer-wrapper {
|
223 |
+
border: 1px solid #cccccc;
|
224 |
+
margin: 10px auto;
|
225 |
+
width: 140px;
|
226 |
+
}
|
227 |
+
#p3-quick-report div.p3-callout-inner-wrapper {
|
228 |
+
width: 140px;
|
229 |
+
height: 92px;
|
230 |
+
}
|
231 |
+
#p3-quick-report td div.p3-callout-caption {
|
232 |
+
text-align: center;
|
233 |
+
position: relative;
|
234 |
+
}
|
235 |
+
#p3-quick-report td div.p3-callout-caption:first-child {
|
236 |
+
top: 5px;
|
237 |
+
}
|
238 |
+
#p3-quick-report td div.p3-callout-caption:last-child {
|
239 |
+
top: -6px;
|
240 |
+
}
|
241 |
+
#p3-quick-report div.p3-callout-data {
|
242 |
+
font-weight: bold;
|
243 |
+
text-align: center;
|
244 |
+
font-size: 40px;
|
245 |
+
position: relative;
|
246 |
+
top: 22px;
|
247 |
+
height: 60px;
|
248 |
+
}
|
249 |
+
.p3-faded-grey {
|
250 |
+
color: #dddddd;
|
251 |
+
}
|
252 |
+
|
253 |
+
|
254 |
+
|
255 |
+
/** Enter your IP dialog **/
|
256 |
+
#p3-ip-dialog {
|
257 |
+
padding: 15px;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
/** Tabs shim **/
|
262 |
+
#p3-tabs ul li:first-child {
|
263 |
+
margin-left: 4px;
|
264 |
+
}
|
265 |
+
|
266 |
+
|
267 |
+
/** Copyright notice **/
|
268 |
+
#p3-copyright {
|
269 |
+
text-align: center;
|
270 |
+
margin: 45px auto 5px auto;
|
271 |
+
}
|
272 |
+
#p3-copyright img {
|
273 |
+
margin-bottom: 7px;
|
274 |
+
height: 47px;
|
275 |
+
width: 125px;
|
276 |
+
}
|
277 |
+
|
278 |
+
|
279 |
+
/** Rotated y-axis label **/
|
280 |
+
div.p3-y-axis-label {
|
281 |
+
|
282 |
+
position: relative;
|
283 |
+
top: 135px;
|
284 |
+
left: -20px;
|
285 |
+
|
286 |
+
/* Safari */
|
287 |
+
-webkit-transform: rotate(-90deg);
|
288 |
+
|
289 |
+
/* Firefox */
|
290 |
+
-moz-transform: rotate(-90deg);
|
291 |
+
|
292 |
+
/* Opera */
|
293 |
+
-o-transform: rotate(-90deg);
|
294 |
+
|
295 |
+
/* Internet Explorer */
|
296 |
+
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
|
297 |
+
}
|
298 |
+
|
299 |
+
|
300 |
+
/** X axis label **/
|
301 |
+
div.p3-x-axis-label {
|
302 |
+
position: relative;
|
303 |
+
top: 20px;
|
304 |
+
left: 235px;
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
+
/** Jack up the font size on the tooltips **/
|
309 |
+
.ui-tooltip {
|
310 |
+
font-size: 120%;
|
311 |
+
line-height: 125%;
|
312 |
+
}
|
313 |
+
|
314 |
+
|
315 |
+
/** Email these results button **/
|
316 |
+
#p3-email-results {
|
317 |
+
margin: 20px auto 30px auto;
|
318 |
+
}
|
319 |
+
#p3-email-results a {
|
320 |
+
display: inline-block;
|
321 |
+
position: relative;
|
322 |
+
top: 1px;
|
323 |
+
left: 4px;
|
324 |
+
}
|
325 |
+
#p3-email-sending-dialog img {
|
326 |
+
left: 132px;
|
327 |
+
top: 40px;
|
328 |
+
position: relative;
|
329 |
+
}
|
330 |
+
#p3-email-sending-close {
|
331 |
+
margin: 20px auto;
|
332 |
+
text-align: center;
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
/** Help page questions **/
|
337 |
+
div.p3-question {
|
338 |
+
border: 1px solid #cccccc;
|
339 |
+
margin-bottom: 10px;
|
340 |
+
padding: 8px;
|
341 |
+
}
|
342 |
+
div.p3-question h2.p3-help-question {
|
343 |
+
margin-top: -15px;
|
344 |
+
border-bottom: 1px solid #cccccc;
|
345 |
+
}
|
css/wordwrap.xml
ADDED
@@ -0,0 +1,22 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version = "1.0"?>
|
2 |
+
<bindings xmlns = "http://www.mozilla.org/xbl" xmlns:html = "http://www.w3.org/1999/xhtml">
|
3 |
+
<binding id = "wordwrap" applyauthorstyles = "false">
|
4 |
+
<implementation>
|
5 |
+
<constructor>
|
6 |
+
//<![CDATA[
|
7 |
+
var elem = this;
|
8 |
+
doWrap();
|
9 |
+
elem.addEventListener('overflow', doWrap, false);
|
10 |
+
function doWrap() {
|
11 |
+
var walker = document.createTreeWalker(elem, NodeFilter.SHOW_TEXT, null, false);
|
12 |
+
while (walker.nextNode()) {
|
13 |
+
var node = walker.currentNode;
|
14 |
+
node.nodeValue = node.nodeValue.split('').join(String.fromCharCode('8203'));
|
15 |
+
}
|
16 |
+
elem.innerHTML = elem.innerHTML.replace(/^\s+|\s+$/g,"");
|
17 |
+
}
|
18 |
+
//]]>
|
19 |
+
</constructor>
|
20 |
+
</implementation>
|
21 |
+
</binding>
|
22 |
+
</bindings>
|
index.php
ADDED
@@ -0,0 +1,2 @@
|
|
Â
|
|
Â
|
1 |
+
<?php header( 'Status: 404 Not found' ); ?>
|
2 |
+
Not found
|
js/jquery.corner.js
ADDED
@@ -0,0 +1,22 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*!
|
2 |
+
* jQuery corner plugin: simple corner rounding
|
3 |
+
* Examples and documentation at: http://jquery.malsup.com/corner/
|
4 |
+
* version 2.12 (23-MAY-2011)
|
5 |
+
* Requires jQuery v1.3.2 or later
|
6 |
+
* Dual licensed under the MIT and GPL licenses:
|
7 |
+
* http://www.opensource.org/licenses/mit-license.php
|
8 |
+
* http://www.gnu.org/licenses/gpl.html
|
9 |
+
* Authors: Dave Methvin and Mike Alsup
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* corner() takes a single string argument: $('#myDiv').corner("effect corners width")
|
14 |
+
*
|
15 |
+
* effect: name of the effect to apply, such as round, bevel, notch, bite, etc (default is round).
|
16 |
+
* corners: one or more of: top, bottom, tr, tl, br, or bl. (default is all corners)
|
17 |
+
* width: width of the effect; in the case of rounded corners this is the radius.
|
18 |
+
* specify this value using the px suffix such as 10px (yes, it must be pixels).
|
19 |
+
*/
|
20 |
+
;(function($){var style=document.createElement('div').style,moz=style['MozBorderRadius']!==undefined,webkit=style['WebkitBorderRadius']!==undefined,radius=style['borderRadius']!==undefined||style['BorderRadius']!==undefined,mode=document.documentMode||0,noBottomFold=$.browser.msie&&(($.browser.version<8&&!mode)||mode<8),expr=$.browser.msie&&(function(){var div=document.createElement('div');try{div.style.setExpression('width','0+0');div.style.removeExpression('width');}catch(e){return false;}return true;})();$.support=$.support||{};$.support.borderRadius=moz||webkit||radius;function sz(el,p){return parseInt($.css(el,p))||0;};function hex2(s){s=parseInt(s).toString(16);return(s.length<2)?'0'+s:s;};function gpc(node){while(node){var v=$.css(node,'backgroundColor'),rgb;if(v&&v!='transparent'&&v!='rgba(0, 0, 0, 0)'){if(v.indexOf('rgb')>=0){rgb=v.match(/\d+/g);return'#'+hex2(rgb[0])+hex2(rgb[1])+hex2(rgb[2]);}return v;}if(node.nodeName.toLowerCase()=='html')break;node=node.parentNode;}return'#ffffff';};function getWidth(fx,i,width){switch(fx){case'round':return Math.round(width*(1-Math.cos(Math.asin(i/width))));case'cool':return Math.round(width*(1+Math.cos(Math.asin(i/width))));case'sharp':return width-i;case'bite':return Math.round(width*(Math.cos(Math.asin((width-i-1)/width))));case'slide':return Math.round(width*(Math.atan2(i,width/i)));case'jut':return Math.round(width*(Math.atan2(width,(width-i-1))));case'curl':return Math.round(width*(Math.atan(i)));case'tear':return Math.round(width*(Math.cos(i)));case'wicked':return Math.round(width*(Math.tan(i)));case'long':return Math.round(width*(Math.sqrt(i)));case'sculpt':return Math.round(width*(Math.log((width-i-1),width)));case'dogfold':case'dog':return(i&1)?(i+1):width;case'dog2':return(i&2)?(i+1):width;case'dog3':return(i&3)?(i+1):width;case'fray':return(i%2)*width;case'notch':return width;case'bevelfold':case'bevel':return i+1;case'steep':return i/2+1;case'invsteep':return(width-i)/2+1;}};$.fn.corner=function(options){if(this.length==0){if(!$.isReady&&this.selector){var s=this.selector,c=this.context;$(function(){$(s,c).corner(options);});}return this;}return this.each(function(index){var $this=$(this),o=[$this.attr($.fn.corner.defaults.metaAttr)||'',options||''].join(' ').toLowerCase(),keep=/keep/.test(o),cc=((o.match(/cc:(#[0-9a-f]+)/)||[])[1]),sc=((o.match(/sc:(#[0-9a-f]+)/)||[])[1]),width=parseInt((o.match(/(\d+)px/)||[])[1])||10,re=/round|bevelfold|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dogfold|dog|invsteep|steep/,fx=((o.match(re)||['round'])[0]),fold=/dogfold|bevelfold/.test(o),edges={T:0,B:1},opts={TL:/top|tl|left/.test(o),TR:/top|tr|right/.test(o),BL:/bottom|bl|left/.test(o),BR:/bottom|br|right/.test(o)},strip,pad,cssHeight,j,bot,d,ds,bw,i,w,e,c,common,$horz;if(!opts.TL&&!opts.TR&&!opts.BL&&!opts.BR)opts={TL:1,TR:1,BL:1,BR:1};if($.fn.corner.defaults.useNative&&fx=='round'&&(radius||moz||webkit)&&!cc&&!sc){if(opts.TL)$this.css(radius?'border-top-left-radius':moz?'-moz-border-radius-topleft':'-webkit-border-top-left-radius',width+'px');if(opts.TR)$this.css(radius?'border-top-right-radius':moz?'-moz-border-radius-topright':'-webkit-border-top-right-radius',width+'px');if(opts.BL)$this.css(radius?'border-bottom-left-radius':moz?'-moz-border-radius-bottomleft':'-webkit-border-bottom-left-radius',width+'px');if(opts.BR)$this.css(radius?'border-bottom-right-radius':moz?'-moz-border-radius-bottomright':'-webkit-border-bottom-right-radius',width+'px');return;}strip=document.createElement('div');$(strip).css({overflow:'hidden',height:'1px',minHeight:'1px',fontSize:'1px',backgroundColor:sc||'transparent',borderStyle:'solid'});pad={T:parseInt($.css(this,'paddingTop'))||0,R:parseInt($.css(this,'paddingRight'))||0,B:parseInt($.css(this,'paddingBottom'))||0,L:parseInt($.css(this,'paddingLeft'))||0};if(typeof this.style.zoom!=undefined)this.style.zoom=1;if(!keep)this.style.border='none';strip.style.borderColor=cc||gpc(this.parentNode);cssHeight=$(this).outerHeight();for(j in edges){bot=edges[j];if((bot&&(opts.BL||opts.BR))||(!bot&&(opts.TL||opts.TR))){strip.style.borderStyle='none '+(opts[j+'R']?'solid':'none')+' none '+(opts[j+'L']?'solid':'none');d=document.createElement('div');$(d).addClass('jquery-corner');ds=d.style;bot?this.appendChild(d):this.insertBefore(d,this.firstChild);if(bot&&cssHeight!='auto'){if($.css(this,'position')=='static')this.style.position='relative';ds.position='absolute';ds.bottom=ds.left=ds.padding=ds.margin='0';if(expr)ds.setExpression('width','this.parentNode.offsetWidth');else
|
21 |
+
ds.width='100%';}else if(!bot&&$.browser.msie){if($.css(this,'position')=='static')this.style.position='relative';ds.position='absolute';ds.top=ds.left=ds.right=ds.padding=ds.margin='0';if(expr){bw=sz(this,'borderLeftWidth')+sz(this,'borderRightWidth');ds.setExpression('width','this.parentNode.offsetWidth - '+bw+'+ "px"');}else
|
22 |
+
ds.width='100%';}else{ds.position='relative';ds.margin=!bot?'-'+pad.T+'px -'+pad.R+'px '+(pad.T-width)+'px -'+pad.L+'px':(pad.B-width)+'px -'+pad.R+'px -'+pad.B+'px -'+pad.L+'px';}for(i=0;i<width;i++){w=Math.max(0,getWidth(fx,i,width));e=strip.cloneNode(false);e.style.borderWidth='0 '+(opts[j+'R']?w:0)+'px 0 '+(opts[j+'L']?w:0)+'px';bot?d.appendChild(e):d.insertBefore(e,d.firstChild);}if(fold&&$.support.boxModel){if(bot&&noBottomFold)continue;for(c in opts){if(!opts[c])continue;if(bot&&(c=='TL'||c=='TR'))continue;if(!bot&&(c=='BL'||c=='BR'))continue;common={position:'absolute',border:'none',margin:0,padding:0,overflow:'hidden',backgroundColor:strip.style.borderColor};$horz=$('<div/>').css(common).css({width:width+'px',height:'1px'});switch(c){case'TL':$horz.css({bottom:0,left:0});break;case'TR':$horz.css({bottom:0,right:0});break;case'BL':$horz.css({top:0,left:0});break;case'BR':$horz.css({top:0,right:0});break;}d.appendChild($horz[0]);var $vert=$('<div/>').css(common).css({top:0,bottom:0,width:'1px',height:width+'px'});switch(c){case'TL':$vert.css({left:width});break;case'TR':$vert.css({right:width});break;case'BL':$vert.css({left:width});break;case'BR':$vert.css({right:width});break;}d.appendChild($vert[0]);}}}}});};$.fn.uncorner=function(){if(radius||moz||webkit)this.css(radius?'border-radius':moz?'-moz-border-radius':'-webkit-border-radius',0);$('div.jquery-corner',this).remove();return this;};$.fn.corner.defaults={useNative:true,metaAttr:'data-corner'};})(jQuery);
|
js/jquery.flot.min.js
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
Javascript plotting library for jQuery ~ v0.7 ~ Copyright (c) 2007-2011 IOLA and Ole Laursen
|
3 |
+
Licensed under the MIT License ~ https://raw.github.com/flot/flot/master/LICENSE.txt
|
4 |
+
*/
|
5 |
+
(function(b){b.color={};b.color.make=function(d,e,g,f){var c={};c.r=d||0;c.g=e||0;c.b=g||0;c.a=f!=null?f:1;c.add=function(h,j){for(var k=0;k<h.length;++k){c[h.charAt(k)]+=j}return c.normalize()};c.scale=function(h,j){for(var k=0;k<h.length;++k){c[h.charAt(k)]*=j}return c.normalize()};c.toString=function(){if(c.a>=1){return"rgb("+[c.r,c.g,c.b].join(",")+")"}else{return"rgba("+[c.r,c.g,c.b,c.a].join(",")+")"}};c.normalize=function(){function h(k,j,l){return j<k?k:(j>l?l:j)}c.r=h(0,parseInt(c.r),255);c.g=h(0,parseInt(c.g),255);c.b=h(0,parseInt(c.b),255);c.a=h(0,c.a,1);return c};c.clone=function(){return b.color.make(c.r,c.b,c.g,c.a)};return c.normalize()};b.color.extract=function(d,e){var c;do{c=d.css(e).toLowerCase();if(c!=""&&c!="transparent"){break}d=d.parent()}while(!b.nodeName(d.get(0),"body"));if(c=="rgba(0, 0, 0, 0)"){c="transparent"}return b.color.parse(c)};b.color.parse=function(c){var d,f=b.color.make;if(d=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c)){return f(parseInt(d[1],10),parseInt(d[2],10),parseInt(d[3],10))}if(d=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(c)){return f(parseInt(d[1],10),parseInt(d[2],10),parseInt(d[3],10),parseFloat(d[4]))}if(d=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c)){return f(parseFloat(d[1])*2.55,parseFloat(d[2])*2.55,parseFloat(d[3])*2.55)}if(d=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(c)){return f(parseFloat(d[1])*2.55,parseFloat(d[2])*2.55,parseFloat(d[3])*2.55,parseFloat(d[4]))}if(d=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c)){return f(parseInt(d[1],16),parseInt(d[2],16),parseInt(d[3],16))}if(d=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c)){return f(parseInt(d[1]+d[1],16),parseInt(d[2]+d[2],16),parseInt(d[3]+d[3],16))}var e=b.trim(c).toLowerCase();if(e=="transparent"){return f(255,255,255,0)}else{d=a[e]||[0,0,0];return f(d[0],d[1],d[2])}};var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],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],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function(c){function b(av,ai,J,af){var Q=[],O={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{show:null,position:"bottom",mode:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},az=null,ad=null,y=null,H=null,A=null,p=[],aw=[],q={left:0,right:0,top:0,bottom:0},G=0,I=0,h=0,w=0,ak={processOptions:[],processRawData:[],processDatapoints:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},aq=this;aq.setData=aj;aq.setupGrid=t;aq.draw=W;aq.getPlaceholder=function(){return av};aq.getCanvas=function(){return az};aq.getPlotOffset=function(){return q};aq.width=function(){return h};aq.height=function(){return w};aq.offset=function(){var aB=y.offset();aB.left+=q.left;aB.top+=q.top;return aB};aq.getData=function(){return Q};aq.getAxes=function(){var aC={},aB;c.each(p.concat(aw),function(aD,aE){if(aE){aC[aE.direction+(aE.n!=1?aE.n:"")+"axis"]=aE}});return aC};aq.getXAxes=function(){return p};aq.getYAxes=function(){return aw};aq.c2p=C;aq.p2c=ar;aq.getOptions=function(){return O};aq.highlight=x;aq.unhighlight=T;aq.triggerRedrawOverlay=f;aq.pointOffset=function(aB){return{left:parseInt(p[aA(aB,"x")-1].p2c(+aB.x)+q.left),top:parseInt(aw[aA(aB,"y")-1].p2c(+aB.y)+q.top)}};aq.shutdown=ag;aq.resize=function(){B();g(az);g(ad)};aq.hooks=ak;F(aq);Z(J);X();aj(ai);t();W();ah();function an(aD,aB){aB=[aq].concat(aB);for(var aC=0;aC<aD.length;++aC){aD[aC].apply(this,aB)}}function F(){for(var aB=0;aB<af.length;++aB){var aC=af[aB];aC.init(aq);if(aC.options){c.extend(true,O,aC.options)}}}function Z(aC){var aB;c.extend(true,O,aC);if(O.xaxis.color==null){O.xaxis.color=O.grid.color}if(O.yaxis.color==null){O.yaxis.color=O.grid.color}if(O.xaxis.tickColor==null){O.xaxis.tickColor=O.grid.tickColor}if(O.yaxis.tickColor==null){O.yaxis.tickColor=O.grid.tickColor}if(O.grid.borderColor==null){O.grid.borderColor=O.grid.color}if(O.grid.tickColor==null){O.grid.tickColor=c.color.parse(O.grid.color).scale("a",0.22).toString()}for(aB=0;aB<Math.max(1,O.xaxes.length);++aB){O.xaxes[aB]=c.extend(true,{},O.xaxis,O.xaxes[aB])}for(aB=0;aB<Math.max(1,O.yaxes.length);++aB){O.yaxes[aB]=c.extend(true,{},O.yaxis,O.yaxes[aB])}if(O.xaxis.noTicks&&O.xaxis.ticks==null){O.xaxis.ticks=O.xaxis.noTicks}if(O.yaxis.noTicks&&O.yaxis.ticks==null){O.yaxis.ticks=O.yaxis.noTicks}if(O.x2axis){O.xaxes[1]=c.extend(true,{},O.xaxis,O.x2axis);O.xaxes[1].position="top"}if(O.y2axis){O.yaxes[1]=c.extend(true,{},O.yaxis,O.y2axis);O.yaxes[1].position="right"}if(O.grid.coloredAreas){O.grid.markings=O.grid.coloredAreas}if(O.grid.coloredAreasColor){O.grid.markingsColor=O.grid.coloredAreasColor}if(O.lines){c.extend(true,O.series.lines,O.lines)}if(O.points){c.extend(true,O.series.points,O.points)}if(O.bars){c.extend(true,O.series.bars,O.bars)}if(O.shadowSize!=null){O.series.shadowSize=O.shadowSize}for(aB=0;aB<O.xaxes.length;++aB){V(p,aB+1).options=O.xaxes[aB]}for(aB=0;aB<O.yaxes.length;++aB){V(aw,aB+1).options=O.yaxes[aB]}for(var aD in ak){if(O.hooks[aD]&&O.hooks[aD].length){ak[aD]=ak[aD].concat(O.hooks[aD])}}an(ak.processOptions,[O])}function aj(aB){Q=Y(aB);ax();z()}function Y(aE){var aC=[];for(var aB=0;aB<aE.length;++aB){var aD=c.extend(true,{},O.series);if(aE[aB].data!=null){aD.data=aE[aB].data;delete aE[aB].data;c.extend(true,aD,aE[aB]);aE[aB].data=aD.data}else{aD.data=aE[aB]}aC.push(aD)}return aC}function aA(aC,aD){var aB=aC[aD+"axis"];if(typeof aB=="object"){aB=aB.n}if(typeof aB!="number"){aB=1}return aB}function m(){return c.grep(p.concat(aw),function(aB){return aB})}function C(aE){var aC={},aB,aD;for(aB=0;aB<p.length;++aB){aD=p[aB];if(aD&&aD.used){aC["x"+aD.n]=aD.c2p(aE.left)}}for(aB=0;aB<aw.length;++aB){aD=aw[aB];if(aD&&aD.used){aC["y"+aD.n]=aD.c2p(aE.top)}}if(aC.x1!==undefined){aC.x=aC.x1}if(aC.y1!==undefined){aC.y=aC.y1}return aC}function ar(aF){var aD={},aC,aE,aB;for(aC=0;aC<p.length;++aC){aE=p[aC];if(aE&&aE.used){aB="x"+aE.n;if(aF[aB]==null&&aE.n==1){aB="x"}if(aF[aB]!=null){aD.left=aE.p2c(aF[aB]);break}}}for(aC=0;aC<aw.length;++aC){aE=aw[aC];if(aE&&aE.used){aB="y"+aE.n;if(aF[aB]==null&&aE.n==1){aB="y"}if(aF[aB]!=null){aD.top=aE.p2c(aF[aB]);break}}}return aD}function V(aC,aB){if(!aC[aB-1]){aC[aB-1]={n:aB,direction:aC==p?"x":"y",options:c.extend(true,{},aC==p?O.xaxis:O.yaxis)}}return aC[aB-1]}function ax(){var aG;var aM=Q.length,aB=[],aE=[];for(aG=0;aG<Q.length;++aG){var aJ=Q[aG].color;if(aJ!=null){--aM;if(typeof aJ=="number"){aE.push(aJ)}else{aB.push(c.color.parse(Q[aG].color))}}}for(aG=0;aG<aE.length;++aG){aM=Math.max(aM,aE[aG]+1)}var aC=[],aF=0;aG=0;while(aC.length<aM){var aI;if(O.colors.length==aG){aI=c.color.make(100,100,100)}else{aI=c.color.parse(O.colors[aG])}var aD=aF%2==1?-1:1;aI.scale("rgb",1+aD*Math.ceil(aF/2)*0.2);aC.push(aI);++aG;if(aG>=O.colors.length){aG=0;++aF}}var aH=0,aN;for(aG=0;aG<Q.length;++aG){aN=Q[aG];if(aN.color==null){aN.color=aC[aH].toString();++aH}else{if(typeof aN.color=="number"){aN.color=aC[aN.color].toString()}}if(aN.lines.show==null){var aL,aK=true;for(aL in aN){if(aN[aL]&&aN[aL].show){aK=false;break}}if(aK){aN.lines.show=true}}aN.xaxis=V(p,aA(aN,"x"));aN.yaxis=V(aw,aA(aN,"y"))}}function z(){var aO=Number.POSITIVE_INFINITY,aI=Number.NEGATIVE_INFINITY,aB=Number.MAX_VALUE,aU,aS,aR,aN,aD,aJ,aT,aP,aH,aG,aC,a0,aX,aL;function aF(a3,a2,a1){if(a2<a3.datamin&&a2!=-aB){a3.datamin=a2}if(a1>a3.datamax&&a1!=aB){a3.datamax=a1}}c.each(m(),function(a1,a2){a2.datamin=aO;a2.datamax=aI;a2.used=false});for(aU=0;aU<Q.length;++aU){aJ=Q[aU];aJ.datapoints={points:[]};an(ak.processRawData,[aJ,aJ.data,aJ.datapoints])}for(aU=0;aU<Q.length;++aU){aJ=Q[aU];var aZ=aJ.data,aW=aJ.datapoints.format;if(!aW){aW=[];aW.push({x:true,number:true,required:true});aW.push({y:true,number:true,required:true});if(aJ.bars.show||(aJ.lines.show&&aJ.lines.fill)){aW.push({y:true,number:true,required:false,defaultValue:0});if(aJ.bars.horizontal){delete aW[aW.length-1].y;aW[aW.length-1].x=true}}aJ.datapoints.format=aW}if(aJ.datapoints.pointsize!=null){continue}aJ.datapoints.pointsize=aW.length;aP=aJ.datapoints.pointsize;aT=aJ.datapoints.points;insertSteps=aJ.lines.show&&aJ.lines.steps;aJ.xaxis.used=aJ.yaxis.used=true;for(aS=aR=0;aS<aZ.length;++aS,aR+=aP){aL=aZ[aS];var aE=aL==null;if(!aE){for(aN=0;aN<aP;++aN){a0=aL[aN];aX=aW[aN];if(aX){if(aX.number&&a0!=null){a0=+a0;if(isNaN(a0)){a0=null}else{if(a0==Infinity){a0=aB}else{if(a0==-Infinity){a0=-aB}}}}if(a0==null){if(aX.required){aE=true}if(aX.defaultValue!=null){a0=aX.defaultValue}}}aT[aR+aN]=a0}}if(aE){for(aN=0;aN<aP;++aN){a0=aT[aR+aN];if(a0!=null){aX=aW[aN];if(aX.x){aF(aJ.xaxis,a0,a0)}if(aX.y){aF(aJ.yaxis,a0,a0)}}aT[aR+aN]=null}}else{if(insertSteps&&aR>0&&aT[aR-aP]!=null&&aT[aR-aP]!=aT[aR]&&aT[aR-aP+1]!=aT[aR+1]){for(aN=0;aN<aP;++aN){aT[aR+aP+aN]=aT[aR+aN]}aT[aR+1]=aT[aR-aP+1];aR+=aP}}}}for(aU=0;aU<Q.length;++aU){aJ=Q[aU];an(ak.processDatapoints,[aJ,aJ.datapoints])}for(aU=0;aU<Q.length;++aU){aJ=Q[aU];aT=aJ.datapoints.points,aP=aJ.datapoints.pointsize;var aK=aO,aQ=aO,aM=aI,aV=aI;for(aS=0;aS<aT.length;aS+=aP){if(aT[aS]==null){continue}for(aN=0;aN<aP;++aN){a0=aT[aS+aN];aX=aW[aN];if(!aX||a0==aB||a0==-aB){continue}if(aX.x){if(a0<aK){aK=a0}if(a0>aM){aM=a0}}if(aX.y){if(a0<aQ){aQ=a0}if(a0>aV){aV=a0}}}}if(aJ.bars.show){var aY=aJ.bars.align=="left"?0:-aJ.bars.barWidth/2;if(aJ.bars.horizontal){aQ+=aY;aV+=aY+aJ.bars.barWidth}else{aK+=aY;aM+=aY+aJ.bars.barWidth}}aF(aJ.xaxis,aK,aM);aF(aJ.yaxis,aQ,aV)}c.each(m(),function(a1,a2){if(a2.datamin==aO){a2.datamin=null}if(a2.datamax==aI){a2.datamax=null}})}function j(aB,aC){var aD=document.createElement("canvas");aD.className=aC;aD.width=G;aD.height=I;if(!aB){c(aD).css({position:"absolute",left:0,top:0})}c(aD).appendTo(av);if(!aD.getContext){aD=window.G_vmlCanvasManager.initElement(aD)}aD.getContext("2d").save();return aD}function B(){G=av.width();I=av.height();if(G<=0||I<=0){throw"Invalid dimensions for plot, width = "+G+", height = "+I}}function g(aC){if(aC.width!=G){aC.width=G}if(aC.height!=I){aC.height=I}var aB=aC.getContext("2d");aB.restore();aB.save()}function X(){var aC,aB=av.children("canvas.base"),aD=av.children("canvas.overlay");if(aB.length==0||aD==0){av.html("");av.css({padding:0});if(av.css("position")=="static"){av.css("position","relative")}B();az=j(true,"base");ad=j(false,"overlay");aC=false}else{az=aB.get(0);ad=aD.get(0);aC=true}H=az.getContext("2d");A=ad.getContext("2d");y=c([ad,az]);if(aC){av.data("plot").shutdown();aq.resize();A.clearRect(0,0,G,I);y.unbind();av.children().not([az,ad]).remove()}av.data("plot",aq)}function ah(){if(O.grid.hoverable){y.mousemove(aa);y.mouseleave(l)}if(O.grid.clickable){y.click(R)}an(ak.bindEvents,[y])}function ag(){if(M){clearTimeout(M)}y.unbind("mousemove",aa);y.unbind("mouseleave",l);y.unbind("click",R);an(ak.shutdown,[y])}function r(aG){function aC(aH){return aH}var aF,aB,aD=aG.options.transform||aC,aE=aG.options.inverseTransform;if(aG.direction=="x"){aF=aG.scale=h/Math.abs(aD(aG.max)-aD(aG.min));aB=Math.min(aD(aG.max),aD(aG.min))}else{aF=aG.scale=w/Math.abs(aD(aG.max)-aD(aG.min));aF=-aF;aB=Math.max(aD(aG.max),aD(aG.min))}if(aD==aC){aG.p2c=function(aH){return(aH-aB)*aF}}else{aG.p2c=function(aH){return(aD(aH)-aB)*aF}}if(!aE){aG.c2p=function(aH){return aB+aH/aF}}else{aG.c2p=function(aH){return aE(aB+aH/aF)}}}function L(aD){var aB=aD.options,aF,aJ=aD.ticks||[],aI=[],aE,aK=aB.labelWidth,aG=aB.labelHeight,aC;function aH(aM,aL){return c('<div style="position:absolute;top:-10000px;'+aL+'font-size:smaller"><div class="'+aD.direction+"Axis "+aD.direction+aD.n+'Axis">'+aM.join("")+"</div></div>").appendTo(av)}if(aD.direction=="x"){if(aK==null){aK=Math.floor(G/(aJ.length>0?aJ.length:1))}if(aG==null){aI=[];for(aF=0;aF<aJ.length;++aF){aE=aJ[aF].label;if(aE){aI.push('<div class="tickLabel" style="float:left;width:'+aK+'px">'+aE+"</div>")}}if(aI.length>0){aI.push('<div style="clear:left"></div>');aC=aH(aI,"width:10000px;");aG=aC.height();aC.remove()}}}else{if(aK==null||aG==null){for(aF=0;aF<aJ.length;++aF){aE=aJ[aF].label;if(aE){aI.push('<div class="tickLabel">'+aE+"</div>")}}if(aI.length>0){aC=aH(aI,"");if(aK==null){aK=aC.children().width()}if(aG==null){aG=aC.find("div.tickLabel").height()}aC.remove()}}}if(aK==null){aK=0}if(aG==null){aG=0}aD.labelWidth=aK;aD.labelHeight=aG}function au(aD){var aC=aD.labelWidth,aL=aD.labelHeight,aH=aD.options.position,aF=aD.options.tickLength,aG=O.grid.axisMargin,aJ=O.grid.labelMargin,aK=aD.direction=="x"?p:aw,aE;var aB=c.grep(aK,function(aN){return aN&&aN.options.position==aH&&aN.reserveSpace});if(c.inArray(aD,aB)==aB.length-1){aG=0}if(aF==null){aF="full"}var aI=c.grep(aK,function(aN){return aN&&aN.reserveSpace});var aM=c.inArray(aD,aI)==0;if(!aM&&aF=="full"){aF=5}if(!isNaN(+aF)){aJ+=+aF}if(aD.direction=="x"){aL+=aJ;if(aH=="bottom"){q.bottom+=aL+aG;aD.box={top:I-q.bottom,height:aL}}else{aD.box={top:q.top+aG,height:aL};q.top+=aL+aG}}else{aC+=aJ;if(aH=="left"){aD.box={left:q.left+aG,width:aC};q.left+=aC+aG}else{q.right+=aC+aG;aD.box={left:G-q.right,width:aC}}}aD.position=aH;aD.tickLength=aF;aD.box.padding=aJ;aD.innermost=aM}function U(aB){if(aB.direction=="x"){aB.box.left=q.left;aB.box.width=h}else{aB.box.top=q.top;aB.box.height=w}}function t(){var aC,aE=m();c.each(aE,function(aF,aG){aG.show=aG.options.show;if(aG.show==null){aG.show=aG.used}aG.reserveSpace=aG.show||aG.options.reserveSpace;n(aG)});allocatedAxes=c.grep(aE,function(aF){return aF.reserveSpace});q.left=q.right=q.top=q.bottom=0;if(O.grid.show){c.each(allocatedAxes,function(aF,aG){S(aG);P(aG);ap(aG,aG.ticks);L(aG)});for(aC=allocatedAxes.length-1;aC>=0;--aC){au(allocatedAxes[aC])}var aD=O.grid.minBorderMargin;if(aD==null){aD=0;for(aC=0;aC<Q.length;++aC){aD=Math.max(aD,Q[aC].points.radius+Q[aC].points.lineWidth/2)}}for(var aB in q){q[aB]+=O.grid.borderWidth;q[aB]=Math.max(aD,q[aB])}}h=G-q.left-q.right;w=I-q.bottom-q.top;c.each(aE,function(aF,aG){r(aG)});if(O.grid.show){c.each(allocatedAxes,function(aF,aG){U(aG)});k()}o()}function n(aE){var aF=aE.options,aD=+(aF.min!=null?aF.min:aE.datamin),aB=+(aF.max!=null?aF.max:aE.datamax),aH=aB-aD;if(aH==0){var aC=aB==0?1:0.01;if(aF.min==null){aD-=aC}if(aF.max==null||aF.min!=null){aB+=aC}}else{var aG=aF.autoscaleMargin;if(aG!=null){if(aF.min==null){aD-=aH*aG;if(aD<0&&aE.datamin!=null&&aE.datamin>=0){aD=0}}if(aF.max==null){aB+=aH*aG;if(aB>0&&aE.datamax!=null&&aE.datamax<=0){aB=0}}}}aE.min=aD;aE.max=aB}function S(aG){var aM=aG.options;var aH;if(typeof aM.ticks=="number"&&aM.ticks>0){aH=aM.ticks}else{aH=0.3*Math.sqrt(aG.direction=="x"?G:I)}var aT=(aG.max-aG.min)/aH,aO,aB,aN,aR,aS,aQ,aI;if(aM.mode=="time"){var aJ={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var aK=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var aC=0;if(aM.minTickSize!=null){if(typeof aM.tickSize=="number"){aC=aM.tickSize}else{aC=aM.minTickSize[0]*aJ[aM.minTickSize[1]]}}for(var aS=0;aS<aK.length-1;++aS){if(aT<(aK[aS][0]*aJ[aK[aS][1]]+aK[aS+1][0]*aJ[aK[aS+1][1]])/2&&aK[aS][0]*aJ[aK[aS][1]]>=aC){break}}aO=aK[aS][0];aN=aK[aS][1];if(aN=="year"){aQ=Math.pow(10,Math.floor(Math.log(aT/aJ.year)/Math.LN10));aI=(aT/aJ.year)/aQ;if(aI<1.5){aO=1}else{if(aI<3){aO=2}else{if(aI<7.5){aO=5}else{aO=10}}}aO*=aQ}aG.tickSize=aM.tickSize||[aO,aN];aB=function(aX){var a2=[],a0=aX.tickSize[0],a3=aX.tickSize[1],a1=new Date(aX.min);var aW=a0*aJ[a3];if(a3=="second"){a1.setUTCSeconds(a(a1.getUTCSeconds(),a0))}if(a3=="minute"){a1.setUTCMinutes(a(a1.getUTCMinutes(),a0))}if(a3=="hour"){a1.setUTCHours(a(a1.getUTCHours(),a0))}if(a3=="month"){a1.setUTCMonth(a(a1.getUTCMonth(),a0))}if(a3=="year"){a1.setUTCFullYear(a(a1.getUTCFullYear(),a0))}a1.setUTCMilliseconds(0);if(aW>=aJ.minute){a1.setUTCSeconds(0)}if(aW>=aJ.hour){a1.setUTCMinutes(0)}if(aW>=aJ.day){a1.setUTCHours(0)}if(aW>=aJ.day*4){a1.setUTCDate(1)}if(aW>=aJ.year){a1.setUTCMonth(0)}var a5=0,a4=Number.NaN,aY;do{aY=a4;a4=a1.getTime();a2.push(a4);if(a3=="month"){if(a0<1){a1.setUTCDate(1);var aV=a1.getTime();a1.setUTCMonth(a1.getUTCMonth()+1);var aZ=a1.getTime();a1.setTime(a4+a5*aJ.hour+(aZ-aV)*a0);a5=a1.getUTCHours();a1.setUTCHours(0)}else{a1.setUTCMonth(a1.getUTCMonth()+a0)}}else{if(a3=="year"){a1.setUTCFullYear(a1.getUTCFullYear()+a0)}else{a1.setTime(a4+aW)}}}while(a4<aX.max&&a4!=aY);return a2};aR=function(aV,aY){var a0=new Date(aV);if(aM.timeformat!=null){return c.plot.formatDate(a0,aM.timeformat,aM.monthNames)}var aW=aY.tickSize[0]*aJ[aY.tickSize[1]];var aX=aY.max-aY.min;var aZ=(aM.twelveHourClock)?" %p":"";if(aW<aJ.minute){fmt="%h:%M:%S"+aZ}else{if(aW<aJ.day){if(aX<2*aJ.day){fmt="%h:%M"+aZ}else{fmt="%b %d %h:%M"+aZ}}else{if(aW<aJ.month){fmt="%b %d"}else{if(aW<aJ.year){if(aX<aJ.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return c.plot.formatDate(a0,fmt,aM.monthNames)}}else{var aU=aM.tickDecimals;var aP=-Math.floor(Math.log(aT)/Math.LN10);if(aU!=null&&aP>aU){aP=aU}aQ=Math.pow(10,-aP);aI=aT/aQ;if(aI<1.5){aO=1}else{if(aI<3){aO=2;if(aI>2.25&&(aU==null||aP+1<=aU)){aO=2.5;++aP}}else{if(aI<7.5){aO=5}else{aO=10}}}aO*=aQ;if(aM.minTickSize!=null&&aO<aM.minTickSize){aO=aM.minTickSize}aG.tickDecimals=Math.max(0,aU!=null?aU:aP);aG.tickSize=aM.tickSize||aO;aB=function(aX){var aZ=[];var a0=a(aX.min,aX.tickSize),aW=0,aV=Number.NaN,aY;do{aY=aV;aV=a0+aW*aX.tickSize;aZ.push(aV);++aW}while(aV<aX.max&&aV!=aY);return aZ};aR=function(aV,aW){return aV.toFixed(aW.tickDecimals)}}if(aM.alignTicksWithAxis!=null){var aF=(aG.direction=="x"?p:aw)[aM.alignTicksWithAxis-1];if(aF&&aF.used&&aF!=aG){var aL=aB(aG);if(aL.length>0){if(aM.min==null){aG.min=Math.min(aG.min,aL[0])}if(aM.max==null&&aL.length>1){aG.max=Math.max(aG.max,aL[aL.length-1])}}aB=function(aX){var aY=[],aV,aW;for(aW=0;aW<aF.ticks.length;++aW){aV=(aF.ticks[aW].v-aF.min)/(aF.max-aF.min);aV=aX.min+aV*(aX.max-aX.min);aY.push(aV)}return aY};if(aG.mode!="time"&&aM.tickDecimals==null){var aE=Math.max(0,-Math.floor(Math.log(aT)/Math.LN10)+1),aD=aB(aG);if(!(aD.length>1&&/\..*0$/.test((aD[1]-aD[0]).toFixed(aE)))){aG.tickDecimals=aE}}}}aG.tickGenerator=aB;if(c.isFunction(aM.tickFormatter)){aG.tickFormatter=function(aV,aW){return""+aM.tickFormatter(aV,aW)}}else{aG.tickFormatter=aR}}function P(aF){var aH=aF.options.ticks,aG=[];if(aH==null||(typeof aH=="number"&&aH>0)){aG=aF.tickGenerator(aF)}else{if(aH){if(c.isFunction(aH)){aG=aH({min:aF.min,max:aF.max})}else{aG=aH}}}var aE,aB;aF.ticks=[];for(aE=0;aE<aG.length;++aE){var aC=null;var aD=aG[aE];if(typeof aD=="object"){aB=+aD[0];if(aD.length>1){aC=aD[1]}}else{aB=+aD}if(aC==null){aC=aF.tickFormatter(aB,aF)}if(!isNaN(aB)){aF.ticks.push({v:aB,label:aC})}}}function ap(aB,aC){if(aB.options.autoscaleMargin&&aC.length>0){if(aB.options.min==null){aB.min=Math.min(aB.min,aC[0].v)}if(aB.options.max==null&&aC.length>1){aB.max=Math.max(aB.max,aC[aC.length-1].v)}}}function W(){H.clearRect(0,0,G,I);var aC=O.grid;if(aC.show&&aC.backgroundColor){N()}if(aC.show&&!aC.aboveData){ac()}for(var aB=0;aB<Q.length;++aB){an(ak.drawSeries,[H,Q[aB]]);d(Q[aB])}an(ak.draw,[H]);if(aC.show&&aC.aboveData){ac()}}function D(aB,aI){var aE,aH,aG,aD,aF=m();for(i=0;i<aF.length;++i){aE=aF[i];if(aE.direction==aI){aD=aI+aE.n+"axis";if(!aB[aD]&&aE.n==1){aD=aI+"axis"}if(aB[aD]){aH=aB[aD].from;aG=aB[aD].to;break}}}if(!aB[aD]){aE=aI=="x"?p[0]:aw[0];aH=aB[aI+"1"];aG=aB[aI+"2"]}if(aH!=null&&aG!=null&&aH>aG){var aC=aH;aH=aG;aG=aC}return{from:aH,to:aG,axis:aE}}function N(){H.save();H.translate(q.left,q.top);H.fillStyle=am(O.grid.backgroundColor,w,0,"rgba(255, 255, 255, 0)");H.fillRect(0,0,h,w);H.restore()}function ac(){var aF;H.save();H.translate(q.left,q.top);var aH=O.grid.markings;if(aH){if(c.isFunction(aH)){var aK=aq.getAxes();aK.xmin=aK.xaxis.min;aK.xmax=aK.xaxis.max;aK.ymin=aK.yaxis.min;aK.ymax=aK.yaxis.max;aH=aH(aK)}for(aF=0;aF<aH.length;++aF){var aD=aH[aF],aC=D(aD,"x"),aI=D(aD,"y");if(aC.from==null){aC.from=aC.axis.min}if(aC.to==null){aC.to=aC.axis.max}if(aI.from==null){aI.from=aI.axis.min}if(aI.to==null){aI.to=aI.axis.max}if(aC.to<aC.axis.min||aC.from>aC.axis.max||aI.to<aI.axis.min||aI.from>aI.axis.max){continue}aC.from=Math.max(aC.from,aC.axis.min);aC.to=Math.min(aC.to,aC.axis.max);aI.from=Math.max(aI.from,aI.axis.min);aI.to=Math.min(aI.to,aI.axis.max);if(aC.from==aC.to&&aI.from==aI.to){continue}aC.from=aC.axis.p2c(aC.from);aC.to=aC.axis.p2c(aC.to);aI.from=aI.axis.p2c(aI.from);aI.to=aI.axis.p2c(aI.to);if(aC.from==aC.to||aI.from==aI.to){H.beginPath();H.strokeStyle=aD.color||O.grid.markingsColor;H.lineWidth=aD.lineWidth||O.grid.markingsLineWidth;H.moveTo(aC.from,aI.from);H.lineTo(aC.to,aI.to);H.stroke()}else{H.fillStyle=aD.color||O.grid.markingsColor;H.fillRect(aC.from,aI.to,aC.to-aC.from,aI.from-aI.to)}}}var aK=m(),aM=O.grid.borderWidth;for(var aE=0;aE<aK.length;++aE){var aB=aK[aE],aG=aB.box,aQ=aB.tickLength,aN,aL,aP,aJ;if(!aB.show||aB.ticks.length==0){continue}H.strokeStyle=aB.options.tickColor||c.color.parse(aB.options.color).scale("a",0.22).toString();H.lineWidth=1;if(aB.direction=="x"){aN=0;if(aQ=="full"){aL=(aB.position=="top"?0:w)}else{aL=aG.top-q.top+(aB.position=="top"?aG.height:0)}}else{aL=0;if(aQ=="full"){aN=(aB.position=="left"?0:h)}else{aN=aG.left-q.left+(aB.position=="left"?aG.width:0)}}if(!aB.innermost){H.beginPath();aP=aJ=0;if(aB.direction=="x"){aP=h}else{aJ=w}if(H.lineWidth==1){aN=Math.floor(aN)+0.5;aL=Math.floor(aL)+0.5}H.moveTo(aN,aL);H.lineTo(aN+aP,aL+aJ);H.stroke()}H.beginPath();for(aF=0;aF<aB.ticks.length;++aF){var aO=aB.ticks[aF].v;aP=aJ=0;if(aO<aB.min||aO>aB.max||(aQ=="full"&&aM>0&&(aO==aB.min||aO==aB.max))){continue}if(aB.direction=="x"){aN=aB.p2c(aO);aJ=aQ=="full"?-w:aQ;if(aB.position=="top"){aJ=-aJ}}else{aL=aB.p2c(aO);aP=aQ=="full"?-h:aQ;if(aB.position=="left"){aP=-aP}}if(H.lineWidth==1){if(aB.direction=="x"){aN=Math.floor(aN)+0.5}else{aL=Math.floor(aL)+0.5}}H.moveTo(aN,aL);H.lineTo(aN+aP,aL+aJ)}H.stroke()}if(aM){H.lineWidth=aM;H.strokeStyle=O.grid.borderColor;H.strokeRect(-aM/2,-aM/2,h+aM,w+aM)}H.restore()}function k(){av.find(".tickLabels").remove();var aG=['<div class="tickLabels" style="font-size:smaller">'];var aJ=m();for(var aD=0;aD<aJ.length;++aD){var aC=aJ[aD],aF=aC.box;if(!aC.show){continue}aG.push('<div class="'+aC.direction+"Axis "+aC.direction+aC.n+'Axis" style="color:'+aC.options.color+'">');for(var aE=0;aE<aC.ticks.length;++aE){var aH=aC.ticks[aE];if(!aH.label||aH.v<aC.min||aH.v>aC.max){continue}var aK={},aI;if(aC.direction=="x"){aI="center";aK.left=Math.round(q.left+aC.p2c(aH.v)-aC.labelWidth/2);if(aC.position=="bottom"){aK.top=aF.top+aF.padding}else{aK.bottom=I-(aF.top+aF.height-aF.padding)}}else{aK.top=Math.round(q.top+aC.p2c(aH.v)-aC.labelHeight/2);if(aC.position=="left"){aK.right=G-(aF.left+aF.width-aF.padding);aI="right"}else{aK.left=aF.left+aF.padding;aI="left"}}aK.width=aC.labelWidth;var aB=["position:absolute","text-align:"+aI];for(var aL in aK){aB.push(aL+":"+aK[aL]+"px")}aG.push('<div class="tickLabel" style="'+aB.join(";")+'">'+aH.label+"</div>")}aG.push("</div>")}aG.push("</div>");av.append(aG.join(""))}function d(aB){if(aB.lines.show){at(aB)}if(aB.bars.show){e(aB)}if(aB.points.show){ao(aB)}}function at(aE){function aD(aP,aQ,aI,aU,aT){var aV=aP.points,aJ=aP.pointsize,aN=null,aM=null;H.beginPath();for(var aO=aJ;aO<aV.length;aO+=aJ){var aL=aV[aO-aJ],aS=aV[aO-aJ+1],aK=aV[aO],aR=aV[aO+1];if(aL==null||aK==null){continue}if(aS<=aR&&aS<aT.min){if(aR<aT.min){continue}aL=(aT.min-aS)/(aR-aS)*(aK-aL)+aL;aS=aT.min}else{if(aR<=aS&&aR<aT.min){if(aS<aT.min){continue}aK=(aT.min-aS)/(aR-aS)*(aK-aL)+aL;aR=aT.min}}if(aS>=aR&&aS>aT.max){if(aR>aT.max){continue}aL=(aT.max-aS)/(aR-aS)*(aK-aL)+aL;aS=aT.max}else{if(aR>=aS&&aR>aT.max){if(aS>aT.max){continue}aK=(aT.max-aS)/(aR-aS)*(aK-aL)+aL;aR=aT.max}}if(aL<=aK&&aL<aU.min){if(aK<aU.min){continue}aS=(aU.min-aL)/(aK-aL)*(aR-aS)+aS;aL=aU.min}else{if(aK<=aL&&aK<aU.min){if(aL<aU.min){continue}aR=(aU.min-aL)/(aK-aL)*(aR-aS)+aS;aK=aU.min}}if(aL>=aK&&aL>aU.max){if(aK>aU.max){continue}aS=(aU.max-aL)/(aK-aL)*(aR-aS)+aS;aL=aU.max}else{if(aK>=aL&&aK>aU.max){if(aL>aU.max){continue}aR=(aU.max-aL)/(aK-aL)*(aR-aS)+aS;aK=aU.max}}if(aL!=aN||aS!=aM){H.moveTo(aU.p2c(aL)+aQ,aT.p2c(aS)+aI)}aN=aK;aM=aR;H.lineTo(aU.p2c(aK)+aQ,aT.p2c(aR)+aI)}H.stroke()}function aF(aI,aQ,aP){var aW=aI.points,aV=aI.pointsize,aN=Math.min(Math.max(0,aP.min),aP.max),aX=0,aU,aT=false,aM=1,aL=0,aR=0;while(true){if(aV>0&&aX>aW.length+aV){break}aX+=aV;var aZ=aW[aX-aV],aK=aW[aX-aV+aM],aY=aW[aX],aJ=aW[aX+aM];if(aT){if(aV>0&&aZ!=null&&aY==null){aR=aX;aV=-aV;aM=2;continue}if(aV<0&&aX==aL+aV){H.fill();aT=false;aV=-aV;aM=1;aX=aL=aR+aV;continue}}if(aZ==null||aY==null){continue}if(aZ<=aY&&aZ<aQ.min){if(aY<aQ.min){continue}aK=(aQ.min-aZ)/(aY-aZ)*(aJ-aK)+aK;aZ=aQ.min}else{if(aY<=aZ&&aY<aQ.min){if(aZ<aQ.min){continue}aJ=(aQ.min-aZ)/(aY-aZ)*(aJ-aK)+aK;aY=aQ.min}}if(aZ>=aY&&aZ>aQ.max){if(aY>aQ.max){continue}aK=(aQ.max-aZ)/(aY-aZ)*(aJ-aK)+aK;aZ=aQ.max}else{if(aY>=aZ&&aY>aQ.max){if(aZ>aQ.max){continue}aJ=(aQ.max-aZ)/(aY-aZ)*(aJ-aK)+aK;aY=aQ.max}}if(!aT){H.beginPath();H.moveTo(aQ.p2c(aZ),aP.p2c(aN));aT=true}if(aK>=aP.max&&aJ>=aP.max){H.lineTo(aQ.p2c(aZ),aP.p2c(aP.max));H.lineTo(aQ.p2c(aY),aP.p2c(aP.max));continue}else{if(aK<=aP.min&&aJ<=aP.min){H.lineTo(aQ.p2c(aZ),aP.p2c(aP.min));H.lineTo(aQ.p2c(aY),aP.p2c(aP.min));continue}}var aO=aZ,aS=aY;if(aK<=aJ&&aK<aP.min&&aJ>=aP.min){aZ=(aP.min-aK)/(aJ-aK)*(aY-aZ)+aZ;aK=aP.min}else{if(aJ<=aK&&aJ<aP.min&&aK>=aP.min){aY=(aP.min-aK)/(aJ-aK)*(aY-aZ)+aZ;aJ=aP.min}}if(aK>=aJ&&aK>aP.max&&aJ<=aP.max){aZ=(aP.max-aK)/(aJ-aK)*(aY-aZ)+aZ;aK=aP.max}else{if(aJ>=aK&&aJ>aP.max&&aK<=aP.max){aY=(aP.max-aK)/(aJ-aK)*(aY-aZ)+aZ;aJ=aP.max}}if(aZ!=aO){H.lineTo(aQ.p2c(aO),aP.p2c(aK))}H.lineTo(aQ.p2c(aZ),aP.p2c(aK));H.lineTo(aQ.p2c(aY),aP.p2c(aJ));if(aY!=aS){H.lineTo(aQ.p2c(aY),aP.p2c(aJ));H.lineTo(aQ.p2c(aS),aP.p2c(aJ))}}}H.save();H.translate(q.left,q.top);H.lineJoin="round";var aG=aE.lines.lineWidth,aB=aE.shadowSize;if(aG>0&&aB>0){H.lineWidth=aB;H.strokeStyle="rgba(0,0,0,0.1)";var aH=Math.PI/18;aD(aE.datapoints,Math.sin(aH)*(aG/2+aB/2),Math.cos(aH)*(aG/2+aB/2),aE.xaxis,aE.yaxis);H.lineWidth=aB/2;aD(aE.datapoints,Math.sin(aH)*(aG/2+aB/4),Math.cos(aH)*(aG/2+aB/4),aE.xaxis,aE.yaxis)}H.lineWidth=aG;H.strokeStyle=aE.color;var aC=ae(aE.lines,aE.color,0,w);if(aC){H.fillStyle=aC;aF(aE.datapoints,aE.xaxis,aE.yaxis)}if(aG>0){aD(aE.datapoints,0,0,aE.xaxis,aE.yaxis)}H.restore()}function ao(aE){function aH(aN,aM,aU,aK,aS,aT,aQ,aJ){var aR=aN.points,aI=aN.pointsize;for(var aL=0;aL<aR.length;aL+=aI){var aP=aR[aL],aO=aR[aL+1];if(aP==null||aP<aT.min||aP>aT.max||aO<aQ.min||aO>aQ.max){continue}H.beginPath();aP=aT.p2c(aP);aO=aQ.p2c(aO)+aK;if(aJ=="circle"){H.arc(aP,aO,aM,0,aS?Math.PI:Math.PI*2,false)}else{aJ(H,aP,aO,aM,aS)}H.closePath();if(aU){H.fillStyle=aU;H.fill()}H.stroke()}}H.save();H.translate(q.left,q.top);var aG=aE.points.lineWidth,aC=aE.shadowSize,aB=aE.points.radius,aF=aE.points.symbol;if(aG>0&&aC>0){var aD=aC/2;H.lineWidth=aD;H.strokeStyle="rgba(0,0,0,0.1)";aH(aE.datapoints,aB,null,aD+aD/2,true,aE.xaxis,aE.yaxis,aF);H.strokeStyle="rgba(0,0,0,0.2)";aH(aE.datapoints,aB,null,aD/2,true,aE.xaxis,aE.yaxis,aF)}H.lineWidth=aG;H.strokeStyle=aE.color;aH(aE.datapoints,aB,ae(aE.points,aE.color),0,false,aE.xaxis,aE.yaxis,aF);H.restore()}function E(aN,aM,aV,aI,aQ,aF,aD,aL,aK,aU,aR,aC){var aE,aT,aJ,aP,aG,aB,aO,aH,aS;if(aR){aH=aB=aO=true;aG=false;aE=aV;aT=aN;aP=aM+aI;aJ=aM+aQ;if(aT<aE){aS=aT;aT=aE;aE=aS;aG=true;aB=false}}else{aG=aB=aO=true;aH=false;aE=aN+aI;aT=aN+aQ;aJ=aV;aP=aM;if(aP<aJ){aS=aP;aP=aJ;aJ=aS;aH=true;aO=false}}if(aT<aL.min||aE>aL.max||aP<aK.min||aJ>aK.max){return}if(aE<aL.min){aE=aL.min;aG=false}if(aT>aL.max){aT=aL.max;aB=false}if(aJ<aK.min){aJ=aK.min;aH=false}if(aP>aK.max){aP=aK.max;aO=false}aE=aL.p2c(aE);aJ=aK.p2c(aJ);aT=aL.p2c(aT);aP=aK.p2c(aP);if(aD){aU.beginPath();aU.moveTo(aE,aJ);aU.lineTo(aE,aP);aU.lineTo(aT,aP);aU.lineTo(aT,aJ);aU.fillStyle=aD(aJ,aP);aU.fill()}if(aC>0&&(aG||aB||aO||aH)){aU.beginPath();aU.moveTo(aE,aJ+aF);if(aG){aU.lineTo(aE,aP+aF)}else{aU.moveTo(aE,aP+aF)}if(aO){aU.lineTo(aT,aP+aF)}else{aU.moveTo(aT,aP+aF)}if(aB){aU.lineTo(aT,aJ+aF)}else{aU.moveTo(aT,aJ+aF)}if(aH){aU.lineTo(aE,aJ+aF)}else{aU.moveTo(aE,aJ+aF)}aU.stroke()}}function e(aD){function aC(aJ,aI,aL,aG,aK,aN,aM){var aO=aJ.points,aF=aJ.pointsize;for(var aH=0;aH<aO.length;aH+=aF){if(aO[aH]==null){continue}E(aO[aH],aO[aH+1],aO[aH+2],aI,aL,aG,aK,aN,aM,H,aD.bars.horizontal,aD.bars.lineWidth)}}H.save();H.translate(q.left,q.top);H.lineWidth=aD.bars.lineWidth;H.strokeStyle=aD.color;var aB=aD.bars.align=="left"?0:-aD.bars.barWidth/2;var aE=aD.bars.fill?function(aF,aG){return ae(aD.bars,aD.color,aF,aG)}:null;aC(aD.datapoints,aB,aB+aD.bars.barWidth,0,aE,aD.xaxis,aD.yaxis);H.restore()}function ae(aD,aB,aC,aF){var aE=aD.fill;if(!aE){return null}if(aD.fillColor){return am(aD.fillColor,aC,aF,aB)}var aG=c.color.parse(aB);aG.a=typeof aE=="number"?aE:0.4;aG.normalize();return aG.toString()}function o(){av.find(".legend").remove();if(!O.legend.show){return}var aH=[],aF=false,aN=O.legend.labelFormatter,aM,aJ;for(var aE=0;aE<Q.length;++aE){aM=Q[aE];aJ=aM.label;if(!aJ){continue}if(aE%O.legend.noColumns==0){if(aF){aH.push("</tr>")}aH.push("<tr>");aF=true}if(aN){aJ=aN(aJ,aM)}aH.push('<td class="legendColorBox"><div style="border:1px solid '+O.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+aM.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+aJ+"</td>")}if(aF){aH.push("</tr>")}if(aH.length==0){return}var aL='<table style="font-size:smaller;color:'+O.grid.color+'">'+aH.join("")+"</table>";if(O.legend.container!=null){c(O.legend.container).html(aL)}else{var aI="",aC=O.legend.position,aD=O.legend.margin;if(aD[0]==null){aD=[aD,aD]}if(aC.charAt(0)=="n"){aI+="top:"+(aD[1]+q.top)+"px;"}else{if(aC.charAt(0)=="s"){aI+="bottom:"+(aD[1]+q.bottom)+"px;"}}if(aC.charAt(1)=="e"){aI+="right:"+(aD[0]+q.right)+"px;"}else{if(aC.charAt(1)=="w"){aI+="left:"+(aD[0]+q.left)+"px;"}}var aK=c('<div class="legend">'+aL.replace('style="','style="position:absolute;'+aI+";")+"</div>").appendTo(av);if(O.legend.backgroundOpacity!=0){var aG=O.legend.backgroundColor;if(aG==null){aG=O.grid.backgroundColor;if(aG&&typeof aG=="string"){aG=c.color.parse(aG)}else{aG=c.color.extract(aK,"background-color")}aG.a=1;aG=aG.toString()}var aB=aK.children();c('<div style="position:absolute;width:'+aB.width()+"px;height:"+aB.height()+"px;"+aI+"background-color:"+aG+';"> </div>').prependTo(aK).css("opacity",O.legend.backgroundOpacity)}}}var ab=[],M=null;function K(aI,aG,aD){var aO=O.grid.mouseActiveRadius,a0=aO*aO+1,aY=null,aR=false,aW,aU;for(aW=Q.length-1;aW>=0;--aW){if(!aD(Q[aW])){continue}var aP=Q[aW],aH=aP.xaxis,aF=aP.yaxis,aV=aP.datapoints.points,aT=aP.datapoints.pointsize,aQ=aH.c2p(aI),aN=aF.c2p(aG),aC=aO/aH.scale,aB=aO/aF.scale;if(aH.options.inverseTransform){aC=Number.MAX_VALUE}if(aF.options.inverseTransform){aB=Number.MAX_VALUE}if(aP.lines.show||aP.points.show){for(aU=0;aU<aV.length;aU+=aT){var aK=aV[aU],aJ=aV[aU+1];if(aK==null){continue}if(aK-aQ>aC||aK-aQ<-aC||aJ-aN>aB||aJ-aN<-aB){continue}var aM=Math.abs(aH.p2c(aK)-aI),aL=Math.abs(aF.p2c(aJ)-aG),aS=aM*aM+aL*aL;if(aS<a0){a0=aS;aY=[aW,aU/aT]}}}if(aP.bars.show&&!aY){var aE=aP.bars.align=="left"?0:-aP.bars.barWidth/2,aX=aE+aP.bars.barWidth;for(aU=0;aU<aV.length;aU+=aT){var aK=aV[aU],aJ=aV[aU+1],aZ=aV[aU+2];if(aK==null){continue}if(Q[aW].bars.horizontal?(aQ<=Math.max(aZ,aK)&&aQ>=Math.min(aZ,aK)&&aN>=aJ+aE&&aN<=aJ+aX):(aQ>=aK+aE&&aQ<=aK+aX&&aN>=Math.min(aZ,aJ)&&aN<=Math.max(aZ,aJ))){aY=[aW,aU/aT]}}}}if(aY){aW=aY[0];aU=aY[1];aT=Q[aW].datapoints.pointsize;return{datapoint:Q[aW].datapoints.points.slice(aU*aT,(aU+1)*aT),dataIndex:aU,series:Q[aW],seriesIndex:aW}}return null}function aa(aB){if(O.grid.hoverable){u("plothover",aB,function(aC){return aC.hoverable!=false})}}function l(aB){if(O.grid.hoverable){u("plothover",aB,function(aC){return false})}}function R(aB){u("plotclick",aB,function(aC){return aC.clickable!=false})}function u(aC,aB,aD){var aE=y.offset(),aH=aB.pageX-aE.left-q.left,aF=aB.pageY-aE.top-q.top,aJ=C({left:aH,top:aF});aJ.pageX=aB.pageX;aJ.pageY=aB.pageY;var aK=K(aH,aF,aD);if(aK){aK.pageX=parseInt(aK.series.xaxis.p2c(aK.datapoint[0])+aE.left+q.left);aK.pageY=parseInt(aK.series.yaxis.p2c(aK.datapoint[1])+aE.top+q.top)}if(O.grid.autoHighlight){for(var aG=0;aG<ab.length;++aG){var aI=ab[aG];if(aI.auto==aC&&!(aK&&aI.series==aK.series&&aI.point[0]==aK.datapoint[0]&&aI.point[1]==aK.datapoint[1])){T(aI.series,aI.point)}}if(aK){x(aK.series,aK.datapoint,aC)}}av.trigger(aC,[aJ,aK])}function f(){if(!M){M=setTimeout(s,30)}}function s(){M=null;A.save();A.clearRect(0,0,G,I);A.translate(q.left,q.top);var aC,aB;for(aC=0;aC<ab.length;++aC){aB=ab[aC];if(aB.series.bars.show){v(aB.series,aB.point)}else{ay(aB.series,aB.point)}}A.restore();an(ak.drawOverlay,[A])}function x(aD,aB,aF){if(typeof aD=="number"){aD=Q[aD]}if(typeof aB=="number"){var aE=aD.datapoints.pointsize;aB=aD.datapoints.points.slice(aE*aB,aE*(aB+1))}var aC=al(aD,aB);if(aC==-1){ab.push({series:aD,point:aB,auto:aF});f()}else{if(!aF){ab[aC].auto=false}}}function T(aD,aB){if(aD==null&&aB==null){ab=[];f()}if(typeof aD=="number"){aD=Q[aD]}if(typeof aB=="number"){aB=aD.data[aB]}var aC=al(aD,aB);if(aC!=-1){ab.splice(aC,1);f()}}function al(aD,aE){for(var aB=0;aB<ab.length;++aB){var aC=ab[aB];if(aC.series==aD&&aC.point[0]==aE[0]&&aC.point[1]==aE[1]){return aB}}return -1}function ay(aE,aD){var aC=aD[0],aI=aD[1],aH=aE.xaxis,aG=aE.yaxis;if(aC<aH.min||aC>aH.max||aI<aG.min||aI>aG.max){return}var aF=aE.points.radius+aE.points.lineWidth/2;A.lineWidth=aF;A.strokeStyle=c.color.parse(aE.color).scale("a",0.5).toString();var aB=1.5*aF,aC=aH.p2c(aC),aI=aG.p2c(aI);A.beginPath();if(aE.points.symbol=="circle"){A.arc(aC,aI,aB,0,2*Math.PI,false)}else{aE.points.symbol(A,aC,aI,aB,false)}A.closePath();A.stroke()}function v(aE,aB){A.lineWidth=aE.bars.lineWidth;A.strokeStyle=c.color.parse(aE.color).scale("a",0.5).toString();var aD=c.color.parse(aE.color).scale("a",0.5).toString();var aC=aE.bars.align=="left"?0:-aE.bars.barWidth/2;E(aB[0],aB[1],aB[2]||0,aC,aC+aE.bars.barWidth,0,function(){return aD},aE.xaxis,aE.yaxis,A,aE.bars.horizontal,aE.bars.lineWidth)}function am(aJ,aB,aH,aC){if(typeof aJ=="string"){return aJ}else{var aI=H.createLinearGradient(0,aH,0,aB);for(var aE=0,aD=aJ.colors.length;aE<aD;++aE){var aF=aJ.colors[aE];if(typeof aF!="string"){var aG=c.color.parse(aC);if(aF.brightness!=null){aG=aG.scale("rgb",aF.brightness)}if(aF.opacity!=null){aG.a*=aF.opacity}aF=aG.toString()}aI.addColorStop(aE/(aD-1),aF)}return aI}}}c.plot=function(g,e,d){var f=new b(c(g),e,d,c.plot.plugins);return f};c.plot.version="0.7";c.plot.plugins=[];c.plot.formatDate=function(l,f,h){var o=function(d){d=""+d;return d.length==1?"0"+d:d};var e=[];var p=false,j=false;var n=l.getUTCHours();var k=n<12;if(h==null){h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(f.search(/%p|%P/)!=-1){if(n>12){n=n-12}else{if(n==0){n=12}}}for(var g=0;g<f.length;++g){var m=f.charAt(g);if(p){switch(m){case"h":m=""+n;break;case"H":m=o(n);break;case"M":m=o(l.getUTCMinutes());break;case"S":m=o(l.getUTCSeconds());break;case"d":m=""+l.getUTCDate();break;case"m":m=""+(l.getUTCMonth()+1);break;case"y":m=""+l.getUTCFullYear();break;case"b":m=""+h[l.getUTCMonth()];break;case"p":m=(k)?("am"):("pm");break;case"P":m=(k)?("AM"):("PM");break;case"0":m="";j=true;break}if(m&&j){m=o(m);j=false}e.push(m);if(!j){p=false}}else{if(m=="%"){p=true}else{e.push(m)}}}return e.join("")};function a(e,d){return d*Math.floor(e/d)}})(jQuery);
|
js/jquery.flot.navigate.js
ADDED
@@ -0,0 +1,6 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
Javascript plotting library for jQuery ~ v0.8 beta ~ Copyright (c) 2007-2011 IOLA and Ole Laursen
|
3 |
+
http://code.google.com/p/flot/issues/detail?id=643
|
4 |
+
Licensed under the MIT License ~ https://raw.github.com/flot/flot/master/LICENSE.txt
|
5 |
+
*/
|
6 |
+
(function(a){a.fn.drag=function(b,c,d){var e=typeof b=="string"?b:"",g=a.isFunction(b)?b:a.isFunction(c)?c:null;if(e.indexOf("drag")!==0)e="drag"+e;d=(b==g?c:d)||{};return g?this.bind(e,d,g):this.trigger(e)};var b=a.event,c=b.special,d=c.drag={defaults:{which:1,distance:0,not:":input",handle:null,relative:false,drop:true,click:false},datakey:"dragdata",livekey:"livedrag",add:function(c){var e=a.data(this,d.datakey),g=c.data||{};e.related+=1;if(!e.live&&c.selector){e.live=true;b.add(this,"draginit."+d.livekey,d.delegate)}a.each(d.defaults,function(a){if(g[a]!==undefined)e[a]=g[a]})},remove:function(){a.data(this,d.datakey).related-=1},setup:function(){if(!a.data(this,d.datakey)){var c=a.extend({related:0},d.defaults);a.data(this,d.datakey,c);b.add(this,"mousedown",d.init,c);this.attachEvent&&this.attachEvent("ondragstart",d.dontstart)}},teardown:function(){if(!a.data(this,d.datakey).related){a.removeData(this,d.datakey);b.remove(this,"mousedown",d.init);b.remove(this,"draginit",d.delegate);d.textselect(true);this.detachEvent&&this.detachEvent("ondragstart",d.dontstart)}},init:function(e){var g=e.data,j;if(!(g.which>0&&e.which!=g.which))if(!a(e.target).is(g.not))if(!(g.handle&&!a(e.target).closest(g.handle,e.currentTarget).length)){g.propagates=1;g.interactions=[d.interaction(this,g)];g.target=e.target;g.pageX=e.pageX;g.pageY=e.pageY;g.dragging=null;j=d.hijack(e,"draginit",g);if(g.propagates){if((j=d.flatten(j))&&j.length){g.interactions=[];a.each(j,function(){g.interactions.push(d.interaction(this,g))})}g.propagates=g.interactions.length;g.drop!==false&&c.drop&&c.drop.handler(e,g);d.textselect(false);b.add(document,"mousemove mouseup",d.handler,g);return false}}},interaction:function(b,c){return{drag:b,callback:new d.callback,droppable:[],offset:a(b)[c.relative?"position":"offset"]()||{top:0,left:0}}},handler:function(a){var e=a.data;switch(a.type){case!e.dragging&&"mousemove":if(Math.pow(a.pageX-e.pageX,2)+Math.pow(a.pageY-e.pageY,2)<Math.pow(e.distance,2))break;a.target=e.target;d.hijack(a,"dragstart",e);if(e.propagates)e.dragging=true;case"mousemove":if(e.dragging){d.hijack(a,"drag",e);if(e.propagates){e.drop!==false&&c.drop&&c.drop.handler(a,e);break}a.type="mouseup"};case"mouseup":b.remove(document,"mousemove mouseup",d.handler);if(e.dragging){e.drop!==false&&c.drop&&c.drop.handler(a,e);d.hijack(a,"dragend",e)}d.textselect(true);if(e.click===false&&e.dragging){jQuery.event.triggered=true;setTimeout(function(){jQuery.event.triggered=false},20);e.dragging=false}break}},delegate:function(c){var e=[],g,h=a.data(this,"events")||{};a.each(h.live||[],function(h,j){if(j.preType.indexOf("drag")===0)if(g=a(c.target).closest(j.selector,c.currentTarget)[0]){b.add(g,j.origType+"."+d.livekey,j.origHandler,j.data);a.inArray(g,e)<0&&e.push(g)}});if(!e.length)return false;return a(e).bind("dragend."+d.livekey,function(){b.remove(this,"."+d.livekey)})},hijack:function(c,e,g,h,j){if(g){var k={event:c.originalEvent,type:c.type},l=e.indexOf("drop")?"drag":"drop",m,n=h||0,o,p;h=!isNaN(h)?h:g.interactions.length;c.type=e;c.originalEvent=null;g.results=[];do if(o=g.interactions[n])if(!(e!=="dragend"&&o.cancelled)){p=d.properties(c,g,o);o.results=[];a(j||o[l]||g.droppable).each(function(h,j){m=(p.target=j)?b.handle.call(j,c,p):null;if(m===false){if(l=="drag"){o.cancelled=true;g.propagates-=1}if(e=="drop")o[l][h]=null}else if(e=="dropinit")o.droppable.push(d.element(m)||j);if(e=="dragstart")o.proxy=a(d.element(m)||o.drag)[0];o.results.push(m);delete c.result;if(e!=="dropinit")return m});g.results[n]=d.flatten(o.results);if(e=="dropinit")o.droppable=d.flatten(o.droppable);e=="dragstart"&&!o.cancelled&&p.update()}while(++n<h);c.type=k.type;c.originalEvent=k.event;return d.flatten(g.results)}},properties:function(a,b,c){var e=c.callback;e.drag=c.drag;e.proxy=c.proxy||c.drag;e.startX=b.pageX;e.startY=b.pageY;e.deltaX=a.pageX-b.pageX;e.deltaY=a.pageY-b.pageY;e.originalX=c.offset.left;e.originalY=c.offset.top;e.offsetX=a.pageX-(b.pageX-e.originalX);e.offsetY=a.pageY-(b.pageY-e.originalY);e.drop=d.flatten((c.drop||[]).slice());e.available=d.flatten((c.droppable||[]).slice());return e},element:function(a){if(a&&(a.jquery||a.nodeType==1))return a},flatten:function(b){return a.map(b,function(b){return b&&b.jquery?a.makeArray(b):b&&b.length?d.flatten(b):b})},textselect:function(b){a(document)[b?"unbind":"bind"]("selectstart",d.dontstart).attr("unselectable",b?"off":"on").css("MozUserSelect",b?"":"none")},dontstart:function(){return false},callback:function(){}};d.callback.prototype={update:function(){c.drop&&this.available.length&&a.each(this.available,function(a){c.drop.locate(this,a)})}};c.draginit=c.dragstart=c.dragend=d})(jQuery);(function(a){function b(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var c=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var d=c.length;d;)a.event.fixHooks[c[--d]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],b,!1);else this.onmousewheel=b},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],b,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);(function(a){function c(b){function m(a,b){b.unbind(a.getOptions().zoom.trigger,c);b.unbind("mousewheel",d);b.unbind("dragstart",i);b.unbind("drag",j);b.unbind("dragend",k);if(h)clearTimeout(h)}function l(a,b){var e=a.getOptions();if(e.zoom.interactive){b[e.zoom.trigger](c);b.mousewheel(d)}if(e.pan.interactive){b.bind("dragstart",{distance:10},i);b.bind("drag",j);b.bind("dragend",k)}}function k(a){if(h){clearTimeout(h);h=null}b.getPlaceholder().css("cursor",e);b.pan({left:f-a.pageX,top:g-a.pageY})}function j(a){var c=b.getOptions().pan.frameRate;if(h||!c)return;h=setTimeout(function(){b.pan({left:f-a.pageX,top:g-a.pageY});f=a.pageX;g=a.pageY;h=null},1/c*1e3)}function i(a){if(a.which!=1)return false;var c=b.getPlaceholder().css("cursor");if(c)e=c;b.getPlaceholder().css("cursor",b.getOptions().pan.cursor);f=a.pageX;g=a.pageY}function d(a,b){c(a,b<0);return false}function c(a,c){var d=b.offset();d.left=a.pageX-d.left;d.top=a.pageY-d.top;if(c)b.zoomOut({center:d});else b.zoom({center:d})}var e="default",f=0,g=0,h=null;b.zoomOut=function(a){if(!a)a={};if(!a.amount)a.amount=b.getOptions().zoom.amount;a.amount=1/a.amount;b.zoom(a)};b.zoom=function(c){if(!c)c={};var d=c.center,e=c.amount||b.getOptions().zoom.amount,f=b.width(),g=b.height();if(!d)d={left:f/2,top:g/2};var h=d.left/f,i=d.top/g,j={x:{min:d.left-h*f/e,max:d.left+(1-h)*f/e},y:{min:d.top-i*g/e,max:d.top+(1-i)*g/e}};a.each(b.getAxes(),function(a,b){var c=b.options,d=j[b.direction].min,e=j[b.direction].max,f=c.zoomRange;if(f===false)return;d=b.c2p(d);e=b.c2p(e);if(d>e){var g=d;d=e;e=g}var h=e-d;if(f&&(f[0]!=null&&h<f[0]||f[1]!=null&&h>f[1]))return;c.min=d;c.max=e});b.setupGrid();b.draw();if(!c.preventEvent)b.getPlaceholder().trigger("plotzoom",[b])};b.pan=function(c){var d={x:+c.left,y:+c.top};if(isNaN(d.x))d.x=0;if(isNaN(d.y))d.y=0;a.each(b.getAxes(),function(a,b){var c=b.options,e,f,g=d[b.direction];e=b.c2p(b.p2c(b.min)+g),f=b.c2p(b.p2c(b.max)+g);var h=c.panRange;if(h===false)return;if(h){if(h[0]!=null&&h[0]>e){g=h[0]-e;e+=g;f+=g}if(h[1]!=null&&h[1]<f){g=h[1]-f;e+=g;f+=g}}c.min=e;c.max=f});b.setupGrid();b.draw();if(!c.preventEvent)b.getPlaceholder().trigger("plotpan",[b])};b.hooks.bindEvents.push(l);b.hooks.shutdown.push(m)}var b={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false,cursor:"move",frameRate:20}};a.plot.plugins.push({init:c,options:b,name:"navigate",version:"1.3"})})(jQuery)
|
js/jquery.flot.pie.min.js
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
Flot plugin for rendering pie charts ~1.0 ~ Copyright (c) 2007-2011 IOLA and Ole Laursen
|
3 |
+
Licensed under the MIT License ~ https://raw.github.com/flot/flot/master/LICENSE.txt
|
4 |
+
*/
|
5 |
+
(function(b){function c(D){var h=null;var L=null;var n=null;var B=null;var p=null;var M=0;var F=true;var o=10;var w=0.95;var A=0;var d=false;var z=false;var j=[];D.hooks.processOptions.push(g);D.hooks.bindEvents.push(e);function g(O,N){if(N.series.pie.show){N.grid.show=false;if(N.series.pie.label.show=="auto"){if(N.legend.show){N.series.pie.label.show=false}else{N.series.pie.label.show=true}}if(N.series.pie.radius=="auto"){if(N.series.pie.label.show){N.series.pie.radius=3/4}else{N.series.pie.radius=1}}if(N.series.pie.tilt>1){N.series.pie.tilt=1}if(N.series.pie.tilt<0){N.series.pie.tilt=0}O.hooks.processDatapoints.push(E);O.hooks.drawOverlay.push(H);O.hooks.draw.push(r)}}function e(P,N){var O=P.getOptions();if(O.series.pie.show&&O.grid.hoverable){N.unbind("mousemove").mousemove(t)}if(O.series.pie.show&&O.grid.clickable){N.unbind("click").click(l)}}function G(O){var P="";function N(S,T){if(!T){T=0}for(var R=0;R<S.length;++R){for(var Q=0;Q<T;Q++){P+="\t"}if(typeof S[R]=="object"){P+=""+R+":\n";N(S[R],T+1)}else{P+=""+R+": "+S[R]+"\n"}}}N(O);alert(P)}function q(P){for(var N=0;N<P.length;++N){var O=parseFloat(P[N].data[0][1]);if(O){M+=O}}}function E(Q,N,O,P){if(!d){d=true;h=Q.getCanvas();L=b(h).parent();a=Q.getOptions();Q.setData(K(Q.getData()))}}function I(){A=L.children().filter(".legend").children().width();n=Math.min(h.width,(h.height/a.series.pie.tilt))/2;p=(h.height/2)+a.series.pie.offset.top;B=(h.width/2);if(a.series.pie.offset.left=="auto"){if(a.legend.position.match("w")){B+=A/2}else{B-=A/2}}else{B+=a.series.pie.offset.left}if(B<n){B=n}else{if(B>h.width-n){B=h.width-n}}}function v(O){for(var N=0;N<O.length;++N){if(typeof(O[N].data)=="number"){O[N].data=[[1,O[N].data]]}else{if(typeof(O[N].data)=="undefined"||typeof(O[N].data[0])=="undefined"){if(typeof(O[N].data)!="undefined"&&typeof(O[N].data.label)!="undefined"){O[N].label=O[N].data.label}O[N].data=[[1,0]]}}}return O}function K(Q){Q=v(Q);q(Q);var P=0;var S=0;var N=a.series.pie.combine.color;var R=[];for(var O=0;O<Q.length;++O){Q[O].data[0][1]=parseFloat(Q[O].data[0][1]);if(!Q[O].data[0][1]){Q[O].data[0][1]=0}if(Q[O].data[0][1]/M<=a.series.pie.combine.threshold){P+=Q[O].data[0][1];S++;if(!N){N=Q[O].color}}else{R.push({data:[[1,Q[O].data[0][1]]],color:Q[O].color,label:Q[O].label,angle:(Q[O].data[0][1]*(Math.PI*2))/M,percent:(Q[O].data[0][1]/M*100)})}}if(S>0){R.push({data:[[1,P]],color:N,label:a.series.pie.combine.label,angle:(P*(Math.PI*2))/M,percent:(P/M*100)})}return R}function r(S,Q){if(!L){return}ctx=Q;I();var T=S.getData();var P=0;while(F&&P<o){F=false;if(P>0){n*=w}P+=1;N();if(a.series.pie.tilt<=0.8){O()}R()}if(P>=o){N();L.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>')}if(S.setSeries&&S.insertLegend){S.setSeries(T);S.insertLegend()}function N(){ctx.clearRect(0,0,h.width,h.height);L.children().filter(".pieLabel, .pieLabelBackground").remove()}function O(){var Z=5;var Y=15;var W=10;var X=0.02;if(a.series.pie.radius>1){var U=a.series.pie.radius}else{var U=n*a.series.pie.radius}if(U>=(h.width/2)-Z||U*a.series.pie.tilt>=(h.height/2)-Y||U<=W){return}ctx.save();ctx.translate(Z,Y);ctx.globalAlpha=X;ctx.fillStyle="#000";ctx.translate(B,p);ctx.scale(1,a.series.pie.tilt);for(var V=1;V<=W;V++){ctx.beginPath();ctx.arc(0,0,U,0,Math.PI*2,false);ctx.fill();U-=V}ctx.restore()}function R(){startAngle=Math.PI*a.series.pie.startAngle;if(a.series.pie.radius>1){var U=a.series.pie.radius}else{var U=n*a.series.pie.radius}ctx.save();ctx.translate(B,p);ctx.scale(1,a.series.pie.tilt);ctx.save();var Y=startAngle;for(var W=0;W<T.length;++W){T[W].startAngle=Y;X(T[W].angle,T[W].color,true)}ctx.restore();ctx.save();ctx.lineWidth=a.series.pie.stroke.width;Y=startAngle;for(var W=0;W<T.length;++W){X(T[W].angle,a.series.pie.stroke.color,false)}ctx.restore();J(ctx);if(a.series.pie.label.show){V()}ctx.restore();function X(ab,Z,aa){if(ab<=0){return}if(aa){ctx.fillStyle=Z}else{ctx.strokeStyle=Z;ctx.lineJoin="round"}ctx.beginPath();if(Math.abs(ab-Math.PI*2)>1e-9){ctx.moveTo(0,0)}else{if(b.browser.msie){ab-=0.0001}}ctx.arc(0,0,U,Y,Y+ab,false);ctx.closePath();Y+=ab;if(aa){ctx.fill()}else{ctx.stroke()}}function V(){var ac=startAngle;if(a.series.pie.label.radius>1){var Z=a.series.pie.label.radius}else{var Z=n*a.series.pie.label.radius}for(var ab=0;ab<T.length;++ab){if(T[ab].percent>=a.series.pie.label.threshold*100){aa(T[ab],ac,ab)}ac+=T[ab].angle}function aa(ap,ai,ag){if(ap.data[0][1]==0){return}var ar=a.legend.labelFormatter,aq,ae=a.series.pie.label.formatter;if(ar){aq=ar(ap.label,ap)}else{aq=ap.label}if(ae){aq=ae(aq,ap)}var aj=((ai+ap.angle)+ai)/2;var ao=B+Math.round(Math.cos(aj)*Z);var am=p+Math.round(Math.sin(aj)*Z)*a.series.pie.tilt;var af='<span class="pieLabel" id="pieLabel'+ag+'" style="position:absolute;top:'+am+"px;left:"+ao+'px;">'+aq+"</span>";L.append(af);var an=L.children("#pieLabel"+ag);var ad=(am-an.height()/2);var ah=(ao-an.width()/2);an.css("top",ad);an.css("left",ah);if(0-ad>0||0-ah>0||h.height-(ad+an.height())<0||h.width-(ah+an.width())<0){F=true}if(a.series.pie.label.background.opacity!=0){var ak=a.series.pie.label.background.color;if(ak==null){ak=ap.color}var al="top:"+ad+"px;left:"+ah+"px;";b('<div class="pieLabelBackground" style="position:absolute;width:'+an.width()+"px;height:"+an.height()+"px;"+al+"background-color:"+ak+';"> </div>').insertBefore(an).css("opacity",a.series.pie.label.background.opacity)}}}}}function J(N){if(a.series.pie.innerRadius>0){N.save();innerRadius=a.series.pie.innerRadius>1?a.series.pie.innerRadius:n*a.series.pie.innerRadius;N.globalCompositeOperation="destination-out";N.beginPath();N.fillStyle=a.series.pie.stroke.color;N.arc(0,0,innerRadius,0,Math.PI*2,false);N.fill();N.closePath();N.restore();N.save();N.beginPath();N.strokeStyle=a.series.pie.stroke.color;N.arc(0,0,innerRadius,0,Math.PI*2,false);N.stroke();N.closePath();N.restore()}}function s(Q,R){for(var S=false,P=-1,N=Q.length,O=N-1;++P<N;O=P){((Q[P][1]<=R[1]&&R[1]<Q[O][1])||(Q[O][1]<=R[1]&&R[1]<Q[P][1]))&&(R[0]<(Q[O][0]-Q[P][0])*(R[1]-Q[P][1])/(Q[O][1]-Q[P][1])+Q[P][0])&&(S=!S)}return S}function u(R,P){var T=D.getData(),O=D.getOptions(),N=O.series.pie.radius>1?O.series.pie.radius:n*O.series.pie.radius;for(var Q=0;Q<T.length;++Q){var S=T[Q];if(S.pie.show){ctx.save();ctx.beginPath();ctx.moveTo(0,0);ctx.arc(0,0,N,S.startAngle,S.startAngle+S.angle,false);ctx.closePath();x=R-B;y=P-p;if(ctx.isPointInPath){if(ctx.isPointInPath(R-B,P-p)){ctx.restore();return{datapoint:[S.percent,S.data],dataIndex:0,series:S,seriesIndex:Q}}}else{p1X=(N*Math.cos(S.startAngle));p1Y=(N*Math.sin(S.startAngle));p2X=(N*Math.cos(S.startAngle+(S.angle/4)));p2Y=(N*Math.sin(S.startAngle+(S.angle/4)));p3X=(N*Math.cos(S.startAngle+(S.angle/2)));p3Y=(N*Math.sin(S.startAngle+(S.angle/2)));p4X=(N*Math.cos(S.startAngle+(S.angle/1.5)));p4Y=(N*Math.sin(S.startAngle+(S.angle/1.5)));p5X=(N*Math.cos(S.startAngle+S.angle));p5Y=(N*Math.sin(S.startAngle+S.angle));arrPoly=[[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];arrPoint=[x,y];if(s(arrPoly,arrPoint)){ctx.restore();return{datapoint:[S.percent,S.data],dataIndex:0,series:S,seriesIndex:Q}}}ctx.restore()}}return null}function t(N){m("plothover",N)}function l(N){m("plotclick",N)}function m(N,T){var O=D.offset(),R=parseInt(T.pageX-O.left),P=parseInt(T.pageY-O.top),V=u(R,P);if(a.grid.autoHighlight){for(var Q=0;Q<j.length;++Q){var S=j[Q];if(S.auto==N&&!(V&&S.series==V.series)){f(S.series)}}}if(V){k(V.series,N)}var U={pageX:T.pageX,pageY:T.pageY};L.trigger(N,[U,V])}function k(O,P){if(typeof O=="number"){O=series[O]}var N=C(O);if(N==-1){j.push({series:O,auto:P});D.triggerRedrawOverlay()}else{if(!P){j[N].auto=false}}}function f(O){if(O==null){j=[];D.triggerRedrawOverlay()}if(typeof O=="number"){O=series[O]}var N=C(O);if(N!=-1){j.splice(N,1);D.triggerRedrawOverlay()}}function C(P){for(var N=0;N<j.length;++N){var O=j[N];if(O.series==P){return N}}return -1}function H(Q,R){var P=Q.getOptions();var N=P.series.pie.radius>1?P.series.pie.radius:n*P.series.pie.radius;R.save();R.translate(B,p);R.scale(1,P.series.pie.tilt);for(i=0;i<j.length;++i){O(j[i].series)}J(R);R.restore();function O(S){if(S.angle<0){return}R.fillStyle="rgba(255, 255, 255, "+P.series.pie.highlight.opacity+")";R.beginPath();if(Math.abs(S.angle-Math.PI*2)>1e-9){R.moveTo(0,0)}R.arc(0,0,N,S.startAngle,S.startAngle+S.angle,false);R.closePath();R.fill()}}}var a={series:{pie:{show:false,radius:"auto",innerRadius:0,startAngle:3/2,tilt:1,offset:{top:0,left:"auto"},stroke:{color:"#FFF",width:1},label:{show:"auto",formatter:function(d,e){return'<div style="font-size:x-small;text-align:center;padding:2px;color:'+e.color+';">'+d+"<br/>"+Math.round(e.percent)+"%</div>"},radius:1,background:{color:null,opacity:0},threshold:0},combine:{threshold:-1,color:null,label:"Other"},highlight:{opacity:0.5}}}};b.plot.plugins.push({init:c,options:a,name:"pie",version:"1.0"})})(jQuery);
|
js/jquery.qtip.min.js
ADDED
@@ -0,0 +1,13 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* qTip2 - Pretty powerful tooltips
|
3 |
+
* http://craigsworks.com/projects/qtip2/
|
4 |
+
*
|
5 |
+
* Version: nightly
|
6 |
+
* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com
|
7 |
+
*
|
8 |
+
* Dual licensed under MIT or GPLv2 licenses
|
9 |
+
* http://en.wikipedia.org/wiki/MIT_License
|
10 |
+
* http://en.wikipedia.org/wiki/GNU_General_Public_License
|
11 |
+
*
|
12 |
+
* Date: Thu Oct 20 13:41:21.0000000000 2011
|
13 |
+
*//*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true *//*global window: false, jQuery: false, console: false */(function(a,b,c){function B(b,g){function w(a){var b=a.precedance==="y",c=n[b?"width":"height"],d=n[b?"height":"width"],e=a.string().indexOf("center")>-1,f=c*(e?.5:1),g=Math.pow,h=Math.round,i,j,k,l=Math.sqrt(g(f,2)+g(d,2)),m=[p/f*l,p/d*l];m[2]=Math.sqrt(g(m[0],2)-g(p,2)),m[3]=Math.sqrt(g(m[1],2)-g(p,2)),i=l+m[2]+m[3]+(e?0:m[0]),j=i/l,k=[h(j*d),h(j*c)];return{height:k[b?0:1],width:k[b?1:0]}}function v(b){var c=k.titlebar&&b.y==="top",d=c?k.titlebar:k.content,e=a.browser.mozilla,f=e?"-moz-":a.browser.webkit?"-webkit-":"",g=b.y+(e?"":"-")+b.x,h=f+(e?"border-radius-"+g:"border-"+g+"-radius");return parseInt(d.css(h),10)||parseInt(l.css(h),10)||0}function u(a,b,c){b=b?b:a[a.precedance];var d=l.hasClass(r),e=k.titlebar&&a.y==="top",f=e?k.titlebar:k.content,g="border-"+b+"-width",h;l.addClass(r),h=parseInt(f.css(g),10),h=(c?h||parseInt(l.css(g),10):h)||0,l.toggleClass(r,d);return h}function t(f,g,h,l){if(k.tip){var n=a.extend({},i.corner),o=h.adjusted,p=b.options.position.adjust.method.split(" "),q=p[0],r=p[1]||p[0],s={left:e,top:e,x:0,y:0},t,u={},v;i.corner.fixed!==d&&(q==="shift"&&n.precedance==="x"&&o.left&&n.y!=="center"?n.precedance=n.precedance==="x"?"y":"x":q==="flip"&&o.left&&(n.x=n.x==="center"?o.left>0?"left":"right":n.x==="left"?"right":"left"),r==="shift"&&n.precedance==="y"&&o.top&&n.x!=="center"?n.precedance=n.precedance==="y"?"x":"y":r==="flip"&&o.top&&(n.y=n.y==="center"?o.top>0?"top":"bottom":n.y==="top"?"bottom":"top"),n.string()!==m.corner&&(m.top!==o.top||m.left!==o.left)&&i.update(n,e)),t=i.position(n,o),t.right!==c&&(t.left=-t.right),t.bottom!==c&&(t.top=-t.bottom),t.user=Math.max(0,j.offset);if(s.left=q==="shift"&&!!o.left)n.x==="center"?u["margin-left"]=s.x=t["margin-left"]-o.left:(v=t.right!==c?[o.left,-t.left]:[-o.left,t.left],(s.x=Math.max(v[0],v[1]))>v[0]&&(h.left-=o.left,s.left=e),u[t.right!==c?"right":"left"]=s.x);if(s.top=r==="shift"&&!!o.top)n.y==="center"?u["margin-top"]=s.y=t["margin-top"]-o.top:(v=t.bottom!==c?[o.top,-t.top]:[-o.top,t.top],(s.y=Math.max(v[0],v[1]))>v[0]&&(h.top-=o.top,s.top=e),u[t.bottom!==c?"bottom":"top"]=s.y);k.tip.css(u).toggle(!(s.x&&s.y||n.x==="center"&&s.y||n.y==="center"&&s.x)),h.left-=t.left.charAt?t.user:q!=="shift"||s.top||!s.left&&!s.top?t.left:0,h.top-=t.top.charAt?t.user:r!=="shift"||s.left||!s.left&&!s.top?t.top:0,m.left=o.left,m.top=o.top,m.corner=n.string()}}var i=this,j=b.options.style.tip,k=b.elements,l=k.tooltip,m={top:0,left:0,corner:""},n={width:j.width,height:j.height},o={},p=j.border||0,q=".qtip-tip",s=!!(a("<canvas />")[0]||{}).getContext;i.mimic=i.corner=f,i.border=p,i.offset=j.offset,i.size=n,b.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){i.init()||i.destroy(),b.reposition()},"^style.tip.(height|width)$":function(){n={width:j.width,height:j.height},i.create(),i.update(),b.reposition()},"^content.title.text|style.(classes|widget)$":function(){k.tip&&i.update()}},a.extend(i,{init:function(){var b=i.detectCorner()&&(s||a.browser.msie);b&&(i.create(),i.update(),l.unbind(q).bind("tooltipmove"+q,t));return b},detectCorner:function(){var a=j.corner,c=b.options.position,f=c.at,g=c.my.string?c.my.string():c.my;if(a===e||g===e&&f===e)return e;a===d?i.corner=new h.Corner(g):a.string||(i.corner=new h.Corner(a),i.corner.fixed=d);return i.corner.string()!=="centercenter"},detectColours:function(){var c,d,e,f=k.tip.css({backgroundColor:"",border:""}),g=i.corner,h=g[g.precedance],m="border-"+h+"-color",p="border"+h.charAt(0)+h.substr(1)+"Color",q=/rgba?\(0, 0, 0(, 0)?\)|transparent/i,s="background-color",t="transparent",u=a(document.body).css("color"),v=b.elements.content.css("color"),w=k.titlebar&&(g.y==="top"||g.y==="center"&&f.position().top+n.height/2+j.offset<k.titlebar.outerHeight(1)),x=w?k.titlebar:k.content;l.addClass(r),o.fill=d=f.css(s),o.border=e=f[0].style[p]||f.css(m)||l.css(m);if(!d||q.test(d))o.fill=x.css(s)||t,q.test(o.fill)&&(o.fill=l.css(s)||d);if(!e||q.test(e)||e===u){o.border=x.css(m)||t;if(q.test(o.border)||o.border===v)o.border=e}a("*",f).add(f).css(s,t).css("border",""),l.removeClass(r)},create:function(){var b=n.width,c=n.height,d;k.tip&&k.tip.remove(),k.tip=a("<div />",{"class":"ui-tooltip-tip"}).css({width:b,height:c}).prependTo(l),s?a("<canvas />").appendTo(k.tip)[0].getContext("2d").save():(d='<vml:shape coordorigin="0,0" style="display:inline-block; position:absolute; behavior:url(#default#VML);"></vml:shape>',k.tip.html(d+d))},update:function(b,c){var g=k.tip,l=g.children(),m=n.width,q=n.height,r="px solid ",t="px dashed transparent",v=j.mimic,x=Math.round,y,z,B,C,D;b||(b=i.corner),v===e?v=b:(v=new h.Corner(v),v.precedance=b.precedance,v.x==="inherit"?v.x=b.x:v.y==="inherit"?v.y=b.y:v.x===v.y&&(v[b.precedance]=b[b.precedance])),y=v.precedance,i.detectColours(),o.border!=="transparent"&&o.border!=="#123456"?(p=u(b,f,d),j.border===0&&p>0&&(o.fill=o.border),i.border=p=j.border!==d?j.border:p):i.border=p=0,B=A(v,m,q),i.size=D=w(b),g.css(D),b.precedance==="y"?C=[x(v.x==="left"?p:v.x==="right"?D.width-m-p:(D.width-m)/2),x(v.y==="top"?D.height-q:0)]:C=[x(v.x==="left"?D.width-m:0),x(v.y==="top"?p:v.y==="bottom"?D.height-q-p:(D.height-q)/2)],s?(l.attr(D),z=l[0].getContext("2d"),z.restore(),z.save(),z.clearRect(0,0,3e3,3e3),z.translate(C[0],C[1]),z.beginPath(),z.moveTo(B[0][0],B[0][1]),z.lineTo(B[1][0],B[1][1]),z.lineTo(B[2][0],B[2][1]),z.closePath(),z.fillStyle=o.fill,z.strokeStyle=o.border,z.lineWidth=p*2,z.lineJoin="miter",z.miterLimit=100,p&&z.stroke(),z.fill()):(B="m"+B[0][0]+","+B[0][1]+" l"+B[1][0]+","+B[1][1]+" "+B[2][0]+","+B[2][1]+" xe",C[2]=p&&/^(r|b)/i.test(b.string())?parseFloat(a.browser.version,10)===8?2:1:0,l.css({antialias:""+(v.string().indexOf("center")>-1),left:C[0]-C[2]*Number(y==="x"),top:C[1]-C[2]*Number(y==="y"),width:m+p,height:q+p}).each(function(b){var c=a(this);c[c.prop?"prop":"attr"]({coordsize:m+p+" "+(q+p),path:B,fillcolor:o.fill,filled:!!b,stroked:!b}).css({display:p||b?"block":"none"}),!b&&c.html()===""&&c.html('<vml:stroke weight="'+p*2+'px" color="'+o.border+'" miterlimit="1000" joinstyle="miter" style="behavior:url(#default#VML); display:inline-block;" />')})),c!==e&&i.position(b)},position:function(b){var c=k.tip,f={},g=Math.max(0,j.offset),h,l,m;if(j.corner===e||!c)return e;b=b||i.corner,h=b.precedance,l=w(b),m=[b.x,b.y],h==="x"&&m.reverse(),a.each(m,function(a,c){var e,i;c==="center"?(e=h==="y"?"left":"top",f[e]="50%",f["margin-"+e]=-Math.round(l[h==="y"?"width":"height"]/2)+g):(e=u(b,c,d),i=v(b),f[c]=a?p?u(b,c):0:g+(i>e?i:0))}),f[b[h]]-=l[h==="x"?"width":"height"],c.css({top:"",bottom:"",left:"",right:"",margin:""}).css(f);return f},destroy:function(){k.tip&&k.tip.remove(),l.unbind(q)}}),i.init()}function A(a,b,c){var d=Math.ceil(b/2),e=Math.ceil(c/2),f={bottomright:[[0,0],[b,c],[b,0]],bottomleft:[[0,0],[b,0],[0,c]],topright:[[0,c],[b,0],[b,c]],topleft:[[0,0],[0,c],[b,c]],topcenter:[[0,c],[d,0],[b,c]],bottomcenter:[[0,0],[b,0],[d,c]],rightcenter:[[0,0],[b,e],[0,c]],leftcenter:[[b,0],[b,c],[0,e]]};f.lefttop=f.bottomright,f.righttop=f.bottomleft,f.leftbottom=f.topright,f.rightbottom=f.topleft;return f[a.string()]}function z(b,c){var i,j,k,l,m,n=a(this),o=a(document.body),p=this===document?o:n,q=n.metadata?n.metadata(c.metadata):f,r=c.metadata.type==="html5"&&q?q[c.metadata.name]:f,s=n.data(c.metadata.name||"qtipopts");try{s=typeof s==="string"?(new Function("return "+s))():s}catch(t){w("Unable to parse HTML5 attribute data: "+s)}l=a.extend(d,{},g.defaults,c,typeof s==="object"?x(s):f,x(r||q)),j=l.position,l.id=b;if("boolean"===typeof l.content.text){k=n.attr(l.content.attr);if(l.content.attr!==e&&k)l.content.text=k;else{w("Unable to locate content for tooltip! Aborting render of tooltip on element: ",n);return e}}j.container===e&&(j.container=o),j.target===e&&(j.target=p),l.show.target===e&&(l.show.target=p),l.show.solo===d&&(l.show.solo=o),l.hide.target===e&&(l.hide.target=p),l.position.viewport===d&&(l.position.viewport=j.container),j.at=new h.Corner(j.at),j.my=new h.Corner(j.my);if(a.data(this,"qtip"))if(l.overwrite)n.qtip("destroy");else if(l.overwrite===e)return e;l.suppress&&(m=a.attr(this,"title"))&&a(this).removeAttr("title").attr(u,m),i=new y(n,l,b,!!k),a.data(this,"qtip",i),n.bind("remove.qtip-"+b,function(){i.destroy()});return i}function y(s,t,w,y){function R(){var c=[t.show.target[0],t.hide.target[0],z.rendered&&G.tooltip[0],t.position.container[0],t.position.viewport[0],b,document];z.rendered?a([]).pushStack(a.grep(c,function(a){return typeof a==="object"})).unbind(F):t.show.target.unbind(F+"-create")}function Q(){function p(a){E.is(":visible")&&z.reposition(a)}function o(a){if(E.hasClass(m))return e;clearTimeout(z.timers.inactive),z.timers.inactive=setTimeout(function(){z.hide(a)},t.hide.inactive)}function l(b){if(E.hasClass(m)||C||D)return e;var d=a(b.relatedTarget||b.target),g=d.closest(n)[0]===E[0],h=d[0]===f.show[0];clearTimeout(z.timers.show),clearTimeout(z.timers.hide);if(c.target==="mouse"&&g||t.hide.fixed&&(/mouse(out|leave|move)/.test(b.type)&&(g||h)))try{b.preventDefault(),b.stopImmediatePropagation()}catch(i){}else t.hide.delay>0?z.timers.hide=setTimeout(function(){z.hide(b)},t.hide.delay):z.hide(b)}function k(a){if(E.hasClass(m))return e;f.show.trigger("qtip-"+w+"-inactive"),clearTimeout(z.timers.show),clearTimeout(z.timers.hide);var b=function(){z.toggle(d,a)};t.show.delay>0?z.timers.show=setTimeout(b,t.show.delay):b()}var c=t.position,f={show:t.show.target,hide:t.hide.target,viewport:a(c.viewport),document:a(document),window:a(b)},h={show:a.trim(""+t.show.event).split(" "),hide:a.trim(""+t.hide.event).split(" ")},j=a.browser.msie&&parseInt(a.browser.version,10)===6;E.bind("mouseenter"+F+" mouseleave"+F,function(a){var b=a.type==="mouseenter";b&&z.focus(a),E.toggleClass(q,b)}),t.hide.fixed&&(f.hide=f.hide.add(E),E.bind("mouseover"+F,function(){E.hasClass(m)||clearTimeout(z.timers.hide)})),/mouse(out|leave)/i.test(t.hide.event)?t.hide.leave==="window"&&f.window.bind("mouseout"+F,function(a){/select|option/.test(a.target)&&!a.relatedTarget&&z.hide(a)}):/mouse(over|enter)/i.test(t.show.event)&&f.hide.bind("mouseleave"+F,function(a){clearTimeout(z.timers.show)}),(""+t.hide.event).indexOf("unfocus")>-1&&f.document.bind("mousedown"+F,function(b){var c=a(b.target),d=!E.hasClass(m)&&E.is(":visible");c[0]!==E[0]&&c.parents(n).length===0&&c.add(s).length>1&&!c.is(":disabled")&&z.hide(b)}),"number"===typeof t.hide.inactive&&(f.show.bind("qtip-"+w+"-inactive",o),a.each(g.inactiveEvents,function(a,b){f.hide.add(G.tooltip).bind(b+F+"-inactive",o)})),a.each(h.hide,function(b,c){var d=a.inArray(c,h.show),e=a(f.hide);d>-1&&e.add(f.show).length===e.length||c==="unfocus"?(f.show.bind(c+F,function(a){E.is(":visible")?l(a):k(a)}),delete h.show[d]):f.hide.bind(c+F,l)}),a.each(h.show,function(a,b){f.show.bind(b+F,k)}),"number"===typeof t.hide.distance&&f.show.add(E).bind("mousemove"+F,function(a){var b=H.origin||{},c=t.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&z.hide(a)}),c.target==="mouse"&&(f.show.bind("mousemove"+F,function(a){i={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),c.adjust.mouse&&(t.hide.event&&E.bind("mouseleave"+F,function(a){(a.relatedTarget||a.target)!==f.show[0]&&z.hide(a)}),f.document.bind("mousemove"+F,function(a){!E.hasClass(m)&&E.is(":visible")&&z.reposition(a||i)}))),(c.adjust.resize||f.viewport.length)&&(a.event.special.resize?f.viewport:f.window).bind("resize"+F,p),(f.viewport.length||j&&E.css("position")==="fixed")&&f.viewport.bind("scroll"+F,p)}function P(b,d){function g(b){function i(c){c&&(delete h[c.src],clearTimeout(z.timers.img[c.src]),a(c).unbind(F)),a.isEmptyObject(h)&&(z.redraw(),d!==e&&z.reposition(H.event),b())}var g,h={};if((g=f.find("img:not([height]):not([width])")).length===0)return i();g.each(function(b,d){if(h[d.src]===c){var e=0,f=3;(function g(){if(d.height||d.width||e>f)return i(d);e+=1,z.timers.img[d.src]=setTimeout(g,700)})(),a(d).bind("error"+F+" load"+F,function(){i(this)}),h[d.src]=d}})}var f=G.content;if(!z.rendered||!b)return e;a.isFunction(b)&&(b=b.call(s,H.event,z)||""),b.jquery&&b.length>0?f.empty().append(b.css({display:"block"})):f.html(b),z.rendered<0?E.queue("fx",g):(D=0,g(a.noop));return z}function O(b,c){var d=G.title;if(!z.rendered||!b)return e;a.isFunction(b)&&(b=b.call(s,H.event,z));if(b===e)return K(e);b.jquery&&b.length>0?d.empty().append(b.css({display:"block"})):d.html(b),z.redraw(),c!==e&&z.rendered&&E.is(":visible")&&z.reposition(H.event)}function N(a){var b=G.button,c=G.title;if(!z.rendered)return e;a?(c||M(),L()):b.remove()}function M(){var b=B+"-title";G.titlebar&&K(),G.titlebar=a("<div />",{"class":k+"-titlebar "+(t.style.widget?"ui-widget-header":"")}).append(G.title=a("<div />",{id:b,"class":k+"-title","aria-atomic":d})).insertBefore(G.content).delegate(".ui-state-default","mousedown keydown mouseup keyup mouseout",function(b){a(this).toggleClass("ui-state-active ui-state-focus",b.type.substr(-4)==="down")}).delegate(".ui-state-default","mouseover mouseout",function(b){a(this).toggleClass("ui-state-hover",b.type==="mouseover")}),t.content.title.button?L():z.rendered&&z.redraw()}function L(){var b=t.content.title.button,c=typeof b==="string",d=c?b:"Close tooltip";G.button&&G.button.remove(),b.jquery?G.button=b:G.button=a("<a />",{"class":"ui-state-default "+(t.style.widget?"":k+"-icon"),title:d,"aria-label":d}).prepend(a("<span />",{"class":"ui-icon ui-icon-close",html:"×"})),G.button.appendTo(G.titlebar).attr("role","button").click(function(a){E.hasClass(m)||z.hide(a);return e}),z.redraw()}function K(a){G.title&&(G.titlebar.remove(),G.titlebar=G.title=G.button=f,a!==e&&z.reposition())}function J(){var a=t.style.widget;E.toggleClass(l,a).toggleClass(o,!a),G.content.toggleClass(l+"-content",a),G.titlebar&&G.titlebar.toggleClass(l+"-header",a),G.button&&G.button.toggleClass(k+"-icon",!a)}function I(a){var b=0,c,d=t,e=a.split(".");while(d=d[e[b++]])b<e.length&&(c=d);return[c||t,e.pop()]}var z=this,A=document.body,B=k+"-"+w,C=0,D=0,E=a(),F=".qtip-"+w,G,H;z.id=w,z.rendered=e,z.elements=G={target:s},z.timers={img:{}},z.options=t,z.checks={},z.plugins={},z.cache=H={event:{},target:a(),disabled:e,attr:y},z.checks.builtin={"^id$":function(b,c,f){var h=f===d?g.nextid:f,i=k+"-"+h;h!==e&&h.length>0&&!a("#"+i).length&&(E[0].id=i,G.content[0].id=i+"-content",G.title[0].id=i+"-title")},"^content.text$":function(a,b,c){P(c)},"^content.title.text$":function(a,b,c){if(!c)return K();!G.title&&c&&M(),O(c)},"^content.title.button$":function(a,b,c){N(c)},"^position.(my|at)$":function(a,b,c){"string"===typeof c&&(a[b]=new h.Corner(c))},"^position.container$":function(a,b,c){z.rendered&&E.appendTo(c)},"^show.ready$":function(){z.rendered?z.toggle(d):z.render(1)},"^style.classes$":function(a,b,c){E.attr("class",k+" qtip ui-helper-reset "+c)},"^style.widget|content.title":J,"^events.(render|show|move|hide|focus|blur)$":function(b,c,d){E[(a.isFunction(d)?"":"un")+"bind"]("tooltip"+c,d)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){var a=t.position;E.attr("tracking",a.target==="mouse"&&a.adjust.mouse),R(),Q()}},a.extend(z,{render:function(b){if(z.rendered)return z;var c=t.content.text,f=t.content.title.text,g=t.position,i=a.Event("tooltiprender");a.attr(s[0],"aria-describedby",B),E=G.tooltip=a("<div/>",{id:B,"class":k+" qtip ui-helper-reset "+o+" "+t.style.classes+" "+k+"-pos-"+t.position.my.abbreviation(),width:t.style.width||"",height:t.style.height||"",tracking:g.target==="mouse"&&g.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":e,"aria-describedby":B+"-content","aria-hidden":d}).toggleClass(m,H.disabled).data("qtip",z).appendTo(t.position.container).append(G.content=a("<div />",{"class":k+"-content",id:B+"-content","aria-atomic":d})),z.rendered=-1,C=D=1,f&&(M(),a.isFunction(f)||O(f,e)),a.isFunction(c)||P(c,e),z.rendered=d,J(),a.each(t.events,function(b,c){a.isFunction(c)&&E.bind(b==="toggle"?"tooltipshow tooltiphide":"tooltip"+b,c)}),a.each(h,function(){this.initialize==="render"&&this(z)}),Q(),E.queue("fx",function(a){i.originalEvent=H.event,E.trigger(i,[z]),C=D=0,z.redraw(),(t.show.ready||b)&&z.toggle(d,H.event),a()});return z},get:function(a){var b,c;switch(a.toLowerCase()){case"dimensions":b={height:E.outerHeight(),width:E.outerWidth()};break;case"offset":b=h.offset(E,t.position.container);break;default:c=I(a.toLowerCase()),b=c[0][c[1]],b=b.precedance?b.string():b}return b},set:function(b,c){function m(a,b){var c,d,e;for(c in k)for(d in k[c])if(e=(new RegExp(d,"i")).exec(a))b.push(e),k[c][d].apply(z,b)}var g=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,h=/^content\.(title|attr)|style/i,i=e,j=e,k=z.checks,l;"string"===typeof b?(l=b,b={},b[l]=c):b=a.extend(d,{},b),a.each(b,function(c,d){var e=I(c.toLowerCase()),f;f=e[0][e[1]],e[0][e[1]]="object"===typeof d&&d.nodeType?a(d):d,b[c]=[e[0],e[1],d,f],i=g.test(c)||i,j=h.test(c)||j}),x(t),C=D=1,a.each(b,m),C=D=0,E.is(":visible")&&z.rendered&&(i&&z.reposition(t.position.target==="mouse"?f:H.event),j&&z.redraw());return z},toggle:function(b,c){function q(){b?(a.browser.msie&&E[0].style.removeAttribute("filter"),E.css("overflow",""),"string"===typeof h.autofocus&&a(h.autofocus,E).focus(),p=a.Event("tooltipvisible"),p.originalEvent=c?H.event:f,E.trigger(p,[z])):E.css({display:"",visibility:"",opacity:"",left:"",top:""})}if(!z.rendered)if(b)z.render(0);else return z;var g=b?"show":"hide",h=t[g],j=E.is(":visible"),k=!c||t[g].target.length<2||H.target[0]===c.target,l=t.position,m=t.content,o,p;(typeof b).search("boolean|number")&&(b=!j);if(!E.is(":animated")&&j===b&&k)return z;if(c){if(/over|enter/.test(c.type)&&/out|leave/.test(H.event.type)&&c.target===t.show.target[0]&&E.has(c.relatedTarget).length)return z;H.event=a.extend({},c)}p=a.Event("tooltip"+g),p.originalEvent=c?H.event:f,E.trigger(p,[z,90]);if(p.isDefaultPrevented())return z;a.attr(E[0],"aria-hidden",!b),b?(H.origin=a.extend({},i),z.focus(c),a.isFunction(m.text)&&P(m.text,e),a.isFunction(m.title.text)&&O(m.title.text,e),!v&&l.target==="mouse"&&l.adjust.mouse&&(a(document).bind("mousemove.qtip",function(a){i={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),v=d),z.reposition(c),(p.solo=!!h.solo)&&a(n,h.solo).not(E).qtip("hide",p)):(clearTimeout(z.timers.show),delete H.origin,v&&!a(n+'[tracking="true"]:visible',h.solo).not(E).length&&(a(document).unbind("mousemove.qtip"),v=e),z.blur(c)),k&&E.stop(0,1),h.effect===e?(E[g](),q.call(E)):a.isFunction(h.effect)?(h.effect.call(E,z),E.queue("fx",function(a){q(),a()})):E.fadeTo(90,b?1:0,q),b&&h.target.trigger("qtip-"+w+"-inactive");return z},show:function(a){return z.toggle(d,a)},hide:function(a){return z.toggle(e,a)},focus:function(b){if(!z.rendered)return z;var c=a(n),d=parseInt(E[0].style.zIndex,10),e=g.zindex+c.length,f=a.extend({},b),h,i;E.hasClass(p)||(i=a.Event("tooltipfocus"),i.originalEvent=f,E.trigger(i,[z,e]),i.isDefaultPrevented()||(d!==e&&(c.each(function(){this.style.zIndex>d&&(this.style.zIndex=this.style.zIndex-1)}),c.filter("."+p).qtip("blur",f)),E.addClass(p)[0].style.zIndex=e));return z},blur:function(b){var c=a.extend({},b),d;E.removeClass(p),d=a.Event("tooltipblur"),d.originalEvent=c,E.trigger(d,[z]);return z},reposition:function(c,d){if(!z.rendered||C)return z;C=1;var f=t.position.target,g=t.position,j=g.my,l=g.at,m=g.adjust,n=m.method.split(" "),o=E.outerWidth(),p=E.outerHeight(),q=0,r=0,s=a.Event("tooltipmove"),u=E.css("position")==="fixed",v=g.viewport,w={left:0,top:0},x=e,y=z.plugins.tip,B={horizontal:n[0],vertical:n[1]=n[1]||n[0],enabled:v.jquery&&f[0]!==b&&f[0]!==A&&m.method!=="none",left:function(a){var b=B.horizontal==="shift",c=v.offset.left+v.scrollLeft,d=j.x==="left"?o:j.x==="right"?-o:-o/2,e=l.x==="left"?q:l.x==="right"?-q:-q/2,f=y&&y.size?y.size.width||0:0,g=y&&y.corner&&y.corner.precedance==="x"&&!b?f:0,h=c-a+g,i=a+o-v.width-c+g,k=d-(j.precedance==="x"||j.x===j.y?e:0),n=j.x==="center";b?(g=y&&y.corner&&y.corner.precedance==="y"?f:0,k=(j.x==="left"?1:-1)*d-g,w.left+=h>0?h:i>0?-i:0,w.left=Math.max(v.offset.left+(g&&y.corner.x==="center"?y.offset:0),a-k,Math.min(Math.max(v.offset.left+v.width,a+k),w.left))):(h>0&&(j.x!=="left"||i>0)?w.left-=k:i>0&&(j.x!=="right"||h>0)&&(w.left-=n?-k:k),w.left!==a&&n&&(w.left-=m.x),w.left<c&&-w.left>i&&(w.left=a));return w.left-a},top:function(a){var b=B.vertical==="shift",c=v.offset.top+v.scrollTop,d=j.y==="top"?p:j.y==="bottom"?-p:-p/2,e=l.y==="top"?r:l.y==="bottom"?-r:-r/2,f=y&&y.size?y.size.height||0:0,g=y&&y.corner&&y.corner.precedance==="y"&&!b?f:0,h=c-a+g,i=a+p-v.height-c+g,k=d-(j.precedance==="y"||j.x===j.y?e:0),n=j.y==="center";b?(g=y&&y.corner&&y.corner.precedance==="x"?f:0,k=(j.y==="top"?1:-1)*d-g,w.top+=h>0?h:i>0?-i:0,w.top=Math.max(v.offset.top+(g&&y.corner.x==="center"?y.offset:0),a-k,Math.min(Math.max(v.offset.top+v.height,a+k),w.top))):(h>0&&(j.y!=="top"||i>0)?w.top-=k:i>0&&(j.y!=="bottom"||h>0)&&(w.top-=n?-k:k),w.top!==a&&n&&(w.top-=m.y),w.top<0&&-w.top>i&&(w.top=a));return w.top-a}},D;if(a.isArray(f)&&f.length===2)l={x:"left",y:"top"},w={left:f[0],top:f[1]};else if(f==="mouse"&&(c&&c.pageX||H.event.pageX))l={x:"left",y:"top"},c=(c&&(c.type==="resize"||c.type==="scroll")?H.event:c&&c.pageX&&c.type==="mousemove"?c:i&&i.pageX&&(m.mouse||!c||!c.pageX)?{pageX:i.pageX,pageY:i.pageY}:!m.mouse&&H.origin&&H.origin.pageX?H.origin:c)||c||H.event||i||{},w={top:c.pageY,left:c.pageX};else{f==="event"?c&&c.target&&c.type!=="scroll"&&c.type!=="resize"?f=H.target=a(c.target):f=H.target:H.target=a(f),f=a(f).eq(0);if(f.length===0)return z;f[0]===document||f[0]===b?(q=h.iOS?b.innerWidth:f.width(),r=h.iOS?b.innerHeight:f.height(),f[0]===b&&(w={top:!u||h.iOS?(v||f).scrollTop():0,left:!u||h.iOS?(v||f).scrollLeft():0})):f.is("area")&&h.imagemap?w=h.imagemap(f,l,B.enabled?n:e):f[0].namespaceURI==="http://www.w3.org/2000/svg"&&h.svg?w=h.svg(f,l):(q=f.outerWidth(),r=f.outerHeight(),w=h.offset(f,g.container)),w.offset&&(q=w.width,r=w.height,x=w.flipoffset,w=w.offset);if(h.iOS<4.1&&h.iOS>3.1||h.iOS==4.3||!h.iOS&&u)D=a(b),w.left-=D.scrollLeft(),w.top-=D.scrollTop();w.left+=l.x==="right"?q:l.x==="center"?q/2:0,w.top+=l.y==="bottom"?r:l.y==="center"?r/2:0}w.left+=m.x+(j.x==="right"?-o:j.x==="center"?-o/2:0),w.top+=m.y+(j.y==="bottom"?-p:j.y==="center"?-p/2:0),B.enabled?(v={elem:v,height:v[(v[0]===b?"h":"outerH")+"eight"](),width:v[(v[0]===b?"w":"outerW")+"idth"](),scrollLeft:u?0:v.scrollLeft(),scrollTop:u?0:v.scrollTop(),offset:v.offset()||{left:0,top:0}},w.adjusted={left:B.horizontal!=="none"?B.left(w.left):0,top:B.vertical!=="none"?B.top(w.top):0},w.adjusted.left+w.adjusted.top&&E.attr("class",function(a,b){return b.replace(/ui-tooltip-pos-\w+/i,k+"-pos-"+j.abbreviation())}),x&&w.adjusted.left&&(w.left+=x.left),x&&w.adjusted.top&&(w.top+=x.top)):w.adjusted={left:0,top:0},s.originalEvent=a.extend({},c),E.trigger(s,[z,w,v.elem||v]);if(s.isDefaultPrevented())return z;delete w.adjusted,d===e||isNaN(w.left)||isNaN(w.top)||f==="mouse"||!a.isFunction(g.effect)?E.css(w):a.isFunction(g.effect)&&(g.effect.call(E,z,a.extend({},w)),E.queue(function(b){a(this).css({opacity:"",height:""}),a.browser.msie&&this.style.removeAttribute("filter"),b()})),C=0;return z},redraw:function(){if(z.rendered<1||D)return z;var a=t.position.container,b,c,d,e;D=1,t.style.height&&E.css("height",t.style.height),t.style.width?E.css("width",t.style.width):(E.css("width","").addClass(r),c=E.width()+1,d=E.css("max-width")||"",e=E.css("min-width")||"",b=(d+e).indexOf("%")>-1?a.width()/100:0,d=(d.indexOf("%")>-1?b:1)*parseInt(d,10)||c,e=(e.indexOf("%")>-1?b:1)*parseInt(e,10)||0,c=d+e?Math.min(Math.max(c,e),d):c,E.css("width",Math.round(c)).removeClass(r)),D=0;return z},disable:function(b){"boolean"!==typeof b&&(b=!E.hasClass(m)&&!H.disabled),z.rendered?(E.toggleClass(m,b),a.attr(E[0],"aria-disabled",b)):H.disabled=!!b;return z},enable:function(){return z.disable(e)},destroy:function(){var b=s[0],c=a.attr(b,u),d=s.data("qtip");z.rendered&&(E.remove(),a.each(z.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(z.timers.show),clearTimeout(z.timers.hide),R();if(!d||z===d)a.removeData(b,"qtip"),t.suppress&&c&&(a.attr(b,"title",c),s.removeAttr(u)),s.removeAttr("aria-describedby");s.unbind(".qtip-"+w),delete j[z.id];return s}})}function x(b){var c;if(!b||"object"!==typeof b)return e;"object"!==typeof b.metadata&&(b.metadata={type:b.metadata});if("content"in b){if("object"!==typeof b.content||b.content.jquery)b.content={text:b.content};c=b.content.text||e,!a.isFunction(c)&&(!c&&!c.attr||c.length<1||"object"===typeof c&&!c.jquery)&&(b.content.text=e),"title"in b.content&&("object"!==typeof b.content.title&&(b.content.title={text:b.content.title}),c=b.content.title.text||e,!a.isFunction(c)&&(!c&&!c.attr||c.length<1||"object"===typeof c&&!c.jquery)&&(b.content.title.text=e))}"position"in b&&("object"!==typeof b.position&&(b.position={my:b.position,at:b.position})),"show"in b&&("object"!==typeof b.show&&(b.show.jquery?b.show={target:b.show}:b.show={event:b.show})),"hide"in b&&("object"!==typeof b.hide&&(b.hide.jquery?b.hide={target:b.hide}:b.hide={event:b.hide})),"style"in b&&("object"!==typeof b.style&&(b.style={classes:b.style})),a.each(h,function(){this.sanitize&&this.sanitize(b)});return b}function w(){w.history=w.history||[],w.history.push(arguments);if("object"===typeof console){var a=console[console.warn?"warn":"log"],b=Array.prototype.slice.call(arguments),c;typeof arguments[0]==="string"&&(b[0]="qTip2: "+b[0]),c=a.apply?a.apply(console,b):a(b)}}"use strict";var d=!0,e=!1,f=null,g,h,i,j={},k="ui-tooltip",l="ui-widget",m="ui-state-disabled",n="div.qtip."+k,o=k+"-default",p=k+"-focus",q=k+"-hover",r=k+"-fluid",s="-31000px",t="_replacedByqTip",u="oldtitle",v;g=a.fn.qtip=function(b,h,i){var j=(""+b).toLowerCase(),k=f,l=j==="disable"?[d]:a.makeArray(arguments).slice(1),m=l[l.length-1],n=this[0]?a.data(this[0],"qtip"):f;if(!arguments.length&&n||j==="api")return n;if("string"===typeof b){this.each(function(){var b=a.data(this,"qtip");if(!b)return d;m&&m.timeStamp&&(b.cache.event=m);if(j!=="option"&&j!=="options"||!h)b[j]&&b[j].apply(b[j],l);else if(a.isPlainObject(h)||i!==c)b.set(h,i);else{k=b.get(h);return e}});return k!==f?k:this}if("object"===typeof b||!arguments.length){n=x(a.extend(d,{},b));return g.bind.call(this,n,m)}},g.bind=function(b,f){return this.each(function(k){function r(b){function d(){p.render(typeof b==="object"||l.show.ready),m.show.add(m.hide).unbind(o)}if(p.cache.disabled)return e;p.cache.event=a.extend({},b),p.cache.target=b?a(b.target):[c],l.show.delay>0?(clearTimeout(p.timers.show),p.timers.show=setTimeout(d,l.show.delay),n.show!==n.hide&&m.hide.bind(n.hide,function(){clearTimeout(p.timers.show)})):d()}var l,m,n,o,p,q;q=a.isArray(b.id)?b.id[k]:b.id,q=!q||q===e||q.length<1||j[q]?g.nextid++:j[q]=q,o=".qtip-"+q+"-create",p=z.call(this,q,b);if(p===e)return d;l=p.options,a.each(h,function(){this.initialize==="initialize"&&this(p)}),m={show:l.show.target,hide:l.hide.target},n={show:a.trim(""+l.show.event).replace(/ /g,o+" ")+o,hide:a.trim(""+l.hide.event).replace(/ /g,o+" ")+o},/mouse(over|enter)/i.test(n.show)&&!/mouse(out|leave)/i.test(n.hide)&&(n.hide+=" mouseleave"+o),m.show.bind("mousemove"+o,function(a){i={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),m.show.bind(n.show,r),(l.show.ready||l.prerender)&&r(f)})},h=g.plugins={Corner:function(a){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,"center").toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.precedance=a.charAt(0).search(/^(t|b)/)>-1?"y":"x",this.string=function(){return this.precedance==="y"?this.y+this.x:this.x+this.y},this.abbreviation=function(){var a=this.x.substr(0,1),b=this.y.substr(0,1);return a===b?a:a==="c"||a!=="c"&&b!=="c"?b+a:a+b}},offset:function(a,b){function i(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}var c=a.offset(),d=b,e=0,f=document.body,g,h;if(d){do{d.css("position")!=="static"&&(g=d[0]===f?{left:parseInt(d.css("left"),10)||0,top:parseInt(d.css("top"),10)||0}:d.position(),c.left-=g.left+(parseInt(d.css("borderLeftWidth"),10)||0)+(parseInt(d.css("marginLeft"),10)||0),c.top-=g.top+(parseInt(d.css("borderTopWidth"),10)||0),h=d.css("overflow"),(h==="scroll"||h==="auto")&&++e);if(d[0]===f)break}while(d=d.offsetParent());b[0]!==f&&e&&i(b,1)}return c},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_","."))||e,fn:{attr:function(b,c){if(this.length){var d=this[0],e="title",f=a.data(d,"qtip");if(b===e&&f&&"object"===typeof f&&f.options.suppress){if(arguments.length<2)return a.attr(d,u);f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",c);return this.attr(u,c)}}return a.fn["attr"+t].apply(this,arguments)},clone:function(b){var c=a([]),d="title",e=a.fn["clone"+t].apply(this,arguments);b||e.filter("["+u+"]").attr("title",function(){return a.attr(this,u)}).removeAttr(u);return e},remove:a.ui?f:function(b,c){a(this).each(function(){c||(!b||a.filter(b,[this]).length)&&a("*",this).add(this).each(function(){a(this).triggerHandler("remove")})})}}},a.each(h.fn,function(b,c){if(!c||a.fn[b+t])return d;var e=a.fn[b+t]=a.fn[b];a.fn[b]=function(){return c.apply(this,arguments)||e.apply(this,arguments)}}),g.version="nightly",g.nextid=0,g.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),g.zindex=15e3,g.defaults={prerender:e,id:e,overwrite:d,suppress:d,content:{text:d,attr:"title",title:{text:e,button:e}},position:{my:"top left",at:"bottom right",target:e,container:e,viewport:e,adjust:{x:0,y:0,mouse:d,resize:d,method:"flip flip"},effect:function(b,c,d){a(this).animate(c,{duration:200,queue:e})}},show:{target:e,event:"mouseenter",effect:d,delay:90,solo:e,ready:e,autofocus:e},hide:{target:e,event:"mouseleave",effect:d,delay:0,fixed:e,inactive:e,leave:"window",distance:e},style:{classes:"",widget:e,width:e,height:e},events:{render:f,move:f,show:f,hide:f,toggle:f,visible:f,focus:f,blur:f}},h.tip=function(a){var b=a.plugins.tip;return"object"===typeof b?b:a.plugins.tip=new B(a)},h.tip.initialize="render",h.tip.sanitize=function(a){var b=a.style,c;b&&"tip"in b&&(c=a.style.tip,typeof c!=="object"&&(a.style.tip={corner:c}),/string|boolean/i.test(typeof c.corner)||(c.corner=d),typeof c.width!=="number"&&delete c.width,typeof c.height!=="number"&&delete c.height,typeof c.border!=="number"&&c.border!==d&&delete c.border,typeof c.offset!=="number"&&delete c.offset)},a.extend(d,g.defaults,{style:{tip:{corner:d,mimic:e,width:6,height:6,border:d,offset:0}}}),h.svg=function(b,c){var d=a(document),e=b[0],f={width:0,height:0,offset:{top:1e10,left:1e10}},g,h,i,j,k;if(e.getBBox&&e.parentNode){g=e.getBBox(),h=e.getScreenCTM(),i=e.farthestViewportElement||e;if(!i.createSVGPoint)return f;j=i.createSVGPoint(),j.x=g.x,j.y=g.y,k=j.matrixTransform(h),f.offset.left=k.x,f.offset.top=k.y,j.x+=g.width,j.y+=g.height,k=j.matrixTransform(h),f.width=k.x-f.offset.left,f.height=k.y-f.offset.top,f.offset.left+=d.scrollLeft(),f.offset.top+=d.scrollTop()}return f}})(jQuery,window)
|
license.txt
ADDED
@@ -0,0 +1,339 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
GNU GENERAL PUBLIC LICENSE
|
2 |
+
Version 2, June 1991
|
3 |
+
|
4 |
+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
5 |
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
6 |
+
Everyone is permitted to copy and distribute verbatim copies
|
7 |
+
of this license document, but changing it is not allowed.
|
8 |
+
|
9 |
+
Preamble
|
10 |
+
|
11 |
+
The licenses for most software are designed to take away your
|
12 |
+
freedom to share and change it. By contrast, the GNU General Public
|
13 |
+
License is intended to guarantee your freedom to share and change free
|
14 |
+
software--to make sure the software is free for all its users. This
|
15 |
+
General Public License applies to most of the Free Software
|
16 |
+
Foundation's software and to any other program whose authors commit to
|
17 |
+
using it. (Some other Free Software Foundation software is covered by
|
18 |
+
the GNU Lesser General Public License instead.) You can apply it to
|
19 |
+
your programs, too.
|
20 |
+
|
21 |
+
When we speak of free software, we are referring to freedom, not
|
22 |
+
price. Our General Public Licenses are designed to make sure that you
|
23 |
+
have the freedom to distribute copies of free software (and charge for
|
24 |
+
this service if you wish), that you receive source code or can get it
|
25 |
+
if you want it, that you can change the software or use pieces of it
|
26 |
+
in new free programs; and that you know you can do these things.
|
27 |
+
|
28 |
+
To protect your rights, we need to make restrictions that forbid
|
29 |
+
anyone to deny you these rights or to ask you to surrender the rights.
|
30 |
+
These restrictions translate to certain responsibilities for you if you
|
31 |
+
distribute copies of the software, or if you modify it.
|
32 |
+
|
33 |
+
For example, if you distribute copies of such a program, whether
|
34 |
+
gratis or for a fee, you must give the recipients all the rights that
|
35 |
+
you have. You must make sure that they, too, receive or can get the
|
36 |
+
source code. And you must show them these terms so they know their
|
37 |
+
rights.
|
38 |
+
|
39 |
+
We protect your rights with two steps: (1) copyright the software, and
|
40 |
+
(2) offer you this license which gives you legal permission to copy,
|
41 |
+
distribute and/or modify the software.
|
42 |
+
|
43 |
+
Also, for each author's protection and ours, we want to make certain
|
44 |
+
that everyone understands that there is no warranty for this free
|
45 |
+
software. If the software is modified by someone else and passed on, we
|
46 |
+
want its recipients to know that what they have is not the original, so
|
47 |
+
that any problems introduced by others will not reflect on the original
|
48 |
+
authors' reputations.
|
49 |
+
|
50 |
+
Finally, any free program is threatened constantly by software
|
51 |
+
patents. We wish to avoid the danger that redistributors of a free
|
52 |
+
program will individually obtain patent licenses, in effect making the
|
53 |
+
program proprietary. To prevent this, we have made it clear that any
|
54 |
+
patent must be licensed for everyone's free use or not licensed at all.
|
55 |
+
|
56 |
+
The precise terms and conditions for copying, distribution and
|
57 |
+
modification follow.
|
58 |
+
|
59 |
+
GNU GENERAL PUBLIC LICENSE
|
60 |
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
61 |
+
|
62 |
+
0. This License applies to any program or other work which contains
|
63 |
+
a notice placed by the copyright holder saying it may be distributed
|
64 |
+
under the terms of this General Public License. The "Program", below,
|
65 |
+
refers to any such program or work, and a "work based on the Program"
|
66 |
+
means either the Program or any derivative work under copyright law:
|
67 |
+
that is to say, a work containing the Program or a portion of it,
|
68 |
+
either verbatim or with modifications and/or translated into another
|
69 |
+
language. (Hereinafter, translation is included without limitation in
|
70 |
+
the term "modification".) Each licensee is addressed as "you".
|
71 |
+
|
72 |
+
Activities other than copying, distribution and modification are not
|
73 |
+
covered by this License; they are outside its scope. The act of
|
74 |
+
running the Program is not restricted, and the output from the Program
|
75 |
+
is covered only if its contents constitute a work based on the
|
76 |
+
Program (independent of having been made by running the Program).
|
77 |
+
Whether that is true depends on what the Program does.
|
78 |
+
|
79 |
+
1. You may copy and distribute verbatim copies of the Program's
|
80 |
+
source code as you receive it, in any medium, provided that you
|
81 |
+
conspicuously and appropriately publish on each copy an appropriate
|
82 |
+
copyright notice and disclaimer of warranty; keep intact all the
|
83 |
+
notices that refer to this License and to the absence of any warranty;
|
84 |
+
and give any other recipients of the Program a copy of this License
|
85 |
+
along with the Program.
|
86 |
+
|
87 |
+
You may charge a fee for the physical act of transferring a copy, and
|
88 |
+
you may at your option offer warranty protection in exchange for a fee.
|
89 |
+
|
90 |
+
2. You may modify your copy or copies of the Program or any portion
|
91 |
+
of it, thus forming a work based on the Program, and copy and
|
92 |
+
distribute such modifications or work under the terms of Section 1
|
93 |
+
above, provided that you also meet all of these conditions:
|
94 |
+
|
95 |
+
a) You must cause the modified files to carry prominent notices
|
96 |
+
stating that you changed the files and the date of any change.
|
97 |
+
|
98 |
+
b) You must cause any work that you distribute or publish, that in
|
99 |
+
whole or in part contains or is derived from the Program or any
|
100 |
+
part thereof, to be licensed as a whole at no charge to all third
|
101 |
+
parties under the terms of this License.
|
102 |
+
|
103 |
+
c) If the modified program normally reads commands interactively
|
104 |
+
when run, you must cause it, when started running for such
|
105 |
+
interactive use in the most ordinary way, to print or display an
|
106 |
+
announcement including an appropriate copyright notice and a
|
107 |
+
notice that there is no warranty (or else, saying that you provide
|
108 |
+
a warranty) and that users may redistribute the program under
|
109 |
+
these conditions, and telling the user how to view a copy of this
|
110 |
+
License. (Exception: if the Program itself is interactive but
|
111 |
+
does not normally print such an announcement, your work based on
|
112 |
+
the Program is not required to print an announcement.)
|
113 |
+
|
114 |
+
These requirements apply to the modified work as a whole. If
|
115 |
+
identifiable sections of that work are not derived from the Program,
|
116 |
+
and can be reasonably considered independent and separate works in
|
117 |
+
themselves, then this License, and its terms, do not apply to those
|
118 |
+
sections when you distribute them as separate works. But when you
|
119 |
+
distribute the same sections as part of a whole which is a work based
|
120 |
+
on the Program, the distribution of the whole must be on the terms of
|
121 |
+
this License, whose permissions for other licensees extend to the
|
122 |
+
entire whole, and thus to each and every part regardless of who wrote it.
|
123 |
+
|
124 |
+
Thus, it is not the intent of this section to claim rights or contest
|
125 |
+
your rights to work written entirely by you; rather, the intent is to
|
126 |
+
exercise the right to control the distribution of derivative or
|
127 |
+
collective works based on the Program.
|
128 |
+
|
129 |
+
In addition, mere aggregation of another work not based on the Program
|
130 |
+
with the Program (or with a work based on the Program) on a volume of
|
131 |
+
a storage or distribution medium does not bring the other work under
|
132 |
+
the scope of this License.
|
133 |
+
|
134 |
+
3. You may copy and distribute the Program (or a work based on it,
|
135 |
+
under Section 2) in object code or executable form under the terms of
|
136 |
+
Sections 1 and 2 above provided that you also do one of the following:
|
137 |
+
|
138 |
+
a) Accompany it with the complete corresponding machine-readable
|
139 |
+
source code, which must be distributed under the terms of Sections
|
140 |
+
1 and 2 above on a medium customarily used for software interchange; or,
|
141 |
+
|
142 |
+
b) Accompany it with a written offer, valid for at least three
|
143 |
+
years, to give any third party, for a charge no more than your
|
144 |
+
cost of physically performing source distribution, a complete
|
145 |
+
machine-readable copy of the corresponding source code, to be
|
146 |
+
distributed under the terms of Sections 1 and 2 above on a medium
|
147 |
+
customarily used for software interchange; or,
|
148 |
+
|
149 |
+
c) Accompany it with the information you received as to the offer
|
150 |
+
to distribute corresponding source code. (This alternative is
|
151 |
+
allowed only for noncommercial distribution and only if you
|
152 |
+
received the program in object code or executable form with such
|
153 |
+
an offer, in accord with Subsection b above.)
|
154 |
+
|
155 |
+
The source code for a work means the preferred form of the work for
|
156 |
+
making modifications to it. For an executable work, complete source
|
157 |
+
code means all the source code for all modules it contains, plus any
|
158 |
+
associated interface definition files, plus the scripts used to
|
159 |
+
control compilation and installation of the executable. However, as a
|
160 |
+
special exception, the source code distributed need not include
|
161 |
+
anything that is normally distributed (in either source or binary
|
162 |
+
form) with the major components (compiler, kernel, and so on) of the
|
163 |
+
operating system on which the executable runs, unless that component
|
164 |
+
itself accompanies the executable.
|
165 |
+
|
166 |
+
If distribution of executable or object code is made by offering
|
167 |
+
access to copy from a designated place, then offering equivalent
|
168 |
+
access to copy the source code from the same place counts as
|
169 |
+
distribution of the source code, even though third parties are not
|
170 |
+
compelled to copy the source along with the object code.
|
171 |
+
|
172 |
+
4. You may not copy, modify, sublicense, or distribute the Program
|
173 |
+
except as expressly provided under this License. Any attempt
|
174 |
+
otherwise to copy, modify, sublicense or distribute the Program is
|
175 |
+
void, and will automatically terminate your rights under this License.
|
176 |
+
However, parties who have received copies, or rights, from you under
|
177 |
+
this License will not have their licenses terminated so long as such
|
178 |
+
parties remain in full compliance.
|
179 |
+
|
180 |
+
5. You are not required to accept this License, since you have not
|
181 |
+
signed it. However, nothing else grants you permission to modify or
|
182 |
+
distribute the Program or its derivative works. These actions are
|
183 |
+
prohibited by law if you do not accept this License. Therefore, by
|
184 |
+
modifying or distributing the Program (or any work based on the
|
185 |
+
Program), you indicate your acceptance of this License to do so, and
|
186 |
+
all its terms and conditions for copying, distributing or modifying
|
187 |
+
the Program or works based on it.
|
188 |
+
|
189 |
+
6. Each time you redistribute the Program (or any work based on the
|
190 |
+
Program), the recipient automatically receives a license from the
|
191 |
+
original licensor to copy, distribute or modify the Program subject to
|
192 |
+
these terms and conditions. You may not impose any further
|
193 |
+
restrictions on the recipients' exercise of the rights granted herein.
|
194 |
+
You are not responsible for enforcing compliance by third parties to
|
195 |
+
this License.
|
196 |
+
|
197 |
+
7. If, as a consequence of a court judgment or allegation of patent
|
198 |
+
infringement or for any other reason (not limited to patent issues),
|
199 |
+
conditions are imposed on you (whether by court order, agreement or
|
200 |
+
otherwise) that contradict the conditions of this License, they do not
|
201 |
+
excuse you from the conditions of this License. If you cannot
|
202 |
+
distribute so as to satisfy simultaneously your obligations under this
|
203 |
+
License and any other pertinent obligations, then as a consequence you
|
204 |
+
may not distribute the Program at all. For example, if a patent
|
205 |
+
license would not permit royalty-free redistribution of the Program by
|
206 |
+
all those who receive copies directly or indirectly through you, then
|
207 |
+
the only way you could satisfy both it and this License would be to
|
208 |
+
refrain entirely from distribution of the Program.
|
209 |
+
|
210 |
+
If any portion of this section is held invalid or unenforceable under
|
211 |
+
any particular circumstance, the balance of the section is intended to
|
212 |
+
apply and the section as a whole is intended to apply in other
|
213 |
+
circumstances.
|
214 |
+
|
215 |
+
It is not the purpose of this section to induce you to infringe any
|
216 |
+
patents or other property right claims or to contest validity of any
|
217 |
+
such claims; this section has the sole purpose of protecting the
|
218 |
+
integrity of the free software distribution system, which is
|
219 |
+
implemented by public license practices. Many people have made
|
220 |
+
generous contributions to the wide range of software distributed
|
221 |
+
through that system in reliance on consistent application of that
|
222 |
+
system; it is up to the author/donor to decide if he or she is willing
|
223 |
+
to distribute software through any other system and a licensee cannot
|
224 |
+
impose that choice.
|
225 |
+
|
226 |
+
This section is intended to make thoroughly clear what is believed to
|
227 |
+
be a consequence of the rest of this License.
|
228 |
+
|
229 |
+
8. If the distribution and/or use of the Program is restricted in
|
230 |
+
certain countries either by patents or by copyrighted interfaces, the
|
231 |
+
original copyright holder who places the Program under this License
|
232 |
+
may add an explicit geographical distribution limitation excluding
|
233 |
+
those countries, so that distribution is permitted only in or among
|
234 |
+
countries not thus excluded. In such case, this License incorporates
|
235 |
+
the limitation as if written in the body of this License.
|
236 |
+
|
237 |
+
9. The Free Software Foundation may publish revised and/or new versions
|
238 |
+
of the General Public License from time to time. Such new versions will
|
239 |
+
be similar in spirit to the present version, but may differ in detail to
|
240 |
+
address new problems or concerns.
|
241 |
+
|
242 |
+
Each version is given a distinguishing version number. If the Program
|
243 |
+
specifies a version number of this License which applies to it and "any
|
244 |
+
later version", you have the option of following the terms and conditions
|
245 |
+
either of that version or of any later version published by the Free
|
246 |
+
Software Foundation. If the Program does not specify a version number of
|
247 |
+
this License, you may choose any version ever published by the Free Software
|
248 |
+
Foundation.
|
249 |
+
|
250 |
+
10. If you wish to incorporate parts of the Program into other free
|
251 |
+
programs whose distribution conditions are different, write to the author
|
252 |
+
to ask for permission. For software which is copyrighted by the Free
|
253 |
+
Software Foundation, write to the Free Software Foundation; we sometimes
|
254 |
+
make exceptions for this. Our decision will be guided by the two goals
|
255 |
+
of preserving the free status of all derivatives of our free software and
|
256 |
+
of promoting the sharing and reuse of software generally.
|
257 |
+
|
258 |
+
NO WARRANTY
|
259 |
+
|
260 |
+
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261 |
+
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
262 |
+
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
263 |
+
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
264 |
+
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
265 |
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
266 |
+
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
267 |
+
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
268 |
+
REPAIR OR CORRECTION.
|
269 |
+
|
270 |
+
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
271 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
272 |
+
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
273 |
+
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
274 |
+
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
275 |
+
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
276 |
+
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
277 |
+
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278 |
+
POSSIBILITY OF SUCH DAMAGES.
|
279 |
+
|
280 |
+
END OF TERMS AND CONDITIONS
|
281 |
+
|
282 |
+
How to Apply These Terms to Your New Programs
|
283 |
+
|
284 |
+
If you develop a new program, and you want it to be of the greatest
|
285 |
+
possible use to the public, the best way to achieve this is to make it
|
286 |
+
free software which everyone can redistribute and change under these terms.
|
287 |
+
|
288 |
+
To do so, attach the following notices to the program. It is safest
|
289 |
+
to attach them to the start of each source file to most effectively
|
290 |
+
convey the exclusion of warranty; and each file should have at least
|
291 |
+
the "copyright" line and a pointer to where the full notice is found.
|
292 |
+
|
293 |
+
<one line to give the program's name and a brief idea of what it does.>
|
294 |
+
Copyright (C) <year> <name of author>
|
295 |
+
|
296 |
+
This program is free software; you can redistribute it and/or modify
|
297 |
+
it under the terms of the GNU General Public License as published by
|
298 |
+
the Free Software Foundation; either version 2 of the License, or
|
299 |
+
(at your option) any later version.
|
300 |
+
|
301 |
+
This program is distributed in the hope that it will be useful,
|
302 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
303 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
304 |
+
GNU General Public License for more details.
|
305 |
+
|
306 |
+
You should have received a copy of the GNU General Public License along
|
307 |
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
308 |
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
309 |
+
|
310 |
+
Also add information on how to contact you by electronic and paper mail.
|
311 |
+
|
312 |
+
If the program is interactive, make it output a short notice like this
|
313 |
+
when it starts in an interactive mode:
|
314 |
+
|
315 |
+
Gnomovision version 69, Copyright (C) year name of author
|
316 |
+
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
317 |
+
This is free software, and you are welcome to redistribute it
|
318 |
+
under certain conditions; type `show c' for details.
|
319 |
+
|
320 |
+
The hypothetical commands `show w' and `show c' should show the appropriate
|
321 |
+
parts of the General Public License. Of course, the commands you use may
|
322 |
+
be called something other than `show w' and `show c'; they could even be
|
323 |
+
mouse-clicks or menu items--whatever suits your program.
|
324 |
+
|
325 |
+
You should also get your employer (if you work as a programmer) or your
|
326 |
+
school, if any, to sign a "copyright disclaimer" for the program, if
|
327 |
+
necessary. Here is a sample; alter the names:
|
328 |
+
|
329 |
+
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
330 |
+
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
331 |
+
|
332 |
+
<signature of Ty Coon>, 1 April 1989
|
333 |
+
Ty Coon, President of Vice
|
334 |
+
|
335 |
+
This General Public License does not permit incorporating your program into
|
336 |
+
proprietary programs. If your program is a subroutine library, you may
|
337 |
+
consider it more useful to permit linking proprietary applications with the
|
338 |
+
library. If this is what you want to do, use the GNU Lesser General
|
339 |
+
Public License instead of this License.
|
logo.gif
ADDED
Binary file
|
p3-profiler.php
ADDED
@@ -0,0 +1,798 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: P3 (Plugin Performance Profiler)
|
4 |
+
Plugin URI: http://support.godaddy.com/godaddy/wordpress-p3-plugin/
|
5 |
+
Description: See which plugins are slowing down your site. Create a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.
|
6 |
+
Author: GoDaddy.com
|
7 |
+
Version: 1.0
|
8 |
+
Author URI: http://www.godaddy.com/
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**************************************************************************/
|
12 |
+
/** PACKAGE CONSTANTS **/
|
13 |
+
/**************************************************************************/
|
14 |
+
|
15 |
+
// Shortcut for knowing our path
|
16 |
+
define( 'P3_PATH', realpath( dirname( __FILE__ ) ) );
|
17 |
+
|
18 |
+
// Flag file for enabling profile mode
|
19 |
+
define( 'P3_FLAG_FILE', P3_PATH . DIRECTORY_SEPARATOR . '.profiling_enabled' );
|
20 |
+
|
21 |
+
// Directory for profiles
|
22 |
+
$uploads_dir = wp_upload_dir();
|
23 |
+
define( 'P3_PROFILES_PATH', $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' );
|
24 |
+
|
25 |
+
|
26 |
+
/**************************************************************************/
|
27 |
+
/** START PROFILING **/
|
28 |
+
/**************************************************************************/
|
29 |
+
|
30 |
+
// Start profiling. If it's already been started, this line won't do anything
|
31 |
+
require_once P3_PATH . '/start-profile.php';
|
32 |
+
|
33 |
+
|
34 |
+
/**************************************************************************/
|
35 |
+
/** PLUGIN HOOKS **/
|
36 |
+
/**************************************************************************/
|
37 |
+
|
38 |
+
// Global plugin object
|
39 |
+
$p3_profiler_plugin = new P3_Profiler_Plugin();
|
40 |
+
|
41 |
+
// Admin hooks
|
42 |
+
if ( is_admin() ) {
|
43 |
+
// Show the 'Profiler' option under the 'Plugins' menu
|
44 |
+
add_action( 'admin_menu', array( $p3_profiler_plugin, 'settings_menu' ) );
|
45 |
+
|
46 |
+
// Ajax actions
|
47 |
+
add_action( 'wp_ajax_p3_start_scan', array( $p3_profiler_plugin, 'ajax_start_scan' ) );
|
48 |
+
add_action( 'wp_ajax_p3_stop_scan', array( $p3_profiler_plugin, 'ajax_stop_scan' ) );
|
49 |
+
add_action( 'wp_ajax_p3_send_results', array( $p3_profiler_plugin, 'ajax_send_results' ) );
|
50 |
+
|
51 |
+
// Show any notices
|
52 |
+
add_action( 'admin_notices', array( $p3_profiler_plugin, 'show_notices' ) );
|
53 |
+
|
54 |
+
// Early init actions ( processing bulk table actions, loading libraries, etc.)
|
55 |
+
add_action( 'admin_head', array( $p3_profiler_plugin, 'early_init' ) );
|
56 |
+
}
|
57 |
+
|
58 |
+
// Remove the admin bar when in profiling mode
|
59 |
+
if ( defined( 'WPP_PROFILING_STARTED' ) || isset( $_GET['P3_HIDE_ADMIN_BAR'] ) ) {
|
60 |
+
add_action( 'plugins_loaded', array( $p3_profiler_plugin, 'remove_admin_bar' ) );
|
61 |
+
}
|
62 |
+
|
63 |
+
// Install / uninstall hooks
|
64 |
+
register_activation_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( $p3_profiler_plugin, 'activate' ) );
|
65 |
+
register_deactivation_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( $p3_profiler_plugin, 'deactivate' ) );
|
66 |
+
register_uninstall_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( 'P3_Profiler_Plugin', 'uninstall' ) );
|
67 |
+
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
|
68 |
+
add_action( 'wpmu_add_blog', array( $p3_profiler_plugin, 'sync_profiles_folder' ) );
|
69 |
+
add_action( 'wpmu_delete_blog', array( $p3_profiler_plugin, 'sync_profiles_folder' ) );
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* P3 Plugin Performance Profiler Plugin Controller
|
74 |
+
*
|
75 |
+
* @author GoDaddy.com
|
76 |
+
* @version 1.0
|
77 |
+
* @package P3_Profiler
|
78 |
+
*/
|
79 |
+
class P3_Profiler_Plugin {
|
80 |
+
|
81 |
+
/**
|
82 |
+
* List table of the profile scans
|
83 |
+
* @var P3_Profile_Table
|
84 |
+
*/
|
85 |
+
public $scan_table = null;
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Remove the admin bar from the customer site when profiling is enabled
|
89 |
+
* to prevent skewing the numbers, as much as possible. Also prevent ssl
|
90 |
+
* warnings by forcing content into ssl mode if the admin is in ssl mode
|
91 |
+
* @return void
|
92 |
+
*/
|
93 |
+
public function remove_admin_bar() {
|
94 |
+
if ( !is_admin() ) {
|
95 |
+
remove_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
|
96 |
+
if ( true === force_ssl_admin() ) {
|
97 |
+
add_filter( 'site_url', array( $this, '_fix_url' ) );
|
98 |
+
add_filter( 'admin_url', array( $this, '_fix_url' ) );
|
99 |
+
add_filter( 'post_link', array( $this, '_fix_url' ) );
|
100 |
+
add_filter( 'category_link', array( $this, '_fix_url' ) );
|
101 |
+
add_filter( 'get_archives_link', array( $this, '_fix_url' ) );
|
102 |
+
add_filter( 'tag_link', array( $this, '_fix_url' ) );
|
103 |
+
add_filter( 'home_url', array( $this, '_fix_url' ) );
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Replace http with https to avoid SSL warnings in the preview iframe if the admin is in SSL
|
110 |
+
* This will strip off any port numbers and will not replace URLs in off-site links
|
111 |
+
* @param string $url
|
112 |
+
* @return string
|
113 |
+
*/
|
114 |
+
public function _fix_url( $url ) {
|
115 |
+
static $host = '';
|
116 |
+
if ( empty( $host ) ) {
|
117 |
+
$host = preg_replace( '/[:\d+$]/', '', $_SERVER['HTTP_HOST'] );
|
118 |
+
}
|
119 |
+
return str_ireplace( 'http://' . $host, 'https://' . $host, $url );
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Add the 'Profiler' option under the 'Plugins' menu
|
124 |
+
* @return void
|
125 |
+
*/
|
126 |
+
public function settings_menu() {
|
127 |
+
if ( function_exists( 'add_submenu_page' ) ) {
|
128 |
+
$page = add_submenu_page(
|
129 |
+
'tools.php',
|
130 |
+
'P3 Plugin Profiler',
|
131 |
+
'P3 Plugin Profiler',
|
132 |
+
'manage_options',
|
133 |
+
basename( __FILE__ ),
|
134 |
+
array( $this, 'dispatcher' )
|
135 |
+
);
|
136 |
+
add_action( 'load-' . $page, array( $this, 'load_libraries' ) );
|
137 |
+
add_action( 'admin_print_scripts-' . $page, array( $this, 'load_scripts' ) );
|
138 |
+
add_action( 'admin_print_styles-' . $page, array( $this, 'load_styles' ) );
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Load the necessary resources
|
144 |
+
* @uses wp_enqueue_script
|
145 |
+
* @uses jquery, jquery-ui, jquery.corners
|
146 |
+
* @uses flot, flot.pie
|
147 |
+
* @return void
|
148 |
+
*/
|
149 |
+
public function load_libraries() {
|
150 |
+
|
151 |
+
// Load php libraries libraries
|
152 |
+
include_once P3_PATH . '/class.p3-profile-table-sorter.php';
|
153 |
+
include_once P3_PATH . '/class.p3-profile-table.php';
|
154 |
+
include_once P3_PATH . '/class.p3-profile-reader.php';
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Load javascripts
|
159 |
+
* @uses wp_enqueue_script
|
160 |
+
* @uses jquery, jquery-ui, jquery.corners
|
161 |
+
* @uses flot, flot.pie
|
162 |
+
* @return void
|
163 |
+
*/
|
164 |
+
public function load_scripts() {
|
165 |
+
wp_enqueue_script( 'jquery' );
|
166 |
+
wp_enqueue_script( 'jquery-ui-dialog' );
|
167 |
+
wp_enqueue_script( 'jquery-ui-tabs' );
|
168 |
+
wp_enqueue_script( 'jquery-ui-progressbar' );
|
169 |
+
wp_enqueue_script( 'flot', plugins_url() . '/p3-profiler/js/jquery.flot.min.js', array( 'jquery-ui-core' ) );
|
170 |
+
wp_enqueue_script( 'flot.pie', plugins_url() . '/p3-profiler/js/jquery.flot.pie.min.js', array( 'flot' ) );
|
171 |
+
wp_enqueue_script( 'flot.navigate', plugins_url() . '/p3-profiler/js/jquery.flot.navigate.js', array( 'flot' ) );
|
172 |
+
wp_enqueue_script( 'p3_corners', plugins_url() . '/p3-profiler/js/jquery.corner.js', array( 'jquery-ui-core' ) );
|
173 |
+
wp_enqueue_script( 'p3_qtip', plugins_url() . '/p3-profiler/js/jquery.qtip.min.js', array( 'jquery-ui-core' ) );
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Load styles
|
178 |
+
* @uses wp_enqueue_style
|
179 |
+
* @uses jquery-ui
|
180 |
+
* @return void
|
181 |
+
*/
|
182 |
+
public function load_styles() {
|
183 |
+
wp_enqueue_style( 'p3_jquery_ui_css', plugins_url() . '/p3-profiler/css/custom-theme/jquery-ui-1.8.16.custom.css' );
|
184 |
+
wp_enqueue_style( 'p3_qtip_css', plugins_url() . '/p3-profiler/css/jquery.qtip.min.css' );
|
185 |
+
wp_enqueue_style( 'p3_css', plugins_url() . '/p3-profiler/css/p3.css' );
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Load the necessary resources
|
190 |
+
* @uses wp_enqueue_script
|
191 |
+
* @uses jquery, jquery-ui, jquery.corners
|
192 |
+
* @uses flot, flot.pie
|
193 |
+
* @return void
|
194 |
+
*/
|
195 |
+
public function early_init() {
|
196 |
+
|
197 |
+
// Only for our page
|
198 |
+
if ( isset( $_REQUEST['page'] ) && basename( __FILE__ ) == $_REQUEST['page'] ) {
|
199 |
+
// Load the list table, let it handle any bulk actions
|
200 |
+
$this->scan_table = new P3_Profile_Table();
|
201 |
+
$this->scan_table->prepare_items();
|
202 |
+
|
203 |
+
// Usability message
|
204 |
+
if ( !defined( 'WPP_PROFILING_STARTED' ) ) {
|
205 |
+
$this->add_notice( 'Click "Start Scan" to run a performance scan of your website.' );
|
206 |
+
}
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Dispatcher function. All requests enter through here
|
212 |
+
* and are routed based upon the p3_action request variable
|
213 |
+
* @uses $_REQUEST['p3_action']
|
214 |
+
* @return void
|
215 |
+
*/
|
216 |
+
public function dispatcher() {
|
217 |
+
$p3_action = '';
|
218 |
+
if ( ! empty ( $_REQUEST ['p3_action'] ) ) {
|
219 |
+
$p3_action = $_REQUEST ['p3_action'];
|
220 |
+
}
|
221 |
+
switch ( $p3_action ) {
|
222 |
+
case 'list-scans' :
|
223 |
+
$this->list_scans();
|
224 |
+
break;
|
225 |
+
case 'view-scan' :
|
226 |
+
$this->view_scan();
|
227 |
+
break;
|
228 |
+
case 'start-scan' :
|
229 |
+
$this->start_scan();
|
230 |
+
break;
|
231 |
+
case 'fix-flag-file' :
|
232 |
+
$this->fix_flag_file();
|
233 |
+
break;
|
234 |
+
case 'help' :
|
235 |
+
$this->show_help();
|
236 |
+
break;
|
237 |
+
default :
|
238 |
+
$this->scan_settings_page();
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Write .profiling_enabled file, uses request_filesystem_credentials, if
|
244 |
+
* necessary, to create the file and make it writable
|
245 |
+
* @return void
|
246 |
+
*/
|
247 |
+
public function fix_flag_file() {
|
248 |
+
|
249 |
+
// Don't force a specific file system method
|
250 |
+
$method = '';
|
251 |
+
|
252 |
+
// Define any extra pass-thru fields (none)
|
253 |
+
$form_fields = array();
|
254 |
+
|
255 |
+
// Define the URL to post back to (this one)
|
256 |
+
$url = wp_nonce_url( add_query_arg( array( 'p3_action' => 'fix-flag-file' ) ), 'p3-fix-flag-file' );
|
257 |
+
|
258 |
+
// Ask for credentials, if necessary
|
259 |
+
if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, $form_fields ) ) ) {
|
260 |
+
return true;
|
261 |
+
} elseif ( ! WP_Filesystem($creds) ) {
|
262 |
+
// The credentials are bad, ask again
|
263 |
+
request_filesystem_credentials( $url, $method, true, false, $form_fields );
|
264 |
+
return true;
|
265 |
+
} else {
|
266 |
+
// Once we get here, we should have credentials, do the file system operations
|
267 |
+
global $wp_filesystem;
|
268 |
+
if ( $wp_filesystem->put_contents( $wp_filesystem->wp_plugins_dir() . '/p3-profiler/.profiling_enabled' , '[]', FS_CHMOD_FILE | 0222) ) {
|
269 |
+
include_once P3_PATH . '/templates/template.php';
|
270 |
+
} else {
|
271 |
+
wp_die( 'Error saving file!' );
|
272 |
+
}
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Get a list of pages for the auto-scanner
|
278 |
+
* @return array
|
279 |
+
*/
|
280 |
+
public function list_of_pages() {
|
281 |
+
|
282 |
+
// Start off the scan with the home page
|
283 |
+
$pages = array( get_home_url() ); // Home page
|
284 |
+
|
285 |
+
// Get the default RSS feed
|
286 |
+
$pages[] = get_feed_link();
|
287 |
+
|
288 |
+
// Search for 'e'
|
289 |
+
$pages[] = home_url( '?s=e' );
|
290 |
+
|
291 |
+
// Get the latest 10 posts
|
292 |
+
$tmp = preg_split( '/\s+/', wp_get_archives( 'type=postbypost&limit=10&echo=0' ) );
|
293 |
+
if ( !empty( $tmp ) ) {
|
294 |
+
foreach ( $tmp as $page ) {
|
295 |
+
if ( preg_match( "/href='([^']+)'/", $page, $matches ) ) {
|
296 |
+
$pages[] = $matches[1];
|
297 |
+
}
|
298 |
+
}
|
299 |
+
}
|
300 |
+
|
301 |
+
// Fix SSL
|
302 |
+
if ( true === force_ssl_admin() ) {
|
303 |
+
foreach ( $pages as $k => $v ) {
|
304 |
+
$pages[$k] = str_replace( 'http://', 'https://', $v );
|
305 |
+
}
|
306 |
+
}
|
307 |
+
|
308 |
+
// Done
|
309 |
+
return $pages;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**************************************************************/
|
313 |
+
/** AJAX FUNCTIONS **/
|
314 |
+
/**************************************************************/
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Start scan
|
318 |
+
* @return void
|
319 |
+
*/
|
320 |
+
public function ajax_start_scan() {
|
321 |
+
|
322 |
+
// Check nonce
|
323 |
+
if ( !wp_verify_nonce( $_POST ['p3_nonce'], 'p3_ajax_start_scan' ) ) {
|
324 |
+
wp_die( 'Invalid nonce' );
|
325 |
+
}
|
326 |
+
|
327 |
+
// Sanitize the file name
|
328 |
+
$filename = sanitize_file_name( basename( $_POST['p3_scan_name'] ) );
|
329 |
+
|
330 |
+
// Create flag file
|
331 |
+
if ( file_exists( P3_FLAG_FILE ) ) {
|
332 |
+
$json = json_decode( file_get_contents( P3_FLAG_FILE ) );
|
333 |
+
} else {
|
334 |
+
$json = array();
|
335 |
+
}
|
336 |
+
|
337 |
+
// Site url
|
338 |
+
$site_url = parse_url( get_home_url(), PHP_URL_PATH );
|
339 |
+
if ( null === $site_url ) {
|
340 |
+
$site_url = '/';
|
341 |
+
}
|
342 |
+
|
343 |
+
// Add the entry ( multisite installs can run more than one concurrent profile )
|
344 |
+
$json[] = array(
|
345 |
+
'ip' => $_POST['p3_ip'],
|
346 |
+
'disable_opcode_cache' => ( 'true' == $_POST['p3_disable_opcode_cache'] ),
|
347 |
+
'site_url' => $site_url,
|
348 |
+
'name' => $filename,
|
349 |
+
);
|
350 |
+
|
351 |
+
$flag1 = file_put_contents( P3_FLAG_FILE, json_encode( $json ) );
|
352 |
+
|
353 |
+
// Kick start the profile file
|
354 |
+
if ( !file_exists( P3_PROFILES_PATH . "/$filename.json" ) ) {
|
355 |
+
$flag2 = file_put_contents( P3_PROFILES_PATH . "/$filename.json", '' );
|
356 |
+
} else {
|
357 |
+
$flag2 = true;
|
358 |
+
}
|
359 |
+
|
360 |
+
// Check if either operation failed
|
361 |
+
if ( false === $flag1 & $flag2 ) {
|
362 |
+
wp_die( 0 );
|
363 |
+
} else {
|
364 |
+
echo 1;
|
365 |
+
die();
|
366 |
+
}
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Stop scan
|
371 |
+
* @return void
|
372 |
+
*/
|
373 |
+
public function ajax_stop_scan() {
|
374 |
+
|
375 |
+
// Check nonce
|
376 |
+
if ( !wp_verify_nonce( $_POST ['p3_nonce'], 'p3_ajax_stop_scan' ) ) {
|
377 |
+
wp_die( 'Invalid nonce' );
|
378 |
+
}
|
379 |
+
|
380 |
+
// If there's no file, return an error
|
381 |
+
if ( !file_exists( P3_FLAG_FILE ) ) {
|
382 |
+
wp_die( 0 );
|
383 |
+
}
|
384 |
+
|
385 |
+
// Get the file
|
386 |
+
$json = json_decode( file_get_contents( P3_FLAG_FILE ) );
|
387 |
+
|
388 |
+
// Stop all sites who match the current site's URL
|
389 |
+
$site_url = parse_url( get_home_url(), PHP_URL_PATH );
|
390 |
+
if ( null === $site_url ) {
|
391 |
+
$site_url = '/';
|
392 |
+
}
|
393 |
+
foreach ( (array) $json as $k => $v ) {
|
394 |
+
if ( $site_url == $v->site_url ) {
|
395 |
+
unset( $json[$k] );
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
// Rewrite the file
|
400 |
+
$flag = file_put_contents( P3_FLAG_FILE, json_encode( $json ) );
|
401 |
+
if ( !$flag ) {
|
402 |
+
wp_die( 0 );
|
403 |
+
}
|
404 |
+
|
405 |
+
// Tell the user what happened
|
406 |
+
$this->add_notice( 'Turned off performance scanning.' );
|
407 |
+
|
408 |
+
// Return the last filename
|
409 |
+
if ( property_exists( $v, 'name' ) ) {
|
410 |
+
echo $v->name . '.json';
|
411 |
+
die();
|
412 |
+
} else {
|
413 |
+
wp_die( 0 );
|
414 |
+
}
|
415 |
+
}
|
416 |
+
|
417 |
+
|
418 |
+
/**************************************************************/
|
419 |
+
/** EMAIL RESULTS **/
|
420 |
+
/**************************************************************/
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Send results ( presumably to admin or support )
|
424 |
+
* @return void
|
425 |
+
*/
|
426 |
+
public function ajax_send_results() {
|
427 |
+
|
428 |
+
// Check nonce
|
429 |
+
if ( !wp_verify_nonce( $_POST ['p3_nonce'], 'p3_ajax_send_results' ) ) {
|
430 |
+
wp_die( 'Invalid nonce' );
|
431 |
+
}
|
432 |
+
|
433 |
+
// Check fields
|
434 |
+
$to = sanitize_email( $_POST['p3_to'] );
|
435 |
+
$from = sanitize_email( $_POST['p3_from'] );
|
436 |
+
$subject = filter_var(
|
437 |
+
$_POST['p3_subject'], FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW
|
438 |
+
);
|
439 |
+
$message = strip_tags( $_POST['p3_message'] );
|
440 |
+
$results = strip_tags( $_POST['p3_results'] );
|
441 |
+
|
442 |
+
// Append the results to the message ( if a messge was specified )
|
443 |
+
if ( empty( $message ) ) {
|
444 |
+
$message = stripslashes( $results );
|
445 |
+
} else {
|
446 |
+
$message = stripslashes( $message . "\n\n" .$results );
|
447 |
+
}
|
448 |
+
|
449 |
+
// Check for errors and send message
|
450 |
+
if ( !is_email( $to ) || !is_email( $from ) ) {
|
451 |
+
echo '0|Invalid e-mail';
|
452 |
+
} elseif ( empty( $subject ) ) {
|
453 |
+
echo '0|Invalid subject';
|
454 |
+
} elseif ( false === wp_mail( $to, $subject, $message, "From: $from" ) ) {
|
455 |
+
echo '0|<a href="http://codex.wordpress.org/Function_Reference/wp_mail" target="_blank">wp_mail()</a> function returned false';
|
456 |
+
} else {
|
457 |
+
echo '1';
|
458 |
+
}
|
459 |
+
die();
|
460 |
+
}
|
461 |
+
|
462 |
+
|
463 |
+
/**************************************************************/
|
464 |
+
/** CURRENT PAGE **/
|
465 |
+
/**************************************************************/
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Show the settings page.
|
469 |
+
* This is where the user can start/stop the scan
|
470 |
+
*/
|
471 |
+
public function scan_settings_page() {
|
472 |
+
include_once P3_PATH . '/templates/template.php';
|
473 |
+
}
|
474 |
+
|
475 |
+
|
476 |
+
/**************************************************************/
|
477 |
+
/** HELP PAGE **/
|
478 |
+
/**************************************************************/
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Show the help page.
|
482 |
+
*/
|
483 |
+
public function show_help() {
|
484 |
+
include_once P3_PATH . '/templates/template.php';
|
485 |
+
}
|
486 |
+
|
487 |
+
|
488 |
+
/**************************************************************/
|
489 |
+
/** HISTORY PAGE **/
|
490 |
+
/**************************************************************/
|
491 |
+
|
492 |
+
/**
|
493 |
+
* View the results of a scan
|
494 |
+
* @uses $_REQUEST['name']
|
495 |
+
* @return void
|
496 |
+
*/
|
497 |
+
public function view_scan() {
|
498 |
+
include_once P3_PATH . '/templates/template.php';
|
499 |
+
}
|
500 |
+
|
501 |
+
/**
|
502 |
+
* Show a list of available scans.
|
503 |
+
* Uses WP List table to handle UI and sorting.
|
504 |
+
* Uses P3_Profile_Table to handle deleting
|
505 |
+
* @uses WP_List_Table
|
506 |
+
* @uses jquery
|
507 |
+
* @uses P3_Profile_Table
|
508 |
+
* @return void
|
509 |
+
*/
|
510 |
+
public function list_scans() {
|
511 |
+
include_once P3_PATH . '/templates/template.php';
|
512 |
+
}
|
513 |
+
|
514 |
+
/**
|
515 |
+
* Get the latest performance scan
|
516 |
+
* @return string|false
|
517 |
+
*/
|
518 |
+
public function get_latest_profile() {
|
519 |
+
|
520 |
+
// Open the directory
|
521 |
+
$dir = opendir( P3_PROFILES_PATH );
|
522 |
+
if ( false === $dir ) {
|
523 |
+
wp_die( 'Cannot read profiles directory' );
|
524 |
+
}
|
525 |
+
|
526 |
+
// Loop through the files, get the path and the last modified time
|
527 |
+
$files = array();
|
528 |
+
while ( false !== ( $file = readdir( $dir ) ) ) {
|
529 |
+
if ( '.json' == substr( $file, -5 ) ) {
|
530 |
+
$files[filemtime( P3_PROFILES_PATH . "/$file" )] = P3_PROFILES_PATH . "/$file";
|
531 |
+
}
|
532 |
+
}
|
533 |
+
closedir( $dir );
|
534 |
+
|
535 |
+
// If there are no files, return false
|
536 |
+
if ( empty( $files ) ) {
|
537 |
+
return false;
|
538 |
+
}
|
539 |
+
|
540 |
+
// Sort the files by the last modified time, return the latest
|
541 |
+
ksort( $files );
|
542 |
+
return array_pop( $files );
|
543 |
+
}
|
544 |
+
|
545 |
+
/**
|
546 |
+
* Add a notices
|
547 |
+
* @uses transients
|
548 |
+
* @param string $notice
|
549 |
+
* @return void
|
550 |
+
*/
|
551 |
+
public function add_notice( $notice ) {
|
552 |
+
|
553 |
+
// Get any notices on the stack
|
554 |
+
$notices = get_transient( 'p3_notices' );
|
555 |
+
if ( empty( $notices ) ) {
|
556 |
+
$notices = array();
|
557 |
+
}
|
558 |
+
|
559 |
+
// Add the notice to the stack
|
560 |
+
$notices[] = $notice;
|
561 |
+
|
562 |
+
// Save the stack
|
563 |
+
set_transient( 'p3_notices', $notices );
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* Display notices
|
568 |
+
* @uses transients
|
569 |
+
* @return voide
|
570 |
+
*/
|
571 |
+
public function show_notices() {
|
572 |
+
|
573 |
+
// Skip notices if we're fixing the flag file
|
574 |
+
if ( isset( $_REQUEST['p3_action'] ) && 'fix-flag-file' == $_REQUEST['p3_action'] ) {
|
575 |
+
return true;
|
576 |
+
}
|
577 |
+
|
578 |
+
$notices = get_transient( 'p3_notices' );
|
579 |
+
if ( !empty( $notices ) ) {
|
580 |
+
$notices = array_unique( $notices );
|
581 |
+
foreach ( $notices as $notice ) {
|
582 |
+
echo '<div class="updated"><p>' . htmlentities( $notice ) . '</p></div>';
|
583 |
+
}
|
584 |
+
}
|
585 |
+
set_transient( 'p3_notices', array() );
|
586 |
+
if ( false !== $this->scan_enabled() ) {
|
587 |
+
echo '<div class="updated"><p>Performance scanning is enabled.</p></div>';
|
588 |
+
}
|
589 |
+
|
590 |
+
// Check that we can write .profiling_enabled
|
591 |
+
if ( isset( $_REQUEST['page'] ) && basename( __FILE__ ) == $_REQUEST['page'] && ( !isset( $_REQUEST['p3_action'] ) || 'fix-flag-file' != $_REQUEST['p3_action'] ) ) {
|
592 |
+
if ( !file_exists( P3_FLAG_FILE ) || !is_writable( P3_FLAG_FILE ) ) {
|
593 |
+
@touch( P3_FLAG_FILE );
|
594 |
+
if ( !file_exists( P3_FLAG_FILE ) || !is_writable( P3_FLAG_FILE ) ) {
|
595 |
+
echo '<div class="error"><p>Cannot set profile flag file <input type="button" onclick="location.href=\'' . add_query_arg( array( 'p3_action' => 'fix-flag-file' ) ) . '\';" class="button" value="click here to fix" /></p></div>';
|
596 |
+
}
|
597 |
+
}
|
598 |
+
}
|
599 |
+
}
|
600 |
+
|
601 |
+
/**
|
602 |
+
* Activation hook
|
603 |
+
* Install the profiler loader in the most optimal place
|
604 |
+
* @return void
|
605 |
+
*/
|
606 |
+
public function activate() {
|
607 |
+
$sapi = strtolower( php_sapi_name() );
|
608 |
+
|
609 |
+
// .htaccess for mod_php
|
610 |
+
if ( 'apache2handler' == $sapi ) {
|
611 |
+
insert_with_markers(
|
612 |
+
P3_PATH . '/../../../.htaccess',
|
613 |
+
'p3-profiler',
|
614 |
+
array( 'php_value auto_prepend_file "' . P3_PATH . DIRECTORY_SEPARATOR . 'start-profile.php"' )
|
615 |
+
);
|
616 |
+
}
|
617 |
+
|
618 |
+
// Always try to create the mu-plugin loader in case either of the above methods fail
|
619 |
+
|
620 |
+
// mu-plugins doesn't exist
|
621 |
+
if ( !file_exists( P3_PATH . '/../../mu-plugins/' ) && is_writable( P3_PATH . '/../../' ) ) {
|
622 |
+
$flag = wp_mkdir_p( P3_PATH . '/../../mu-plugins/' );
|
623 |
+
}
|
624 |
+
if ( file_exists( P3_PATH . '/../../mu-plugins/' ) && is_writable( P3_PATH . '/../../mu-plugins' ) ) {
|
625 |
+
file_put_contents(
|
626 |
+
P3_PATH . '/../../mu-plugins/p3-profiler.php',
|
627 |
+
'<' . "?php // Start profiling\nrequire_once( realpath( dirname( __FILE__ ) ) . '/../plugins/p3-profiler/start-profile.php' ); ?" . '>'
|
628 |
+
);
|
629 |
+
}
|
630 |
+
|
631 |
+
// Create the profiles folder
|
632 |
+
$this->sync_profiles_folder();
|
633 |
+
}
|
634 |
+
|
635 |
+
/**
|
636 |
+
* Make the profiles folder
|
637 |
+
* @param string $path
|
638 |
+
* @return void
|
639 |
+
*/
|
640 |
+
private function _make_profiles_folder( $path ) {
|
641 |
+
wp_mkdir_p( $path );
|
642 |
+
if ( !file_exists( "$path/.htaccess" ) ) {
|
643 |
+
file_put_contents( $path . DIRECTORY_SEPARATOR . '.htaccess', "Deny from all\n" );
|
644 |
+
}
|
645 |
+
if ( !file_exists( "$path/index.php" ) ) {
|
646 |
+
file_put_contents( $path. DIRECTORY_SEPARATOR . 'index.php', '<' . "?php header( 'Status: 404 Not found' ); ?" . ">\nNot found" );
|
647 |
+
}
|
648 |
+
}
|
649 |
+
|
650 |
+
/**
|
651 |
+
* Delete the profiles folder
|
652 |
+
* @param string $path
|
653 |
+
* @return void
|
654 |
+
*/
|
655 |
+
private function _delete_profiles_folder( $path ) {
|
656 |
+
$dir = opendir( $path );
|
657 |
+
while ( ( $file = readdir( $dir ) ) !== false ) {
|
658 |
+
if ( $file != '.' && $file != '..' ) {
|
659 |
+
unlink( $path . DIRECTORY_SEPARATOR . $file );
|
660 |
+
}
|
661 |
+
}
|
662 |
+
closedir( $dir );
|
663 |
+
rmdir( $path );
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Deactivation hook
|
668 |
+
* Uninstall the profiler loader
|
669 |
+
* @return void
|
670 |
+
*/
|
671 |
+
public function deactivate() {
|
672 |
+
|
673 |
+
// Remove any .htaccess modifications
|
674 |
+
$file = P3_PATH . '/../../../.htaccess';
|
675 |
+
if ( file_exists( $file ) && array() !== extract_from_markers( $file, 'p3-profiler' ) ) {
|
676 |
+
insert_with_markers( $file, 'p3-profiler', array( '# removed during uninstall' ) );
|
677 |
+
}
|
678 |
+
|
679 |
+
// Remove mu-plugin
|
680 |
+
if ( file_exists( P3_PATH . '/../../mu-plugins/p3-profiler.php' ) ) {
|
681 |
+
if ( is_writable( P3_PATH . '/../../mu-plugins/p3-profiler.php' ) ) {
|
682 |
+
// Some servers give write permission, but not delete permission. Empty the file out, first, then try to delete it.
|
683 |
+
file_put_contents( P3_PATH . '/../../mu-plugins/p3-profiler.php', '' );
|
684 |
+
unlink( P3_PATH . '/../../mu-plugins/p3-profiler.php' );
|
685 |
+
}
|
686 |
+
}
|
687 |
+
}
|
688 |
+
|
689 |
+
/**
|
690 |
+
* Sync profiles folder
|
691 |
+
* Call whenever a blog is added / removed
|
692 |
+
* @return void
|
693 |
+
*/
|
694 |
+
public function sync_profiles_folder() {
|
695 |
+
|
696 |
+
// Base blog profiles folder
|
697 |
+
$uploads_dir = wp_upload_dir();
|
698 |
+
$folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles';
|
699 |
+
$this->_make_profiles_folder( $folder );
|
700 |
+
|
701 |
+
// Only for multisite
|
702 |
+
if ( !function_exists( 'is_multisite' ) || !is_multisite() ) {
|
703 |
+
return;
|
704 |
+
}
|
705 |
+
|
706 |
+
// List profiles/<blog id> folders
|
707 |
+
$folders = array();
|
708 |
+
$dir = opendir( $folder );
|
709 |
+
while ( ( $file = readdir( $dir ) ) !== false ) {
|
710 |
+
if ( $file != '.' && $file != '..' && is_dir( "$folder/$file" ) && is_numeric( $file ) ) {
|
711 |
+
$folders[] = $file;
|
712 |
+
}
|
713 |
+
}
|
714 |
+
closedir( $dir );
|
715 |
+
|
716 |
+
// List blogs
|
717 |
+
$blogs = array();
|
718 |
+
$blogs = get_blog_list( 0, 'all' );
|
719 |
+
foreach ( $blogs as $blog ) {
|
720 |
+
$blogs[] = $blog['blog_id'];
|
721 |
+
}
|
722 |
+
|
723 |
+
// Folders without a blog
|
724 |
+
foreach ( array_diff( $folders, $blogs ) as $id ) {
|
725 |
+
$this->_delete_profiles_folder( $folder . DIRECTORY_SEPARATOR . $id );
|
726 |
+
}
|
727 |
+
|
728 |
+
// Blogs without a folder
|
729 |
+
foreach ( array_diff( $blogs, $folders ) as $id ) {
|
730 |
+
switch_to_blog( $id );
|
731 |
+
$uploads_dir = wp_upload_dir();
|
732 |
+
$folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles';
|
733 |
+
$this->_make_profiles_folder( $folder );
|
734 |
+
restore_current_blog();
|
735 |
+
}
|
736 |
+
}
|
737 |
+
|
738 |
+
/**
|
739 |
+
* Uninstall hook
|
740 |
+
* Remove profile data
|
741 |
+
* @return void
|
742 |
+
*/
|
743 |
+
public static function uninstall() {
|
744 |
+
// This is a static function so it needs an instance
|
745 |
+
// Since I'm myself, I can call my own private methods
|
746 |
+
$class = __CLASS__;
|
747 |
+
$me = new $class();
|
748 |
+
|
749 |
+
// Delete the profiles folder
|
750 |
+
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
|
751 |
+
$blogs = get_blog_list( 0, 'all' );
|
752 |
+
foreach ( $blogs as $blog ) {
|
753 |
+
switch_to_blog( $blog['blog_id'] );
|
754 |
+
$uploads_dir = wp_upload_dir();
|
755 |
+
$folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' . DIRECTORY_SEPARATOR;
|
756 |
+
$me->_delete_profiles_folder( $folder );
|
757 |
+
}
|
758 |
+
restore_current_blog();
|
759 |
+
} else {
|
760 |
+
$me->_delete_profiles_folder( P3_PROFILES_PATH );
|
761 |
+
}
|
762 |
+
}
|
763 |
+
|
764 |
+
/**
|
765 |
+
* Check to see if a scan is enabled
|
766 |
+
* @return array|false
|
767 |
+
*/
|
768 |
+
public function scan_enabled() {
|
769 |
+
if ( !file_exists( P3_FLAG_FILE ) ) {
|
770 |
+
return false;
|
771 |
+
}
|
772 |
+
$site_url = parse_url( get_home_url(), PHP_URL_PATH );
|
773 |
+
if ( null === $site_url ) {
|
774 |
+
$site_url = '/';
|
775 |
+
}
|
776 |
+
$json = json_decode( file_get_contents( P3_FLAG_FILE ), true );
|
777 |
+
foreach ( (array) $json as $v ) {
|
778 |
+
if ( $site_url == $v['site_url'] ) {
|
779 |
+
return $v;
|
780 |
+
}
|
781 |
+
}
|
782 |
+
return false;
|
783 |
+
}
|
784 |
+
|
785 |
+
/**
|
786 |
+
* Convert a filesize ( in bytes ) to a human readable filesize
|
787 |
+
* @param int $size
|
788 |
+
* @return string
|
789 |
+
*/
|
790 |
+
public function readable_size( $size ) {
|
791 |
+
$units = array( 'B', 'KB', 'MB', 'GB', 'TB' );
|
792 |
+
$size = max( $size, 0 );
|
793 |
+
$pow = floor( ( $size ? log( $size ) : 0 ) / log( 1024 ) );
|
794 |
+
$pow = min( $pow, count( $units ) - 1 );
|
795 |
+
$size /= pow( 1024, $pow );
|
796 |
+
return round( $size, 0 ) . ' ' . $units[$pow];
|
797 |
+
}
|
798 |
+
}
|
readme.txt
ADDED
@@ -0,0 +1,67 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
=== P3 (Plugin Performance Profiler) ===
|
2 |
+
Contributors: Godaddy, StarfieldTech
|
3 |
+
Tags: debug, debugging, developer, development, performance, plugin, profiler, speed
|
4 |
+
Requires at least: 3.3
|
5 |
+
Tested up to: 3.3
|
6 |
+
Stable tag: 1.0
|
7 |
+
|
8 |
+
See which plugins are slowing down your site. This plugin creates a performance report for your site.
|
9 |
+
|
10 |
+
== Description ==
|
11 |
+
This plugin creates a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.  Often times, WordPress sites load slowly because of poorly configured plugins or because there are so many of them. By using the P3 plugin, you can narrow down anything causing slowness on your site.
|
12 |
+
|
13 |
+
Requires Firefox, Chrome, Opera, Safari, or IE9 or later.
|
14 |
+
|
15 |
+
== Screenshots ==
|
16 |
+
|
17 |
+
1. First, profile your site. The scanner generates some traffic on your site and monitors your site's performance on the server, then shows you the results. With this information, you can decide what action to take.
|
18 |
+
2. After profiling, you'll see a breakdown of relative runtime for each plugin.
|
19 |
+
3. Callouts at the top give you quick information like how much load time (in seconds) is dedicated to plugins and how many database queries your site is running per page.
|
20 |
+
4. The detailed timeline gives you timing information for every plugin, the theme, and the core for every page during the profile. Find out exactly what's happening on slow loading pages.
|
21 |
+
5. The query timeline gives you the number of database queries for every page during the profile. Find out which pages generate the most database queries.
|
22 |
+
6. Keep a history of your performance scans, compare your current performance with your previous performance.
|
23 |
+
7. Full in-app help documentation
|
24 |
+
8. Send a summary of your performance profile via e-mail. If you want to show your developer, site admin, hosting support, or a plugin developer what's going on with your site, this is good way to start the conversation.
|
25 |
+
|
26 |
+
== Installation ==
|
27 |
+
Automatic installation
|
28 |
+
|
29 |
+
1. Log into your WordPress admin
|
30 |
+
2. Click __Plugins__
|
31 |
+
3. Click __Add New__
|
32 |
+
4. Search for __P3__
|
33 |
+
5. Click __Install Now__ under "P3 (Plugin Performance Profiler)"
|
34 |
+
6. Activate the plugin
|
35 |
+
|
36 |
+
Manual installation:
|
37 |
+
|
38 |
+
1. Download the plugin
|
39 |
+
2. Extract the contents of the zip file
|
40 |
+
3. Upload the contents of the zip file to the wp-content/plugins/ folder of your WordPress installation
|
41 |
+
4. Then activate the Plugin from Plugins page.
|
42 |
+
|
43 |
+
== Frequently Asked Questions ==
|
44 |
+
No FAQs yet.
|
45 |
+
|
46 |
+
== Upgrade Notice ==
|
47 |
+
|
48 |
+
= 1.0 =
|
49 |
+
Initial release.
|
50 |
+
|
51 |
+
== Changelog ==
|
52 |
+
|
53 |
+
= 1.0 =
|
54 |
+
* Automatic site profiling
|
55 |
+
* Manual site profiling
|
56 |
+
* Profile history
|
57 |
+
* Continue a profile session
|
58 |
+
* Clear opcode caches (if possible) to improve plugin function detection
|
59 |
+
* Limit profiling by IP address (regex pattern)
|
60 |
+
* Limit profiling by site URL (for MS compatibility)
|
61 |
+
* Rewrite http URLs to https to avoid SSL warnings when using wp-admin over SSL
|
62 |
+
* Hide the admin toolbar on the front-end when profiling to prevent extra plugin scripts/styles from loading
|
63 |
+
* In-app help / glossary page
|
64 |
+
* Activate / deactivate hooks to try different loader methods so the profiler runs as early as possible
|
65 |
+
* Uninstall hooks to clean up profiles
|
66 |
+
* Hooks add/delete blog to clean up profiles
|
67 |
+
* Send profile summary via e-mail
|
screenshot-1.png
ADDED
Binary file
|
screenshot-2.png
ADDED
Binary file
|
screenshot-3.png
ADDED
Binary file
|
screenshot-4.png
ADDED
Binary file
|
screenshot-5.png
ADDED
Binary file
|
screenshot-6.png
ADDED
Binary file
|
screenshot-7.png
ADDED
Binary file
|
screenshot-8.png
ADDED
Binary file
|
start-profile.php
ADDED
@@ -0,0 +1,8 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// If profiling hasn't started, start it
|
4 |
+
if ( !isset( $GLOBALS['p3_profiler'] ) ) {
|
5 |
+
declare( ticks = 1 ); // Capture ever user function call
|
6 |
+
include_once realpath( dirname( __FILE__ ) ) . '/class.p3-profiler.php';
|
7 |
+
$GLOBALS['p3_profiler'] = new P3_Profiler(); // Go
|
8 |
+
}
|
templates/.htaccess
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
Deny from all
|
templates/callouts.php
ADDED
@@ -0,0 +1,624 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<script type="text/javascript">
|
2 |
+
|
3 |
+
/*****************************************************************/
|
4 |
+
/** AUTO SCANNER HELPER OBJECT **/
|
5 |
+
/*****************************************************************/
|
6 |
+
// This will load all of the pages in the list, then turn off
|
7 |
+
// the profile mode and view the results when complete.
|
8 |
+
var P3_Scan = {
|
9 |
+
|
10 |
+
// List of pages to scan
|
11 |
+
pages: <?php echo json_encode( $this->list_of_pages() ); ?>,
|
12 |
+
|
13 |
+
// Current page
|
14 |
+
current_page: 0,
|
15 |
+
|
16 |
+
// Pause flag
|
17 |
+
paused: false,
|
18 |
+
|
19 |
+
// Start
|
20 |
+
start: function() {
|
21 |
+
|
22 |
+
// Form data
|
23 |
+
data = {
|
24 |
+
'p3_ip' : jQuery( '#p3-advanced-ip' ).val(),
|
25 |
+
'p3_disable_opcode_cache' : jQuery( '#p3-disable-opcode-cache' ).prop( 'checked' ),
|
26 |
+
'p3_scan_name' : jQuery( "#p3-scan-name" ).val(),
|
27 |
+
'action' : 'p3_start_scan',
|
28 |
+
'p3_nonce' : jQuery( "#p3_nonce" ).val()
|
29 |
+
}
|
30 |
+
|
31 |
+
// Turn on the profiler
|
32 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
33 |
+
if ( 1 != response ) {
|
34 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
35 |
+
} else {
|
36 |
+
|
37 |
+
// Start scanning pages
|
38 |
+
jQuery( "#p3-scan-frame" ).attr( "onload", "P3_Scan.next_page();" );
|
39 |
+
jQuery( "#p3-scan-frame" ).attr( "src", P3_Scan.pages[0] );
|
40 |
+
P3_Scan.current_page = 0;
|
41 |
+
P3_Scan.update_display();
|
42 |
+
|
43 |
+
}
|
44 |
+
});
|
45 |
+
},
|
46 |
+
|
47 |
+
// Pause
|
48 |
+
pause: function() {
|
49 |
+
|
50 |
+
// Turn off the profiler
|
51 |
+
data = {
|
52 |
+
'action' : 'p3_stop_scan',
|
53 |
+
'p3_nonce' : '<?php echo wp_create_nonce( 'p3_ajax_stop_scan' ); ?>'
|
54 |
+
}
|
55 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
56 |
+
if ( response.indexOf( '.json' ) < 0 ) {
|
57 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
58 |
+
}
|
59 |
+
|
60 |
+
// Hide the cancel button
|
61 |
+
jQuery( "#p3-cancel-scan-buttonset" ).hide();
|
62 |
+
jQuery( "#p3-resume-scan-buttonset" ).show();
|
63 |
+
jQuery( "#p3-view-results-buttonset" ).hide();
|
64 |
+
|
65 |
+
// Show the view results button
|
66 |
+
jQuery( "#p3-view-incomplete-results-submit" ).attr( "data-scan-name", response );
|
67 |
+
|
68 |
+
// Pause
|
69 |
+
P3_Scan.paused = true;
|
70 |
+
|
71 |
+
// Update the caption
|
72 |
+
jQuery( "#p3-scanning-caption" ).html( "Scanning is paused." ).css( "color", "black" );
|
73 |
+
});
|
74 |
+
},
|
75 |
+
|
76 |
+
// Resume
|
77 |
+
resume: function() {
|
78 |
+
|
79 |
+
data = {
|
80 |
+
'p3_ip' : jQuery( '#p3-advanced-ip' ).val(),
|
81 |
+
'p3_disable_opcode_cache' : jQuery( '#p3-disable-opcode-cache' ).prop( 'checked' ),
|
82 |
+
'p3_scan_name' : jQuery( "#p3-scan-name" ).val(),
|
83 |
+
'action' : 'p3_start_scan',
|
84 |
+
'p3_nonce' : jQuery( "#p3_nonce" ).val()
|
85 |
+
}
|
86 |
+
|
87 |
+
// Turn on the profiler
|
88 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
89 |
+
if ( 1 != response ) {
|
90 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
91 |
+
} else {
|
92 |
+
|
93 |
+
// Show the cancel button
|
94 |
+
P3_Scan.paused = false;
|
95 |
+
jQuery( "#p3-cancel-scan-buttonset" ).show();
|
96 |
+
jQuery( "#p3-resume-scan-buttonset" ).hide();
|
97 |
+
jQuery( "#p3-view-results-buttonset" ).hide();
|
98 |
+
P3_Scan.update_display();
|
99 |
+
P3_Scan.next_page();
|
100 |
+
}
|
101 |
+
});
|
102 |
+
},
|
103 |
+
|
104 |
+
// Stop
|
105 |
+
stop: function() {
|
106 |
+
|
107 |
+
// Turn off the profiler
|
108 |
+
data = {
|
109 |
+
'action' : 'p3_stop_scan',
|
110 |
+
'p3_nonce' : '<?php echo wp_create_nonce( 'p3_ajax_stop_scan' ); ?>'
|
111 |
+
}
|
112 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
113 |
+
if ( response.indexOf( '.json' ) < 0 ) {
|
114 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
115 |
+
}
|
116 |
+
|
117 |
+
// Hide the cancel button
|
118 |
+
jQuery( "#p3-cancel-scan-buttonset" ).hide();
|
119 |
+
jQuery( "#p3-resume-scan-buttonset" ).hide();
|
120 |
+
jQuery( "#p3-view-results-buttonset" ).show();
|
121 |
+
|
122 |
+
// Show the view results button
|
123 |
+
jQuery( "#p3-view-results-submit" ).attr( "data-scan-name", response );
|
124 |
+
|
125 |
+
// Update the caption
|
126 |
+
jQuery( "#p3-scanning-caption" ).html( "Scanning is complete." ).css( "color", "black" );
|
127 |
+
});
|
128 |
+
},
|
129 |
+
|
130 |
+
// Update the display
|
131 |
+
update_display : function() {
|
132 |
+
jQuery( "#p3-scanning-caption" ).html( 'Scanning ' + P3_Scan.pages[P3_Scan.current_page] ).css( "color", "" );
|
133 |
+
jQuery( "#p3-progress" ).progressbar( "value", ( P3_Scan.current_page / ( P3_Scan.pages.length - 1 ) ) * 100 );
|
134 |
+
},
|
135 |
+
|
136 |
+
// Look at the next page
|
137 |
+
next_page : function() {
|
138 |
+
|
139 |
+
// Paused?
|
140 |
+
if ( P3_Scan.paused ) {
|
141 |
+
return true;
|
142 |
+
}
|
143 |
+
|
144 |
+
// Is it time to stop?
|
145 |
+
if ( P3_Scan.current_page >= P3_Scan.pages.length - 1 ) {
|
146 |
+
P3_Scan.stop();
|
147 |
+
return true;
|
148 |
+
}
|
149 |
+
|
150 |
+
// Next page
|
151 |
+
jQuery( "#p3-scan-frame" ).attr( "src", P3_Scan.pages[++P3_Scan.current_page] );
|
152 |
+
|
153 |
+
// Update the display
|
154 |
+
P3_Scan.update_display();
|
155 |
+
}
|
156 |
+
};
|
157 |
+
|
158 |
+
|
159 |
+
// Onload functionality
|
160 |
+
jQuery( document ).ready( function( $) {
|
161 |
+
|
162 |
+
/*****************************************************************/
|
163 |
+
/** DIALOGS **/
|
164 |
+
/*****************************************************************/
|
165 |
+
|
166 |
+
// IP settings
|
167 |
+
$( "#p3-ip-dialog" ).dialog({
|
168 |
+
'autoOpen' : false,
|
169 |
+
'closeOnEscape' : true,
|
170 |
+
'draggable' : false,
|
171 |
+
'resizable' : false,
|
172 |
+
'modal' : true,
|
173 |
+
'width' : 450,
|
174 |
+
'height' : 255,
|
175 |
+
'title' : "Advanced Settings",
|
176 |
+
'buttons' :
|
177 |
+
[
|
178 |
+
{
|
179 |
+
text: 'OK',
|
180 |
+
'class' : 'button-secondary',
|
181 |
+
click: function() {
|
182 |
+
$( this ).dialog( "close" );
|
183 |
+
}
|
184 |
+
},
|
185 |
+
{
|
186 |
+
text: 'Cancel',
|
187 |
+
'class': 'p3-cancel-button',
|
188 |
+
click: function() {
|
189 |
+
$( this ).dialog( "close" );
|
190 |
+
}
|
191 |
+
}
|
192 |
+
]
|
193 |
+
});
|
194 |
+
|
195 |
+
// Iframe scanner
|
196 |
+
$( "#p3-scanner-dialog" ).dialog({
|
197 |
+
'autoOpen' : false,
|
198 |
+
'closeOnEscape' : true,
|
199 |
+
'draggable' : false,
|
200 |
+
'resizable' : false,
|
201 |
+
'modal' : true,
|
202 |
+
'width': 800,
|
203 |
+
'height' : 600,
|
204 |
+
'title' : "Performance Scan",
|
205 |
+
'dialogClass' : 'noPadding'
|
206 |
+
});
|
207 |
+
|
208 |
+
// Auto scan or manual scan
|
209 |
+
$( "#p3-scan-name-dialog" ).dialog({
|
210 |
+
'autoOpen' : false,
|
211 |
+
'closeOnEscape' : true,
|
212 |
+
'draggable' : false,
|
213 |
+
'resizable' : false,
|
214 |
+
'modal' : true,
|
215 |
+
'width' : 425,
|
216 |
+
'height' : 180,
|
217 |
+
'title' : 'Scan Name'
|
218 |
+
// 'dialogClass' : 'noTitle'
|
219 |
+
});
|
220 |
+
|
221 |
+
// Progress dialog
|
222 |
+
$( "#p3-progress-dialog" ).dialog({
|
223 |
+
'autoOpen' : false,
|
224 |
+
'closeOnEscape' : false,
|
225 |
+
'draggable' : false,
|
226 |
+
'resizable' : false,
|
227 |
+
'modal' : true,
|
228 |
+
'width' : 450,
|
229 |
+
'height' : 117,
|
230 |
+
'dialogClass' : 'noTitle'
|
231 |
+
});
|
232 |
+
|
233 |
+
|
234 |
+
|
235 |
+
/*****************************************************************/
|
236 |
+
/** LINKS **/
|
237 |
+
/*****************************************************************/
|
238 |
+
|
239 |
+
// Advanced settings link
|
240 |
+
$( "#p3-advanced-settings" ).click( function() {
|
241 |
+
$( "#p3-ip-dialog" ).dialog( "open" );
|
242 |
+
});
|
243 |
+
|
244 |
+
|
245 |
+
|
246 |
+
/*****************************************************************/
|
247 |
+
/** BUTTONS **/
|
248 |
+
/*****************************************************************/
|
249 |
+
|
250 |
+
// Start scan button
|
251 |
+
$( "#p3-start-scan-submit" ).click( function() {
|
252 |
+
|
253 |
+
// Stay checked to keep the styling
|
254 |
+
$( this ).prop( "checked", true );
|
255 |
+
$( this ).button( "refresh" );
|
256 |
+
|
257 |
+
url = $( "#p3-scan-frame" ).attr( "data-defaultsrc" );
|
258 |
+
if ( url.indexOf('?') >= 0 || url.indexOf('&') >= 0 ) {
|
259 |
+
url += '&P3_HIDE_ADMIN_BAR=1';
|
260 |
+
} else if ( url.charAt(url.length - 1) != '/' ) {
|
261 |
+
url += '/?P3_HIDE_ADMIN_BAR=1';
|
262 |
+
} else {
|
263 |
+
url += '?P3_HIDE_ADMIN_BAR=1';
|
264 |
+
}
|
265 |
+
|
266 |
+
$( "#p3-scan-frame" ).attr( "src", url );
|
267 |
+
$( "#p3-scanner-dialog" ).dialog( "open" );
|
268 |
+
$( "#p3-scan-name-dialog" ).dialog( "open" );
|
269 |
+
});
|
270 |
+
|
271 |
+
// Stop scan button
|
272 |
+
$( "#p3-stop-scan-submit" ).click( function() {
|
273 |
+
|
274 |
+
// Stay checked to keep the styling
|
275 |
+
$( this ).prop( "checked", true );
|
276 |
+
$( this ).button( "refresh" );
|
277 |
+
|
278 |
+
// Turn off the profiler
|
279 |
+
data = {
|
280 |
+
'action' : 'p3_stop_scan',
|
281 |
+
'p3_nonce' : '<?php echo wp_create_nonce( 'p3_ajax_stop_scan' ); ?>'
|
282 |
+
}
|
283 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
284 |
+
if ( response.indexOf( '.json' ) < 0 ) {
|
285 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
286 |
+
}
|
287 |
+
location.reload();
|
288 |
+
});
|
289 |
+
});
|
290 |
+
|
291 |
+
// Auto scan button
|
292 |
+
$( "#p3-auto-scan-submit" ).click( function() {
|
293 |
+
|
294 |
+
// Stay checked to keep the styling
|
295 |
+
$( this ).prop( "checked", true );
|
296 |
+
$( this ).button( "refresh" );
|
297 |
+
|
298 |
+
// Close the "auto or manual" dialog
|
299 |
+
$( "#p3-scan-name-dialog" ).dialog( "close" );
|
300 |
+
|
301 |
+
// Open the progress bar dialog
|
302 |
+
$( "#p3-progress-dialog" ).dialog( "open" );
|
303 |
+
|
304 |
+
// Initialize the progress bar to 0%
|
305 |
+
$( "#p3-progress" ).progressbar({
|
306 |
+
'value': 0
|
307 |
+
});
|
308 |
+
|
309 |
+
P3_Scan.start();
|
310 |
+
});
|
311 |
+
|
312 |
+
// Manual scan button
|
313 |
+
$( "#p3-manual-scan-submit" ).click( function() {
|
314 |
+
|
315 |
+
// Stay checked to keep the styling
|
316 |
+
$( this ).prop( "checked", true );
|
317 |
+
$( this ).button( "refresh" );
|
318 |
+
|
319 |
+
|
320 |
+
// Form data
|
321 |
+
data = {
|
322 |
+
'p3_ip' : jQuery( '#p3-advanced-ip' ).val(),
|
323 |
+
'p3_disable_opcode_cache' : jQuery( '#p3-disable-opcode-cache' ).prop( 'checked' ),
|
324 |
+
'p3_scan_name' : jQuery( "#p3-scan-name" ).val(),
|
325 |
+
'action' : 'p3_start_scan',
|
326 |
+
'p3_nonce' : jQuery( "#p3_nonce" ).val()
|
327 |
+
}
|
328 |
+
|
329 |
+
// Turn on the profiler
|
330 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
331 |
+
if ( 1 != response ) {
|
332 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
333 |
+
}
|
334 |
+
});
|
335 |
+
|
336 |
+
$( "#p3-scan-name-dialog" ).dialog( "close" );
|
337 |
+
$( "#p3-scan-caption" ).hide();
|
338 |
+
$( "#p3-manual-scan-caption" ).show();
|
339 |
+
});
|
340 |
+
|
341 |
+
// Manual scan "I'm done" button
|
342 |
+
$( "#p3-manual-scan-done-submit" ).click( function() {
|
343 |
+
data = {
|
344 |
+
'action' : 'p3_stop_scan',
|
345 |
+
'p3_nonce' : '<?php echo wp_create_nonce( 'p3_ajax_stop_scan' ); ?>'
|
346 |
+
}
|
347 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
348 |
+
if ( response.indexOf( '.json' ) < 0 ) {
|
349 |
+
alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
|
350 |
+
} else {
|
351 |
+
location.href = "<?php echo add_query_arg( array( 'p3_action' => 'view-scan' ) ); ?>&name=" + response;
|
352 |
+
}
|
353 |
+
})
|
354 |
+
$( "#p3-scanner-dialog" ).dialog( "close" );
|
355 |
+
});
|
356 |
+
|
357 |
+
// Manual scan cancel link
|
358 |
+
$( "#p3-manual-scan-cancel" ).click( function() {
|
359 |
+
P3_Scan.pause();
|
360 |
+
$( "#p3-scanner-dialog" ).dialog( "close" );
|
361 |
+
});
|
362 |
+
|
363 |
+
// Cancel scan button
|
364 |
+
$( "#p3-cancel-scan-submit" ).click( function() {
|
365 |
+
|
366 |
+
// Stay checked to keep the styling
|
367 |
+
$( this ).prop( "checked", true );
|
368 |
+
$( this ).button( "refresh" );
|
369 |
+
|
370 |
+
P3_Scan.pause();
|
371 |
+
});
|
372 |
+
|
373 |
+
// Resume
|
374 |
+
$( "#p3-resume-scan-submit" ).click( function() {
|
375 |
+
|
376 |
+
// Stay checked to keep the styling
|
377 |
+
$( this ).prop( "checked", true );
|
378 |
+
$( this ).button( "refresh" );
|
379 |
+
|
380 |
+
P3_Scan.resume();
|
381 |
+
});
|
382 |
+
|
383 |
+
// View results button
|
384 |
+
$( "#p3-view-results-submit" ).click( function() {
|
385 |
+
|
386 |
+
// Stay checked to keep the styling
|
387 |
+
$( this ).prop( "checked", true );
|
388 |
+
$( this ).button( "refresh" );
|
389 |
+
|
390 |
+
// Close the dialogs
|
391 |
+
jQuery( "#p3-scanner-dialog" ).dialog( "close" );
|
392 |
+
jQuery( "#p3-progress-dialog" ).dialog( "close" );
|
393 |
+
|
394 |
+
// View the scan
|
395 |
+
location.href = "<?php echo add_query_arg( array( 'p3_action' => 'view-scan' ) ); ?>&name=" + $( this ).attr( "data-scan-name" );
|
396 |
+
});
|
397 |
+
$( "#p3-view-incomplete-results-submit" ).click( function() {
|
398 |
+
$( "#p3-view-results-submit" ).trigger( "click" );
|
399 |
+
});
|
400 |
+
|
401 |
+
|
402 |
+
/*****************************************************************/
|
403 |
+
/** OTHER **/
|
404 |
+
/*****************************************************************/
|
405 |
+
// Enable / disable buttons based on scan name input
|
406 |
+
$( "#p3-scan-name" ).live( "keyup", function() {
|
407 |
+
if ( $( this ).val().match(/^[a-zA-Z0-9_\.-]+$/) ) {
|
408 |
+
$( "#p3-auto-scan-submit" ).button( "enable" )
|
409 |
+
$( "#p3-manual-scan-submit" ).button( "enable" );
|
410 |
+
} else {
|
411 |
+
$( "#p3-auto-scan-submit" ).button( "disable" );
|
412 |
+
$( "#p3-manual-scan-submit" ).button( "disable" );
|
413 |
+
}
|
414 |
+
});
|
415 |
+
|
416 |
+
// Callouts
|
417 |
+
$( "div.p3-callout-inner-wrapper" )
|
418 |
+
.corner( "round 8px" )
|
419 |
+
.parent()
|
420 |
+
.css( "padding", "4px" )
|
421 |
+
.corner( "round 10px" );
|
422 |
+
|
423 |
+
// Start / stop buttons
|
424 |
+
$( "#p3-scan-form-wrapper" ).corner( "round 8px" );
|
425 |
+
|
426 |
+
// Continue scan
|
427 |
+
$( "a.p3-continue-scan" ).click( function() {
|
428 |
+
$( "#p3-start-scan-submit" ).trigger( "click" );
|
429 |
+
$( "#p3-scan-name" ).val( $( this ).attr( "data-name" ).replace(/\.json$/, '' ) );
|
430 |
+
});
|
431 |
+
});
|
432 |
+
</script>
|
433 |
+
<table id="p3-quick-report" cellpadding="0" cellspacing="0">
|
434 |
+
<tr>
|
435 |
+
|
436 |
+
<td>
|
437 |
+
<div class="ui-widget-header" id="p3-scan-form-wrapper">
|
438 |
+
<?php if ( false !== ( $info = $this->scan_enabled() ) ) { ?>
|
439 |
+
<!-- Stop scan button -->
|
440 |
+
|
441 |
+
<strong>IP:</strong><?php echo htmlentities( $info['ip'] ); ?>
|
442 |
+
<div class="p3-big-button"><input type="checkbox" checked="checked" id="p3-stop-scan-submit" />
|
443 |
+
<label for="p3-stop-scan-submit">Stop Scan</label></div>
|
444 |
+
<?php echo htmlentities( $info['name'] ); ?>
|
445 |
+
|
446 |
+
<?php } else { ?>
|
447 |
+
|
448 |
+
<!-- Start scan button -->
|
449 |
+
<?php echo wp_nonce_field( 'p3_ajax_start_scan', 'p3_nonce' ); ?>
|
450 |
+
<strong>My IP:</strong><?php echo htmlentities( $GLOBALS['p3_profiler']->get_ip() ); ?>
|
451 |
+
<div class="p3-big-button"><input type="checkbox" checked="checked" id="p3-start-scan-submit" />
|
452 |
+
<label for="p3-start-scan-submit">Start Scan</label></div>
|
453 |
+
<a href="javascript:;" id="p3-advanced-settings">Advanced Settings</a>
|
454 |
+
|
455 |
+
<?php } ?>
|
456 |
+
</div>
|
457 |
+
</td>
|
458 |
+
|
459 |
+
<!-- First callout cell -->
|
460 |
+
<td class="p3-callout">
|
461 |
+
<div class="p3-callout-outer-wrapper qtip-tip" title="Total number of active plugins, including must-use plugins, on your site.">
|
462 |
+
<div class="p3-callout-inner-wrapper">
|
463 |
+
<div class="p3-callout-caption">Total plugins:</div>
|
464 |
+
<div class="p3-callout-data">
|
465 |
+
<?php
|
466 |
+
// Get the total number of plugins
|
467 |
+
$active_plugins = count( get_mu_plugins() );
|
468 |
+
foreach ( get_plugins() as $plugin => $junk ) {
|
469 |
+
if ( is_plugin_active( $plugin ) ) {
|
470 |
+
$active_plugins++;
|
471 |
+
}
|
472 |
+
}
|
473 |
+
echo $active_plugins;
|
474 |
+
?>
|
475 |
+
</div>
|
476 |
+
<div class="p3-callout-caption">( currently active )</div>
|
477 |
+
</div>
|
478 |
+
</div>
|
479 |
+
</td>
|
480 |
+
|
481 |
+
<!-- Second callout cell -->
|
482 |
+
<td class="p3-callout">
|
483 |
+
<div class="p3-callout-outer-wrapper qtip-tip" title="Total number of seconds dedicated to plugin code per visit on your site."
|
484 |
+
<?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
|
485 |
+
<div class="p3-callout-inner-wrapper">
|
486 |
+
<div class="p3-callout-caption">Plugin load time</div>
|
487 |
+
<div class="p3-callout-data">
|
488 |
+
<?php if ( null === $profile ) { ?>
|
489 |
+
<span class="p3-faded-grey">n/a</span>
|
490 |
+
<?php } else { ?>
|
491 |
+
<?php printf( '%.3f', $profile->averages['plugins'] ); ?>
|
492 |
+
<?php } ?>
|
493 |
+
</div>
|
494 |
+
<div class="p3-callout-caption">( sec. per visit )</div>
|
495 |
+
</div>
|
496 |
+
</div>
|
497 |
+
</td>
|
498 |
+
|
499 |
+
<!-- Third callout cell -->
|
500 |
+
<td class="p3-callout">
|
501 |
+
<div class="p3-callout-outer-wrapper qtip-tip" title="Percent of load time on your site dedicated to plugin code."
|
502 |
+
<?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
|
503 |
+
<div class="p3-callout-inner-wrapper">
|
504 |
+
<div class="p3-callout-caption">Plugin impact</div>
|
505 |
+
<div class="p3-callout-data">
|
506 |
+
<?php if ( null === $profile ) { ?>
|
507 |
+
<span class="p3-faded-grey">n/a</span>
|
508 |
+
<?php } else { ?>
|
509 |
+
<?php printf( '%.1f%%', $profile->averages['plugin_impact'] ); ?>
|
510 |
+
<?php } ?>
|
511 |
+
</div>
|
512 |
+
<div class="p3-callout-caption">( of page load time )</div>
|
513 |
+
</div>
|
514 |
+
</div>
|
515 |
+
</td>
|
516 |
+
|
517 |
+
<!-- Fourth callout cell -->
|
518 |
+
<td class="p3-callout">
|
519 |
+
<div class="p3-callout-outer-wrapper qtip-tip" title="Total number of database queries per visit."
|
520 |
+
<?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
|
521 |
+
<div class="p3-callout-inner-wrapper">
|
522 |
+
<div class="p3-callout-caption">MySQL Queries</div>
|
523 |
+
<div class="p3-callout-data">
|
524 |
+
<?php if ( null === $profile ) { ?>
|
525 |
+
<span class="p3-faded-grey">n/a</span>
|
526 |
+
<?php } else { ?>
|
527 |
+
<?php echo round( $profile->averages['queries'] ); ?>
|
528 |
+
<?php } ?>
|
529 |
+
</div>
|
530 |
+
<div class="p3-callout-caption">Per visit</div>
|
531 |
+
</div>
|
532 |
+
</div>
|
533 |
+
</td>
|
534 |
+
|
535 |
+
</tr>
|
536 |
+
</table>
|
537 |
+
|
538 |
+
<!-- Dialog for IP settings -->
|
539 |
+
<div id="p3-ip-dialog" class="p3-dialog">
|
540 |
+
<div>
|
541 |
+
IP address or pattern:<br />
|
542 |
+
<input type="text" id="p3-advanced-ip" style="width:90%;" size="35"
|
543 |
+
value="<?php echo $GLOBALS['p3_profiler']->get_ip(); ?>" title="Enter IP address or regular expression pattern" />
|
544 |
+
<br />
|
545 |
+
<em class="p3-em">Example: 1.2.3.4 or ( 1.2.3.4|4.5.6.7 )</em>
|
546 |
+
</div>
|
547 |
+
<br />
|
548 |
+
<div>
|
549 |
+
<input type="checkbox" id="p3-disable-opcode-cache" checked="checked" />
|
550 |
+
<label for="p3-disable-opcode-cache">Attempt to disable opcode caches <em>( recommended )</em></label>
|
551 |
+
<br />
|
552 |
+
<em class="p3-em">This can increase accuracy in plugin detection, but decrease accuracy in timing</em>
|
553 |
+
</div>
|
554 |
+
</div>
|
555 |
+
|
556 |
+
<!-- Dialog for iframe scanner -->
|
557 |
+
<div id="p3-scanner-dialog" class="p3-dialog">
|
558 |
+
<iframe id="p3-scan-frame" frameborder="0"
|
559 |
+
data-defaultsrc="<?php echo ( true === force_ssl_admin() ? str_replace( 'http://', 'https://', home_url() ) : home_url() ); ?>">
|
560 |
+
</iframe>
|
561 |
+
<div id="p3-scan-caption">
|
562 |
+
The scanner will analyze the speed and resource usage of all active plugins on your website.
|
563 |
+
It may take several minutes, and this window must remain open for the scan to finish successfully.
|
564 |
+
</div>
|
565 |
+
<div id="p3-manual-scan-caption" style="display: none;">
|
566 |
+
<table>
|
567 |
+
<tr>
|
568 |
+
<td>
|
569 |
+
Click the links and pages of your site, and the scanner will
|
570 |
+
analyze the speed and resource usage of all of your active
|
571 |
+
plugins.
|
572 |
+
</td>
|
573 |
+
<td width="220">
|
574 |
+
<a href="javascript:;" id="p3-manual-scan-cancel">Cancel</a>
|
575 |
+
|
576 |
+
<span class="p3-big-button">
|
577 |
+
<input type="checkbox" id="p3-manual-scan-done-submit" checked="checked" />
|
578 |
+
<label for="p3-manual-scan-done-submit">I'm Done</label>
|
579 |
+
</span>
|
580 |
+
</td>
|
581 |
+
</tr>
|
582 |
+
</table>
|
583 |
+
</div>
|
584 |
+
</div>
|
585 |
+
|
586 |
+
<!-- Dialog for choose manual or auto scan -->
|
587 |
+
<div id="p3-scan-name-dialog" class="p3-dialog">
|
588 |
+
<div style="padding-top: 10px;">Scan name:
|
589 |
+
<input type="text" name="p3_scan_name" id="p3-scan-name" title="Enter scan name here"
|
590 |
+
value="scan_<?php echo date( 'Y-m-d' ); ?>_<?php echo substr( md5( uniqid() ), -8 );?>" size="35" maxlength="100" />
|
591 |
+
</div>
|
592 |
+
<div style="padding-top: 10px;"><em class="p3-em">Enter the name of a previous scan to continue scanning</em></div>
|
593 |
+
<br />
|
594 |
+
<div class="p3-big-button">
|
595 |
+
<input type="checkbox" id="p3-auto-scan-submit" checked="checked" /><label for="p3-auto-scan-submit">Auto Scan</label>
|
596 |
+
<input type="checkbox" id="p3-manual-scan-submit" checked="checked" /><label for="p3-manual-scan-submit">Manual Scan</label>
|
597 |
+
</div>
|
598 |
+
</div>
|
599 |
+
|
600 |
+
<!-- Dialog for progress bar -->
|
601 |
+
<div id="p3-progress-dialog" class="p3-dialog">
|
602 |
+
<div id="p3-scanning-caption">
|
603 |
+
Scanning ...
|
604 |
+
</div>
|
605 |
+
<div id="p3-progress"></div>
|
606 |
+
|
607 |
+
<!-- Cancel button -->
|
608 |
+
<div class="p3-big-button" id="p3-cancel-scan-buttonset">
|
609 |
+
<input type="checkbox" id="p3-cancel-scan-submit" checked="checked" /><label for="p3-cancel-scan-submit">Stop Scan</label>
|
610 |
+
</div>
|
611 |
+
|
612 |
+
<!-- View / resume buttons -->
|
613 |
+
<div class="p3-big-button" id="p3-resume-scan-buttonset" style="display: none;">
|
614 |
+
<input type="checkbox" id="p3-resume-scan-submit" checked="checked" /><label for="p3-resume-scan-submit">Resume</label>
|
615 |
+
<input type="checkbox" id="p3-view-incomplete-results-submit" checked="checked" data-scan-name="" />
|
616 |
+
<label for="p3-view-incomplete-results-submit">View Results</label>
|
617 |
+
</div>
|
618 |
+
|
619 |
+
<!-- View results button -->
|
620 |
+
<div class="p3-big-button" id="p3-view-results-buttonset" style="display: none;">
|
621 |
+
<input type="checkbox" id="p3-view-results-submit" checked="checked" data-scan-name="" />
|
622 |
+
<label for="p3-view-results-submit">View Results</label>
|
623 |
+
</div>
|
624 |
+
</div>
|
templates/fix-flag-file.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php if ( file_exists( P3_FLAG_FILE ) && is_writable( P3_FLAG_FILE ) ) { ?>
|
2 |
+
<h3>Fixed!</h3>
|
3 |
+
The profiling flag file has been created and is writable.
|
4 |
+
<?php } else { ?>
|
5 |
+
<h3>Still broken!</h3>
|
6 |
+
The profiling flag file needs to exist and be writable.
|
7 |
+
<?php } ?>
|
8 |
+
<br /><br />
|
9 |
+
<code><?php echo realpath( P3_FLAG_FILE ); ?></code>
|
10 |
+
<br /><br />
|
11 |
+
<input type="button" class="button" onclick="location.href='<?php echo add_query_arg( array( 'p3_action' => 'current-scan' ) ); ?>';" value="Go back" />
|
templates/help.php
ADDED
@@ -0,0 +1,471 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<script type="text/javascript">
|
2 |
+
// Set up the tabs
|
3 |
+
jQuery( document ).ready( function( $) {
|
4 |
+
$( "#toggle-glossary" ).click( function() {
|
5 |
+
$( "#glossary-terms" ).toggle();
|
6 |
+
if ( "Hide Glossary" == $( "#toggle-glossary" ).html() ) {
|
7 |
+
$( "#toggle-glossary" ).html( "Show Glossary" );
|
8 |
+
} else {
|
9 |
+
$( "#toggle-glossary" ).html( "Hide Glossary" );
|
10 |
+
}
|
11 |
+
});
|
12 |
+
$( "#glossary-terms td.term" ).click( function() {
|
13 |
+
var definition = $( "div.definition", $( this ) ).html();
|
14 |
+
$( "#p3-glossary-term-display" ).html( definition );
|
15 |
+
$( "#p3-glossary-table td.term.hover" ).removeClass( "hover" );
|
16 |
+
$( this ).addClass( "hover" );
|
17 |
+
});
|
18 |
+
$( "#p3-glossary-table td.term:first" ).click();
|
19 |
+
$( "#p3-hide-glossary" ).click( function() {
|
20 |
+
if ( "Hide" == $( this ).html() ) {
|
21 |
+
$( "#p3-glossary-table tbody" ).hide();
|
22 |
+
$( "#p3-glossary-table tfoot" ).hide();
|
23 |
+
$( this ).html( "Show" );
|
24 |
+
} else {
|
25 |
+
$( "#p3-glossary-table tbody" ).show();
|
26 |
+
$( "#p3-glossary-table tfoot" ).show();
|
27 |
+
$( this ).html( "Hide" );
|
28 |
+
}
|
29 |
+
});
|
30 |
+
// $( "#p3-hide-glossary" ).trigger( "click" );
|
31 |
+
$( "#p3-glossary-container" ).dblclick( function() {
|
32 |
+
$( "#p3-hide-glossary" ).trigger( "click" );
|
33 |
+
});
|
34 |
+
|
35 |
+
// Automatically create the table of contents
|
36 |
+
var links = [];
|
37 |
+
var i = 1;
|
38 |
+
$( "h2.p3-help-question:not(:first )" ).each( function() {
|
39 |
+
$( this ).before( '<a name="q' + i + '"> </a>' );
|
40 |
+
links.push( '<li><a href="#q' + i + '">' + $( this ).html() + '</a></li>' );
|
41 |
+
i++;
|
42 |
+
});
|
43 |
+
$( "div.p3-question blockquote:not(:first )" ).each( function() {
|
44 |
+
$( this ).after( '<a href="#top">Back to top</a>' );
|
45 |
+
});
|
46 |
+
$( "#p3-help-toc" ).html( "<ul>" + links.join( "\n" ) + "</ul>" );
|
47 |
+
|
48 |
+
$( "div.p3-question" ).corner( "round 8px" )
|
49 |
+
});
|
50 |
+
</script>
|
51 |
+
|
52 |
+
<div class="p3-question">
|
53 |
+
<a name="top"> </a>
|
54 |
+
<h2 class="p3-help-question">Contents</h2>
|
55 |
+
<blockquote>
|
56 |
+
<div id="p3-help-toc"></div>
|
57 |
+
</blockquote>
|
58 |
+
</div>
|
59 |
+
|
60 |
+
|
61 |
+
<div class="p3-question">
|
62 |
+
<h2 class="p3-help-question">What does the P3 plugin do?</h2>
|
63 |
+
<blockquote>
|
64 |
+
This plugin does just what its name says, it creates a profile of your WordPress site's plugins' performance
|
65 |
+
by measuring their impact on your site's load time.
|
66 |
+
<br /><br />
|
67 |
+
Often times, WordPress sites load slowly because of poorly-configured plugins or because there are so many of
|
68 |
+
them. This plugin can help you narrow down the cause of your site's slowness.
|
69 |
+
</blockquote>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<div class="p3-question">
|
73 |
+
<h2 class="p3-help-question">How do I use this?</h2>
|
74 |
+
<blockquote>
|
75 |
+
Simply click "Start Scan" to run an automated scan of your site. The scanner generates some traffic on your
|
76 |
+
site and monitors your site's performance on the server, then shows you the results. With this information,
|
77 |
+
you can decide what action to take.
|
78 |
+
</blockquote>
|
79 |
+
</div>
|
80 |
+
|
81 |
+
<div class="p3-question">
|
82 |
+
<h2 class="p3-help-question">What do I do with these results?</h2>
|
83 |
+
<blockquote>
|
84 |
+
If your site loads in an acceptable time (usually < 0.5 seconds), you might consider other explanation for
|
85 |
+
sluggish loading. For example, loading large images, large videos, or a lot of content can cause slowness.
|
86 |
+
Tools like <a href="http://www.webpagetest.org/" target="_blank">webpagetest.org</a>, <a href="http://getfirebug.com/"
|
87 |
+
target="_blank">Firebug</a>, <a href="http://tools.pingdom.com/" target="_blank">Pingdom tools</a>, or
|
88 |
+
<a href="http://developer.apple.com/technologies/safari/developer-tools.html" target="_blank">Safari Developer Tools</a>
|
89 |
+
or <a href="http://code.google.com/chrome/devtools/docs/overview.html" target="_blank">Chrome Developer Tools</a> can
|
90 |
+
show you a connection breakdown of your site's content.
|
91 |
+
</blockquote>
|
92 |
+
</div>
|
93 |
+
|
94 |
+
<div class="p3-question">
|
95 |
+
<h2 class="p3-help-question">How does this work?</h2>
|
96 |
+
<blockquote>
|
97 |
+
When you activate the plugin by clicking "Start Scan," it detects visits from your IP address, and actively monitors
|
98 |
+
all <a href="http://php.net/functions" target="_blank">php user defined function calls</a> while the server generates
|
99 |
+
your WordPress pages. It then records the information in a report file you can view later. When the scan is complete,
|
100 |
+
or you click "Stop Scan," the plugin becomes dormant again.
|
101 |
+
</blockquote>
|
102 |
+
</div>
|
103 |
+
|
104 |
+
<div class="p3-question">
|
105 |
+
<h2 class="p3-help-question">How does my site load the plugin?</h2>
|
106 |
+
<blockquote>
|
107 |
+
The plugin should be active at the earliest point in the code execution. The plugin can be loaded through an
|
108 |
+
auto_prepend_file configuration directive from a .htaccess file or a <a href="http://php.net/manual/en/configuration.file.per-user.php"
|
109 |
+
target="_blank">.user.ini</a>Â file, but be careful. The .user.ini files are cached, so you must remove the entry from your
|
110 |
+
.user.ini file before you remove this plugin.
|
111 |
+
<br /><br />
|
112 |
+
This plugin automatically enables itself in .htaccess if possible, or, if that doesn't succeed, it creates a
|
113 |
+
<a href="http://codex.wordpress.org/Must_Use_Plugins" target="_blank">must-use</a>Â plugin to load before other plugins.
|
114 |
+
If neither of those methods work, it runs like a regular plugin.
|
115 |
+
<br /><br />
|
116 |
+
You are currently using:
|
117 |
+
<?php
|
118 |
+
|
119 |
+
// .htaccess file test
|
120 |
+
$htaccess_file = P3_PATH . '/../../../.htaccess';
|
121 |
+
$htaccess_content = '';
|
122 |
+
if ( file_exists( $htaccess_file ) ) {
|
123 |
+
$htaccess_content = extract_from_markers( $htaccess_file, 'p3-profiler' );
|
124 |
+
foreach ( $htaccess_content as $k => $v ) {
|
125 |
+
if ( '#' == substr( trim( $v ), 0, 1 ) ) {
|
126 |
+
unset( $htaccess_content[$k] ); // Get rid of comment lines
|
127 |
+
}
|
128 |
+
}
|
129 |
+
$htaccess_content = implode( "\n", $htaccess_content );
|
130 |
+
}
|
131 |
+
|
132 |
+
// must-use plugin file
|
133 |
+
$mu_file = P3_PATH . '/../../mu-plugins/p3-profiler.php';
|
134 |
+
|
135 |
+
// List php ini files
|
136 |
+
$ini_files = array_filter(
|
137 |
+
array_merge(
|
138 |
+
array( php_ini_loaded_file() ),
|
139 |
+
explode( ',', php_ini_scanned_files() )
|
140 |
+
)
|
141 |
+
);
|
142 |
+
?>
|
143 |
+
|
144 |
+
<?php /* .htaccess file is there, the profiler content is there, hasn't been commented out, and the auto_prepend_file directive is active */ ?>
|
145 |
+
<?php if (
|
146 |
+
file_exists( $htaccess_file ) &&
|
147 |
+
!empty( $htaccess_content ) &&
|
148 |
+
false !== strpos( $htaccess_content, 'start-profile.php' ) &&
|
149 |
+
false !== strpos( ini_get( 'auto_prepend_file' ), 'start-profile.php' ) ) { ?>
|
150 |
+
<a href="http://php.net/manual/en/configuration.changes.php" target="_blank">.htaccess file</a>
|
151 |
+
- <code><?php echo realpath( $htaccess_file ); ?></code>
|
152 |
+
<?php /* the auto_prepend_file directive is active */ ?>
|
153 |
+
<?php } elseif ( false !== strpos( ini_get( 'auto_prepend_file' ), 'start-profile.php' ) ){ ?>
|
154 |
+
<a href="http://www.php.net/manual/en/configuration.file.php" target="_blank">php.ini</a>
|
155 |
+
<?php if ( version_compare( phpversion(), '5.3.0' ) >= 0 ) { ?>
|
156 |
+
or <a href="http://www.php.net/manual/en/configuration.file.per-user.php" target="_blank">.user.ini</a>
|
157 |
+
<?php } ?>
|
158 |
+
entry from one of these files:
|
159 |
+
<ul>
|
160 |
+
<?php foreach ( $ini_files as $file ) { ?>
|
161 |
+
<ol><code><?php echo trim( $file ); ?></code></ol>
|
162 |
+
<?php } ?>
|
163 |
+
</ul>
|
164 |
+
<?php /* must-use plugin file is there and not-empty */ ?>
|
165 |
+
<?php } elseif ( file_exists( $mu_file ) && filesize( $mu_file ) > 0 ){ ?>
|
166 |
+
<a href="http://codex.wordpress.org/Must_Use_Plugins" target="_blank">must-use plugin</a>
|
167 |
+
- <code><?php echo realpath( $mu_file ); ?></code>
|
168 |
+
<?php /* default, using this plugin file */ ?>
|
169 |
+
<?php } else { ?>
|
170 |
+
<a href="http://codex.wordpress.org/Plugins" target="_blank">plugin</a>
|
171 |
+
- <code><?php echo realpath( P3_PATH . '/p3-profiler.php' ); ?></code>
|
172 |
+
<?php } ?>
|
173 |
+
</blockquote>
|
174 |
+
</div>
|
175 |
+
|
176 |
+
<div class="p3-question">
|
177 |
+
<h2 class="p3-help-question">How accurate are these results?</h2>
|
178 |
+
<blockquote>
|
179 |
+
The results have an inherent margin of error because of the nature of the tool and its multi-layered design.
|
180 |
+
The plugin changes the environment to measure it, and that makes it impossible to get completely accurate results.
|
181 |
+
<br /><br />
|
182 |
+
It gets really close, though! The "margin of error" on the Advanced Metrics page displays the discrepancy between
|
183 |
+
the measured results (the time for your site's PHP code to completely run) and the expected results (sum of the plugins,
|
184 |
+
core, theme, profile load times) to show you the plugin's accuracy.
|
185 |
+
<br /><br />
|
186 |
+
If you want more accurate results, you'll need to resort to a different profiler like <a href="http://xdebug.org/" target="_blank">xdebug</a>,
|
187 |
+
but this will not break down results by plugin.
|
188 |
+
</blockquote>
|
189 |
+
</div>
|
190 |
+
|
191 |
+
<div class="p3-question">
|
192 |
+
<h2 class="p3-help-question">Why are some plugins slow?</h2>
|
193 |
+
<blockquote>
|
194 |
+
WordPress is a complex ecosystem of plugins and themes, and it lives on a complex ecosystem of software on your web server.
|
195 |
+
<br /><br />
|
196 |
+
If a plugin runs slowly just once, it's probably an anomaly, a transient hiccup, and you can safely ignore it.
|
197 |
+
<br /><br />
|
198 |
+
If a plugin shows slowness once on a reguarly basis (e.g. every time you run a scan, once a day, once an hour), a scheduled
|
199 |
+
task might be causing it. Plugins that backup your site, monitor your site for changes, contact outside sources (e.g. RSS feeds),
|
200 |
+
warm up caches, etc. can exhibit this kind of behavior.
|
201 |
+
<br /><br />
|
202 |
+
If a plugin shows as fast-slow-fast-slow-fast-slow, it could be caused as the plugin loads its main code, then a follow-up piece
|
203 |
+
of code, like a piece of generated JavaScript.
|
204 |
+
<br /><br />
|
205 |
+
If a plugin is consistently shows slowness, you might want to contact the plugin author or try deactivating the plugin temporarily
|
206 |
+
to see if it makes a difference on your site.
|
207 |
+
</blockquote>
|
208 |
+
</div>
|
209 |
+
|
210 |
+
<div class="p3-question">
|
211 |
+
<h2 class="p3-help-question">How are these results different from YSlow / PageSpeed / Webpagetest.org / Pingdom Tools?</h2>
|
212 |
+
<blockquote>
|
213 |
+
This plugin measures how your site was generated on the server. Tools like <a href="http://developer.yahoo.com/yslow/"
|
214 |
+
target="_blank">YSlow</a>, <a href="https://developers.google.com/pagespeed/" target="_blank">PageSpeed</a>,
|
215 |
+
<a href="http://www.webpagetest.org/" target="_blank">Webpagetest.org</a>, and <a href="http://tools.pingdom.com/fpt/"
|
216 |
+
target="_blank">Pingdom Tools</a> measure how your site looks to the browser.
|
217 |
+
</blockquote>
|
218 |
+
</div>
|
219 |
+
|
220 |
+
<div class="p3-question">
|
221 |
+
<h2 class="p3-help-question">What can interfere with testing?</h2>
|
222 |
+
<blockquote>
|
223 |
+
Opcode caches can interfere with PHP backtraces. Leaving opcode caches turned on will result in timing that more accurately
|
224 |
+
reflects your site's real performance, but the function calls to plugins may be "optimized" out of the backtraces and some
|
225 |
+
plugins (especially those with only one hook) might not show up. Disabling opcode caches results in slower times, but shows all plugins.
|
226 |
+
<br /><br />
|
227 |
+
By default, this plugin attempts to clear any opcode caches before it runs. You can change this setting by clicking "Advanced
|
228 |
+
Settings" under "Start Scan."
|
229 |
+
<br /><br />
|
230 |
+
Caching plugins that have an option to disable caches for logged in users will not give you the same performance profile that
|
231 |
+
an anonymous users experience. To get around this, you should select a manual scan, then run an incognito browser window, or run
|
232 |
+
another browser, and browse your site as a logged out user. When you're finished, click "I'm done," and your scan should show the
|
233 |
+
performance of an anonymous user.
|
234 |
+
</blockquote>
|
235 |
+
</div>
|
236 |
+
|
237 |
+
<div class="p3-question">
|
238 |
+
<h2 class="p3-help-question">How much room do these profiles take up on my server</h2>
|
239 |
+
<blockquote>
|
240 |
+
<?php
|
241 |
+
$total_size = 0;
|
242 |
+
$dir = opendir( P3_PROFILES_PATH );
|
243 |
+
while ( false !== ( $file = readdir( $dir ) ) ) {
|
244 |
+
if ( '.' != $file && '..' != $file && '.json' == substr( $file, -5 ) ) {
|
245 |
+
$total_size += filesize( P3_PROFILES_PATH . "/$file" );
|
246 |
+
}
|
247 |
+
}
|
248 |
+
closedir( $dir );
|
249 |
+
|
250 |
+
?>
|
251 |
+
The scans are stored in <code><?php echo realpath( P3_PROFILES_PATH ); ?></code> and
|
252 |
+
take up <?php echo $this->readable_size( $total_size ); ?> of disk space. Each time you
|
253 |
+
run a scan, this storage requirement goes up, and each time you delete a scan, it
|
254 |
+
goes down.
|
255 |
+
</blockquote>
|
256 |
+
</div>
|
257 |
+
|
258 |
+
<div class="p3-question">
|
259 |
+
<h2 class="p3-help-question">Is this plugin always running?</h2>
|
260 |
+
<blockquote>
|
261 |
+
The short answer is no.
|
262 |
+
<br /><br />
|
263 |
+
The more detailed answer is the loader is always running, but checks very early in the page
|
264 |
+
loading process to see if you've enabled profiling mode and if the user's IP address matches
|
265 |
+
the IP address the plugin is monitoring. For multisite installations, it also matches the site URL.
|
266 |
+
If all these match, the plugin becomes active and profiles. Otherwise, your site loads as normal
|
267 |
+
with no other code overhead.
|
268 |
+
<br /><br />
|
269 |
+
Deactivating the plugin ensures it's not running at all, and does not delete your scans. However,
|
270 |
+
uninstalling the plugin does delete your scans.
|
271 |
+
</blockquote>
|
272 |
+
</div>
|
273 |
+
|
274 |
+
<div class="p3-question">
|
275 |
+
<h2 class="p3-help-question">How can I test specific pages on my site?</h2>
|
276 |
+
<blockquote>
|
277 |
+
When you start a scan, choose "Manual Scan" and then you can visit specific links on your site that
|
278 |
+
you want to profile. If you want to profile the admin section, just click the "X" in the top right
|
279 |
+
of the scan window and you'll be returned to your admin section. You can browse as normal, then come
|
280 |
+
back to the profile page and click "Stop Scan" when you're ready to view the results.
|
281 |
+
<br /><br />
|
282 |
+
To scan your site as an anonymous user, select "Manual Mode" as above, but instead of clicking your
|
283 |
+
site in the scan window, open a different browser (or an incognito window) and browse your site as a
|
284 |
+
logged out user. When you're done, close that browser and return to your admin. Click "I'm done" and
|
285 |
+
view your scan results.
|
286 |
+
</blockquote>
|
287 |
+
</div>
|
288 |
+
|
289 |
+
<div class="p3-question">
|
290 |
+
<h2 class="p3-help-question">My plugins don't seem to cause site slowness. Why is my site still slow?</h2>
|
291 |
+
<blockquote>
|
292 |
+
Your site can be slow for a number of reasons. Your site could have a lot of traffic, other sites on
|
293 |
+
your server could have a lot of traffic, you could be referencing content from other sites that are slow,
|
294 |
+
your internet connection could be slow, your server could be out of RAM, your site could be very image
|
295 |
+
heavy, your site could require a lot of HTTP requests, etc. In short, a lot of factors can cause slowness
|
296 |
+
on your site
|
297 |
+
<br /><br />
|
298 |
+
Your next stop should be to <a href="http://tools.pingdom.com/" target="_blank">Pingdom Tools</a>,
|
299 |
+
<a href="http://webpagetest.org/" target="_blank">Webpage Test</a>, <a href="http://developer.yahoo.com/yslow/"
|
300 |
+
target="_blank">YSlow</a>, <a href="https://developers.google.com/pagespeed/" target="_blank">Google PageSpeed</a>,
|
301 |
+
and your browser's development tools like <a href="http://getfirebug.com/" target="_blank">Firebug</a> for Firefox,
|
302 |
+
<a href="http://code.google.com/chrome/devtools/docs/overview.html" target="_blank">Chrome Developer Tools</a>Â for
|
303 |
+
Chrome, or <a href="http://developer.apple.com/technologies/safari/developer-tools.html" target="_blank">Safari
|
304 |
+
Developer Tools</a>Â for Safari.
|
305 |
+
<br /><br />
|
306 |
+
After you've tuned your site up as much as possible, if you're still not happy with its performance, you should
|
307 |
+
consult your site/server administrator or hosting support.
|
308 |
+
</blockquote>
|
309 |
+
</div>
|
310 |
+
|
311 |
+
<div class="p3-question">
|
312 |
+
<h2 class="p3-help-question" style="border-bottom-width: 0px !important;">Glossary</h2>
|
313 |
+
<blockquote>
|
314 |
+
<div>
|
315 |
+
<div id="p3-glossary-container">
|
316 |
+
<div class="ui-widget-header" id="p3-glossary-header" style="padding: 8px;">
|
317 |
+
<strong>Glossary</strong>
|
318 |
+
<div style="position: relative; top: 0px; right: 80px; float: right;">
|
319 |
+
<a href="javascript:;" id="p3-hide-glossary">Hide</a>
|
320 |
+
</div>
|
321 |
+
</div>
|
322 |
+
<div>
|
323 |
+
<table class="p3-results-table" id="p3-glossary-table" cellpadding="0" cellspacing="0" border="0">
|
324 |
+
<tbody>
|
325 |
+
<tr>
|
326 |
+
<td colspan="2" style="border-left-width: 1px !important;">
|
327 |
+
<div id="glossary">
|
328 |
+
<table width="100%" cellpadding="0" cellspacing="0" border="0" id="glossary-terms">
|
329 |
+
<tr>
|
330 |
+
<td width="200" class="term"><strong>Total Load Time</strong>
|
331 |
+
<div id="total-load-time-definition" style="display: none;" class="definition">
|
332 |
+
The length of time the site took to load. This is an observed measurement (start timing when
|
333 |
+
the page was requested, stop timing when the page was delivered to the browser, calculate the
|
334 |
+
difference). Lower is better.
|
335 |
+
</div>
|
336 |
+
</td>
|
337 |
+
<td width="400" rowspan="12" id="p3-glossary-term-display"> </td>
|
338 |
+
</tr>
|
339 |
+
<tr>
|
340 |
+
<td class="term"><strong>Site Load Time</strong>
|
341 |
+
<div id="site-load-time-definition" style="display: none;" class="definition">
|
342 |
+
The calculated total load time minus the profile overhead. This is closer to your site's
|
343 |
+
real-life load time. Lower is better.
|
344 |
+
</div>
|
345 |
+
</td>
|
346 |
+
</tr>
|
347 |
+
<tr>
|
348 |
+
<td class="term"><strong>Profile Overhead</strong>
|
349 |
+
<div id="profile-overhead-definition" style="display: none;" class="definition">
|
350 |
+
The load time spent profiling code. Because the profiler slows down your load time, it is
|
351 |
+
important to know how much impact the profiler has. However, it doesn't impact your site's
|
352 |
+
real-life load time.
|
353 |
+
</div>
|
354 |
+
</td>
|
355 |
+
</tr>
|
356 |
+
<tr>
|
357 |
+
<td class="term"><strong>Plugin Load Time</strong>
|
358 |
+
<div id="plugin-load-time-definition" style="display: none;" class="definition">
|
359 |
+
The load time caused by plugins. Because of WordPress' construction, we can trace a
|
360 |
+
function call from a plugin through a theme through the core. The profiler prioritizes
|
361 |
+
plugin calls first, theme calls second, and core calls last. Lower is better.
|
362 |
+
</div>
|
363 |
+
</td>
|
364 |
+
</tr>
|
365 |
+
<tr>
|
366 |
+
<td class="term"><strong>Theme Load Time</strong>
|
367 |
+
<div id="theme-load-time-definition" style="display: none;" class="definition">
|
368 |
+
The load time spent applying the theme. Because of WordPress' construction, we can trace a
|
369 |
+
function call from a plugin through a theme through the core. The profiler prioritizes
|
370 |
+
plugin calls first, theme calls second, and core calls last. Lower is better.
|
371 |
+
</div>
|
372 |
+
</td>
|
373 |
+
</tr>
|
374 |
+
<tr>
|
375 |
+
<td class="term"><strong>Core Load Time</strong>
|
376 |
+
<div id="core-load-time-definition" style="display: none;" class="definition">
|
377 |
+
The load time caused by the WordPress core. Because of WordPress' construction, we can trace
|
378 |
+
a function call from a plugin through a theme through the core. The profiler prioritizes
|
379 |
+
plugin calls first, theme calls second, and core calls last. This will probably be constant.
|
380 |
+
</div>
|
381 |
+
</td>
|
382 |
+
</tr>
|
383 |
+
<tr>
|
384 |
+
<td class="term"><strong>Margin of Error</strong>
|
385 |
+
<div id="drift-definition" style="display: none;" class="definition">
|
386 |
+
This is the difference between the observed runtime (what actually happened) and expected
|
387 |
+
runtime (adding the plugin runtime, theme runtime, core runtime, and profiler overhead).
|
388 |
+
<br /><br />
|
389 |
+
There are several reasons this margin of error can exist. Most likely, the profiler is
|
390 |
+
missing microseconds while adding the runtime it observed. Using a network clock to set the
|
391 |
+
time (NTP) can also cause minute timing changes.
|
392 |
+
<br /><br />
|
393 |
+
Ideally, this number should be zero, but there's nothing you can do to change it. It
|
394 |
+
will give you an idea of how accurate the other results are.
|
395 |
+
</div>
|
396 |
+
</td>
|
397 |
+
</tr>
|
398 |
+
<tr>
|
399 |
+
<td class="term"><strong>Observed</strong>
|
400 |
+
<div id="observed-definition" style="display: none;" class="definition">
|
401 |
+
The time the site took to load. This is an observed measurement (start timing when the
|
402 |
+
page was requested, stop timing when the page was delivered to the browser, calculate the
|
403 |
+
difference).
|
404 |
+
</div>
|
405 |
+
</td>
|
406 |
+
</tr>
|
407 |
+
<tr>
|
408 |
+
<td class="term"><strong>Expected</strong>
|
409 |
+
<div id="expected-definition" style="display: none;" class="definition">
|
410 |
+
The expected site load time calculated by adding plugin load time, core load time, theme
|
411 |
+
load time, and profiler overhead.
|
412 |
+
</div>
|
413 |
+
</td>
|
414 |
+
</tr>
|
415 |
+
<tr>
|
416 |
+
<td class="term"><strong>Plugin Function Calls</strong>
|
417 |
+
<div id="plugin-funciton-calls-definition" style="display: none;" class="definition">
|
418 |
+
The number of PHP function calls generated by a plugin. Fewer is better.
|
419 |
+
</div>
|
420 |
+
</td>
|
421 |
+
</tr>
|
422 |
+
<tr>
|
423 |
+
<td class="term"><strong>Memory Usage</strong>
|
424 |
+
<div id="memory-usage-definition" style="display: none;" class="definition">
|
425 |
+
The amount of RAM usage observed. This is reported by
|
426 |
+
<a href="http://php.net/memory_get_peak_usage"
|
427 |
+
target="_blank">memory_get_peak_usage()</a>. Lower is better.
|
428 |
+
</div>
|
429 |
+
</td>
|
430 |
+
</tr>
|
431 |
+
<tr>
|
432 |
+
<td class="term"><strong>MySQL Queries</strong>
|
433 |
+
<div id="mysql-queries-definition" style="display: none;" class="definition">
|
434 |
+
The number of queries sent to the database. This reported by the WordPress function
|
435 |
+
<a href="http://codex.wordpress.org/Function_Reference/get_num_queries"
|
436 |
+
target="_new">get_num_queries()</a>. Fewer is better.
|
437 |
+
</div>
|
438 |
+
</td>
|
439 |
+
</tr>
|
440 |
+
</table>
|
441 |
+
</div>
|
442 |
+
</td>
|
443 |
+
</tr>
|
444 |
+
</tbody>
|
445 |
+
</table>
|
446 |
+
</div>
|
447 |
+
</div>
|
448 |
+
</div>
|
449 |
+
</blockquote>
|
450 |
+
</div>
|
451 |
+
|
452 |
+
<div class="p3-question">
|
453 |
+
<h2 class="p3-help-question">License</h2>
|
454 |
+
<blockquote>
|
455 |
+
<strong>P3 (Plugin Performance Profiler)</strong>
|
456 |
+
<br />
|
457 |
+
<?php if (date('Y') > 2011) : ?>
|
458 |
+
Copyright © 2011-<?php echo date('Y'); ?> <a href="http://www.godaddy.com/" target="_blank">GoDaddy.com</a>. All rights reserved.
|
459 |
+
<?php else : ?>
|
460 |
+
Copyright © 2011 <a href="http://www.godaddy.com/" target="_blank">GoDaddy.com</a>. All rights reserved.
|
461 |
+
<?php endif; ?>
|
462 |
+
<br /><br />
|
463 |
+
This program is offered under the terms of the GNU General Public License Version 2 as published by the Free Software Foundation.
|
464 |
+
<br /><br />
|
465 |
+
This program offered WITHOUT WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
466 |
+
See the GNU General Public License Version 2 for the specific terms.
|
467 |
+
<br /><br />
|
468 |
+
A copy of the GNU General Public License has been provided with this program. Alternatively, you may find a copy of the license here:
|
469 |
+
<a href="http://www.gnu.org/licenses/gpl-2.0.html" target="_blank">http://www.gnu.org/licenses/gpl-2.0.html</a>.
|
470 |
+
</blockquote>
|
471 |
+
</div>
|
templates/index.php
ADDED
@@ -0,0 +1,2 @@
|
|
Â
|
|
Â
|
1 |
+
<?php header( 'Status: 404 Not found' ); ?>
|
2 |
+
Not found
|
templates/list-scans.php
ADDED
@@ -0,0 +1,39 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<form id="scans-filter" method="post">
|
2 |
+
<input type="hidden" name="page" value="<?php echo $_REQUEST ['page']?>" />
|
3 |
+
<?php echo wp_nonce_field( 'delete_scans', 'p3_nonce' ); ?>
|
4 |
+
<?php $this->scan_table->display(); ?>
|
5 |
+
</form>
|
6 |
+
<script type="text/javascript">
|
7 |
+
jQuery(document).ready(function($) {
|
8 |
+
$("input:submit", "#scans-filter").click(function(evt) {
|
9 |
+
if (0 == $("input:checked", $("#scans-filter")).length) {
|
10 |
+
evt.stopPropagation();
|
11 |
+
evt.preventDefault();
|
12 |
+
} else if (!confirm('Are you sure you want to delete these scans?')) {
|
13 |
+
evt.stopPropagation();
|
14 |
+
evt.preventDefault();
|
15 |
+
} else {
|
16 |
+
return true;
|
17 |
+
}
|
18 |
+
});
|
19 |
+
$("a.delete-scan").click(function(evt) {
|
20 |
+
if (confirm('Are you sure you want to delete this scan?')) {
|
21 |
+
|
22 |
+
// De-select the checkboxes
|
23 |
+
$("#scans-filter input:checked").prop("checked", false);
|
24 |
+
|
25 |
+
// Find the parent TR
|
26 |
+
$tr = $(this).parents("tr");
|
27 |
+
|
28 |
+
// Check the checkbox
|
29 |
+
$("input:checkbox", $tr).prop("checked", true);
|
30 |
+
|
31 |
+
// Select the delete action
|
32 |
+
$("select:first", "#scans-filter").val("delete");
|
33 |
+
|
34 |
+
// Submit the form
|
35 |
+
$("#scans-filter").submit();
|
36 |
+
}
|
37 |
+
});
|
38 |
+
});
|
39 |
+
</script>
|
templates/template.php
ADDED
@@ -0,0 +1,117 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$p3_action = '';
|
3 |
+
if ( !empty( $_REQUEST['p3_action'] ) ) {
|
4 |
+
$p3_action = $_REQUEST['p3_action'];
|
5 |
+
}
|
6 |
+
$scan = $this->get_latest_profile();
|
7 |
+
if ( empty( $p3_action ) || 'current-scan' == $p3_action ) {
|
8 |
+
$p3_action = 'current-scan';
|
9 |
+
} elseif ( 'view-scan' == $p3_action && !empty( $_REQUEST['name'] ) ) {
|
10 |
+
$scan = sanitize_file_name( $_REQUEST['name'] );
|
11 |
+
if ( !file_exists( P3_PROFILES_PATH . "/$scan" ) ) {
|
12 |
+
wp_die( '<div id="message" class="error"><p>Scan does not exist</p></div>' );
|
13 |
+
}
|
14 |
+
$scan = P3_PROFILES_PATH . "/$scan";
|
15 |
+
}
|
16 |
+
$button_current_checked = '';
|
17 |
+
$button_history_checked = '';
|
18 |
+
$button_help_checked = '';
|
19 |
+
if ( 'current-scan' == $p3_action ) {
|
20 |
+
$button_current_checked = 'checked="checked"';
|
21 |
+
} elseif ( 'help' == $p3_action || 'fix-flag-file' == $p3_action ) {
|
22 |
+
$button_help_checked = 'checked="checked"';
|
23 |
+
} else {
|
24 |
+
$button_history_checked = 'checked="checked"';
|
25 |
+
}
|
26 |
+
?>
|
27 |
+
<script type="text/javascript">
|
28 |
+
jQuery( document ).ready( function( $) {
|
29 |
+
$( "#button-current-scan" ).click( function() {
|
30 |
+
location.href = "<?php echo add_query_arg( array( 'p3_action' => 'current-scan' ) ); ?>";
|
31 |
+
});
|
32 |
+
$( "#button-history-scans" ).click( function() {
|
33 |
+
location.href = "<?php echo add_query_arg( array( 'p3_action' => 'list-scans' ) ); ?>";
|
34 |
+
});
|
35 |
+
$( "#button-help" ).click( function() {
|
36 |
+
location.href = "<?php echo add_query_arg( array( 'p3_action' => 'help' ) ); ?>";
|
37 |
+
})
|
38 |
+
$( ".p3-button" ).button();
|
39 |
+
$( "#p3-navbar" ).buttonset();
|
40 |
+
$( "#p3-navbar" ).corner( "round 8px" );
|
41 |
+
$( ".p3-big-button" ).buttonset();
|
42 |
+
$( "#p3-results-table tr:even" ).addClass( "even" );
|
43 |
+
$( "td div.row-actions-visible" ).hide();
|
44 |
+
$( "table.wp-list-table td" ).mouseover( function() {
|
45 |
+
$( "div.row-actions-visible", $( this ) ).show();
|
46 |
+
}).mouseout( function() {
|
47 |
+
$( "div.row-actions-visible", $( this ) ).hide();
|
48 |
+
});
|
49 |
+
$( ".qtip-tip" ).each( function() {
|
50 |
+
$( this ).qtip({
|
51 |
+
content: $( this ).attr( "title" ),
|
52 |
+
position: {
|
53 |
+
my: 'top center',
|
54 |
+
at: 'bottom center'
|
55 |
+
},
|
56 |
+
style: {
|
57 |
+
classes: 'ui-tooltip-blue ui-tooltip-shadow'
|
58 |
+
}
|
59 |
+
});
|
60 |
+
});
|
61 |
+
});
|
62 |
+
</script>
|
63 |
+
<div class="wrap">
|
64 |
+
|
65 |
+
<!-- Header icon / title -->
|
66 |
+
<div id="icon-plugins" class="icon32"><br/></div>
|
67 |
+
<h2>P3 - Plugin Performance Profiler</h2>
|
68 |
+
|
69 |
+
<!-- Header navbar -->
|
70 |
+
<div class="ui-widget-header" id="p3-navbar">
|
71 |
+
<input type="radio" name="p3-nav" id="button-current-scan" <?php echo $button_current_checked; ?> />
|
72 |
+
<label for="button-current-scan">Current</label>
|
73 |
+
<input type="radio" name="p3-nav" id="button-history-scans" <?php echo $button_history_checked; ?> />
|
74 |
+
<label for="button-history-scans">History</label>
|
75 |
+
<input type="radio" name="p3-nav" id="button-help" <?php echo $button_help_checked; ?> /><label for="button-help">Help</label>
|
76 |
+
</div>
|
77 |
+
|
78 |
+
<!-- Start / stop button and callouts -->
|
79 |
+
<?php
|
80 |
+
|
81 |
+
// If there's a scan, create a viewer object
|
82 |
+
if ( !empty( $scan ) ) {
|
83 |
+
try {
|
84 |
+
$profile = new P3_Profile_Reader( $scan );
|
85 |
+
} catch ( Exception $e ) {
|
86 |
+
wp_die( '<div id="message" class="error"><p>Error reading scan</p></div>' );
|
87 |
+
}
|
88 |
+
} else {
|
89 |
+
$profile = null;
|
90 |
+
}
|
91 |
+
|
92 |
+
// Show the callouts bar
|
93 |
+
require_once P3_PATH . '/templates/callouts.php';
|
94 |
+
?>
|
95 |
+
|
96 |
+
<!-- View scan or show a list of scans -->
|
97 |
+
<?php if ( ( 'current-scan' == $p3_action && !empty( $scan ) ) || 'view-scan' == $p3_action ) { ?>
|
98 |
+
<?php include_once P3_PATH . '/templates/view-scan.php'; ?>
|
99 |
+
<?php } elseif ( 'help' == $p3_action ) { ?>
|
100 |
+
<?php include_once P3_PATH . '/templates/help.php'; ?>
|
101 |
+
<?php } elseif ( 'fix-flag-file' == $p3_action ) { ?>
|
102 |
+
<?php include_once P3_PATH . '/templates/fix-flag-file.php'; ?>
|
103 |
+
<?php } else { ?>
|
104 |
+
<?php include_once P3_PATH . '/templates/list-scans.php'; ?>
|
105 |
+
<?php } ?>
|
106 |
+
|
107 |
+
</div>
|
108 |
+
|
109 |
+
<div id="p3-copyright">
|
110 |
+
<img src="<?php echo plugins_url() . '/p3-profiler/logo.gif'; ?>" alt="GoDaddy.com logo" title="GoDaddy.com logo" />
|
111 |
+
<br />
|
112 |
+
<?php if (date('Y') > 2011) : ?>
|
113 |
+
Copyright © 2011-<?php echo date('Y'); ?> <a href="http://www.godaddy.com/" target="_blank">GoDaddy.com</a>. All rights reserved.
|
114 |
+
<?php else : ?>
|
115 |
+
Copyright © 2011 <a href="http://www.godaddy.com/" target="_blank">GoDaddy.com</a>. All rights reserved.
|
116 |
+
<?php endif; ?>
|
117 |
+
</div>
|
templates/view-scan.php
ADDED
@@ -0,0 +1,993 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$url_stats = array();
|
3 |
+
$domain = '';
|
4 |
+
if ( !empty( $profile ) ) {
|
5 |
+
$url_stats = $profile->get_stats_by_url();
|
6 |
+
$domain = @parse_url( $profile->report_url, PHP_URL_HOST );
|
7 |
+
}
|
8 |
+
$pie_chart_id = substr( md5( uniqid() ), -8 );
|
9 |
+
$runtime_chart_id = substr( md5( uniqid() ), -8 );
|
10 |
+
$query_chart_id = substr( md5( uniqid() ), -8 );
|
11 |
+
$component_breakdown_chart_id = substr( md5( uniqid() ), -8 );
|
12 |
+
$component_runtime_chart_id = substr( md5( uniqid() ), -8 );
|
13 |
+
?>
|
14 |
+
<script type="text/javascript">
|
15 |
+
|
16 |
+
/**************************************************************/
|
17 |
+
/** Init **/
|
18 |
+
/**************************************************************/
|
19 |
+
|
20 |
+
// Raw json data ( used in the charts for tooltip data
|
21 |
+
var _data = [];
|
22 |
+
<?php if ( !empty( $scan ) && file_exists( $scan ) ) { ?>
|
23 |
+
<?php foreach ( file( $scan, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ) as $line ) { ?>
|
24 |
+
_data.push(<?php echo $line; ?>);
|
25 |
+
<?php } ?>
|
26 |
+
<?php } ?>
|
27 |
+
|
28 |
+
// Set up the tabs
|
29 |
+
jQuery( document ).ready( function( $) {
|
30 |
+
$( "#p3-tabs" ).tabs();
|
31 |
+
$( "#results-table tr:even" ).addClass( "even" );
|
32 |
+
$( "#p3-email-sending-dialog" ).dialog({
|
33 |
+
'autoOpen' : false,
|
34 |
+
'closeOnEscape' : false,
|
35 |
+
'draggable' : false,
|
36 |
+
'resizable' : false,
|
37 |
+
'modal' : true,
|
38 |
+
'width' : 325,
|
39 |
+
'height' : 120,
|
40 |
+
'dialogClass' : 'noTitle'
|
41 |
+
});
|
42 |
+
$( "#p3-email-results-dialog" ).dialog({
|
43 |
+
'autoOpen' : false,
|
44 |
+
'closeOnEscape' : true,
|
45 |
+
'draggable' : false,
|
46 |
+
'resizable' : false,
|
47 |
+
'modal' : true,
|
48 |
+
'width' : 500,
|
49 |
+
'height' : 560,
|
50 |
+
'title' : "Email Report",
|
51 |
+
'buttons' :
|
52 |
+
[
|
53 |
+
{
|
54 |
+
text: 'Send',
|
55 |
+
'class' : 'button-secondary',
|
56 |
+
click: function() {
|
57 |
+
data = {
|
58 |
+
'p3_to' : jQuery( '#p3-email-results-to' ).val(),
|
59 |
+
'p3_from' : jQuery( '#p3-email-results-from' ).val(),
|
60 |
+
'p3_subject' : jQuery( '#p3-email-results-subject' ).val(),
|
61 |
+
'p3_results' : jQuery( "#p3-email-results-results" ).val(),
|
62 |
+
'p3_message' : jQuery( "#p3-email-results-message" ).val(),
|
63 |
+
'action' : 'p3_send_results',
|
64 |
+
'p3_nonce' : '<?php echo wp_create_nonce( 'p3_ajax_send_results' ); ?>'
|
65 |
+
}
|
66 |
+
|
67 |
+
// Open the "loading" dialog
|
68 |
+
$( "#p3-email-sending-success" ).hide();
|
69 |
+
$( "#p3-email-sending-error" ).hide();
|
70 |
+
$( "#p3-email-sending-loading" ).show();
|
71 |
+
$( "#p3-email-sending-close" ).hide();
|
72 |
+
$( "#p3-email-sending-dialog" ).dialog( "open" );
|
73 |
+
|
74 |
+
// Send the data
|
75 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
76 |
+
if ( "1" == response ) {
|
77 |
+
$( "#p3-email-success-recipient" ).html( jQuery( '#p3-email-results-to' ).val() );
|
78 |
+
$( "#p3-email-sending-success" ).show();
|
79 |
+
$( "#p3-email-sending-error" ).hide();
|
80 |
+
$( "#p3-email-sending-loading" ).hide();
|
81 |
+
$( "#p3-email-sending-close" ).show();
|
82 |
+
} else {
|
83 |
+
if ( "-1" == response ) {
|
84 |
+
$( "#p3-email-error" ).html( "nonce error" );
|
85 |
+
} else if ( "0" == response.charAt( 0 ) ) {
|
86 |
+
$( "#p3-email-error" ).html( response.substr( 2 ) );
|
87 |
+
} else {
|
88 |
+
$( "#p3-email-error" ).html( "unknown error" );
|
89 |
+
}
|
90 |
+
$( "#p3-email-sending-success" ).hide();
|
91 |
+
$( "#p3-email-sending-error" ).show();
|
92 |
+
$( "#p3-email-sending-loading" ).hide();
|
93 |
+
$( "#p3-email-sending-close" ).show();
|
94 |
+
}
|
95 |
+
});
|
96 |
+
}
|
97 |
+
},
|
98 |
+
{
|
99 |
+
text: 'Cancel',
|
100 |
+
'class': 'p3-cancel-button',
|
101 |
+
click: function() {
|
102 |
+
$( this ).dialog( "close" );
|
103 |
+
}
|
104 |
+
}
|
105 |
+
]
|
106 |
+
});
|
107 |
+
$( "#p3-email-sending-close-submit" ).click( function() {
|
108 |
+
$( this ).prop( "checked", true );
|
109 |
+
$( this ).button( "refresh" );
|
110 |
+
$( "#p3-email-sending-dialog" ).dialog( "close" );
|
111 |
+
$( "#p3-email-results-dialog" ).dialog( "close" );
|
112 |
+
});
|
113 |
+
$( "#p3-email-results" ).click( function() {
|
114 |
+
$( "#p3-email-results-dialog" ).dialog( "open" );
|
115 |
+
});
|
116 |
+
$( "#p3-email-sending-close" ).buttonset();
|
117 |
+
});
|
118 |
+
|
119 |
+
|
120 |
+
|
121 |
+
/**************************************************************/
|
122 |
+
/** Hover function for charts **/
|
123 |
+
/**************************************************************/
|
124 |
+
var previousPoint = null;
|
125 |
+
function showTooltip( x, y, contents ) {
|
126 |
+
jQuery( '<div id="p3-tooltip">' + contents + '</div>' ).css(
|
127 |
+
{
|
128 |
+
position: 'absolute',
|
129 |
+
display: 'none',
|
130 |
+
top: y + 5,
|
131 |
+
left: x + 5,
|
132 |
+
border: '1px solid #fdd',
|
133 |
+
padding: '2px',
|
134 |
+
'background-color': '#fee',
|
135 |
+
opacity: 0.80
|
136 |
+
}
|
137 |
+
).appendTo( "body" ).fadeIn( 200 );
|
138 |
+
}
|
139 |
+
|
140 |
+
|
141 |
+
|
142 |
+
/**************************************************************/
|
143 |
+
/** Plugin pie chart **/
|
144 |
+
/**************************************************************/
|
145 |
+
var data_<?php echo $pie_chart_id; ?> = [
|
146 |
+
<?php if ( !empty( $profile ) ){ ?>
|
147 |
+
<?php foreach ( $profile->plugin_times as $k => $v ) { ?>
|
148 |
+
{
|
149 |
+
label: "<?php echo $k; ?>",
|
150 |
+
data: <?php echo $v; ?>
|
151 |
+
},
|
152 |
+
<?php } ?>
|
153 |
+
<?php } else { ?>
|
154 |
+
{ label: 'No plugins', data: 1}
|
155 |
+
<?php } ?>
|
156 |
+
];
|
157 |
+
jQuery( document ).ready( function( $) {
|
158 |
+
$.plot( $(
|
159 |
+
"#p3-holder_<?php echo $pie_chart_id; ?>" ),
|
160 |
+
data_<?php echo $pie_chart_id; ?>,
|
161 |
+
{
|
162 |
+
series: {
|
163 |
+
pie: {
|
164 |
+
show: true,
|
165 |
+
combine: {
|
166 |
+
threshold: .03 // 3% or less
|
167 |
+
}
|
168 |
+
}
|
169 |
+
},
|
170 |
+
grid: {
|
171 |
+
hoverable: true,
|
172 |
+
clickable: true
|
173 |
+
},
|
174 |
+
legend: {
|
175 |
+
container: $( "#p3-legend_<?php echo $pie_chart_id; ?>" )
|
176 |
+
}
|
177 |
+
});
|
178 |
+
|
179 |
+
$( "#p3-holder_<?php echo $pie_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
|
180 |
+
if ( item ) {
|
181 |
+
$( "#p3-tooltip" ).remove();
|
182 |
+
showTooltip( pos.pageX, pos.pageY,
|
183 |
+
item.series.label + "<br />" + Math.round( item.series.percent ) + "%<br />" +
|
184 |
+
Math.round( item.datapoint[1][0][1] * Math.pow( 10, 4 ) ) / Math.pow( 10, 4 ) + " seconds"
|
185 |
+
);
|
186 |
+
} else {
|
187 |
+
$( "#p3-tooltip" ).remove();
|
188 |
+
}
|
189 |
+
});
|
190 |
+
});
|
191 |
+
|
192 |
+
|
193 |
+
|
194 |
+
/**************************************************************/
|
195 |
+
/** Runtime line chart data **/
|
196 |
+
/**************************************************************/
|
197 |
+
var chart_<?php echo $runtime_chart_id; ?> = null;
|
198 |
+
var data_<?php echo $runtime_chart_id; ?> = [
|
199 |
+
{
|
200 |
+
label: "WP Core time",
|
201 |
+
data: [
|
202 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
203 |
+
[
|
204 |
+
<?php echo $k + 1; ?>,
|
205 |
+
<?php echo $v['core']; ?>
|
206 |
+
],
|
207 |
+
<?php } ?>
|
208 |
+
]
|
209 |
+
},
|
210 |
+
{
|
211 |
+
label: "Theme time",
|
212 |
+
data: [
|
213 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
214 |
+
[
|
215 |
+
<?php echo $k + 1; ?>,
|
216 |
+
<?php echo $v['theme']; ?>
|
217 |
+
],
|
218 |
+
<?php } ?>
|
219 |
+
]
|
220 |
+
},
|
221 |
+
{
|
222 |
+
label: "Plugin time",
|
223 |
+
data: [
|
224 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
225 |
+
[
|
226 |
+
<?php echo $k + 1; ?>,
|
227 |
+
<?php echo $v['plugins']; ?>
|
228 |
+
],
|
229 |
+
<?php } ?>
|
230 |
+
]
|
231 |
+
}
|
232 |
+
];
|
233 |
+
jQuery( document ).ready( function( $) {
|
234 |
+
chart_<?php echo $runtime_chart_id; ?> = $.plot( $(
|
235 |
+
"#p3-holder_<?php echo $runtime_chart_id; ?>" ),
|
236 |
+
data_<?php echo $runtime_chart_id; ?>,
|
237 |
+
{
|
238 |
+
series: {
|
239 |
+
lines: { show: true },
|
240 |
+
points: { show: true },
|
241 |
+
},
|
242 |
+
grid: {
|
243 |
+
hoverable: true,
|
244 |
+
clickable: true
|
245 |
+
},
|
246 |
+
legend : {
|
247 |
+
container: $( "#p3-legend_<?php echo $runtime_chart_id; ?>" )
|
248 |
+
},
|
249 |
+
zoom: {
|
250 |
+
interactive: true
|
251 |
+
},
|
252 |
+
pan: {
|
253 |
+
interactive: true
|
254 |
+
},
|
255 |
+
xaxis: {
|
256 |
+
show: false
|
257 |
+
}
|
258 |
+
});
|
259 |
+
|
260 |
+
// zoom buttons
|
261 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
|
262 |
+
.appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
|
263 |
+
e.preventDefault();
|
264 |
+
chart_<?php echo $runtime_chart_id; ?>.zoomOut();
|
265 |
+
});
|
266 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
|
267 |
+
.appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
|
268 |
+
e.preventDefault();
|
269 |
+
chart_<?php echo $runtime_chart_id; ?>.zoom();
|
270 |
+
});
|
271 |
+
|
272 |
+
$( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
|
273 |
+
if ( item ) {
|
274 |
+
if ( previousPoint != item.dataIndex ) {
|
275 |
+
previousPoint = item.dataIndex;
|
276 |
+
|
277 |
+
$( "#p3-tooltip" ).remove();
|
278 |
+
var x = item.datapoint[0].toFixed( 2 ),
|
279 |
+
y = item.datapoint[1].toFixed( 2 );
|
280 |
+
|
281 |
+
url = _data[item["dataIndex"]]["url"];
|
282 |
+
|
283 |
+
// Get rid of the domain
|
284 |
+
url = url.replace(/http[s]?:\/\/<?php echo $domain; ?>(:\d+)?/, "" );
|
285 |
+
|
286 |
+
showTooltip( item.pageX, item.pageY,
|
287 |
+
item.series.label + "<br />" +
|
288 |
+
url + "<br />" +
|
289 |
+
y + " seconds" );
|
290 |
+
}
|
291 |
+
} else {
|
292 |
+
$( "#p3-tooltip" ).remove();
|
293 |
+
previousPoint = null;
|
294 |
+
}
|
295 |
+
});
|
296 |
+
});
|
297 |
+
|
298 |
+
|
299 |
+
|
300 |
+
/**************************************************************/
|
301 |
+
/** Query line chart data **/
|
302 |
+
/**************************************************************/
|
303 |
+
var chart_<?php echo $query_chart_id; ?> = null;
|
304 |
+
var data_<?php echo $query_chart_id; ?> = [
|
305 |
+
{
|
306 |
+
label: "# of Queries",
|
307 |
+
data: [
|
308 |
+
<?php if ( !empty( $profile ) ){ ?>
|
309 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
310 |
+
[
|
311 |
+
<?php echo $k + 1; ?>,
|
312 |
+
<?php echo $v['queries']; ?>
|
313 |
+
],
|
314 |
+
<?php } ?>
|
315 |
+
<?php } ?>
|
316 |
+
]
|
317 |
+
}
|
318 |
+
];
|
319 |
+
jQuery( document ).ready( function( $) {
|
320 |
+
chart_<?php echo $query_chart_id; ?> = $.plot( $(
|
321 |
+
"#p3-holder_<?php echo $query_chart_id; ?>" ),
|
322 |
+
data_<?php echo $query_chart_id; ?>,
|
323 |
+
{
|
324 |
+
series: {
|
325 |
+
lines: { show: true },
|
326 |
+
points: { show: true }
|
327 |
+
},
|
328 |
+
grid: {
|
329 |
+
hoverable: true,
|
330 |
+
clickable: true
|
331 |
+
},
|
332 |
+
legend : {
|
333 |
+
container: $( "#p3-legend_<?php echo $query_chart_id; ?>" )
|
334 |
+
},
|
335 |
+
zoom: {
|
336 |
+
interactive: true
|
337 |
+
},
|
338 |
+
pan: {
|
339 |
+
interactive: true
|
340 |
+
},
|
341 |
+
xaxis: {
|
342 |
+
show: false
|
343 |
+
}
|
344 |
+
});
|
345 |
+
|
346 |
+
// zoom buttons
|
347 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
|
348 |
+
.appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
|
349 |
+
e.preventDefault();
|
350 |
+
chart_<?php echo $query_chart_id; ?>.zoomOut();
|
351 |
+
});
|
352 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
|
353 |
+
.appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
|
354 |
+
e.preventDefault();
|
355 |
+
chart_<?php echo $query_chart_id; ?>.zoom();
|
356 |
+
});
|
357 |
+
|
358 |
+
$( "#p3-holder_<?php echo $query_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
|
359 |
+
if ( item ) {
|
360 |
+
if ( previousPoint != item.dataIndex ) {
|
361 |
+
previousPoint = item.dataIndex;
|
362 |
+
|
363 |
+
$( "#p3-tooltip" ).remove();
|
364 |
+
var x = item.datapoint[0].toFixed( 2 ),
|
365 |
+
y = item.datapoint[1]; //.toFixed( 2 );
|
366 |
+
|
367 |
+
url = _data[item["dataIndex"]]["url"];
|
368 |
+
|
369 |
+
// Get rid of the domain
|
370 |
+
url = url.replace(/http[s]?:\/\/<?php echo $domain; ?>(:\d+)?/, "" );
|
371 |
+
|
372 |
+
qword = ( y == 1 ) ? "query" : "queries";
|
373 |
+
showTooltip( item.pageX, item.pageY,
|
374 |
+
item.series.label + "<br />" +
|
375 |
+
url + "<br />" +
|
376 |
+
y + " " + qword );
|
377 |
+
}
|
378 |
+
} else {
|
379 |
+
$( "#p3-tooltip" ).remove();
|
380 |
+
previousPoint = null;
|
381 |
+
}
|
382 |
+
});
|
383 |
+
});
|
384 |
+
|
385 |
+
|
386 |
+
/**************************************************************/
|
387 |
+
/** Compnent bar chart data **/
|
388 |
+
/**************************************************************/
|
389 |
+
var chart_<?php echo $component_breakdown_chart_id; ?> = null;
|
390 |
+
var data_<?php echo $component_breakdown_chart_id; ?> = [
|
391 |
+
{
|
392 |
+
label: 'Site Load Time',
|
393 |
+
bars: {show: false},
|
394 |
+
points: {show: false},
|
395 |
+
lines: {show: true, lineWidth: 3},
|
396 |
+
shadowSize: 0,
|
397 |
+
data: [
|
398 |
+
<?php for ( $i = -999 ; $i < 999 + 2; $i++ ) { ?>
|
399 |
+
[
|
400 |
+
<?php echo $i; ?>,
|
401 |
+
<?php echo $profile->averages['site']; ?>
|
402 |
+
],
|
403 |
+
<?php } ?>
|
404 |
+
]
|
405 |
+
},
|
406 |
+
{
|
407 |
+
label: 'WP Core Time',
|
408 |
+
data: [[0, <?php echo $profile->averages['core']; ?>]]
|
409 |
+
},
|
410 |
+
{
|
411 |
+
label: 'Theme',
|
412 |
+
data: [[1, <?php echo $profile->averages['theme']; ?>]]
|
413 |
+
},
|
414 |
+
<?php $i = 2; $other = 0; ?>
|
415 |
+
<?php foreach ( $profile->plugin_times as $k => $v ) { ?>
|
416 |
+
{
|
417 |
+
label: '<?php echo $k; ?>',
|
418 |
+
data: [[
|
419 |
+
<?php echo $i++; ?>,
|
420 |
+
<?php echo $v; ?>
|
421 |
+
]],
|
422 |
+
},
|
423 |
+
<?php } ?>
|
424 |
+
];
|
425 |
+
|
426 |
+
jQuery( document ).ready( function( $) {
|
427 |
+
chart_<?php echo $component_breakdown_chart_id; ?> = $.plot( $(
|
428 |
+
"#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ),
|
429 |
+
data_<?php echo $component_breakdown_chart_id; ?>,
|
430 |
+
{
|
431 |
+
series: {
|
432 |
+
bars: {
|
433 |
+
show: true,
|
434 |
+
barWidth: 0.9,
|
435 |
+
align: 'center'
|
436 |
+
},
|
437 |
+
stack: false,
|
438 |
+
lines: {
|
439 |
+
show: false,
|
440 |
+
steps: false,
|
441 |
+
}
|
442 |
+
},
|
443 |
+
grid: {
|
444 |
+
hoverable: true,
|
445 |
+
clickable: true,
|
446 |
+
},
|
447 |
+
xaxis: {
|
448 |
+
show: false,
|
449 |
+
ticks: [
|
450 |
+
[0, 'Site Load Time'],
|
451 |
+
[1, 'WP Core Time'],
|
452 |
+
[2, 'Theme'],
|
453 |
+
<?php $i = 3; ?>
|
454 |
+
<?php foreach ( $profile->plugin_times as $k => $v ) { ?>
|
455 |
+
[
|
456 |
+
<?php echo $i++ ?>,
|
457 |
+
'<?php echo $k; ?>'
|
458 |
+
],
|
459 |
+
<?php } ?>
|
460 |
+
],
|
461 |
+
min: 0,
|
462 |
+
max: <?php echo $i; ?>,
|
463 |
+
},
|
464 |
+
legend : {
|
465 |
+
container: $( "#p3-legend_<?php echo $component_breakdown_chart_id; ?>" )
|
466 |
+
},
|
467 |
+
zoom: {
|
468 |
+
interactive: true
|
469 |
+
},
|
470 |
+
pan: {
|
471 |
+
interactive: true
|
472 |
+
}
|
473 |
+
});
|
474 |
+
|
475 |
+
$( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
|
476 |
+
if ( item ) {
|
477 |
+
$( "#p3-tooltip" ).remove();
|
478 |
+
showTooltip( pos.pageX, pos.pageY,
|
479 |
+
item.series.label + "<br />" + Math.round( item.datapoint[1] * Math.pow( 10, 4 ) ) / Math.pow( 10, 4 ) + " seconds"
|
480 |
+
);
|
481 |
+
} else {
|
482 |
+
$( "#p3-tooltip" ).remove();
|
483 |
+
}
|
484 |
+
});
|
485 |
+
|
486 |
+
// zoom buttons
|
487 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
|
488 |
+
.appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
|
489 |
+
e.preventDefault();
|
490 |
+
chart_<?php echo $component_breakdown_chart_id; ?>.zoomOut();
|
491 |
+
});
|
492 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
|
493 |
+
.appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
|
494 |
+
e.preventDefault();
|
495 |
+
chart_<?php echo $component_breakdown_chart_id; ?>.zoom();
|
496 |
+
});
|
497 |
+
});
|
498 |
+
|
499 |
+
/**************************************************************/
|
500 |
+
/** Runtime by component line chart data **/
|
501 |
+
/**************************************************************/
|
502 |
+
var chart_<?php echo $component_runtime_chart_id; ?> = null;
|
503 |
+
var data_<?php echo $component_runtime_chart_id; ?> = [
|
504 |
+
{
|
505 |
+
label: "WP Core Time",
|
506 |
+
data: [
|
507 |
+
<?php if ( !empty( $profile ) ){ ?>
|
508 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
509 |
+
[
|
510 |
+
<?php echo $k + 1; ?>,
|
511 |
+
<?php echo $v['core']; ?>
|
512 |
+
],
|
513 |
+
<?php } ?>
|
514 |
+
<?php } ?>
|
515 |
+
]
|
516 |
+
},
|
517 |
+
{
|
518 |
+
label: "Theme",
|
519 |
+
data: [
|
520 |
+
<?php if ( !empty( $profile ) ){ ?>
|
521 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
522 |
+
[
|
523 |
+
<?php echo $k + 1; ?>,
|
524 |
+
<?php echo $v['theme']; ?>
|
525 |
+
],
|
526 |
+
<?php } ?>
|
527 |
+
<?php } ?>
|
528 |
+
]
|
529 |
+
},
|
530 |
+
<?php if ( !empty( $profile ) && !empty( $profile->detected_plugins ) ) { ?>
|
531 |
+
<?php foreach ( $profile->detected_plugins as $plugin ) { ?>
|
532 |
+
{
|
533 |
+
label: "<?php echo $plugin; ?>",
|
534 |
+
data: [
|
535 |
+
<?php foreach ( array_values( $url_stats ) as $k => $v ) { ?>
|
536 |
+
<?php if ( array_key_exists( $plugin, $v['breakdown'] ) ) { ?>
|
537 |
+
[
|
538 |
+
<?php echo $k + 1; ?>,
|
539 |
+
<?php echo $v['breakdown'][$plugin]; ?>
|
540 |
+
],
|
541 |
+
<?php } ?>
|
542 |
+
<?php } ?>
|
543 |
+
]
|
544 |
+
},
|
545 |
+
<?php } ?>
|
546 |
+
<?php } ?>
|
547 |
+
];
|
548 |
+
jQuery( document ).ready( function( $) {
|
549 |
+
chart_<?php echo $component_runtime_chart_id; ?> = $.plot(
|
550 |
+
$( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ),
|
551 |
+
data_<?php echo $component_runtime_chart_id; ?>,
|
552 |
+
{
|
553 |
+
series: {
|
554 |
+
lines: { show: true },
|
555 |
+
points: { show: true }
|
556 |
+
},
|
557 |
+
grid: {
|
558 |
+
hoverable: true,
|
559 |
+
clickable: true
|
560 |
+
},
|
561 |
+
legend : {
|
562 |
+
container: $( "#p3-legend_<?php echo $component_runtime_chart_id; ?>" )
|
563 |
+
},
|
564 |
+
zoom: {
|
565 |
+
interactive: true
|
566 |
+
},
|
567 |
+
pan: {
|
568 |
+
interactive: true
|
569 |
+
},
|
570 |
+
xaxis: {
|
571 |
+
show: false
|
572 |
+
}
|
573 |
+
});
|
574 |
+
|
575 |
+
$( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
|
576 |
+
if ( item ) {
|
577 |
+
if ( previousPoint != item.dataIndex ) {
|
578 |
+
previousPoint = item.dataIndex;
|
579 |
+
|
580 |
+
$( "#p3-tooltip" ).remove();
|
581 |
+
var x = item.datapoint[0].toFixed( 2 ),
|
582 |
+
y = item.datapoint[1]; //.toFixed( 2 );
|
583 |
+
|
584 |
+
url = _data[item["dataIndex"]]["url"];
|
585 |
+
|
586 |
+
// Get rid of the domain
|
587 |
+
url = url.replace(/http[s]?:\/\/<?php echo $domain; ?>(:\d+)?/, "" );
|
588 |
+
|
589 |
+
showTooltip( item.pageX, item.pageY,
|
590 |
+
item.series.label + "<br />" +
|
591 |
+
url + "<br />" +
|
592 |
+
y + " seconds" );
|
593 |
+
}
|
594 |
+
} else {
|
595 |
+
$( "#p3-tooltip" ).remove();
|
596 |
+
previousPoint = null;
|
597 |
+
}
|
598 |
+
});
|
599 |
+
|
600 |
+
// zoom buttons
|
601 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
|
602 |
+
.appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
|
603 |
+
e.preventDefault();
|
604 |
+
chart_<?php echo $component_runtime_chart_id; ?>.zoomOut();
|
605 |
+
});
|
606 |
+
$( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
|
607 |
+
.appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
|
608 |
+
e.preventDefault();
|
609 |
+
chart_<?php echo $component_runtime_chart_id; ?>.zoom();
|
610 |
+
});
|
611 |
+
});
|
612 |
+
|
613 |
+
</script>
|
614 |
+
<div id="p3-tabs">
|
615 |
+
<ul>
|
616 |
+
<li><a href="#p3-tabs-1">Runtime By Plugin</a></li>
|
617 |
+
<li><a href="#p3-tabs-5">Detailed Breakdown</a></li>
|
618 |
+
<li><a href="#p3-tabs-2">Simple Timeline</a></li>
|
619 |
+
<li><a href="#p3-tabs-6">Detailed Timeline</a></li>
|
620 |
+
<li><a href="#p3-tabs-3">Query Timeline</a></li>
|
621 |
+
<li><a href="#p3-tabs-4">Advanced Metrics</a></li>
|
622 |
+
</ul>
|
623 |
+
|
624 |
+
<!-- Plugin bar chart -->
|
625 |
+
<div id="p3-tabs-5">
|
626 |
+
<h2>Detailed Breakdown</h2>
|
627 |
+
<div class="p3-plugin-graph">
|
628 |
+
<table>
|
629 |
+
<tr>
|
630 |
+
<td rowspan="2">
|
631 |
+
<div class="p3-y-axis-label">
|
632 |
+
<em class="p3-em">Seconds</em>
|
633 |
+
</div>
|
634 |
+
</td>
|
635 |
+
<td rowspan="2">
|
636 |
+
<div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $component_breakdown_chart_id; ?>"></div>
|
637 |
+
</td>
|
638 |
+
<td>
|
639 |
+
<h3>Legend</h3>
|
640 |
+
</td>
|
641 |
+
</tr>
|
642 |
+
<tr>
|
643 |
+
<td>
|
644 |
+
<div class="p3-custom-legend" id="p3-legend_<?php echo $component_breakdown_chart_id; ?>"></div>
|
645 |
+
</td>
|
646 |
+
</tr>
|
647 |
+
<tr>
|
648 |
+
<td> </td>
|
649 |
+
<td colspan="2">
|
650 |
+
<div class="p3-x-axis-label" style="top: -10px;">
|
651 |
+
<em class="p3-em">Component</em>
|
652 |
+
</div>
|
653 |
+
</td>
|
654 |
+
</tr>
|
655 |
+
</table>
|
656 |
+
</div>
|
657 |
+
</div>
|
658 |
+
|
659 |
+
<!-- Plugin pie chart div -->
|
660 |
+
<div id="p3-tabs-1">
|
661 |
+
<h2>Runtime by Plugin</h2>
|
662 |
+
<div class="p3-plugin-graph">
|
663 |
+
<table>
|
664 |
+
<tr>
|
665 |
+
<td rowspan="2">
|
666 |
+
<div style="width: 370px;" class="p3-line p3-graph-holder" id="p3-holder_<?php echo $pie_chart_id; ?>"></div>
|
667 |
+
</td>
|
668 |
+
<td>
|
669 |
+
<h3>Legend</h3>
|
670 |
+
</td>
|
671 |
+
</tr>
|
672 |
+
<tr>
|
673 |
+
<td>
|
674 |
+
<div style="width: 250px;" class="p3-custom-legend" id="p3-legend_<?php echo $pie_chart_id;?>"></div>
|
675 |
+
</td>
|
676 |
+
</tr>
|
677 |
+
</table>
|
678 |
+
</div>
|
679 |
+
</div>
|
680 |
+
|
681 |
+
<!-- Runtime line chart div -->
|
682 |
+
<div id="p3-tabs-2">
|
683 |
+
<h2>Summary Timeline</h2>
|
684 |
+
<div class="p3-plugin-graph">
|
685 |
+
<table>
|
686 |
+
<tr>
|
687 |
+
<td rowspan="2">
|
688 |
+
<div class="p3-y-axis-label">
|
689 |
+
<em class="p3-em">Seconds</em>
|
690 |
+
</div>
|
691 |
+
</td>
|
692 |
+
<td rowspan="2">
|
693 |
+
<div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $runtime_chart_id; ?>"></div>
|
694 |
+
</td>
|
695 |
+
<td>
|
696 |
+
<h3>Legend</h3>
|
697 |
+
</td>
|
698 |
+
</tr>
|
699 |
+
<tr>
|
700 |
+
<td>
|
701 |
+
<div class="p3-custom-legend" id="p3-legend_<?php echo $runtime_chart_id; ?>"></div>
|
702 |
+
</td>
|
703 |
+
</tr>
|
704 |
+
<tr>
|
705 |
+
<td> </td>
|
706 |
+
<td colspan="2">
|
707 |
+
<div class="p3-x-axis-label">
|
708 |
+
<!-- <em class="p3-em">Visit</em> -->
|
709 |
+
</div>
|
710 |
+
</td>
|
711 |
+
</tr>
|
712 |
+
</table>
|
713 |
+
</div>
|
714 |
+
</div>
|
715 |
+
|
716 |
+
<!-- Query line chart div -->
|
717 |
+
<div id="p3-tabs-3">
|
718 |
+
<h2>Query Timeline</h2>
|
719 |
+
<div class="p3-plugin-graph">
|
720 |
+
<table>
|
721 |
+
<tr>
|
722 |
+
<td rowspan="2">
|
723 |
+
<div class="p3-y-axis-label">
|
724 |
+
<em class="p3-em">Queries</em>
|
725 |
+
</div>
|
726 |
+
</td>
|
727 |
+
<td rowspan="2">
|
728 |
+
<div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $query_chart_id; ?>"></div>
|
729 |
+
</td>
|
730 |
+
<td>
|
731 |
+
<h3>Legend</h3>
|
732 |
+
</td>
|
733 |
+
</tr>
|
734 |
+
<tr>
|
735 |
+
<td>
|
736 |
+
<div class="p3-custom-legend" id="p3-legend_<?php echo $query_chart_id; ?>"></div>
|
737 |
+
</td>
|
738 |
+
</tr>
|
739 |
+
<tr>
|
740 |
+
<td> </td>
|
741 |
+
<td colspan="2">
|
742 |
+
<div class="p3-x-axis-label">
|
743 |
+
<!-- <em class="p3-em">Visit</em> -->
|
744 |
+
</div>
|
745 |
+
</td>
|
746 |
+
</tr>
|
747 |
+
</table>
|
748 |
+
</div>
|
749 |
+
</div>
|
750 |
+
|
751 |
+
<!-- Component runtime chart div -->
|
752 |
+
<div id="p3-tabs-6">
|
753 |
+
<h2>Detailed Timeline</h2>
|
754 |
+
<div class="p3-plugin-graph">
|
755 |
+
<table>
|
756 |
+
<tr>
|
757 |
+
<td rowspan="2">
|
758 |
+
<div class="p3-y-axis-label">
|
759 |
+
<em class="p3-em">Seconds</em>
|
760 |
+
</div>
|
761 |
+
</td>
|
762 |
+
<td rowspan="2">
|
763 |
+
<div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $component_runtime_chart_id; ?>"></div>
|
764 |
+
</td>
|
765 |
+
<td>
|
766 |
+
<h3>Legend</h3>
|
767 |
+
</td>
|
768 |
+
</tr>
|
769 |
+
<tr>
|
770 |
+
<td>
|
771 |
+
<div class="p3-custom-legend" id="p3-legend_<?php echo $component_runtime_chart_id; ?>"></div>
|
772 |
+
</td>
|
773 |
+
</tr>
|
774 |
+
<tr>
|
775 |
+
<td> </td>
|
776 |
+
<td colspan="2">
|
777 |
+
<div class="p3-x-axis-label">
|
778 |
+
<!-- <em class="p3-em">Visit</em> -->
|
779 |
+
</div>
|
780 |
+
</td>
|
781 |
+
</tr>
|
782 |
+
</table>
|
783 |
+
</div>
|
784 |
+
</div>
|
785 |
+
|
786 |
+
<!-- Advanced data -->
|
787 |
+
<div id="p3-tabs-4">
|
788 |
+
<div id="p3-metrics-container">
|
789 |
+
<div class="ui-widget-header" id="p3-metrics-header" style="padding: 8px;">
|
790 |
+
<strong>Advanced Metrics</strong>
|
791 |
+
</div>
|
792 |
+
<div>
|
793 |
+
<table class="p3-results-table" id="p3-results-table" cellpadding="0" cellspacing="0" border="0">
|
794 |
+
<tbody>
|
795 |
+
<tr class="advanced">
|
796 |
+
<td class="qtip-tip" title="The time the site took to load. This is an observed measurement (start
|
797 |
+
timing when the page was requested, stop timing when the page was delivered to the browser,
|
798 |
+
calculate the difference). Lower is better.">
|
799 |
+
<strong>Total Load Time: </strong>
|
800 |
+
</td>
|
801 |
+
<td>
|
802 |
+
<?php printf( '%.4f', $profile->averages['total'] ); ?> seconds <em class="p3-em">avg.</em>
|
803 |
+
</td>
|
804 |
+
</tr>
|
805 |
+
<tr>
|
806 |
+
<td class="qtip-tip" title="The calculated total load time minus the profile overhead. This is closer to your
|
807 |
+
site's real-life load time. Lower is better.">
|
808 |
+
<strong>Site Load Time</small></em></strong>
|
809 |
+
</td>
|
810 |
+
<td>
|
811 |
+
<?php printf( '%.4f', $profile->averages['site'] ); ?> seconds <em class="p3-em">avg.</em>
|
812 |
+
</td>
|
813 |
+
</tr>
|
814 |
+
<tr class="advanced">
|
815 |
+
<td class="qtip-tip" title="The load time spent profiling code. Because the profiler slows down your load time,
|
816 |
+
it is important to know how much impact the profiler has. However, it doesn't impact your site's
|
817 |
+
real-life load time.">
|
818 |
+
<strong>Profile Overhead: </strong>
|
819 |
+
</td>
|
820 |
+
<td>
|
821 |
+
<?php printf( '%.4f', $profile->averages['profile'] ); ?> seconds <em class="p3-em">avg.</em>
|
822 |
+
</td>
|
823 |
+
</tr>
|
824 |
+
<tr>
|
825 |
+
<td class="qtip-tip" title="The load time caused by plugins. Because of WordPress' construction, we can trace a
|
826 |
+
function call from a plugin through a theme through the core. The profiler prioritizes plugin calls
|
827 |
+
first, theme calls second, and core calls last. Lower is better.">
|
828 |
+
<strong>Plugin Load Time: </strong>
|
829 |
+
</td>
|
830 |
+
<td>
|
831 |
+
<?php printf( '%.4f', $profile->averages['plugins'] ); ?> seconds <em class="p3-em">avg.</em>
|
832 |
+
</td>
|
833 |
+
</tr>
|
834 |
+
<tr>
|
835 |
+
<td class="qtip-tip" title="The load time spent applying the theme. Because of WordPress' construction, we can trace
|
836 |
+
a function call from a plugin through a theme through the core. The profiler prioritizes plugin calls
|
837 |
+
first, theme calls second, and core calls last. Lower is better.">
|
838 |
+
<strong>Theme Load Time: </strong>
|
839 |
+
</td>
|
840 |
+
<td>
|
841 |
+
<?php printf( '%.4f', $profile->averages['theme'] ); ?> seconds <em class="p3-em">avg.</em>
|
842 |
+
</td>
|
843 |
+
</tr>
|
844 |
+
<tr>
|
845 |
+
<td class="qtip-tip" title="The load time caused by the WordPress core. Because of WordPress' construction, we can
|
846 |
+
trace a function call from a plugin through a theme through the core. The profiler prioritizes plugin
|
847 |
+
calls first, theme calls second, and core calls last. This will probably be constant.">
|
848 |
+
<strong>Core Load Time: </strong>
|
849 |
+
</td>
|
850 |
+
<td>
|
851 |
+
<?php printf( '%.4f', $profile->averages['core'] ); ?> seconds <em class="p3-em">avg.</em>
|
852 |
+
</td>
|
853 |
+
</tr>
|
854 |
+
<tr class="advanced">
|
855 |
+
<td class="qtip-tip" title="This is the difference between the observed runtime (what actually happened) and expected
|
856 |
+
runtime (adding the plugin runtime, theme runtime, core runtime, and profiler overhead).
|
857 |
+
There are several reasons this margin of error can exist. Most likely, the profiler is
|
858 |
+
missing microseconds while adding the runtime it observed. Using a network clock to set the
|
859 |
+
time (NTP) can also cause minute timing changes.
|
860 |
+
Ideally, this number should be zero, but there's nothing you can do to change it. It
|
861 |
+
will give you an idea of how accurate the other results are.">
|
862 |
+
<strong>Margin of Error: </strong>
|
863 |
+
</td>
|
864 |
+
<td>
|
865 |
+
<?php printf( '%.4f', $profile->averages['drift'] ); ?> seconds <em class="p3-em">avg.</em>
|
866 |
+
<br />
|
867 |
+
<em class="p3-em">
|
868 |
+
(<span class="qtip-tip" title="How long the site took to load. This is an observed measurement (start timing
|
869 |
+
when the page was requested, stop timing when the page was delivered to the browser, calculate the
|
870 |
+
difference)."><?php printf( '%.4f', $profile->averages['observed'] ); ?> observed<span>,
|
871 |
+
<span class="qtip-tip" title="The expected site load time calculated by adding plugin load time, core
|
872 |
+
load time, theme load time, and profiler overhead.">
|
873 |
+
<?php printf( '%.4f', $profile->averages['expected'] ); ?> expected</span>)
|
874 |
+
</em>
|
875 |
+
</td>
|
876 |
+
</tr>
|
877 |
+
<tr class="advanced">
|
878 |
+
<td class="qtip-tip" title="The number of visits registered during a profiling session. More visits produce a more
|
879 |
+
accurate summary.">
|
880 |
+
<strong>Visits: </strong>
|
881 |
+
</td>
|
882 |
+
<td>
|
883 |
+
<?php echo number_format( $profile->visits ); ?>
|
884 |
+
</td>
|
885 |
+
</tr>
|
886 |
+
<tr class="advanced">
|
887 |
+
<td class="qtip-tip" title="The number of PHP function calls generated by a plugin. Fewer is better.">
|
888 |
+
<strong>Number of Plugin Function Calls: </strong>
|
889 |
+
</td>
|
890 |
+
<td>
|
891 |
+
<?php echo number_format( $profile->averages['plugin_calls'] ); ?> calls <em class="p3-em">avg.</em>
|
892 |
+
</td>
|
893 |
+
</tr>
|
894 |
+
<tr>
|
895 |
+
<td class="qtip-tip" title="The amount of RAM usage observed. This is reported by memory_get_peak_usage().
|
896 |
+
Lower is better.">
|
897 |
+
<strong>Memory Usage: </strong>
|
898 |
+
</td>
|
899 |
+
<td>
|
900 |
+
<?php echo number_format( $profile->averages['memory'] / 1024 / 1024, 2 ); ?> MB <em class="p3-em">avg.</em>
|
901 |
+
</td>
|
902 |
+
</tr>
|
903 |
+
<tr>
|
904 |
+
<td class="qtip-tip" title="The count of queries sent to the database. This reported by the WordPress function
|
905 |
+
get_num_queries(). Lower is better.">
|
906 |
+
<strong>MySQL Queries: </strong>
|
907 |
+
</td>
|
908 |
+
<td>
|
909 |
+
<?php echo round( $profile->averages['queries'] ); ?> queries <em class="p3-em">avg.</em>
|
910 |
+
</td>
|
911 |
+
</tr>
|
912 |
+
</tbody>
|
913 |
+
</table>
|
914 |
+
</div>
|
915 |
+
</div>
|
916 |
+
</div>
|
917 |
+
|
918 |
+
<!-- Email these results -->
|
919 |
+
<div class="button" id="p3-email-results" style="width: 155px; padding: 5px;">
|
920 |
+
<img src="<?php echo plugins_url(); ?>/p3-profiler/css/icon_mail.gif" height="22" width="22" align="center"
|
921 |
+
alt="Email these results" title="Email these results" />
|
922 |
+
<a href="javascript:;">Email these results</a>
|
923 |
+
</div>
|
924 |
+
|
925 |
+
<!-- Email results dialog -->
|
926 |
+
<div id="p3-email-results-dialog" class="p3-dialog">
|
927 |
+
<div>
|
928 |
+
From:<br />
|
929 |
+
<input type="text" id="p3-email-results-from" style="width:95%;" size="35"
|
930 |
+
value="<?php $user = wp_get_current_user(); echo $user->user_email; ?>" title="Enter the e-mail address to send from" />
|
931 |
+
</div>
|
932 |
+
<br />
|
933 |
+
<div>
|
934 |
+
Recipient:<br />
|
935 |
+
<input type="text" id="p3-email-results-to" style="width:95%;" size="35"
|
936 |
+
value="<?php $user = wp_get_current_user(); echo $user->user_email; ?>"
|
937 |
+
title="Enter the e-mail address where you would like to send these results" />
|
938 |
+
</div>
|
939 |
+
<br />
|
940 |
+
<div>
|
941 |
+
Subject:<br />
|
942 |
+
<input type="text" id="p3-email-results-subject" style="width:95%;" size="35"
|
943 |
+
value="Performance Profile Results - <?php bloginfo( 'name' ); ?>" title="Enter the e-mail subject" />
|
944 |
+
</div>
|
945 |
+
<br />
|
946 |
+
<div>
|
947 |
+
Message: <em class="p3-em">( optional )</em><br />
|
948 |
+
<textarea id="p3-email-results-message" style="width: 95%; height: 100px;">Hello,
|
949 |
+
|
950 |
+
I profiled my WordPress site's performance using the Profile Plugin and I wanted
|
951 |
+
to share the results with you. Please take a look at the information below:</textarea>
|
952 |
+
</div>
|
953 |
+
<br />
|
954 |
+
<div>
|
955 |
+
Results: <em class="p3-em">( system generated, do not edit )</em><br />
|
956 |
+
<textarea disabled="disabled" id="p3-email-results-results" style="width: 95%; height: 120px;"><?php
|
957 |
+
echo "WordPress Plugin Profile Report\n";
|
958 |
+
echo "===========================================\n";
|
959 |
+
echo 'Report date: ' . date( 'D M j, Y', $profile->report_date ) . "\n";
|
960 |
+
echo 'Pages browsed: ' . $profile->visits . "\n";
|
961 |
+
echo 'Avg. load time: ' . sprintf( '%.4f', $profile->averages['site'] ) . " sec\n";
|
962 |
+
echo 'Number of plugins: ' . count( $profile->detected_plugins ) . " \n";
|
963 |
+
echo 'Plugin impact: ' . sprintf( '%.2f%%', $profile->averages['plugin_impact'] ) . " % of load time\n";
|
964 |
+
echo 'Avg. plugin time: ' . sprintf( '%.4f', $profile->averages['plugins'] ) . " sec\n";
|
965 |
+
echo 'Avg. core time: ' . sprintf( '%.4f', $profile->averages['core'] ) . " sec\n";
|
966 |
+
echo 'Avg. theme time: ' . sprintf( '%.4f', $profile->averages['theme'] ) . " sec\n";
|
967 |
+
echo 'Avg. mem usage: ' . number_format( $profile->averages['memory'] / 1024 / 1024, 2 ) . " MB\n";
|
968 |
+
echo 'Avg. plugin calls: ' . number_format( $profile->averages['plugin_calls'] ) . "\n";
|
969 |
+
echo 'Avg. db queries : ' . sprintf( '%.2f', $profile->averages['queries'] ) . "\n";
|
970 |
+
echo 'Margin of error : ' . sprintf( '%.4f', $profile->averages['drift'] ) . " sec\n";
|
971 |
+
echo "\nPlugin list:\n";
|
972 |
+
echo "===========================================\n";
|
973 |
+
echo implode( "\n", $profile->detected_plugins ) . "\n";
|
974 |
+
?></textarea>
|
975 |
+
</div>
|
976 |
+
<input type="hidden" id="p3-email-results-scan" value="<?php echo basename( $scan ); ?>" />
|
977 |
+
</div>
|
978 |
+
|
979 |
+
<!-- Email sending dialog -->
|
980 |
+
<div id="p3-email-sending-dialog" class="p3-dialog">
|
981 |
+
<div id="p3-email-sending-loading">
|
982 |
+
<img src="<?php echo get_site_url() . '/wp-admin/images/loading.gif' ?>" height="16" width="16" title="Loading" alt="Loading" />
|
983 |
+
</div>
|
984 |
+
<div id="p3-email-sending-error">
|
985 |
+
There was a problem sending the e-mail: <span id="p3-email-error"></span>
|
986 |
+
</div>
|
987 |
+
<div id="p3-email-sending-success">
|
988 |
+
Your report was sent successfully to <span id="p3-email-success-recipient"></span>
|
989 |
+
</div>
|
990 |
+
<div id="p3-email-sending-close">
|
991 |
+
<input type="checkbox" id="p3-email-sending-close-submit" checked="checked" /><label for="p3-email-sending-close-submit">Done</label>
|
992 |
+
</div>
|
993 |
+
</div>
|