101 Commits
Author SHA1 Message Date
Andrey Savchenko d2bece68e5 Added sanity check for invalid priority returned by core
Fixes #9
2017-06-28 14:25:45 +03:00
Andrey Savchenko f50faf6ba6 Added downloads badge to readme. 2016-12-06 21:32:31 +02:00
Andrey Savchenko bca3f42ee5 Updated version and change log for 1.4.2 release. 2016-12-02 19:18:58 +02:00
Andrey Savchenko 68302633c0 Restored functionality on WP 4.7 beta with new current_priority() method. 2016-12-02 19:18:41 +02:00
Andrey Savchenko 67ad1370ef Added Scrutinizer badge to readme. 2016-12-01 22:10:39 +02:00
Andrey Savchenko 4b7ee062c8 Updated change log and version for release 1.4.1. 2016-12-01 20:35:19 +02:00
Andrey Savchenko 2e7a948bfe Added access modifier to methods. 2016-12-01 20:34:15 +02:00
Andrey Savchenko 68ae657962 Added check for Toolbar event start before closing it. 2016-12-01 20:33:55 +02:00
Andrey Savchenko 3edaf2dbc9 Added check for hook priority failing on WP 4.7. 2016-12-01 20:30:48 +02:00
Andrey Savchenko fa155f00e7 Fixed return type hint. 2016-12-01 20:30:15 +02:00
Andrey Savchenko 82b3d1e4e3 Moved license to a separate file. 2016-12-01 20:29:52 +02:00
Andrey Savchenko 0984debd79 Release 1.4 2016-10-01 20:17:36 +03:00
Andrey Savchenko 2ddbd04b29 Colorized SQL writes as warnings. 2016-10-01 20:16:17 +03:00
Andrey Savchenko a16eebd026 Corrected change log heading markup. 2016-10-01 15:34:47 +03:00
Andrey Savchenko 274d294a65 Added screen reader text to events. 2016-10-01 15:29:06 +03:00
Andrey Savchenko ec5adbf47a Recompiled assets. 2016-10-01 14:59:11 +03:00
Andrey Savchenko b26ea48216 Updated dependencies. 2016-10-01 14:58:55 +03:00
Andrey Savchenko 711371c226 Removed release Robo task. 2016-10-01 14:52:48 +03:00
Andrey Savchenko 72ff60fe6e Updated change log to keepachangelog format. 2016-10-01 14:51:22 +03:00
Andrey Savchenko 357753f84b Updated changelog and version for 1.3.2 2015-08-27 14:06:08 +03:00
Andrey Savchenko 9d1dddb462 Normalized slashing on adding files to release zip file. 2015-08-27 14:05:48 +03:00
Andrey Savchenko d88a566aee Fixed dynamic method call to prevent crash on PHP 7. 2015-08-27 14:05:19 +03:00
Andrey Savchenko b976b26454 Updated version in header 2015-08-15 21:06:35 +03:00
Andrey Savchenko a00b11f78a Updated changelog for 1.3.1 2015-08-12 00:15:24 +03:00
Andrey Savchenko 32f300af7f Added check to catch event stops without matching starts
Fixes #7
2015-08-12 00:14:33 +03:00
Andrey Savchenko a3572063d2 Updated changelog and version 2015-06-12 22:06:33 +03:00
Andrey Savchenko e8f8e9a4b6 Implemented release command in robo 2015-06-12 21:06:07 +03:00
Andrey Savchenko cf44efbe64 Added version getter to robo file 2015-06-12 21:05:50 +03:00
Andrey Savchenko 2289923666 Updated main file for code style 2015-06-12 21:05:24 +03:00
Andrey Savchenko b82cd35cf8 Updated gitignore 2015-06-12 20:58:52 +03:00
Andrey Savchenko 8e441c935f Added task to set plugin version 2015-06-11 17:23:31 +03:00
Andrey Savchenko 7dfea751f5 Made method calls more compact 2015-06-11 12:40:19 +03:00
Andrey Savchenko a3cc36b661 Removed commented out debug code 2015-06-11 12:40:07 +03:00
Andrey Savchenko 47caf94cfe Another end of file new line 2015-06-11 12:33:45 +03:00
Andrey Savchenko d8298b1700 Made comparisons strict 2015-06-11 12:27:28 +03:00
Andrey Savchenko 5072bbbaad Added new lines to end of files for code style 2015-06-11 12:26:27 +03:00
Andrey Savchenko b32d60dfce Updated Stopwatch dependency 2015-06-11 12:26:00 +03:00
Andrey Savchenko c593e1e925 Tightened condition on Hybrid events to prevent breakage with v3
Fixes #4
2015-06-11 11:56:02 +03:00
Andrey Savchenko 112c14fde3 Added events class for Yoast plugins 2015-04-06 10:19:57 +03:00
Andrey Savchenko df40e389ad Precompiled Mustache template 2015-04-06 09:46:09 +03:00
Andrey Savchenko fb7b2f025a Added Robo task for precompiling Mustache cache 2015-04-06 09:45:44 +03:00
Andrey Savchenko b87ce58f4a Implemented class for loading precompiled Mustache cache 2015-04-06 09:45:12 +03:00
Andrey Savchenko 424fb74b29 Updated dependencies 2015-04-06 09:44:18 +03:00
Andrey Savchenko 5ed687499f Recompiled assets after dependencies update 2015-03-28 23:36:08 +02:00
Andrey Savchenko 1db8318edb Updated dependencies 2015-03-28 23:35:05 +02:00
Andrey Savchenko edb804d35f Update README.md
Added link to releases section for archive download.
2015-02-06 23:20:32 +01:00
Andrey Savchenko ce265e6dd2 Updated array keys for coding style. 2015-01-03 21:24:58 +02:00
Andrey Savchenko f3438de84b Implemented minified assets in queue. 2015-01-03 21:06:32 +02:00
Andrey Savchenko d0d70fddaf Recompiled assets. 2015-01-03 21:06:11 +02:00
Andrey Savchenko 48424c2b4c Updated RoboFile for less sourcemap and minified assets. 2015-01-03 21:05:40 +02:00
Andrey Savchenko b3be169798 Updated dependencies. 2015-01-03 20:49:14 +02:00
Andrey Savchenko 5a33c9329b Split plugins load into file load and following hook. 2014-11-07 20:55:37 +02:00
Andrey Savchenko 6fda82d443 Recompiled assets after Bootstrap update. 2014-10-30 17:34:15 +02:00
Andrey Savchenko c912f263a2 Updated Bootstrap dependency to 3.3.0 2014-10-30 17:32:56 +02:00
Andrey Savchenko 6c75879465 Adjusted command name in RoboFile to make what, not what from. 2014-10-24 15:42:22 +03:00
Andrey Savchenko db87114e3f Elaborated on Composer code use in license section. 2014-10-24 15:10:12 +03:00
Andrey Savchenko 6c7b6d6195 Added links to themes and docs. 2014-10-24 15:09:47 +03:00
Andrey Savchenko 40fd25490b Moved screenshot up for eye candy. 2014-10-24 15:09:22 +03:00
Andrey Savchenko f2f3c4f474 Updated dependencies. 2014-10-23 22:38:26 +03:00
Andrey Savchenko 59bc49bd56 Updated readme and moved changelog to separate file. 2014-10-23 22:15:24 +03:00
Andrey Savchenko 234ed808aa Recompiled JS and updated for new script name. 2014-10-23 22:11:53 +03:00
Andrey Savchenko b5161c2955 Updated compilation and watch commands in RoboFile. 2014-10-23 22:11:06 +03:00
Andrey Savchenko 4cdf206de9 Moved JS from inline PHP to own source file. 2014-10-23 22:09:48 +03:00
Andrey Savchenko 1d87865377 Updated readme. 2014-07-11 17:48:19 +03:00
Andrey Savchenko 283f8632df Disabled tooltip animation to fix JS error and UI disappearing from under cursor. 2014-07-11 17:47:54 +03:00
Andrey Savchenko eac2ab5fad Simplified robo task for tooltip to single write. 2014-06-29 00:25:59 +03:00
Andrey Savchenko 26df4f5579 Updated Bootstrap license info in readme. 2014-06-28 23:25:50 +03:00
Andrey Savchenko 83972fdb69 Updated tooltip script. 2014-06-28 23:25:02 +03:00
Andrey Savchenko e42787ec16 Added robo task to generate edited tooltip script from Bootstrap source. 2014-06-28 23:10:48 +03:00
Andrey Savchenko 174b171cdd Refactored less workflow to reference Bootstrap sources. 2014-06-28 22:26:26 +03:00
Andrey Savchenko 2a6c9339d3 Added Robo configuration file for automation. 2014-06-28 22:24:48 +03:00
Andrey Savchenko 103e0c36f5 Committed composer.lock file. 2014-06-28 22:24:05 +03:00
Andrey Savchenko 0e48a61157 Added Bootstrap as development dependency. 2014-06-28 22:23:39 +03:00
Andrey Savchenko 68f8ae42e9 Updated plugin header 2014-05-31 21:36:04 +03:00
Andrey Savchenko f8fa008ec7 Updated links in composer.json for GitHub 2014-05-31 21:32:59 +03:00
Andrey Savchenko b0d376ea8c Updated version in plugin header. 2014-05-24 19:09:54 +03:00
Andrey Savchenko 5cea91d656 Updated readme for 1.2 release. 2014-05-18 23:04:09 +03:00
Andrey Savchenko f568830513 Positioned timeline containers to fix absolute positioning of events inside. 2014-05-18 23:01:09 +03:00
Andrey Savchenko 00ba356da7 Refactored Toolbar event. 2014-05-18 22:41:45 +03:00
Andrey Savchenko 54bb79b202 Updated installation instructions for Packagist. 2014-05-18 22:02:46 +03:00
Andrey Savchenko 334d1cbacc Renamed .hgignore to .gitignore 2014-05-18 22:00:51 +03:00
Tom Nowell 32d8752261 use the core event category rather than admin 2014-04-14 14:36:38 +00:00
Tom Nowell 84eba6e39d Add additional core events 2014-04-12 18:41:11 +00:00
Andrey Savchenko b774292fda Added tag 1.1 for changeset a0de24fa9421 2013-12-11 18:05:59 +02:00
Andrey Savchenko 8c21576f02 Updated version and readme 2013-12-11 18:05:35 +02:00
Andrey Savchenko edb6941eb7 Cleaned up for inspection (coding style, PHPDoc) 2013-12-11 17:47:45 +02:00
Andrey Savchenko 68d6154a5e Switched handling of minimum event width to CSS 2013-12-06 19:17:55 +02:00
Andrey Savchenko 6565cf9cdb Implemented initial HTTP timeline 2013-12-06 00:58:59 +02:00
Andrey Savchenko 247f6f53aa More coding style stuff 2013-12-06 00:15:32 +02:00
Andrey Savchenko 4cc18430da Moved script to normal queue since noConflict was a bust 2013-12-05 23:49:08 +02:00
Andrey Savchenko 0ed37d4d92 Updated for coding style 2013-12-05 23:40:42 +02:00
Andrey Savchenko b7028e1f5a Changed dependency versions to allow minor version updates 2013-12-05 23:35:11 +02:00
Andrey Savchenko 3031ca5ca0 Implemented stacking close queries 2013-12-04 23:18:31 +02:00
Andrey Savchenko e2a176f8ef Switched tooltips implementation to modified Bootstrap script 2013-12-04 22:18:38 +02:00
Andrey Savchenko d8f354afbc Added initial take on SQL queries timeline. 2013-11-30 18:14:36 +02:00
Andrey Savchenko 06c4d5a57a Updates styles with Bootstrap v3 2013-11-27 19:14:33 +02:00
Rarst ea99e8bd35 Tweaked styling for multiple timelines. 2013-06-19 01:21:29 +03:00
Rarst 382f61a78d Clarified it is a plugin in readme, moved screenshot section higher. 2013-04-23 00:47:50 +03:00
Rarst 100411fb7d Added plugin URL and text domain to header. 2013-04-23 00:42:18 +03:00
Rarst 9b7c6e303d Added info about supported stages and frameworks to readme. 2013-04-22 23:45:01 +03:00
Rarst 8d9ff845cf Added tag 1.0 for changeset bf0eefc37428 2013-04-22 23:38:22 +03:00
31 changed files with 1987 additions and 514 deletions

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
/vendor
/release
-2
View File
@@ -1,2 +0,0 @@
vendor
composer.lock
+91
View File
@@ -0,0 +1,91 @@
# Change Log
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
## 1.4.3 - 2017-06-28
### Fixed
- sanity check for invalid priority returned by core
## 1.4.2 - 2016-12-02
### Fixed
- back to fully functional on WP 4.7 beta
## 1.4.1 - 2016-12-01
### Fixed
- errors and crash on WP 4.7 beta (not fully functional yet)
## 1.4 - 2016-10-01
### Added
- added screen reader text to events
- colorized writing SQL queries to warning color
### Changed
- updated change log format to Keep a Changelog
- updated dependencies (Stopwatch 2.8.11, Mustache 2.11.1, Bootstrap 3.3.7)
- updated assets
### Removed
- removed release Robo task
## 1.3.2 - 2015-08-27
### Fixed
- fixed dynamic method call crash on PHP 7
- fixed issue with slashes in generated release archives
## 1.3.1 - 2015-08-12
### Fixed
- fixed crash on event stop without matching start
## 1.3 - 2015-06-12
### Added
- implemented minified assets
- implemented pre-cached template
- implemented release build command
- added WP SEO event
### Changed
- split plugins_loaded hook into separate event
### Fixed
- fixed crash with upcoming Hybrid Core v3
## 1.2.1 - 2014-07-12
### Fixed
- disabled tooltip animation to fix JS errors and UI disappearing from under cursor
## 1.2 - 2014-05-18
### Added
- implemented (ballpark) toolbar event
### Changed
- merged RP with additional core events in admin
### Fixed
- fixed issue with event offsets in timelines
## 1.1 - 2013-12-11
### Added
- added SQL timeline
- added HTTP timeline
### Changed
- switched tooltips implementation to Bootstrap script
## 1.0 - 2013-04-22
### Added
- Initial public release
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013 Andrey Savchenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+48
View File
@@ -0,0 +1,48 @@
# Laps — light WordPress profiler
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Rarst/laps/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Rarst/laps/?branch=master)
[![Total Downloads](https://poser.pugx.org/rarst/laps/downloads)](https://packagist.org/packages/rarst/laps)
![Laps screenshot](http://i.imgur.com/zFokmkU.png)
Laps is light WordPress profiler (in a plugin), which aims to be:
- always on and zero click (just hover on toolbar entry) away
- quick indicator of what hogs page in general or right now
It is no match or replacement for *real* profiler, but is friendly and cute.
Out of the box Laps supports common stage of WordPress page life cycle:
- plugins load
- themes load
- core init
- main loop
And some of third party hooks conventions for themes using:
- [Theme Hook Alliance](http://zamoose.github.io/themehookalliance/)
- [Hybrid](http://themehybrid.com/)
- [Genesis](http://my.studiopress.com/themes/genesis/)
- [Thematic](http://thematictheme.com/)
There are also additional optional timelines, displaying:
- SQL queries (with [`SAVEQUERIES` constant](http://codex.wordpress.org/Editing_wp-config.php#Save_queries_for_analysis) enabled)
- HTTP requests performed
## Installation
Download plugin archive from [releases section](https://github.com/Rarst/laps/releases).
Or install in plugin directory via [Composer](https://getcomposer.org/):
composer create-project rarst/laps --no-dev
## License Info
Laps own code is licensed under MIT and it makes use of code from:
- Composer Installers (MIT)
- Symfony Stopwatch (MIT)
- Mustache.php (MIT)
- Twitter Bootstrap (MIT)
+92
View File
@@ -0,0 +1,92 @@
<?php
require __DIR__ . '/vendor/autoload.php';
/**
* This is project's console commands configuration for Robo task runner.
*
* @see http://robo.li/
*/
class RoboFile extends \Robo\Tasks {
/**
* Watches for changes.
*/
public function watch() {
$this->taskWatch()
->monitor( [ 'css/variables.less', 'css/laps.less' ], function () {
$this->makeCss();
} )
->monitor( 'js/source.js', function () {
$this->makeJs();
} )
->run();
}
/**
* Compiles all assets.
*/
public function makeAll() {
$this->makeCss();
$this->makeJs();
$this->makeMustache();
}
/**
* Compiles plugin's css file from less.
*/
public function makeCss() {
$this->taskExec( 'lessc css/laps.less css/laps.css --source-map=css/laps.css.map' )->run();
$this->taskMinify( 'css/laps.css' )
->run();
}
/**
* Creates plugin's script file.
*/
public function makeJs() {
$this->taskConcat( [
'vendor/twbs/bootstrap/js/tooltip.js',
'js/source.js',
] )
->to( 'js/laps.js' )
->run();
$this->taskMinify( 'js/laps.js' )
->run();
}
/**
* Compiles plugin's mustache template
*/
public function makeMustache() {
$dir = __DIR__ . '/views/cache';
$this->_cleanDir( $dir );
$mustache = new \Mustache_Engine(
array(
'loader' => new \Mustache_Loader_FilesystemLoader( __DIR__ . '/views' ),
'cache' => $dir,
)
);
$mustache->loadTemplate( 'laps' );
}
/**
* Sets the plugin version in header.
*
* @param string $version Version string.
*/
public function versionSet( $version ) {
$this->taskReplaceInFile( 'laps.php' )
->regex( '|^Version:.*$|m' )
->to( 'Version: ' . $version )
->run();
}
}
+7 -5
View File
@@ -3,7 +3,7 @@
"description": "Light WordPress profiler.", "description": "Light WordPress profiler.",
"keywords" : ["wordpress", "performance"], "keywords" : ["wordpress", "performance"],
"type" : "wordpress-plugin", "type" : "wordpress-plugin",
"homepage" : "https://bitbucket.org/Rarst/laps", "homepage" : "https://github.com/Rarst/laps",
"license" : "MIT", "license" : "MIT",
"authors" : [ "authors" : [
{ {
@@ -13,15 +13,17 @@
} }
], ],
"support" : { "support" : {
"issues": "https://bitbucket.org/Rarst/laps/issues", "issues": "https://github.com/Rarst/laps/issues"
"source": "https://bitbucket.org/Rarst/laps/src"
}, },
"autoload" : { "autoload" : {
"classmap": ["src/"] "classmap": ["src/"]
}, },
"require" : { "require" : {
"composer/installers": "~1.0", "composer/installers": "~1.0",
"symfony/stopwatch" : "~2.2.0", "symfony/stopwatch" : "~2.4",
"mustache/mustache" : "~2.3.0" "mustache/mustache" : "~2.4"
},
"require-dev": {
"twbs/bootstrap": "~3.2"
} }
} }
Generated
+273
View File
@@ -0,0 +1,273 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "7495421e8df337988c9906e05aab637b",
"content-hash": "3a8ac6bb545eee9eb5d1ce8b87136995",
"packages": [
{
"name": "composer/installers",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
"reference": "d78064c68299743e0161004f2de3a0204e33b804"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/installers/zipball/d78064c68299743e0161004f2de3a0204e33b804",
"reference": "d78064c68299743e0161004f2de3a0204e33b804",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0"
},
"replace": {
"roundcube/plugin-installer": "*",
"shama/baton": "*"
},
"require-dev": {
"composer/composer": "1.0.*@dev",
"phpunit/phpunit": "4.1.*"
},
"type": "composer-plugin",
"extra": {
"class": "Composer\\Installers\\Plugin",
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Installers\\": "src/Composer/Installers"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kyle Robinson Young",
"email": "kyle@dontkry.com",
"homepage": "https://github.com/shama"
}
],
"description": "A multi-framework Composer library installer",
"homepage": "https://composer.github.io/installers/",
"keywords": [
"Craft",
"Dolibarr",
"Hurad",
"ImageCMS",
"MODX Evo",
"Mautic",
"OXID",
"Plentymarkets",
"RadPHP",
"SMF",
"Thelia",
"WolfCMS",
"agl",
"aimeos",
"annotatecms",
"attogram",
"bitrix",
"cakephp",
"chef",
"cockpit",
"codeigniter",
"concrete5",
"croogo",
"dokuwiki",
"drupal",
"elgg",
"expressionengine",
"fuelphp",
"grav",
"installer",
"joomla",
"kohana",
"laravel",
"lithium",
"magento",
"mako",
"mediawiki",
"modulework",
"moodle",
"phpbb",
"piwik",
"ppi",
"puppet",
"reindex",
"roundcube",
"shopware",
"silverstripe",
"symfony",
"typo3",
"wordpress",
"yawik",
"zend",
"zikula"
],
"time": "2016-08-13 20:53:52"
},
{
"name": "mustache/mustache",
"version": "v2.11.1",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/mustache.php.git",
"reference": "a3f6d55996dd28b58f3a909d474189a3c1aa693f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/a3f6d55996dd28b58f3a909d474189a3c1aa693f",
"reference": "a3f6d55996dd28b58f3a909d474189a3c1aa693f",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~1.11",
"phpunit/phpunit": "~3.7|~4.0|~5.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Mustache": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Justin Hileman",
"email": "justin@justinhileman.info",
"homepage": "http://justinhileman.com"
}
],
"description": "A Mustache implementation in PHP.",
"homepage": "https://github.com/bobthecow/mustache.php",
"keywords": [
"mustache",
"templating"
],
"time": "2016-07-31 06:18:27"
},
{
"name": "symfony/stopwatch",
"version": "v2.8.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "35bae476693150728b0eb51647faac82faf9aaca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/35bae476693150728b0eb51647faac82faf9aaca",
"reference": "35bae476693150728b0eb51647faac82faf9aaca",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Stopwatch\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2016-06-29 05:29:29"
}
],
"packages-dev": [
{
"name": "twbs/bootstrap",
"version": "v3.3.7",
"source": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git",
"reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/0b9c4a4007c44201dce9a6cc1a38407005c26c86",
"reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86",
"shasum": ""
},
"replace": {
"twitter/bootstrap": "self.version"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jacob Thornton",
"email": "jacobthornton@gmail.com"
},
{
"name": "Mark Otto",
"email": "markdotto@gmail.com"
}
],
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
"homepage": "http://getbootstrap.com",
"keywords": [
"JS",
"css",
"framework",
"front-end",
"less",
"mobile-first",
"responsive",
"web"
],
"time": "2016-07-25 15:51:55"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
-265
View File
@@ -1,265 +0,0 @@
/*! Hint.css - v1.2.1 - 2013-03-24
* http://kushagragour.in/lab/hint/
* Copyright (c) 2013 Kushagra Gour; Licensed MIT */
/*-------------------------------------*\
HINT.css - A CSS tooltip library
\*-------------------------------------*/
/**
* HINT.css is a tooltip library made in pure CSS.
*
* Source: https://github.com/chinchang/hint.css
* Demo: http://kushagragour.in/labs/hint/
*
* Release under The MIT License
*
*/
/**
* source: hint-core.scss
*
* Defines the basic styling for the tooltip.
* Each tooltip is made of 2 parts:
* 1) body (:after)
* 2) arrow (:before)
*
* Classes added:
* 1) hint
*/
.hint, [data-hint] {
position: relative;
display: inline-block;
/**
* tooltip arrow
*/
/**
* tooltip body
*/ }
.hint:before, .hint:after, [data-hint]:before, [data-hint]:after {
position: absolute;
visibility: hidden;
opacity: 0;
z-index: 1000000;
pointer-events: none;
-webkit-transition: 0.3s ease;
-moz-transition: 0.3s ease;
transition: 0.3s ease; }
.hint:hover:before, .hint:hover:after, [data-hint]:hover:before, [data-hint]:hover:after {
visibility: visible;
opacity: 1; }
.hint:before, [data-hint]:before {
content: '';
position: absolute;
background: transparent;
border: 6px solid transparent;
z-index: 1000001; }
.hint:after, [data-hint]:after {
content: attr(data-hint);
background: #383838;
color: white;
text-shadow: 0 -1px 0px black;
padding: 8px 10px;
font-size: 12px;
line-height: 12px;
white-space: nowrap;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); }
/**
* source: hint-position.scss
*
* Defines the positoning logic for the tooltips.
*
* Classes added:
* 1) hint--top
* 2) hint--bottom
* 3) hint--left
* 4) hint--right
*/
/**
* set default color for tooltip arrows
*/
.hint--top:before {
border-top-color: #383838; }
.hint--bottom:before {
border-bottom-color: #383838; }
.hint--left:before {
border-left-color: #383838; }
.hint--right:before {
border-right-color: #383838; }
/**
* top tooltip
*/
.hint--top:before {
margin-bottom: -12px; }
.hint--top:after {
margin-left: -18px; }
.hint--top:before, .hint--top:after {
bottom: 100%;
left: 50%; }
.hint--top:hover:before, .hint--top:hover:after {
-webkit-transform: translateY(-8px);
-moz-transform: translateY(-8px);
transform: translateY(-8px); }
/**
* bottom tooltip
*/
.hint--bottom:before {
margin-top: -12px; }
.hint--bottom:after {
margin-left: -18px; }
.hint--bottom:before, .hint--bottom:after {
top: 100%;
left: 50%; }
.hint--bottom:hover:before, .hint--bottom:hover:after {
-webkit-transform: translateY(8px);
-moz-transform: translateY(8px);
transform: translateY(8px); }
/**
* right tooltip
*/
.hint--right:before {
margin-left: -12px;
margin-bottom: -6px; }
.hint--right:after {
margin-bottom: -14px; }
.hint--right:before, .hint--right:after {
left: 100%;
bottom: 50%; }
.hint--right:hover:before, .hint--right:hover:after {
-webkit-transform: translateX(8px);
-moz-transform: translateX(8px);
transform: translateX(8px); }
/**
* left tooltip
*/
.hint--left:before {
margin-right: -12px;
margin-bottom: -6px; }
.hint--left:after {
margin-bottom: -14px; }
.hint--left:before, .hint--left:after {
right: 100%;
bottom: 50%; }
.hint--left:hover:before, .hint--left:hover:after {
-webkit-transform: translateX(-8px);
-moz-transform: translateX(-8px);
transform: translateX(-8px); }
/**
* source: hint-color-types.scss
*
* Contains tooltips of various types based on color differences.
*
* Classes added:
* 1) hint--error
* 2) hint--warning
* 3) hint--info
* 4) hint--success
*
*/
/**
* Error
*/
.hint--error:after {
background-color: #b34e4d;
text-shadow: 0 -1px 0px #5a2626; }
.hint--error.hint--top:before {
border-top-color: #b34e4d; }
.hint--error.hint--bottom:before {
border-bottom-color: #b34e4d; }
.hint--error.hint--left:before {
border-left-color: #b34e4d; }
.hint--error.hint--right:before {
border-right-color: #b34e4d; }
/**
* Warning
*/
.hint--warning:after {
background-color: #c09854;
text-shadow: 0 -1px 0px #6d5228; }
.hint--warning.hint--top:before {
border-top-color: #c09854; }
.hint--warning.hint--bottom:before {
border-bottom-color: #c09854; }
.hint--warning.hint--left:before {
border-left-color: #c09854; }
.hint--warning.hint--right:before {
border-right-color: #c09854; }
/**
* Info
*/
.hint--info:after {
background-color: #3986ac;
text-shadow: 0 -1px 0px #193c4c; }
.hint--info.hint--top:before {
border-top-color: #3986ac; }
.hint--info.hint--bottom:before {
border-bottom-color: #3986ac; }
.hint--info.hint--left:before {
border-left-color: #3986ac; }
.hint--info.hint--right:before {
border-right-color: #3986ac; }
/**
* Success
*/
.hint--success:after {
background-color: #458746;
text-shadow: 0 -1px 0px #1a331a; }
.hint--success.hint--top:before {
border-top-color: #458746; }
.hint--success.hint--bottom:before {
border-bottom-color: #458746; }
.hint--success.hint--left:before {
border-left-color: #458746; }
.hint--success.hint--right:before {
border-right-color: #458746; }
/**
* source: hint-always.scss
*
* Defines a persisted tooltip which shows always.
*
* Classes added:
* 1) hint--always
*
*/
.hint--always:after, .hint--always:before {
opacity: 1;
visibility: visible; }
.hint--always.hint--top:after, .hint--always.hint--top:before {
-webkit-transform: translateY(-8px);
-moz-transform: translateY(-8px);
transform: translateY(-8px); }
.hint--always.hint--bottom:after, .hint--always.hint--bottom:before {
-webkit-transform: translateY(8px);
-moz-transform: translateY(8px);
transform: translateY(8px); }
.hint--always.hint--left:after, .hint--always.hint--left:before {
-webkit-transform: translateX(-8px);
-moz-transform: translateX(-8px);
transform: translateX(-8px); }
.hint--always.hint--right:after, .hint--always.hint--right:before {
-webkit-transform: translateX(8px);
-moz-transform: translateX(8px);
transform: translateX(8px); }
/**
* source: hint-rounded.scss
*
* Defines rounded corner tooltips.
*
* Classes added:
* 1) hint--rounded
*
*/
.hint--rounded:after {
border-radius: 4px; }
+157 -63
View File
@@ -4,6 +4,9 @@
position: fixed; position: fixed;
left: 5%; left: 5%;
} }
#wpadminbar #wp-admin-bar-laps .ab-submenu {
padding: 0;
}
#wpadminbar #wp-admin-bar-laps_output { #wpadminbar #wp-admin-bar-laps_output {
padding: 0 10px; padding: 0 10px;
} }
@@ -16,89 +19,180 @@
#wpadminbar .laps-timeline { #wpadminbar .laps-timeline {
overflow: hidden; overflow: hidden;
height: 20px; height: 20px;
background-color: #f7f7f7; margin-bottom: 20px;
background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); background-color: #f5f5f5;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px; border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
margin: 6px 0;
position: relative;
} }
#wpadminbar .laps-timeline .event { #wpadminbar .laps-timeline .event {
width: 0%;
height: 20px;
color: #fff;
float: left; float: left;
width: 0%;
height: 100%;
font-size: 12px; font-size: 12px;
line-height: 20px;
color: #fff;
text-align: center; text-align: center;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #5bc0de;
background-color: #dd514c;
background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: width 0.6s ease; -webkit-transition: width 0.6s ease;
-moz-transition: width 0.6s ease;
-o-transition: width 0.6s ease; -o-transition: width 0.6s ease;
transition: width 0.6s ease; transition: width 0.6s ease;
position: absolute; position: absolute;
} border-left: 1px solid #f5f5f5;
#wpadminbar .laps-timeline .event + .event { min-width: 2px;
-webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
-moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
} }
#wpadminbar .laps-timeline .event-theme { #wpadminbar .laps-timeline .event-theme {
background-color: #5eb95e; background-color: #5cb85c;
background-image: -moz-linear-gradient(top, #62c462, #57a957);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
background-image: -webkit-linear-gradient(top, #62c462, #57a957);
background-image: -o-linear-gradient(top, #62c462, #57a957);
background-image: linear-gradient(to bottom, #62c462, #57a957);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
} }
#wpadminbar .laps-timeline .event-plugin { #wpadminbar .laps-timeline .event-plugin {
background-color: #4bb1cf; background-color: #428bca;
background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
} }
#wpadminbar .laps-timeline .event-core { #wpadminbar .laps-timeline .event-core {
background-color: #faa732; background-color: #f0ad4e;
background-image: -moz-linear-gradient(top, #fbb450, #f89406);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
background-image: -o-linear-gradient(top, #fbb450, #f89406);
background-image: linear-gradient(to bottom, #fbb450, #f89406);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
} }
#wpadminbar [data-hint]:after { #wpadminbar .laps-timeline .event-query-read {
font-size: 13px; background-color: #5bc0de;
background-color: #464646; }
#wpadminbar .laps-timeline .event-query-write {
background-color: #d9534f;
}
#wpadminbar .laps-timeline .event-http {
background-color: #d9534f;
}
#wpadminbar .laps-timeline .sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
#wpadminbar .tooltip {
position: absolute;
z-index: 100000;
display: block;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-style: normal;
font-weight: normal;
letter-spacing: normal;
line-break: auto;
line-height: 1.42857143;
text-align: left;
text-align: start;
text-decoration: none;
text-shadow: none; text-shadow: none;
text-transform: none;
white-space: normal;
word-break: normal;
word-spacing: normal;
word-wrap: normal;
font-size: 12px;
opacity: 0;
filter: alpha(opacity=0);
} }
#wpadminbar .hint--bottom:before { #wpadminbar .tooltip.in {
opacity: 0.9;
filter: alpha(opacity=90);
}
#wpadminbar .tooltip.top {
margin-top: -3px;
padding: 5px 0;
}
#wpadminbar .tooltip.right {
margin-left: 3px;
padding: 0 5px;
}
#wpadminbar .tooltip.bottom {
margin-top: 3px;
padding: 5px 0;
}
#wpadminbar .tooltip.left {
margin-left: -3px;
padding: 0 5px;
}
#wpadminbar .tooltip-inner {
max-width: 300px;
padding: 3px 8px;
color: #ccc;
text-align: center;
background-color: #464646;
border-radius: 4px;
}
#wpadminbar .tooltip-arrow {
position: absolute;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
#wpadminbar .tooltip.top .tooltip-arrow {
bottom: 0;
left: 50%;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: #464646;
}
#wpadminbar .tooltip.top-left .tooltip-arrow {
bottom: 0;
right: 5px;
margin-bottom: -5px;
border-width: 5px 5px 0;
border-top-color: #464646;
}
#wpadminbar .tooltip.top-right .tooltip-arrow {
bottom: 0;
left: 5px;
margin-bottom: -5px;
border-width: 5px 5px 0;
border-top-color: #464646;
}
#wpadminbar .tooltip.right .tooltip-arrow {
top: 50%;
left: 0;
margin-top: -5px;
border-width: 5px 5px 5px 0;
border-right-color: #464646;
}
#wpadminbar .tooltip.left .tooltip-arrow {
top: 50%;
right: 0;
margin-top: -5px;
border-width: 5px 0 5px 5px;
border-left-color: #464646;
}
#wpadminbar .tooltip.bottom .tooltip-arrow {
top: 0;
left: 50%;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: #464646; border-bottom-color: #464646;
} }
#wpadminbar .tooltip.bottom-left .tooltip-arrow {
top: 0;
right: 5px;
margin-top: -5px;
border-width: 0 5px 5px;
border-bottom-color: #464646;
}
#wpadminbar .tooltip.bottom-right .tooltip-arrow {
top: 0;
left: 5px;
margin-top: -5px;
border-width: 0 5px 5px;
border-bottom-color: #464646;
}
#wpadminbar .tooltip.in {
opacity: 1;
filter: alpha(opacity=100);
}
#wpadminbar .tooltip-inner {
line-height: 20px;
text-align: left;
}
/*# sourceMappingURL=laps.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["laps.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/progress-bars.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/mixins/vendor-prefixes.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/scaffolding.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/tooltip.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/mixins/reset-text.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/variables.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/mixins/opacity.less"],"names":[],"mappings":"AAMA,WAEC,mBAEC;EACC,cAAA;EACA,UAAA;EACA,eAAA;EACA,QAAA;;AARH,WAEC,mBASC;EACC,UAAA;;AAZH,WAgBC;EAEC,eAAA;;AAEA,WAJD,0BAIE;EACA,6BAAA;;AArBH,WAgBC,0BAQC;EACC,aAAA;;AAzBH,WA6BC;ECTC,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,yBAAA;EACA,kBAAA;ECsCA,sDAAA;EACQ,8CAAA;EFhCR,aAAA;EACA,kBAAA;;AAhCF,WA6BC,eAKC;ECJA,WAAA;EACA,SAAA;EACA,YAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;EACA,kBAAA;EACA,yBAAA;ECyBA,sDAAA;EACQ,8CAAA;EAyHR,mCAAA;EACK,8BAAA;EACG,2BAAA;EFtJP,kBAAA;EACA,8BAAA;EACA,cAAA;;AAtCH,WA6BC,eAYC;EACC,yBAAA;;AA1CH,WA6BC,eAeC;EACC,yBAAA;;AA7CH,WA6BC,eAkBC;EACC,yBAAA;;AAhDH,WA6BC,eAqBC;EACC,yBAAA;;AAnDH,WA6BC,eAwBC;EACC,yBAAA;;AAtDH,WA6BC,eA2BC;EACC,yBAAA;;AAzDH,WA6BC,eA+BC;EG2DA,kBAAA;EACA,UAAA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,gBAAA;EACA,MAAM,gBAAN;EACA,SAAA;;AH9HF,WIAA;EACE,kBAAA;EACA,eAAA;EACA,cAAA;ECRA,aC2CwB,8CD3CxB;EAEA,kBAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,uBAAA;EACA,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kBAAA;EACA,oBAAA;EACA,iBAAA;EDHA,eAAA;EGVA,UAAA;EAGA,wBAAA;;AHWA,WAXF,SAWG;EGdD,YAAA;EAGA,yBAAA;;AHYA,WAZF,SAYG;EAAU,gBAAA;EAAmB,cAAA;;AAC9B,WAbF,SAaG;EAAU,gBAAA;EAAmB,cAAA;;AAC9B,WAdF,SAcG;EAAU,eAAA;EAAmB,cAAA;;AAC9B,WAfF,SAeG;EAAU,iBAAA;EAAmB,cAAA;;AJfhC,WImBA;EACE,gBAAA;EACA,gBAAA;EACA,WAAA;EACA,kBAAA;EACA,yBAAA;EACA,kBAAA;;AJzBF,WI6BA;EACE,kBAAA;EACA,QAAA;EACA,SAAA;EACA,yBAAA;EACA,mBAAA;;AAIA,WADF,SACG,IAAK;EACJ,SAAA;EACA,SAAA;EACA,iBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WARF,SAQG,SAAU;EACT,SAAA;EACA,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WAfF,SAeG,UAAW;EACV,SAAA;EACA,SAAA;EACA,mBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WAtBF,SAsBG,MAAO;EACN,QAAA;EACA,OAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;;AAEF,WA7BF,SA6BG,KAAM;EACL,QAAA;EACA,QAAA;EACA,gBAAA;EACA,2BAAA;EACA,0BAAA;;AAEF,WApCF,SAoCG,OAAQ;EACP,MAAA;EACA,SAAA;EACA,iBAAA;EACA,uBAAA;EACA,4BAAA;;AAEF,WA3CF,SA2CG,YAAa;EACZ,MAAA;EACA,UAAA;EACA,gBAAA;EACA,uBAAA;EACA,4BAAA;;AAEF,WAlDF,SAkDG,aAAc;EACb,MAAA;EACA,SAAA;EACA,gBAAA;EACA,uBAAA;EACA,4BAAA;;AJ5FJ,WAmEC,SAAQ;EOtEP,UAAA;EAGA,0BAAA;;APAF,WAuEC;EACC,iBAAA;EACA,gBAAA","file":"laps.css"}
+47 -41
View File
@@ -1,15 +1,25 @@
@import "mixins.less"; @import (reference) "../vendor/twbs/bootstrap/less/variables.less";
@import (reference) "../vendor/twbs/bootstrap/less/mixins.less";
@import (reference) "../vendor/twbs/bootstrap/less/progress-bars.less";
@import (reference) "../vendor/twbs/bootstrap/less/scaffolding.less";
@import "variables.less";
#wpadminbar { #wpadminbar {
#wp-admin-bar-laps .ab-sub-wrapper { #wp-admin-bar-laps {
// display: block !important;
.ab-sub-wrapper {
min-width: 90%; min-width: 90%;
width: 90%; width: 90%;
position: fixed; position: fixed;
left: 5%; left: 5%;
} }
.ab-submenu {
padding: 0;
}
}
#wp-admin-bar-laps_output { #wp-admin-bar-laps_output {
padding: 0 10px; padding: 0 10px;
@@ -21,57 +31,53 @@
.ab-empty-item { .ab-empty-item {
display: none; display: none;
} }
} }
.laps-timeline { .laps-timeline {
overflow: hidden; .progress;
height: 20px; margin: 6px 0;
#gradient > .vertical(#f5f5f5, #f9f9f9); position: relative;
.box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
.border-radius(4px); .event {
.progress-bar;
position: absolute; // disable stacking at start
border-left: 1px solid @timeline-bg;
min-width: 2px;
} }
.laps-timeline .event { .event-theme {
width: 0%; background-color: @event-theme-color;
height: 20px; }
color: #fff; .event-plugin {
float: left; background-color: @event-plugin-color;
font-size: 12px; }
text-align: center; .event-core {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); background-color: @event-core-color;
#gradient > .vertical(#ee5f5b, #c43c35); }
.box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); .event-query-read {
.box-sizing(border-box); background-color: @event-info-color;
.transition(width .6s ease); }
.event-query-write {
position: absolute; background-color: @event-warning-color;
}
.event-http {
background-color: @event-warning-color;
} }
.laps-timeline .event + .event { .sr-only {
.box-shadow(~"inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15)"); .sr-only;
} }
.laps-timeline .event-theme {
#gradient > .vertical(#62c462, #57a957);
}
.laps-timeline .event-plugin {
#gradient > .vertical(#5bc0de, #339bb9);
} }
.laps-timeline .event-core { @import "../vendor/twbs/bootstrap/less/tooltip.less";
#gradient > .vertical(lighten(#f89406, 15%), #f89406);
}
[data-hint]:after { .tooltip.in {
font-size: 13px; .opacity(1);
background-color: #464646;
text-shadow: none;
} }
.hint--bottom:before { .tooltip-inner {
border-bottom-color: #464646; line-height: 20px;
text-align: left;
} }
} }
+1
View File
@@ -0,0 +1 @@
#wpadminbar #wp-admin-bar-laps .ab-sub-wrapper{min-width:90%;width:90%;position:fixed;left:5%}#wpadminbar #wp-admin-bar-laps .ab-submenu{padding:0}#wpadminbar #wp-admin-bar-laps_output{padding:0 10px}#wpadminbar #wp-admin-bar-laps_output:hover{background-color:transparent}#wpadminbar #wp-admin-bar-laps_output .ab-empty-item{display:none}#wpadminbar .laps-timeline{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);margin:6px 0;position:relative}#wpadminbar .laps-timeline .event{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#5bc0de;-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;position:absolute;border-left:1px solid #f5f5f5;min-width:2px}#wpadminbar .laps-timeline .event-theme{background-color:#5cb85c}#wpadminbar .laps-timeline .event-plugin{background-color:#428bca}#wpadminbar .laps-timeline .event-core{background-color:#f0ad4e}#wpadminbar .laps-timeline .event-query-read{background-color:#5bc0de}#wpadminbar .laps-timeline .event-query-write{background-color:#d9534f}#wpadminbar .laps-timeline .event-http{background-color:#d9534f}#wpadminbar .laps-timeline .sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}#wpadminbar .tooltip{position:absolute;z-index:100000;display:block;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}#wpadminbar .tooltip.in{opacity:0.9;filter:alpha(opacity=90)}#wpadminbar .tooltip.top{margin-top:-3px;padding:5px 0}#wpadminbar .tooltip.right{margin-left:3px;padding:0 5px}#wpadminbar .tooltip.bottom{margin-top:3px;padding:5px 0}#wpadminbar .tooltip.left{margin-left:-3px;padding:0 5px}#wpadminbar .tooltip-inner{max-width:300px;padding:3px 8px;color:#ccc;text-align:center;background-color:#464646;border-radius:4px}#wpadminbar .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}#wpadminbar .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#464646}#wpadminbar .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#464646}#wpadminbar .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.in{opacity:1;filter:alpha(opacity=100)}#wpadminbar .tooltip-inner{line-height:20px;text-align:left}
-38
View File
@@ -1,38 +0,0 @@
.transition(@transition) {
-webkit-transition: @transition;
-moz-transition: @transition;
-o-transition: @transition;
transition: @transition;
}
.box-sizing(@boxmodel) {
-webkit-box-sizing: @boxmodel;
-moz-box-sizing: @boxmodel;
box-sizing: @boxmodel;
}
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
.box-shadow(@shadow) {
-webkit-box-shadow: @shadow;
-moz-box-shadow: @shadow;
box-shadow: @shadow;
}
#gradient {
.vertical(@startColor: #555, @endColor: #333) {
background-color: mix(@startColor, @endColor, 60%);
background-image: -moz-linear-gradient(top, @startColor, @endColor); // FF 3.6+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(top, @startColor, @endColor); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(top, @startColor, @endColor); // Opera 11.10
background-image: linear-gradient(to bottom, @startColor, @endColor); // Standard, IE10
background-repeat: repeat-x;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@startColor), argb(@endColor))); // IE9 and down
}
}
+21
View File
@@ -0,0 +1,21 @@
@font-size-small: 12px;
@line-height-computed: 20px;
// colors
@timeline-bg: #f5f5f5;
@event-theme-color: #5cb85c;
@event-plugin-color: #428bca;
@event-core-color: #f0ad4e;
@event-info-color: #5bc0de;
@event-warning-color: #d9534f;
@progress-bg: @timeline-bg;
@progress-bar-bg: @event-info-color;
// because admin bar is 99999
@zindex-tooltip: 100000;
@tooltip-max-width: 300px;
@tooltip-color: #ccc;
@tooltip-bg: #464646;
@tooltip-arrow-width: 5px;
@tooltip-arrow-color: @tooltip-bg;
@border-radius-base: 4px;
+533
View File
@@ -0,0 +1,533 @@
/* ========================================================================
* Bootstrap: tooltip.js v3.3.7
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) {
this.type = null
this.options = null
this.enabled = null
this.timeout = null
this.hoverState = null
this.$element = null
this.inState = null
this.init('tooltip', element, options)
}
Tooltip.VERSION = '3.3.7'
Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
selector: false,
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
container: false,
viewport: {
selector: 'body',
padding: 0
}
}
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
this.inState = { click: false, hover: false, focus: false }
if (this.$element[0] instanceof document.constructor && !this.options.selector) {
throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
}
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () {
return Tooltip.DEFAULTS
}
Tooltip.prototype.getOptions = function (options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay,
hide: options.delay
}
}
return options
}
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
}
if (self.tip().hasClass('in') || self.hoverState == 'in') {
self.hoverState = 'in'
return
}
clearTimeout(self.timeout)
self.hoverState = 'in'
if (!self.options.delay || !self.options.delay.show) return self.show()
self.timeout = setTimeout(function () {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.isInStateTrue = function () {
for (var key in this.inState) {
if (this.inState[key]) return true
}
return false
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
}
if (self.isInStateTrue()) return
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.' + this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
var $tip = this.tip()
var tipId = this.getUID(this.type)
this.setContent()
$tip.attr('id', tipId)
this.$element.attr('aria-describedby', tipId)
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
this.$element.trigger('inserted.bs.' + this.type)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var orgPlacement = placement
var viewportDim = this.getPosition(this.$viewport)
placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
Tooltip.prototype.applyPlacement = function (offset, placement) {
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
offset.top += marginTop
offset.left += marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
$.offset.setOffset($tip[0], $.extend({
using: function (props) {
$tip.css({
top: Math.round(props.top),
left: Math.round(props.left)
})
}
}, offset), 0)
$tip.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var isVertical = /top|bottom/.test(placement)
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
this.arrow()
.css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
.css(isVertical ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = $(this.$tip)
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
that.$element
.removeAttr('aria-describedby')
.trigger('hidden.bs.' + that.type)
}
callback && callback()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && $tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
return this
}
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var isSvg = window.SVGElement && el instanceof window.SVGElement
// Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
// See https://github.com/twbs/bootstrap/issues/20280
var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
var delta = { top: 0, left: 0 }
if (!this.$viewport) return delta
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
var viewportDimensions = this.getPosition(this.$viewport)
if (/right|left/.test(placement)) {
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (topEdgeOffset < viewportDimensions.top) { // top overflow
delta.top = viewportDimensions.top - topEdgeOffset
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
}
} else {
var leftEdgeOffset = pos.left - viewportPadding
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset
} else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
}
}
return delta
}
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
Tooltip.prototype.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
Tooltip.prototype.tip = function () {
if (!this.$tip) {
this.$tip = $(this.options.template)
if (this.$tip.length != 1) {
throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
}
}
return this.$tip
}
Tooltip.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = this
if (e) {
self = $(e.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
$(e.currentTarget).data('bs.' + this.type, self)
}
}
if (e) {
self.inState.click = !self.inState.click
if (self.isInStateTrue()) self.enter(self)
else self.leave(self)
} else {
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
}
Tooltip.prototype.destroy = function () {
var that = this
clearTimeout(this.timeout)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
if (that.$tip) {
that.$tip.detach()
}
that.$tip = null
that.$arrow = null
that.$viewport = null
that.$element = null
})
}
// TOOLTIP PLUGIN DEFINITION
// =========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.tooltip
$.fn.tooltip = Plugin
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(jQuery);
jQuery.fn.lapstooltip = jQuery.fn.tooltip.noConflict();
jQuery(document).ready(function () {
jQuery(".laps-timeline .event").lapstooltip({
container: '#wpadminbar',
placement: 'bottom',
html : true,
animation: false
});
});
+6
View File
@@ -0,0 +1,6 @@
+function(t){'use strict';var e=function(t,e){this.type=null;this.options=null;this.enabled=null;this.timeout=null;this.hoverState=null;this.$element=null;this.inState=null;this.init('tooltip',t,e)};e.VERSION='3.3.7';e.TRANSITION_DURATION=150;e.DEFAULTS={animation:!0,placement:'top',selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:'hover focus',title:'',delay:0,html:!1,container:!1,viewport:{selector:'body',padding:0}};e.prototype.init=function(e,i,o){this.enabled=!0;this.type=e;this.$element=t(i);this.options=this.getOptions(o);this.$viewport=this.options.viewport&&t(t.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):(this.options.viewport.selector||this.options.viewport));this.inState={click:!1,hover:!1,focus:!1};if(this.$element[0]instanceof document.constructor&&!this.options.selector){throw new Error('`selector` option must be specified when initializing '+this.type+' on the window.document object!')};var r=this.options.trigger.split(' ');for(var s=r.length;s--;){var n=r[s];if(n=='click'){this.$element.on('click.'+this.type,this.options.selector,t.proxy(this.toggle,this))}
else if(n!='manual'){var l=n=='hover'?'mouseenter':'focusin',a=n=='hover'?'mouseleave':'focusout';this.$element.on(l+'.'+this.type,this.options.selector,t.proxy(this.enter,this));this.$element.on(a+'.'+this.type,this.options.selector,t.proxy(this.leave,this))}};this.options.selector?(this._options=t.extend({},this.options,{trigger:'manual',selector:''})):this.fixTitle()};e.prototype.getDefaults=function(){return e.DEFAULTS};e.prototype.getOptions=function(e){e=t.extend({},this.getDefaults(),this.$element.data(),e);if(e.delay&&typeof e.delay=='number'){e.delay={show:e.delay,hide:e.delay}};return e};e.prototype.getDelegateOptions=function(){var e={};var i=this.getDefaults();this._options&&t.each(this._options,function(t,o){if(i[t]!=o)e[t]=o});return e};e.prototype.enter=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data('bs.'+this.type);if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)};if(e instanceof t.Event){i.inState[e.type=='focusin'?'focus':'hover']=!0};if(i.tip().hasClass('in')||i.hoverState=='in'){i.hoverState='in';return};clearTimeout(i.timeout);i.hoverState='in';if(!i.options.delay||!i.options.delay.show)return i.show();i.timeout=setTimeout(function(){if(i.hoverState=='in')i.show()},i.options.delay.show)};e.prototype.isInStateTrue=function(){for(var t in this.inState){if(this.inState[t])return!0};return!1};e.prototype.leave=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data('bs.'+this.type);if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)};if(e instanceof t.Event){i.inState[e.type=='focusout'?'focus':'hover']=!1};if(i.isInStateTrue())return;clearTimeout(i.timeout);i.hoverState='out';if(!i.options.delay||!i.options.delay.hide)return i.hide();i.timeout=setTimeout(function(){if(i.hoverState=='out')i.hide()},i.options.delay.hide)};e.prototype.show=function(){var c=t.Event('show.bs.'+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(c);var v=t.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(c.isDefaultPrevented()||!v)return;var n=this,o=this.tip(),u=this.getUID(this.type);this.setContent();o.attr('id',u);this.$element.attr('aria-describedby',u);if(this.options.animation)o.addClass('fade');var i=typeof this.options.placement=='function'?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,f=h.test(i);if(f)i=i.replace(h,'')||'top';o.detach().css({top:0,left:0,display:'block'}).addClass(i).data('bs.'+this.type,this);this.options.container?o.appendTo(this.options.container):o.insertAfter(this.$element);this.$element.trigger('inserted.bs.'+this.type);var s=this.getPosition(),l=o[0].offsetWidth,a=o[0].offsetHeight;if(f){var m=i,r=this.getPosition(this.$viewport);i=i=='bottom'&&s.bottom+a>r.bottom?'top':i=='top'&&s.top-a<r.top?'bottom':i=='right'&&s.right+l>r.width?'left':i=='left'&&s.left-l<r.left?'right':i;o.removeClass(m).addClass(i)};var d=this.getCalculatedOffset(i,s,l,a);this.applyPlacement(d,i);var p=function(){var t=n.hoverState;n.$element.trigger('shown.bs.'+n.type);n.hoverState=null;if(t=='out')n.leave(n)};t.support.transition&&this.$tip.hasClass('fade')?o.one('bsTransitionEnd',p).emulateTransitionEnd(e.TRANSITION_DURATION):p()}};e.prototype.applyPlacement=function(e,o){var i=this.tip(),c=i[0].offsetWidth,l=i[0].offsetHeight,a=parseInt(i.css('margin-top'),10),p=parseInt(i.css('margin-left'),10);if(isNaN(a))a=0;if(isNaN(p))p=0;e.top+=a;e.left+=p;t.offset.setOffset(i[0],t.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},e),0);i.addClass('in');var h=i[0].offsetWidth,s=i[0].offsetHeight;if(o=='top'&&s!=l){e.top=e.top+l-s};var n=this.getViewportAdjustedDelta(o,e,h,s);if(n.left)e.left+=n.left;else e.top+=n.top;var r=/top|bottom/.test(o),f=r?n.left*2-c+h:n.top*2-l+s,u=r?'offsetWidth':'offsetHeight';i.offset(e);this.replaceArrow(f,i[0][u],r)};e.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?'left':'top',50*(1-t/e)+'%').css(i?'top':'left','')};e.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find('.tooltip-inner')[this.options.html?'html':'text'](e);t.removeClass('fade in top bottom left right')};e.prototype.hide=function(i){var o=this,n=t(this.$tip),s=t.Event('hide.bs.'+this.type);function r(){if(o.hoverState!='in')n.detach();if(o.$element){o.$element.removeAttr('aria-describedby').trigger('hidden.bs.'+o.type)};i&&i()};this.$element.trigger(s);if(s.isDefaultPrevented())return;n.removeClass('in');t.support.transition&&n.hasClass('fade')?n.one('bsTransitionEnd',r).emulateTransitionEnd(e.TRANSITION_DURATION):r();this.hoverState=null;return this};e.prototype.fixTitle=function(){var t=this.$element;if(t.attr('title')||typeof t.attr('data-original-title')!='string'){t.attr('data-original-title',t.attr('title')||'').attr('title','')}};e.prototype.hasContent=function(){return this.getTLine truncated
else if(h>e.top+e.height){o.top=e.top+e.height-h}}
else{var l=i.left-s,a=i.left+s+n;if(l<e.left){o.left=e.left-l}
else if(a>e.right){o.left=e.left+e.width-a}};return o};e.prototype.getTitle=function(){var e,i=this.$element,t=this.options;e=i.attr('data-original-title')||(typeof t.title=='function'?t.title.call(i[0]):t.title);return e};e.prototype.getUID=function(t){do t+=~~(Math.random()*1000000);while(document.getElementById(t))return t};e.prototype.tip=function(){if(!this.$tip){this.$tip=t(this.options.template);if(this.$tip.length!=1){throw new Error(this.type+' `template` option must consist of exactly 1 top-level element!')}};return this.$tip};e.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find('.tooltip-arrow'))};e.prototype.enable=function(){this.enabled=!0};e.prototype.disable=function(){this.enabled=!1};e.prototype.toggleEnabled=function(){this.enabled=!this.enabled};e.prototype.toggle=function(e){var i=this;if(e){i=t(e.currentTarget).data('bs.'+this.type);if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)}};if(e){i.inState.click=!i.inState.click;if(i.isInStateTrue())i.enter(i);else i.leave(i)}
else{i.tip().hasClass('in')?i.leave(i):i.enter(i)}};e.prototype.destroy=function(){var t=this;clearTimeout(this.timeout);this.hide(function(){t.$element.off('.'+t.type).removeData('bs.'+t.type);if(t.$tip){t.$tip.detach()};t.$tip=null;t.$arrow=null;t.$viewport=null;t.$element=null})};function o(i){return this.each(function(){var n=t(this),o=n.data('bs.tooltip'),s=typeof i=='object'&&i;if(!o&&/destroy|hide/.test(i))return;if(!o)n.data('bs.tooltip',(o=new e(this,s)));if(typeof i=='string')o[i]()})};var i=t.fn.tooltip;t.fn.tooltip=o;t.fn.tooltip.Constructor=e;t.fn.tooltip.noConflict=function(){t.fn.tooltip=i;return this}}(jQuery);jQuery.fn.lapstooltip=jQuery.fn.tooltip.noConflict();jQuery(document).ready(function(){jQuery('.laps-timeline .event').lapstooltip({container:'#wpadminbar',placement:'bottom',html:!0,animation:!1})});
+11
View File
@@ -0,0 +1,11 @@
jQuery.fn.lapstooltip = jQuery.fn.tooltip.noConflict();
jQuery(document).ready(function () {
jQuery(".laps-timeline .event").lapstooltip({
container: '#wpadminbar',
placement: 'bottom',
html : true,
animation: false
});
});
+5 -22
View File
@@ -1,35 +1,18 @@
<?php <?php
/* /*
Plugin Name: Laps Plugin Name: Laps
Plugin URI: Plugin URI: https://github.com/Rarst/laps
Description: Light WordPress profiler. Description: Light WordPress profiler.
Author: Andrey "Rarst" Savchenko Author: Andrey "Rarst" Savchenko
Version: 1.0 Version: 1.4.2
Author URI: http://www.rarst.net/ Author URI: http://www.rarst.net/
Text Domain: Text Domain: laps
Domain Path: /lang Domain Path: /lang
License: MIT License: MIT
Copyright (c) 2013 Andrey "Rarst" Savchenko
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/ */
if( file_exists( __DIR__ . '/vendor/autoload.php' ) ) if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/vendor/autoload.php';
}
Rarst\Laps\Laps::on_load(); Rarst\Laps\Laps::on_load();
-38
View File
@@ -1,38 +0,0 @@
# Description
Laps is light WordPress profiler, which aims to be:
- always on and zero click (just hover on toolbar entry) away
- quick indicator of what hogs page in general or right now
It is no match or replacement for *real* profiler, but is friendly and cute.
# Installation
Laps is a Composer package and can be installed via:
php composer.phar create-project rarst/laps --repository-url=http://rarst.net
# Frequently Asked Questions
None... Yet.
# Screenshot
![Laps screenshot](http://i.imgur.com/zFokmkU.png)
# Changelog
## 1.0
- Initial public release
# License Info
Laps own code is licensed under MIT and it makes use of code from:
- Composer (MIT)
- Symfony Stopwatch (MIT)
- Mustache.php (MIT)
- Twitter Bootstrap (Apache License 2.0)
- Hint.css (MIT)
+55 -1
View File
@@ -2,18 +2,35 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Main set of events for WordPress core
*/
class Core_Events extends Laps_Events { class Core_Events extends Laps_Events {
/**
* @return array
*/
public function get_events() { public function get_events() {
$stops = array(); $stops = array();
$stops['plugins_loaded'][20] = array( $stops['plugins_loaded'][ - 2 ] = array(
'action' => 'stop', 'action' => 'stop',
'event' => 'Plugins Load', 'event' => 'Plugins Load',
'category' => 'plugin', 'category' => 'plugin',
); );
$stops['plugins_loaded'][ - 1 ] = array(
'event' => 'Plugins Loaded Hook',
'category' => 'plugin',
);
$stops['plugins_loaded'][20] = array(
'action' => 'stop',
'event' => 'Plugins Loaded Hook',
'category' => 'plugin',
);
$stops['setup_theme'][0] = array( $stops['setup_theme'][0] = array(
'event' => 'Themes Load', 'event' => 'Themes Load',
'category' => 'theme', 'category' => 'theme',
@@ -36,6 +53,32 @@ class Core_Events extends Laps_Events {
'category' => 'core', 'category' => 'core',
); );
$stops['admin_init'][- 1] = array(
'event' => 'Core Admin Init',
'category' => 'core',
);
$stops['admin_init'][ PHP_INT_MAX -1 ] = array(
'action' => 'stop',
'event' => 'Core Admin Init',
'category' => 'core',
);
$stops['_admin_menu'][- 1] = array(
'event' => 'Admin Menu',
'category' => 'core',
);
$stops['admin_menu'][ PHP_INT_MAX -1 ] = array(
'action' => 'stop',
'event' => 'Admin Menu',
'category' => 'core',
);
$stops['admin_bar_menu'][-1] = array(
'event' => 'Toolbar',
'category' => 'core',
);
$stops['loop_start'][10] = array( $stops['loop_start'][10] = array(
'event' => 'Main Loop', 'event' => 'Main Loop',
'category' => 'theme', 'category' => 'theme',
@@ -47,6 +90,17 @@ class Core_Events extends Laps_Events {
'category' => 'theme', 'category' => 'theme',
); );
$stops['admin_enqueue_scripts'][10] = array(
'event' => 'Admin Print Scripts',
'category' => 'core',
);
$stops['admin_print_scripts'][10] = array(
'action' => 'stop',
'event' => 'Admin Print Scripts',
'category' => 'core',
);
return $stops; return $stops;
} }
} }
+21 -11
View File
@@ -2,9 +2,28 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Base class for bulk event providers
*/
abstract class Laps_Events { abstract class Laps_Events {
/** /**
* Retrieve array of event data
*
* @return array
*/
public function get() {
if ( $this->is_applicable() ) {
return $this->get_events();
}
return array();
}
/**
* Is event pack relevant to current runtime
*
* @return bool * @return bool
*/ */
protected function is_applicable() { protected function is_applicable() {
@@ -13,18 +32,9 @@ abstract class Laps_Events {
} }
/** /**
* Inherit with internal events compiling and return
*
* @return array * @return array
*/ */
public function get() {
if( $this->is_applicable() )
return $this->get_events();
return array();
}
/**
* @return array()
*/
abstract protected function get_events(); abstract protected function get_events();
} }
+11
View File
@@ -2,13 +2,24 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Events for Genesis Framework based themes
*
* @link http://my.studiopress.com/themes/genesis/
*/
class Genesis_Events extends Laps_Events { class Genesis_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() { protected function is_applicable() {
return function_exists( 'genesis' ); return function_exists( 'genesis' );
} }
/**
* @return array
*/
protected function get_events() { protected function get_events() {
$events = array(); $events = array();
+14 -2
View File
@@ -2,13 +2,24 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Events for Hybrid Core based themes
*
* @link http://themehybrid.com/hybrid-core
*/
class Hybrid_Events extends Laps_Events { class Hybrid_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() { protected function is_applicable() {
return defined( 'HYBRID_VERSION' ); return defined( 'HYBRID_VERSION' ) && function_exists( 'hybrid_get_prefix' );
} }
/**
* @return array
*/
protected function get_events() { protected function get_events() {
$events = array(); $events = array();
@@ -27,7 +38,7 @@ class Hybrid_Events extends Laps_Events {
$sidebars = get_theme_support( 'hybrid-core-sidebars' ); $sidebars = get_theme_support( 'hybrid-core-sidebars' );
if ( ! empty( $sidebars[0] ) ) if ( ! empty( $sidebars[0] ) ) {
foreach ( $sidebars[0] as $sidebar ) { foreach ( $sidebars[0] as $sidebar ) {
$events["{$prefix}_before_{$sidebar}"][10] = array( $events["{$prefix}_before_{$sidebar}"][10] = array(
@@ -41,6 +52,7 @@ class Hybrid_Events extends Laps_Events {
'category' => 'theme', 'category' => 'theme',
); );
} }
}
return $events; return $events;
} }
+168 -25
View File
@@ -12,14 +12,16 @@ class Laps {
/** @var Stopwatch $stopwatch */ /** @var Stopwatch $stopwatch */
public static $stopwatch; public static $stopwatch;
public static $events = array(); public static $events = array();
public static $query_starts = array();
/** /**
* Start Stopwatch and timing plugin load immediately, then set up core events and needed hooks. * Start Stopwatch and timing plugin load immediately, then set up core events and needed hooks.
*/ */
static function on_load() { public static function on_load() {
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
return; return;
}
self::$stopwatch = new Stopwatch(); self::$stopwatch = new Stopwatch();
self::$stopwatch->start( 'Plugins Load', 'plugin' ); self::$stopwatch->start( 'Plugins Load', 'plugin' );
@@ -28,8 +30,14 @@ class Laps {
add_action( 'pre_update_option_active_plugins', array( __CLASS__, 'pre_update_option_active_plugins' ) ); add_action( 'pre_update_option_active_plugins', array( __CLASS__, 'pre_update_option_active_plugins' ) );
add_action( 'pre_update_site_option_active_sitewide_plugins', array( __CLASS__, 'pre_update_option_active_plugins' ) ); add_action( 'pre_update_site_option_active_sitewide_plugins', array( __CLASS__, 'pre_update_option_active_plugins' ) );
add_action( 'pre_http_request', array( __CLASS__, 'pre_http_request' ), 10, 3 );
add_action( 'http_api_debug', array( __CLASS__, 'http_api_debug' ), 10, 5 );
add_action( 'after_setup_theme', array( __CLASS__, 'after_setup_theme' ), 15 ); add_action( 'after_setup_theme', array( __CLASS__, 'after_setup_theme' ), 15 );
add_action( 'init', array( __CLASS__, 'init' ) ); add_action( 'init', array( __CLASS__, 'init' ) );
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
add_filter( 'query', array( __CLASS__, 'query' ), 20 );
}
} }
/** /**
@@ -37,7 +45,7 @@ class Laps {
* *
* @param array $stops * @param array $stops
*/ */
static function add_events( $stops ) { public static function add_events( $stops ) {
self::$events = array_merge( self::$events, $stops ); self::$events = array_merge( self::$events, $stops );
@@ -57,7 +65,7 @@ class Laps {
* *
* @return array * @return array
*/ */
static function pre_update_option_active_plugins( $plugins ) { public static function pre_update_option_active_plugins( $plugins ) {
$plugin = plugin_basename( dirname( __DIR__ ) . '/laps.php' ); $plugin = plugin_basename( dirname( __DIR__ ) . '/laps.php' );
$key = array_search( $plugin, $plugins ); $key = array_search( $plugin, $plugins );
@@ -79,74 +87,153 @@ class Laps {
* *
* @return mixed * @return mixed
*/ */
static function tick( $input = null ) { public static function tick( $input = null ) {
global $wp_filter; global $wp_filter;
$filter = current_filter(); $filter_name = current_filter();
$priority = key( $wp_filter[$filter] ); $filter_instance = $wp_filter[ $filter_name ];
$priority = $filter_instance instanceof \WP_Hook ? $filter_instance->current_priority() : key( $filter_instance );
$event = wp_parse_args( self::$events[$filter][$priority], array( // See https://core.trac.wordpress.org/ticket/41185 on broken priority, but more general sanity check.
if ( empty( self::$events[ $filter_name ][ $priority ] ) ) {
return $input;
}
$event = wp_parse_args(
self::$events[ $filter_name ][ $priority ],
array(
'action' => 'start', 'action' => 'start',
'category' => null, 'category' => null,
) ); )
);
self::$stopwatch->$event['action']( $event['event'], $event['category'] ); if ( 'stop' === $event['action'] && ! self::$stopwatch->isStarted( $event['event'] ) ) {
return $input;
}
self::$stopwatch->{$event['action']}( $event['event'], $event['category'] );
return $input; return $input;
} }
/** /**
* When theme is done possibly add theme-specific events. * Capture SQL queries start times
*
* @param string $query
*
* @return string
*/ */
static function after_setup_theme() { public static function query( $query ) {
foreach ( array( 'THA', 'Hybrid', 'Genesis', 'Thematic' ) as $theme ) { global $wpdb;
$class = "Rarst\\Laps\\{$theme}_Events"; if ( empty( self::$query_starts ) && ! empty( $wpdb->queries ) ) {
self::$query_starts[ count( $wpdb->queries ) ] = microtime( true ) * 1000;
} else {
self::$query_starts[] = microtime( true ) * 1000;
}
return $query;
}
/**
* Capture start time of HTTP request
*
* @param boolean $false
* @param array $args
* @param string $url
*
* @return boolean
*/
public static function pre_http_request( $false, $args, $url ) {
self::$stopwatch->start( $url, 'http' );
return $false;
}
/**
* Capture end time of HTTP request
*
* @param array|\WP_Error $response
* @param string $type
* @param object $class
* @param array $args
* @param string $url
*
* @return mixed
*/
public static function http_api_debug( $response, $type, $class, $args, $url ) {
self::$stopwatch->stop( $url );
return $response;
}
/**
* When theme is done possibly add vendor-specific events.
*/
public static function after_setup_theme() {
foreach ( array( 'THA', 'Hybrid', 'Genesis', 'Thematic', 'Yoast' ) as $vendor ) {
$class = "Rarst\\Laps\\{$vendor}_Events";
/** @var Laps_Events $events */ /** @var Laps_Events $events */
$events = new $class; $events = new $class;
self::add_events( $events->get() ); self::add_events( $events->get() );
} }
} }
static function init() { public static function init() {
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) ); add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) ); add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
add_action( 'admin_bar_menu', array( __CLASS__, 'admin_bar_menu' ), 100 ); add_action( 'admin_bar_menu', array( __CLASS__, 'admin_bar_menu' ), 100 );
} }
static function enqueue_scripts() { public static function enqueue_scripts() {
wp_register_style( 'laps-hint', plugins_url( 'css/hint.css', __DIR__ ), array(), '1.2.1' ); $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
wp_register_style( 'laps', plugins_url( 'css/laps.css', __DIR__ ), array( 'laps-hint' ) ); wp_register_script( 'laps', plugins_url( "js/laps{$suffix}.js", __DIR__ ), array( 'jquery' ), '3.3.1', true );
wp_register_style( 'laps', plugins_url( "css/laps{$suffix}.css", __DIR__ ) );
if ( is_admin_bar_showing() ) if ( is_admin_bar_showing() ) {
wp_enqueue_script( 'laps' );
wp_enqueue_style( 'laps' ); wp_enqueue_style( 'laps' );
} }
}
/** /**
* Render interface and add to the toolbar. * Render interface and add to the toolbar.
* *
* @param \WP_Admin_Bar $wp_admin_bar * @param \WP_Admin_Bar $wp_admin_bar
*/ */
static function admin_bar_menu( $wp_admin_bar ) { public static function admin_bar_menu( $wp_admin_bar ) {
if ( ! apply_filters( 'laps_can_see', current_user_can( 'manage_options' ) ) ) if ( ! apply_filters( 'laps_can_see', current_user_can( 'manage_options' ) ) ) {
return; return;
}
global $timestart; global $timestart, $wpdb;
$mustache = new \Mustache_Engine( array( $mustache = new \Mustache_Engine(
array(
'loader' => new \Mustache_Loader_FilesystemLoader( dirname( __DIR__ ) . '/views' ), 'loader' => new \Mustache_Loader_FilesystemLoader( dirname( __DIR__ ) . '/views' ),
) ); 'cache' => new Mustache_Cache_FrozenCache( dirname( __DIR__ ) . '/views/cache' ),
)
);
if ( self::$stopwatch->isStarted( 'Toolbar' ) ) {
self::$stopwatch->stop( 'Toolbar' );
}
$events = self::$stopwatch->getSectionEvents( '__root__' ); $events = self::$stopwatch->getSectionEvents( '__root__' );
$start = $timestart * 1000; $start = $timestart * 1000;
$end = microtime( true ) * 1000; $end = microtime( true ) * 1000;
$total = $end - $start; $total = $end - $start;
$event_data = array(); $event_data = array();
$http_data = array();
foreach ( $events as $name => $event ) { foreach ( $events as $name => $event ) {
@@ -154,12 +241,68 @@ class Laps {
$duration = $event->getDuration(); $duration = $event->getDuration();
$width = round( $duration / $total * 100, 2 ); $width = round( $duration / $total * 100, 2 );
$category = $event->getCategory(); $category = $event->getCategory();
if ( 'http' === $category ) {
$http_data[] = compact( 'name', 'offset', 'duration', 'width', 'category' );
continue;
}
$memory = $event->getMemory() / 1024 / 1024; $memory = $event->getMemory() / 1024 / 1024;
$event_data[] = compact( 'name', 'offset', 'duration', 'width', 'category', 'memory' ); $event_data[] = compact( 'name', 'offset', 'duration', 'width', 'category', 'memory' );
} }
$html = $mustache->render( 'laps', array( 'events' => $event_data ) ); $query_data = array();
$last_query_end = 0;
$last_offset = 0;
$last_duration = 0;
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
foreach ( $wpdb->queries as $key => $query ) {
$query_start = isset( self::$query_starts[ $key ] ) ? self::$query_starts[ $key ] : $last_query_end;
list( $sql, $duration, $trace ) = $query;
$sql = trim( $sql );
$category = 'query-read';
if ( 0 === stripos( $sql, 'INSERT' ) || 0 === stripos( $sql, 'UPDATE' ) ) {
$category = 'query-write';
}
$duration *= 1000;
$last_query_end = $query_start + $duration;
$offset = round( ( $query_start - $start ) / $total * 100, 2 );
// if query is indistinguishably close to previous then stack it
if ( $offset === $last_offset ) {
$key = count( $query_data ) - 1;
$query_data[ $key ]['sql'] .= '<br />' . $sql;
$last_duration += $duration;
$width = round( $last_duration / $total * 100, 2 );
$query_data[ $key ]['width'] = $width;
continue;
}
$width = round( $duration / $total * 100, 2 );
$last_offset = $offset;
$last_duration = $duration;
$query_data[] = compact( 'sql', 'duration', 'offset', 'width', 'category' );
}
}
$html = $mustache->render(
'laps',
array(
'events' => $event_data,
'queries' => $query_data,
'savequeries' => defined( 'SAVEQUERIES' ) && SAVEQUERIES,
'http' => $http_data,
'savehttp' => ! empty( $http_data ),
)
);
$wp_admin_bar->add_node( array( $wp_admin_bar->add_node( array(
'id' => 'laps', 'id' => 'laps',
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Rarst\Laps;
/**
* Implements read-only filesystem cache
*/
class Mustache_Cache_FrozenCache extends \Mustache_Cache_FilesystemCache {
/**
* Cache and load a compiled Mustache_Template class.
*
* @param string $key
* @param string $value
*
* @return void
*/
public function cache( $key, $value ) {
$this->log(
\Mustache_Logger::WARNING,
'Read only cache file missing, evaluating "{className}" class at runtime',
array( 'className' => $key )
);
eval( '?>' . $value );
}
}
+11
View File
@@ -2,13 +2,24 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Events for Theme Hook Alliance
*
* @link http://zamoose.github.io/themehookalliance/
*/
class THA_Events extends Laps_Events { class THA_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() { protected function is_applicable() {
return defined( 'THA_HOOKS_VERSION' ); return defined( 'THA_HOOKS_VERSION' );
} }
/**
* @return array
*/
protected function get_events() { protected function get_events() {
$events = array(); $events = array();
+11
View File
@@ -2,13 +2,24 @@
namespace Rarst\Laps; namespace Rarst\Laps;
/**
* Events for Thematic Framework based themes
*
* @link http://thematictheme.com/
*/
class Thematic_Events extends Laps_Events { class Thematic_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() { protected function is_applicable() {
return function_exists( 'thematic_init' ); return function_exists( 'thematic_init' );
} }
/**
* @return array
*/
protected function get_events() { protected function get_events() {
$events = array(); $events = array();
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace Rarst\Laps;
/**
* Events for Yoast plugins
*/
class Yoast_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() {
return class_exists( 'WPSEO_Frontend' );
}
/**
* @return array
*/
public function get_events() {
$stops = array();
$stops['wpseo_head'][1] = array(
'event' => 'WP SEO head hook',
'category' => 'plugin',
);
$stops['wpseo_head'][100] = array(
'action' => 'stop',
'event' => 'WP SEO head hook',
'category' => 'plugin',
);
return $stops;
}
}
@@ -0,0 +1,292 @@
<?php
class __Mustache_797f2a84b9a5a7b601644494da75d61e extends Mustache_Template
{
private $lambdaHelper;
public function renderInternal(Mustache_Context $context, $indent = '')
{
$this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
$buffer = '';
$blocksContext = array();
$buffer .= $indent . '<div class="laps-timeline">
';
// 'events' section
$value = $context->find('events');
$buffer .= $this->section940385acb9865793d8943db356869c18($context, $indent, $value);
$buffer .= $indent . '</div>
';
$buffer .= $indent . '
';
// 'savequeries' section
$value = $context->find('savequeries');
$buffer .= $this->sectionB93c1beb6bc5c41326a972381b0dd94a($context, $indent, $value);
$buffer .= $indent . '
';
// 'savehttp' section
$value = $context->find('savehttp');
$buffer .= $this->section238f05e38d8d133266503e545e18de7e($context, $indent, $value);
return $buffer;
}
private function section940385acb9865793d8943db356869c18(Mustache_Context $context, $indent, $value)
{
$buffer = '';
$blocksContext = array();
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" data-toggle="tooltip" title="{{name}} - {{duration}} ms - {{memory}} MB" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{name}} - {{duration}} ms - {{memory}} MB</span>
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" data-toggle="tooltip" title="';
$value = $this->resolveValue($context->find('name'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms - ';
$value = $this->resolveValue($context->find('memory'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' MB" style="width:';
$value = $this->resolveValue($context->find('width'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;">
';
$buffer .= $indent . ' <span class="sr-only">';
$value = $this->resolveValue($context->find('name'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms - ';
$value = $this->resolveValue($context->find('memory'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' MB</span>
';
$buffer .= $indent . ' </div>
';
$context->pop();
}
}
return $buffer;
}
private function section372053fedd826e7e297c29f607930cbc(Mustache_Context $context, $indent, $value)
{
$buffer = '';
$blocksContext = array();
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" title="{{sql}}" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{sql}}</span>
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" title="';
$value = $this->resolveValue($context->find('sql'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" style="width:';
$value = $this->resolveValue($context->find('width'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;">
';
$buffer .= $indent . ' <span class="sr-only">';
$value = $this->resolveValue($context->find('sql'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '</span>
';
$buffer .= $indent . ' </div>
';
$context->pop();
}
}
return $buffer;
}
private function sectionB93c1beb6bc5c41326a972381b0dd94a(Mustache_Context $context, $indent, $value)
{
$buffer = '';
$blocksContext = array();
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="laps-timeline">
{{#queries}}
<div class="event event-{{category}}" title="{{sql}}" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{sql}}</span>
</div>
{{/queries}}
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . '<div class="laps-timeline">
';
// 'queries' section
$value = $context->find('queries');
$buffer .= $this->section372053fedd826e7e297c29f607930cbc($context, $indent, $value);
$buffer .= $indent . '</div>
';
$context->pop();
}
}
return $buffer;
}
private function section26362c0132f6d74333e6154005595603(Mustache_Context $context, $indent, $value)
{
$buffer = '';
$blocksContext = array();
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" title="{{name}} - {{duration}} ms" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{name}} - {{duration}} ms</span>
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" title="';
$value = $this->resolveValue($context->find('name'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms" style="width:';
$value = $this->resolveValue($context->find('width'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;">
';
$buffer .= $indent . ' <span class="sr-only">';
$value = $this->resolveValue($context->find('name'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms</span>
';
$buffer .= $indent . ' </div>
';
$context->pop();
}
}
return $buffer;
}
private function section238f05e38d8d133266503e545e18de7e(Mustache_Context $context, $indent, $value)
{
$buffer = '';
$blocksContext = array();
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="laps-timeline">
{{#http}}
<div class="event event-{{category}}" title="{{name}} - {{duration}} ms" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{name}} - {{duration}} ms</span>
</div>
{{/http}}
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . '<div class="laps-timeline">
';
// 'http' section
$value = $context->find('http');
$buffer .= $this->section26362c0132f6d74333e6154005595603($context, $indent, $value);
$buffer .= $indent . '</div>
';
$context->pop();
}
}
return $buffer;
}
}
+23 -1
View File
@@ -1,5 +1,27 @@
<div class="laps-timeline"> <div class="laps-timeline">
{{#events}} {{#events}}
<div class="event event-{{category}} hint--bottom" data-hint="{{name}} - {{duration}} ms - {{memory}} MB" style="width:{{width}}%; left:{{offset}}%;"></div> <div class="event event-{{category}}" data-toggle="tooltip" title="{{name}} - {{duration}} ms - {{memory}} MB" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{name}} - {{duration}} ms - {{memory}} MB</span>
</div>
{{/events}} {{/events}}
</div> </div>
{{#savequeries}}
<div class="laps-timeline">
{{#queries}}
<div class="event event-{{category}}" title="{{sql}}" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{sql}}</span>
</div>
{{/queries}}
</div>
{{/savequeries}}
{{#savehttp}}
<div class="laps-timeline">
{{#http}}
<div class="event event-{{category}}" title="{{name}} - {{duration}} ms" style="width:{{width}}%; left:{{offset}}%;">
<span class="sr-only">{{name}} - {{duration}} ms</span>
</div>
{{/http}}
</div>
{{/savehttp}}