├── Resources ├── Private │ ├── .htaccess │ └── Language │ │ └── locallang_dl.xlf └── Public │ ├── Icons │ └── Extension.png │ ├── Contrib │ ├── images │ │ ├── logo.png │ │ └── style.css │ ├── samples │ │ ├── images │ │ │ ├── 0.gif │ │ │ ├── 1.gif │ │ │ ├── 2.gif │ │ │ ├── 3.gif │ │ │ ├── bg.jpg │ │ │ ├── car.png │ │ │ ├── bgSky.jpg │ │ │ ├── board.jpg │ │ │ ├── star.png │ │ │ ├── bicycle.png │ │ │ ├── redstar.png │ │ │ └── motorcycle.png │ │ ├── style.css │ │ ├── pieSimple.html │ │ ├── _JSON_pieWithLegend.html │ │ ├── _JSON_radarSimple.html │ │ ├── angularGaugeWithTwoAxes.html │ │ ├── _JSON_angularGauge.html │ │ ├── pie3D.html │ │ ├── pyramidChart.html │ │ ├── pyramidChart3D.html │ │ ├── funnelChart.html │ │ ├── radarSimple.html │ │ ├── angularGauge.html │ │ ├── clock.html │ │ ├── pieDonut3D.html │ │ ├── _JSON_barAndLineMix.html │ │ ├── barFloating.html │ │ ├── xyBubbleSimple.html │ │ ├── bar3D.html │ │ ├── _JSON_lineWithFilledValueRanges.html │ │ ├── pieWithPatterns.html │ │ ├── clockWithTwoFaces.html │ │ ├── columnWithGradientFills.html │ │ ├── columnWithImages.html │ │ ├── xyError.html │ │ ├── barClustered.html │ │ ├── radarPolar.html │ │ ├── _JSON_xyBubbleWithZoom.html │ │ ├── errorChart.html │ │ ├── _JSON_xyWithGuides.html │ │ ├── columnWithPatterns.html │ │ ├── barAndLineMix.html │ │ ├── columnSimple.html │ │ ├── barWithBackgroundImage.html │ │ ├── _JSON_lineWithScrollAndZoom.html │ │ └── areaWithTimeBasedData.html │ ├── amcharts │ │ ├── images │ │ │ ├── lens.png │ │ │ ├── export.png │ │ │ ├── dragIcon.gif │ │ │ ├── dragIconH.gif │ │ │ ├── lensWhite.png │ │ │ ├── exportWhite.png │ │ │ ├── dragIconBlack.gif │ │ │ └── dragIconHBlack.gif │ │ ├── patterns │ │ │ ├── black │ │ │ │ ├── pattern1.png │ │ │ │ ├── pattern10.png │ │ │ │ ├── pattern11.png │ │ │ │ ├── pattern12.png │ │ │ │ ├── pattern13.png │ │ │ │ ├── pattern14.png │ │ │ │ ├── pattern15.png │ │ │ │ ├── pattern16.png │ │ │ │ ├── pattern17.png │ │ │ │ ├── pattern18.png │ │ │ │ ├── pattern19.png │ │ │ │ ├── pattern2.png │ │ │ │ ├── pattern20.png │ │ │ │ ├── pattern21.png │ │ │ │ ├── pattern3.png │ │ │ │ ├── pattern4.png │ │ │ │ ├── pattern5.png │ │ │ │ ├── pattern6.png │ │ │ │ ├── pattern7.png │ │ │ │ ├── pattern8.png │ │ │ │ └── pattern9.png │ │ │ ├── chalk │ │ │ │ ├── pattern1.jpg │ │ │ │ ├── pattern1r.jpg │ │ │ │ ├── pattern2.jpg │ │ │ │ ├── pattern3.jpg │ │ │ │ ├── pattern4.jpg │ │ │ │ ├── pattern5.jpg │ │ │ │ └── pattern6.jpg │ │ │ └── white │ │ │ │ ├── pattern1.png │ │ │ │ ├── pattern10.png │ │ │ │ ├── pattern11.png │ │ │ │ ├── pattern12.png │ │ │ │ ├── pattern13.png │ │ │ │ ├── pattern14.png │ │ │ │ ├── pattern15.png │ │ │ │ ├── pattern16.png │ │ │ │ ├── pattern17.png │ │ │ │ ├── pattern18.png │ │ │ │ ├── pattern19.png │ │ │ │ ├── pattern2.png │ │ │ │ ├── pattern20.png │ │ │ │ ├── pattern21.png │ │ │ │ ├── pattern3.png │ │ │ │ ├── pattern4.png │ │ │ │ ├── pattern5.png │ │ │ │ ├── pattern6.png │ │ │ │ ├── pattern7.png │ │ │ │ ├── pattern8.png │ │ │ │ └── pattern9.png │ │ ├── plugins │ │ │ └── responsive │ │ │ │ └── examples │ │ │ │ ├── images │ │ │ │ ├── car.png │ │ │ │ ├── bicycle.png │ │ │ │ └── motorcycle.png │ │ │ │ ├── pie1.html │ │ │ │ ├── pie2.html │ │ │ │ ├── radar.html │ │ │ │ ├── gauge.html │ │ │ │ ├── funnel.html │ │ │ │ ├── serial2.html │ │ │ │ ├── serial3.html │ │ │ │ ├── index.html │ │ │ │ └── xy.html │ │ └── lang │ │ │ ├── bg.js │ │ │ ├── id.js │ │ │ ├── sk.js │ │ │ ├── tr.js │ │ │ ├── hu.js │ │ │ ├── pt.js │ │ │ ├── ro.js │ │ │ ├── es.js │ │ │ ├── mk.js │ │ │ ├── nl.js │ │ │ ├── no.js │ │ │ ├── ru.js │ │ │ ├── az.js │ │ │ ├── mt.js │ │ │ ├── fo.js │ │ │ ├── hr.js │ │ │ ├── it.js │ │ │ ├── th.js │ │ │ ├── fr.js │ │ │ ├── pl.js │ │ │ ├── is.js │ │ │ ├── lv.js │ │ │ ├── mn.js │ │ │ ├── lt.js │ │ │ ├── rw.js │ │ │ ├── fi.js │ │ │ ├── so.js │ │ │ └── de.js │ ├── licence.txt │ ├── thirdPartySoftwareList.txt │ └── index.html │ ├── Documentation │ └── screenshot.png │ ├── Images │ ├── background_mobile.png │ └── background_desktop.png │ ├── JavaScript │ └── PageSpeedModule.js │ └── Styles │ └── speed.css ├── .crowdin.yml ├── ext_conf_template.txt ├── ext_tables.php ├── ext_emconf.php ├── Classes ├── Domain │ └── Model │ │ ├── Response │ │ ├── Result.php │ │ ├── UrlBlock.php │ │ ├── Screenshot.php │ │ └── Rule.php │ │ └── Dto │ │ └── Configuration.php └── ViewHelpers │ ├── IndicatorViewHelper.php │ ├── IndicatorRulesViewHelper.php │ ├── ResultViewHelper.php │ ├── Chart │ ├── GaugeViewHelper.php │ └── AssetsViewHelper.php │ └── UrlBlockViewHelper.php ├── ext_localconf.php ├── composer.json └── README.rst /Resources/Private/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | deny from all -------------------------------------------------------------------------------- /Resources/Public/Icons/Extension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Icons/Extension.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/images/logo.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/0.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/1.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/2.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/3.gif -------------------------------------------------------------------------------- /Resources/Public/Documentation/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Documentation/screenshot.png -------------------------------------------------------------------------------- /Resources/Public/Images/background_mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Images/background_mobile.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/bg.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/car.png -------------------------------------------------------------------------------- /Resources/Public/Images/background_desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Images/background_desktop.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/lens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/lens.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/bgSky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/bgSky.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/board.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/star.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/export.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/bicycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/bicycle.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/redstar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/redstar.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/dragIcon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/dragIcon.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/dragIconH.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/dragIconH.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/lensWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/lensWhite.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/images/motorcycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/samples/images/motorcycle.png -------------------------------------------------------------------------------- /.crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /Resources/Private/Language/locallang*.xlf 3 | translation: /Resources/Private/Language/%two_letters_code%.%original_file_name% 4 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/exportWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/exportWhite.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/dragIconBlack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/dragIconBlack.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/images/dragIconHBlack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/images/dragIconHBlack.gif -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern1.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern10.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern11.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern12.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern13.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern14.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern15.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern16.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern17.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern18.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern19.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern2.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern20.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern21.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern3.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern4.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern5.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern6.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern7.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern8.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/black/pattern9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/black/pattern9.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern1.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern1r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern1r.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern2.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern3.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern4.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern5.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/chalk/pattern6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/chalk/pattern6.jpg -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern1.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern10.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern11.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern12.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern13.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern14.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern15.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern16.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern17.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern18.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern19.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern2.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern20.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern21.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern3.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern4.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern5.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern6.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern7.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern8.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/patterns/white/pattern9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/patterns/white/pattern9.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/car.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/bicycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/bicycle.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/motorcycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgringer/page_speed/HEAD/Resources/Public/Contrib/amcharts/plugins/responsive/examples/images/motorcycle.png -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Tahoma,Arial,Verdana; 3 | font-size: 12px; 4 | color: black; 5 | } 6 | 7 | a:link {color: #84c4e2;} 8 | a:visited {color:#84c4e2;} 9 | a:hover {color: #cd82ad;} 10 | a:active {color: #84c4e2;} -------------------------------------------------------------------------------- /ext_conf_template.txt: -------------------------------------------------------------------------------- 1 | # cat=basic/enable/2; type=string; label=LLL:EXT:page_speed/Resources/Private/Language/locallang.xlf:extmng.key 2 | key = 3 | 4 | # cat=basic/enable/3; type=int; label=LLL:EXT:page_speed/Resources/Private/Language/locallang.xlf:extmng.cacheTime 5 | cacheTime = 86400 6 | 7 | # cat=basic/enable/3; type=boolean; label=LLL:EXT:page_speed/Resources/Private/Language/locallang.xlf:extmng.demo 8 | demo = 1 -------------------------------------------------------------------------------- /ext_tables.php: -------------------------------------------------------------------------------- 1 | 'Check your site with Google PageSpeed Insights', 5 | 'description' => 'Performance & Usability are important to any site. Check every page for it and know how the site can be improved.', 6 | 'category' => 'backend', 7 | 'author' => 'Georg Ringer', 8 | 'author_email' => 'georg.ringer@gmail.com', 9 | 'state' => 'beta', 10 | 'clearCacheOnLoad' => true, 11 | 'version' => '3.1.0', 12 | 'constraints' => [ 13 | 'depends' => [ 14 | 'typo3' => '9.5.0-9.9.99', 15 | ], 16 | 'conflicts' => [], 17 | 'suggests' => [], 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/images/style.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Lato:300); 2 | 3 | body { 4 | background-color: #FFFFFF; 5 | margin-left: 32px; 6 | margin-top: 20px; 7 | margin-right: 20px; 8 | margin-bottom: 20px; 9 | font-family: "Lato", Arial; 10 | font-size: 14px; 11 | line-height:16px; 12 | } 13 | 14 | hr{ 15 | border: 1px solid #FFFFFF; 16 | } 17 | 18 | a:link{ 19 | color:#0055CC; 20 | } 21 | a:visited{ 22 | color:#990099; 23 | } 24 | a:hover{ 25 | color:#CC0000; 26 | } 27 | 28 | th{ 29 | background-color:#FFFFFF; 30 | font-weight:bold; 31 | } 32 | 33 | td{ 34 | background-color:#ecf7fe; 35 | text-align:center; 36 | } -------------------------------------------------------------------------------- /Resources/Private/Language/locallang_dl.xlf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | Speed 8 | 9 | 10 | PageSpeed Check 11 | 12 | 13 | Use the API of Google's PageSpeed to check your sites. 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/lang/de.js: -------------------------------------------------------------------------------- 1 | AmCharts.translations.de = { 2 | "monthNames": ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 3 | "shortMonthNames": ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], 4 | "dayNames": ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], 5 | "shortDayNames": ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], 6 | "zoomOutText": "Alle anzeigen", 7 | "fromText": "Von:", 8 | "toText":"Bis:", 9 | "periodsText":"Ansicht:", 10 | "selectText":"Auswahl:", 11 | "comboBoxSelectText":"Auswahl...", 12 | "compareText":"Vergleichen mit:" 13 | } -------------------------------------------------------------------------------- /Classes/Domain/Model/Response/Result.php: -------------------------------------------------------------------------------- 1 | format = $raw['format']; 18 | if (isset($raw['args'])) { 19 | $this->arguments = $raw['args']; 20 | } 21 | } 22 | 23 | public function getFormat(): string 24 | { 25 | return $this->format; 26 | } 27 | 28 | public function getArguments(): array 29 | { 30 | return $this->arguments; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ext_localconf.php: -------------------------------------------------------------------------------- 1 | \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, 12 | 'backend' => \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class, 13 | 'options' => [ 14 | 'defaultLifetime' => $configuration->getCacheTime(), 15 | ], 16 | // 'groups' => array('system') 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /Classes/Domain/Model/Response/UrlBlock.php: -------------------------------------------------------------------------------- 1 | header = new Result($raw['header']); 18 | 19 | if (isset($raw['urls']) && is_array($raw['urls'])) { 20 | foreach ($raw['urls'] as $item) { 21 | $this->urls[] = new Result($item['result']); 22 | } 23 | } 24 | } 25 | 26 | public function getHeader(): Result 27 | { 28 | return $this->header; 29 | } 30 | 31 | public function getUrls(): array 32 | { 33 | return $this->urls; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Classes/ViewHelpers/IndicatorViewHelper.php: -------------------------------------------------------------------------------- 1 | registerArgument('number', 'int', 'number'); 14 | } 15 | 16 | public function render() 17 | { 18 | $number = (int)$this->arguments['number']; 19 | if ($number === 0) { 20 | return 'none'; 21 | } elseif ($number <= Response::INDICATOR_LOW) { 22 | return 'danger'; 23 | } elseif ($number > Response::INDICATOR_HIGH) { 24 | return 'ok'; 25 | } else { 26 | return 'warning'; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/licence.txt: -------------------------------------------------------------------------------- 1 | ********************************************************************************* 2 | This AmCharts software is free under a linkware license. 3 | 4 | This means you may not remove or hide in any other way link to amcharts 5 | web site - www.amcharts.com. 6 | 7 | If you wish to remove the link, you should purchase commercial license. 8 | 9 | You may not redistribute, sublicense or sell this program without written 10 | permission of Antanas Marcelionis, the author of amcharts software. 11 | 12 | This software is provided without warranty. 13 | ********************************************************************************* 14 | A commercial version (without link) is available at amCharts's website: 15 | http://shop.amcharts.com/ 16 | ********************************************************************************* -------------------------------------------------------------------------------- /Classes/ViewHelpers/IndicatorRulesViewHelper.php: -------------------------------------------------------------------------------- 1 | registerArgument('number', 'int', 'number'); 14 | } 15 | 16 | public function render() 17 | { 18 | $number = (int)$this->arguments['number']; 19 | if ($number === 0) { 20 | return 'none'; 21 | } elseif ($number <= Response::INDICATOR_LOW) { 22 | return 'danger'; 23 | } elseif ($number > Response::INDICATOR_HIGH) { 24 | return 'ok'; 25 | } else { 26 | return 'warning'; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "georgringer/page_speed", 3 | "type": "typo3-cms-extension", 4 | "description": "Performance & Usability are important to any site. Check every page for it and know how the site can be improved.", 5 | "keywords": [ 6 | "TYPO3", 7 | "extension", 8 | "google", 9 | "speed", 10 | "mobile", 11 | "performance" 12 | ], 13 | "homepage": "http://ringer.it", 14 | "license": [ 15 | "GPL-2.0+" 16 | ], 17 | "require": { 18 | "typo3/cms-core": "^9.5" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "GeorgRinger\\PageSpeed\\": "Classes" 23 | } 24 | }, 25 | "replace": { 26 | "page_speed": "self.version", 27 | "typo3-ter/page-speed": "self.version" 28 | }, 29 | "config": { 30 | "vendor-dir": ".Build/vendor", 31 | "bin-dir": ".Build/bin" 32 | }, 33 | "scripts": { 34 | "post-autoload-dump": [ 35 | "mkdir -p .Build/Web/typo3conf/ext/", 36 | "[ -L .Build/Web/typo3conf/ext/page_speed ] || ln -snvf ../../../../. .Build/Web/typo3conf/ext/page_speed" 37 | ] 38 | }, 39 | "extra": { 40 | "typo3/cms": { 41 | "cms-package-dir": "{$vendor-dir}/typo3/cms", 42 | "web-dir": ".Build/Web" 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/thirdPartySoftwareList.txt: -------------------------------------------------------------------------------- 1 | ********************************************************************************* 2 | Third party software used: 3 | 4 | Jason S. Kerchner base class (http://livingmachines.net) 5 | Licensed under BSD license: http://livingmachines.net/license/ 6 | 7 | David Knape & Patrick Mineault Bezier curves drawing logic. 8 | 9 | Code optimization made using Closure Compiling service: 10 | http://closure-compiler.appspot.com/home 11 | 12 | Libraries used for exporting charts as image/pdf/svg: 13 | 14 | canvg.js - Javascript SVG parser and renderer on Canvas 15 | MIT Licensed 16 | Gabe Lerner (gabelerner@gmail.com) 17 | http://code.google.com/p/canvg/ 18 | 19 | rgbcolor.js 20 | A class to parse color values 21 | author Stoyan Stefanov, sstoo@gmail.com 22 | http://www.phpied.com/rgb-color-parser-in-javascript/ 23 | license Use it if you like it 24 | 25 | FileSaver.js 26 | A saveAs() FileSaver implementation. 27 | By Eli Grey, http://eligrey.com 28 | License: X11/MIT 29 | 30 | jsPDF.js 31 | By James Hall 32 | License: MIT 33 | 34 | ********************************************************************************* -------------------------------------------------------------------------------- /Classes/Domain/Model/Response/Screenshot.php: -------------------------------------------------------------------------------- 1 | mimeType = $raw['mime_type']; 28 | $this->data = str_replace(['_', '-'], ['/', '+'], $raw['data']); 29 | $this->width = (int)$raw['width']; 30 | $this->height = (int)$raw['height']; 31 | $this->pageRect = $raw['page_rect']; 32 | } 33 | } 34 | 35 | public function getMimeType(): string 36 | { 37 | return $this->mimeType; 38 | } 39 | 40 | public function getData(): string 41 | { 42 | return $this->data; 43 | } 44 | 45 | public function getWidth(): int 46 | { 47 | return $this->width; 48 | } 49 | 50 | public function getHeight(): int 51 | { 52 | return $this->height; 53 | } 54 | 55 | public function getPageRect(): array 56 | { 57 | return $this->pageRect; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Resources/Public/JavaScript/PageSpeedModule.js: -------------------------------------------------------------------------------- 1 | define(['jquery', 'TYPO3/CMS/Backend/Tooltip'], function ($) { 2 | 3 | 4 | $(document).ready(function () { 5 | var calc = 1.422222222; 6 | 7 | jQuery(".single-rule .title").click(function () { 8 | jQuery(this).children('i').toggleClass('fa-minus'); 9 | jQuery(this).next('.description').toggle(); 10 | }); 11 | 12 | jQuery(".screenshot-toggle").click(function () { 13 | if (jQuery(this).hasClass('active')) { 14 | jQuery('.snapshot-rect').remove(); 15 | } else { 16 | addOverlay(this, 'rects', ''); 17 | addOverlay(this, 'rects-secondary', 'secondary'); 18 | } 19 | jQuery(this).toggleClass('active'); 20 | 21 | }); 22 | 23 | function addOverlay(link, attribute, additionalClass) { 24 | jQuery('.snapshot-rect').remove(); 25 | var areas = jQuery(link).data(attribute).split(';'); 26 | for (var i = 0; i < areas.length; i++) { 27 | var item = areas[i].split(','); 28 | jQuery("
") 29 | .addClass('snapshot-rect ' + additionalClass) 30 | .css({ 31 | left: item[0] / calc, 32 | top: item[1] / calc, 33 | width: item[2] / calc, 34 | height: item[3] / calc 35 | }) 36 | .insertAfter(jQuery('#screenshot-' + jQuery(link).data('strategy'))); 37 | } 38 | } 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /Classes/Domain/Model/Dto/Configuration.php: -------------------------------------------------------------------------------- 1 | get('page_speed'); 27 | } catch (\Exception $e) { 28 | $configuration = []; 29 | } 30 | $this->key = (string)$configuration['key']; 31 | $this->demo = (bool)$configuration['demo']; 32 | $this->cacheTime = (int)$configuration['cacheTime']; 33 | } 34 | 35 | /** 36 | * @return bool 37 | */ 38 | public function isValid(): bool 39 | { 40 | if ($this->demo) { 41 | return true; 42 | } 43 | return !empty($this->key); 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getKey(): string 50 | { 51 | return $this->key; 52 | } 53 | 54 | /** 55 | * @return bool 56 | */ 57 | public function isDemo(): bool 58 | { 59 | return $this->demo; 60 | } 61 | 62 | /** 63 | * @return int 64 | */ 65 | public function getCacheTime(): int 66 | { 67 | return $this->cacheTime; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Classes/Domain/Model/Response/Rule.php: -------------------------------------------------------------------------------- 1 | localizedRuleName = $raw['localizedRuleName']; 27 | $this->ruleImpact = $raw['ruleImpact']; 28 | $this->group = $raw['groups'][0]; 29 | 30 | if (isset($raw['summary']) && is_array($raw['summary'])) { 31 | $this->summary = new Result($raw['summary']); 32 | } 33 | if (isset($raw['urlBlocks']) && is_array($raw['urlBlocks'])) { 34 | foreach ($raw['urlBlocks'] as $item) { 35 | $this->urlBlocks[] = new UrlBlock($item); 36 | } 37 | } 38 | } 39 | 40 | public function getSummary(): Result 41 | { 42 | return $this->summary; 43 | } 44 | 45 | public function getLocalizedRuleName(): string 46 | { 47 | return $this->localizedRuleName; 48 | } 49 | 50 | public function getRuleImpact(): float 51 | { 52 | return $this->ruleImpact; 53 | } 54 | 55 | public function getGroup(): string 56 | { 57 | return $this->group; 58 | } 59 | 60 | public function getHasImpact(): string 61 | { 62 | return (float)$this->ruleImpact > 0 ? 'danger' : 'success'; 63 | } 64 | 65 | public function getUrlBlocks(): array 66 | { 67 | return $this->urlBlocks; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Classes/ViewHelpers/ResultViewHelper.php: -------------------------------------------------------------------------------- 1 | registerArgument('result', Result::class, 'Result', false, null); 21 | $this->registerArgument('hsc', 'bool', 'HSC', false, true); 22 | } 23 | 24 | public function render() 25 | { 26 | $result = $this->arguments['result']; 27 | $hsc = $this->arguments['hsc']; 28 | 29 | if ($result === null) { 30 | return ''; 31 | } 32 | $searchReplace = []; 33 | foreach ($result->getArguments() as $argument) { 34 | $value = $hsc ? htmlspecialchars($argument['value']) : $argument['value']; 35 | switch ($argument['type']) { 36 | case 'HYPERLINK': 37 | $searchReplace['{{BEGIN_LINK}}'] = sprintf('', $value); 38 | $searchReplace['{{END_LINK}}'] = ''; 39 | break; 40 | case 'DURATION': 41 | $searchReplace['{{' . $argument['key'] . '}}'] = '' . $value . ''; 42 | break; 43 | 44 | default: 45 | $searchReplace['{{' . $argument['key'] . '}}'] = '' . $value . ''; 46 | } 47 | } 48 | 49 | $search = array_keys($searchReplace); 50 | $replace = array_values($searchReplace); 51 | 52 | return str_replace($search, $replace, $result->getFormat()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pieSimple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 52 | 53 | 54 | 55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_pieWithLegend.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/pie1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_radarSimple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 57 | 58 | 59 | 60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/angularGaugeWithTwoAxes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/pie2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/radar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 61 | 62 | 63 | 64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/gauge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Intro to JavaScript amCharts 5 | 6 | 7 | 8 | 9 | 10 |

11 |
12 |

A very short tutorial for those who don't like reading

13 |
    14 |
  • Copy amcharts folder to your working dir.
  • 15 |
  • Go to samples folder and open one of HTML files in your browser - you should see a chart.
  • 16 |
  • View source of the page or open this HTML file with text editor.
  • 17 |
  • Try to make some changes.
  • 18 |
  • Copy/Paste everything to your html/php/asp/etc file and fix paths to scripts
  • 19 |
  • Open your file in browser - you should see the same chart.
  • 20 |
  • Now it's time to read all the tutorials and check the examples :)
  • 21 |
22 |
23 |

Documentation

24 | 27 |
28 |

Live Editor

29 |
    30 |
  • It's a lot esier to configure your charts using our Live Editor. Even if you are not programmer, you can create stunning charts!
  • 31 |
32 |
33 |

Tutorials

34 | 37 |
38 |

Examples

39 | We think that the best way to start learning amCharts (and any other similar software) is to study examples. Check samples folder - there are plenty of them! In case you prefer working in jsFiddle, visit our web site - all samples have a link to jsFiddle where you can edit and view the result instantly. 40 |

Support

41 | In case you have a question, go to our support section. You'll find a lot of information there, and if you won't - you can always ask. 42 |
43 |

Good luck!

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_angularGauge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 61 | 62 | 63 | 64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pie3D.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 60 | 61 | 62 | 63 |
64 | 65 | 66 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/funnel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 66 | 67 | 68 | 69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pyramidChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 61 | 62 | 63 | 64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /Classes/ViewHelpers/Chart/GaugeViewHelper.php: -------------------------------------------------------------------------------- 1 | getScoreSpeed() > 0) { 27 | $arrows[] = '{ 28 | "color": "blue", 29 | "innerRadius": "10%", 30 | "nailRadius": 0, 31 | "value": ' . $response->getScoreSpeed() . ', 32 | "title": "Speed", 33 | "radius": "100%" 34 | }'; 35 | } 36 | if ($response->getScoreUsability() > 0) { 37 | $arrows[] = '{ 38 | "color": "redo", 39 | "title": "Usability", 40 | "innerRadius": "0%", 41 | "nailRadius": 0, 42 | "value": ' . $response->getScoreUsability() . ', 43 | "radius": "100%" 44 | }'; 45 | } 46 | return ''; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pyramidChart3D.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 66 | 67 | 68 | 69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/funnelChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 66 | 67 | 68 | 69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/radarSimple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/angularGauge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/clock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 87 | 88 | 89 | 90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /Resources/Public/Styles/speed.css: -------------------------------------------------------------------------------- 1 | .screenshot { 2 | height: 485px; 3 | position: relative; 4 | width: 250px; 5 | } 6 | 7 | .screenshot.desktop { 8 | background: url(../Images/background_desktop.png) no-repeat; 9 | } 10 | 11 | .screenshot.mobile { 12 | background: url(../Images/background_mobile.png) no-repeat; 13 | } 14 | 15 | .screenshot.desktop .screenshot-img-container { 16 | width: 180px; 17 | height: 112px; 18 | clip: rect(0, 180px, 112px, 0); 19 | top: 45px; 20 | left: 32px; 21 | } 22 | 23 | .screenshot.mobile .screenshot-img-container { 24 | width: 225px; 25 | height: 375px; 26 | clip: rect(0, 225px, 375px, 0); 27 | top: 54px; 28 | left: 12px; 29 | right: 13px; 30 | } 31 | 32 | .screenshot-img-container { 33 | position: absolute; 34 | margin: 0; 35 | padding: 0; 36 | overflow: hidden; 37 | } 38 | 39 | .screenshot-img-container .snapshot-rect { 40 | position: absolute; 41 | background-color: rgba(255, 0, 0, 0.15); 42 | outline: 2px solid #f00; 43 | margin: 0; 44 | padding: 0; 45 | z-index: 3; 46 | } 47 | 48 | .screenshot-img-container .snapshot-rect.secondary { 49 | background-color: rgba(0, 0, 255, 0.15); 50 | outline: 2px dotted #00f; 51 | z-index: 2; 52 | } 53 | 54 | .screenshot-img-container img { 55 | position: absolute; 56 | width: 100%; 57 | height: auto; 58 | top: 0; 59 | left: 0; 60 | z-index: 1; 61 | } 62 | 63 | .color-danger { 64 | background-color: #dd4b39; 65 | color: #fff; 66 | } 67 | 68 | .color-warning { 69 | background-color: #fda100; 70 | color: #fff; 71 | } 72 | 73 | .color-ok { 74 | background-color: #009a2d; 75 | color: #fff; 76 | } 77 | 78 | .rules .indicator { 79 | padding: 2px 5px; 80 | margin-right: 7px; 81 | } 82 | 83 | .rules h3 { 84 | margin-bottom: 17px; 85 | border-bottom: 1px solid #ccc; 86 | padding-bottom: 10px; 87 | margin-top: 30px; 88 | } 89 | 90 | .single-rule { 91 | display: block !important; 92 | } 93 | 94 | .single-rule .title { 95 | cursor: pointer; 96 | } 97 | 98 | .single-rule .title .fa { 99 | margin-right: 5px; 100 | color: #666; 101 | } 102 | 103 | .url-blocks ul { 104 | list-style: none; 105 | max-height: 200px; 106 | overflow-y: scroll; 107 | background: #fff; 108 | padding: 10px; 109 | margin-top: 10px; 110 | } 111 | 112 | .url-blocks ul li:first-child { 113 | border-top: none; 114 | } 115 | 116 | .url-blocks ul li { 117 | border-top: 1px #ccc dashed; 118 | padding: 3px; 119 | word-wrap: break-word; 120 | } 121 | 122 | a.screenshot-toggle, a.link { 123 | color: cornflowerblue; 124 | } 125 | 126 | .score { 127 | list-style: none; 128 | padding: 10px; 129 | font-size: 20px; 130 | } 131 | 132 | .score li { 133 | margin-bottom: 10px; 134 | } 135 | 136 | .score .indicator { 137 | padding: 2px 4px; 138 | } -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pieDonut3D.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 74 | 75 | 76 | 77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/serial2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 12 | 19 | 78 | 79 | 80 | 81 |
82 | 83 | 84 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_barAndLineMix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 12 | 73 | 74 | 75 | 76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/barFloating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 81 | 82 | 83 | 84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/xyBubbleSimple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 88 | 89 | 90 | 91 |
92 | 93 | 94 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/bar3D.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 82 | 83 | 84 | 85 |
86 | 87 | 88 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_lineWithFilledValueRanges.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 12 | 81 | 82 | 83 | 84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/pieWithPatterns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 73 | 74 | 75 | 76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /Classes/ViewHelpers/UrlBlockViewHelper.php: -------------------------------------------------------------------------------- 1 | registerArgument('result', Result::class, 'Result', false, null); 22 | $this->registerArgument('hsc', 'bool', 'HSC', false, true); 23 | $this->registerArgument('strategy', 'string', 'stragey', false, ''); 24 | } 25 | 26 | public function render() 27 | { 28 | $result = $this->arguments['result']; 29 | $hsc = $this->arguments['hsc']; 30 | $strategy = $this->arguments['strategy']; 31 | if (is_null($result)) { 32 | return ''; 33 | } 34 | 35 | $searchReplace = []; 36 | foreach ($result->getArguments() as $argument) { 37 | $value = $hsc ? htmlspecialchars($argument['value']) : $argument['value']; 38 | switch ($argument['type']) { 39 | case 'HYPERLINK': 40 | $searchReplace['{{BEGIN_LINK}}'] = sprintf('', $value); 41 | $searchReplace['{{END_LINK}}'] = ''; 42 | break; 43 | case 'DURATION': 44 | $searchReplace['{{' . $argument['key'] . '}}'] = '' . $value . ''; 45 | break; 46 | 47 | case 'INT_LITERAL': 48 | $searchReplace['{{' . $argument['key'] . '}}'] = '' . $value . ''; 49 | break; 50 | case 'SNAPSHOT_RECT': 51 | $searchReplace['{{' . $argument['key'] . '}}'] = sprintf( 52 | 'siehe screen', 53 | $strategy, 54 | $this->generateRectAttribute($argument['rects']), 55 | $this->generateRectAttribute($argument['secondary_rects']) 56 | ); 57 | break; 58 | case 'BYTES': 59 | case 'DISTANCE': 60 | case 'PERCENTAGE': 61 | case 'STRING_LITERAL': 62 | case 'URL': 63 | case 'VERBATIM_STRING': 64 | default: 65 | 66 | $searchReplace['{{' . $argument['key'] . '}}'] = '' . $value . ''; 67 | } 68 | } 69 | 70 | $search = array_keys($searchReplace); 71 | $replace = array_values($searchReplace); 72 | 73 | return str_replace($search, $replace, $result->getFormat()); 74 | } 75 | 76 | /** 77 | * @param array $data 78 | * @return string 79 | */ 80 | protected function generateRectAttribute(array $data = null) 81 | { 82 | if (!is_array($data)) { 83 | return ''; 84 | } 85 | $tmp = []; 86 | foreach ($data as $item) { 87 | $val = implode(',', $item); 88 | $tmp[$val] = $val; 89 | } 90 | 91 | return implode(';', $tmp); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. ================================================== 2 | .. FOR YOUR INFORMATION 3 | .. -------------------------------------------------- 4 | .. -*- coding: utf-8 -*- with BOM. 5 | 6 | 7 | TYPO3 CMS Extension "page_speed" 8 | ================================ 9 | This extensions provides an entry in the info module to check the **usability** & **performance** 10 | of the selected page by using the API of `Google PageSpeed Insights `_. 11 | 12 | Every page is automatically checked for the resolution **desktop** & **mobile**. 13 | 14 | Screenshot 15 | ---------- 16 | 17 | .. figure:: Resources/Public/Documentation/screenshot.png 18 | :alt: Screenshot of the backend 19 | 20 | Requirements 21 | ------------ 22 | - TYPO3 CMS 9.5+ 23 | - Google Account 24 | 25 | Installation & Configuration 26 | ---------------------------- 27 | The extension just needs to be installed as any other extension. 28 | To make it work, you need a Google account and activate the PageSpeed service. 29 | After successfully activating the PageSpeed service you need to set the key in the configuration in EM and deactivate the demo mode. 30 | 31 | Enable PageSpeed Service 32 | ^^^^^^^^^^^^^^^^^^^^^^^^ 33 | 1) Open `console.developers.google.com `_ and create a new project. 34 | 2) Open the project and switch to *APIs and auth* > *APIs*, select *PageSpeed Insights API* and **Activate the API**. 35 | 3) Switch to *Credentials* and click the button **Create new key** for *public API access*. 36 | 4) Create either a *Server key* or a *Browser key**. 37 | 5) Test the access by using cUrl on the server where you want to use the extension by calling the command ``curl 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed?strategy=desktop&url=http://www.bbc.co.uk/&key=AIzaSyA2rQEy7UyQz-9D1-7bnmw1jzSo0FmobYM'``. (If you get a ``Bad request``, just wait a few minutes to get the key deployed on all Google servers) 38 | 39 | Preview Domain 40 | ^^^^^^^^^^^^^^ 41 | If you need to use a different domain in the frontend or no sys domain record is available, you can use the following configuration inside your **PageTsConfig**: :: 42 | 43 | TCEMAIN.previewDomain = localhost/sites/t3/master 44 | 45 | Avoid error "require_once(Net/URL2.php)" 46 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 47 | If you see an exception about the 48 | file ``Net/URL2.php`` not found, please open the file ``typo3/contrib/vendor/pear/http_request2/HTTP/Request2.php`` and 49 | remove the *require_once* statement in line 24. This bug will be gone soon. 50 | 51 | Technical background 52 | -------------------- 53 | A little bit technical information for the ones who are interested in: 54 | 55 | The API is described in detail at `developers.google.com/speed/docs/insights/v2/reference/pagespeedapi/runpagespeed `_ 56 | and it is very simple to test by just using curl: :: 57 | 58 | # Desktop 59 | curl 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed?strategy=desktop&screenshot=true&url=http://www.typo3.org&key=' 60 | # Mobile 61 | curl 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed?strategy=mobile&screenshot=true&url=http://www.typo3.org&key= 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 108 | 109 | 110 | 111 |
112 | 113 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/serial3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 98 | 99 | 100 | 101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/columnWithGradientFills.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 94 | 95 | 96 | 97 |
98 | 99 | 100 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/columnWithImages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 89 | 90 | 91 | 92 |
93 | 94 | 95 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/xyError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 99 | 100 | 101 | 102 |
103 | 104 | 105 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/barClustered.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 100 | 101 | 102 | 103 |
104 | 105 | 106 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts Responsive Example 7 | 8 | 9 | 10 | 49 | 50 | 79 | 80 | 81 | 82 | 83 |
84 | 85 | 86 | 87 | 88 | 101 | 102 |
103 | 104 |
800x500px
105 |
106 | 107 |
108 | 109 | 110 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/radarPolar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 107 | 108 | 109 | 110 |
111 | 112 | 113 | -------------------------------------------------------------------------------- /Classes/ViewHelpers/Chart/AssetsViewHelper.php: -------------------------------------------------------------------------------- 1 | registerArgument('id', 'string', 'ID'); 22 | $this->registerArgument('result', 'array', 'Result'); 23 | } 24 | 25 | public function render() 26 | { 27 | return ''; 74 | } 75 | 76 | /** 77 | * @param array $result 78 | * @return array 79 | */ 80 | protected function getData(array $result) 81 | { 82 | /** @var Response $mobile */ 83 | $mobile = $result['mobile']; 84 | /** @var Response $desktop */ 85 | $desktop = $result['desktop']; 86 | 87 | $data = [ 88 | [ 89 | 'type' => $this->translate('resources.html'), 90 | 'desktop' => $desktop->getPageStats()->getHtmlResponseKb(), 91 | 'mobile' => $mobile->getPageStats()->getHtmlResponseKb(), 92 | ], [ 93 | 'type' => $this->translate('resources.css'), 94 | 'desktop' => $desktop->getPageStats()->getCssResponseKb(), 95 | 'mobile' => $mobile->getPageStats()->getCssResponseKb(), 96 | ], 97 | [ 98 | 'type' => $this->translate('resources.js'), 99 | 'desktop' => $desktop->getPageStats()->getJavascriptResponseKb(), 100 | 'mobile' => $mobile->getPageStats()->getJavascriptResponseKb(), 101 | ], 102 | [ 103 | 'type' => $this->translate('resources.img'), 104 | 'desktop' => $desktop->getPageStats()->getImageResponseKb(), 105 | 'mobile' => $mobile->getPageStats()->getImageResponseKb(), 106 | ], 107 | [ 108 | 'type' => $this->translate('resources.other'), 109 | 'desktop' => $desktop->getPageStats()->getOtherResponseKb(), 110 | 'mobile' => $mobile->getPageStats()->getOtherResponseKb(), 111 | ], 112 | ]; 113 | 114 | return $data; 115 | } 116 | 117 | /** 118 | * @param string $key 119 | * @return string 120 | */ 121 | protected function translate($key) 122 | { 123 | return LocalizationUtility::translate($key, 'page_speed'); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_xyBubbleWithZoom.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 117 | 118 | 119 | 120 |
121 | 122 | 123 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/amcharts/plugins/responsive/examples/xy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | amCharts Responsive Example 8 | 9 | 10 | 11 | 18 | 139 | 140 | 141 | 142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/errorChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 101 | 102 | 103 | 104 |
105 | 106 | 107 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_xyWithGuides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 123 | 124 | 125 | 126 |
127 | 128 | 129 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/columnWithPatterns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 100 | 101 | 102 | 103 |
104 | 105 | 106 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/barAndLineMix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 107 | 108 | 109 | 110 |
111 | 112 | 113 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/columnSimple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 124 | 125 | 126 | 127 |
128 | 129 | 130 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/barWithBackgroundImage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 111 | 112 | 113 | 114 |
115 | 116 | 117 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/_JSON_lineWithScrollAndZoom.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 11 | 102 | 103 | 104 | 105 |
106 |
107 | Select 108 | Pan 109 |
110 | 111 | 112 | -------------------------------------------------------------------------------- /Resources/Public/Contrib/samples/areaWithTimeBasedData.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | amCharts examples 7 | 8 | 9 | 10 | 97 | 98 | 99 | 100 |
101 | 102 | 103 | --------------------------------------------------------------------------------