diff --git a/front/src/css/rule.css b/front/src/css/rule.css index 57d9b17..cbdcfee 100644 --- a/front/src/css/rule.css +++ b/front/src/css/rule.css @@ -82,17 +82,64 @@ font-size: 3em; margin-bottom: 1em; } +.offenders .eltButton { + display: inline-block; + position: relative; + background: #efe; + padding: 0 0.5em; + margin: 0.2em 0; + border-radius: 0.4em; + z-index: 1; +} +.offenders .eltButton.opens { + padding-right: 0.75em; +} +.offenders .eltButton.opens:after { + position: relative; + left: 0.5em; + content: '\25BC'; + font-size: 0.8em; +} +.offenders .eltButton > div { + display: none; + position: absolute; + right: 0; + min-width: 100%; + background: inherit; + border-bottom-left-radius: 0.4em; + border-bottom-right-radius: 0.4em; + border-top: 1px solid #999; +} +.offenders .eltButton .domTree { + text-align: left; + white-space: nowrap; +} +.offenders .eltButton .domTree > div { + margin: 0.5em; +} +.offenders .eltButton .domTree > div div { + margin-left: 1em; +} +.offenders .eltButton:hover { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background: #ffe0cc; + z-index: 2; +} +.offenders .eltButton:hover > div { + display: block; +} .offendersHtml { display: inline-block; } -.offendersHtml .domTree div { +.domTree div { text-align: left; margin-left: 1em; } -.offendersHtml .domTree div span:only-child { +.domTree div span:only-child { font-weight: bold; } -.offendersHtml .domTree div span:only-child span { +.domTree div span:only-child span { font-style: italic; font-weight: normal; } diff --git a/front/src/less/rule.less b/front/src/less/rule.less index feddc09..a54a753 100644 --- a/front/src/less/rule.less +++ b/front/src/less/rule.less @@ -90,19 +90,77 @@ } } -.offendersHtml { - display: inline-block; +.offenders { + .eltButton { + display: inline-block; + position: relative; + background: #efe; + padding: 0 0.5em; + margin: 0.2em 0; + border-radius: 0.4em; + z-index: 1; - .domTree div { - text-align: left; - margin-left: 1em; + &.opens { + padding-right: 0.75em; - span:only-child { - font-weight: bold; - span { - font-style: italic; - font-weight: normal; + &:after { + position: relative; + left: 0.5em; + content: '\25BC'; + font-size: 0.8em; + } + } + + > div { + display: none; + position: absolute; + right: 0; + min-width: 100%; + background: inherit; + border-bottom-left-radius: 0.4em; + border-bottom-right-radius: 0.4em; + border-top: 1px solid #999; + } + + .domTree { + text-align: left; + white-space: nowrap; + + > div { + margin: 0.5em; + + div { + margin-left: 1em; + } + } + } + + &:hover { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background: #ffe0cc; + z-index: 2; + + & > div { + display: block; } } } +} + +.offendersHtml { + display: inline-block; +} + +.domTree div { + text-align: left; + margin-left: 1em; + + span:only-child { + font-weight: bold; + span { + font-style: italic; + font-weight: normal; + } + } } \ No newline at end of file diff --git a/lib/metadata/policies.js b/lib/metadata/policies.js index 9c12353..f0cdb18 100644 --- a/lib/metadata/policies.js +++ b/lib/metadata/policies.js @@ -38,8 +38,8 @@ var policies = { "isAbnormalThreshold": 10, "offendersTransformFn": function(offenders) { return offenders.map(function(offender) { - var results = /^(.*): (\d) occurrences$/.exec(offender); - return '#' + results[1] + ': ' + results[2] + ' occurrences'; + var parts = /^(.*): (\d) occurrences$/.exec(offender); + return '#' + parts[1] + ': ' + parts[2] + ' occurrences'; }); } }, @@ -49,7 +49,14 @@ var policies = { "message": "

Working with the DOM in JavaScript triggers layout calculations and slows down the page.

Try, as much as possible, to have an HTML page fully generated by the server instead of making changes with JS.

", "isOkThreshold": 10, "isBadThreshold": 400, - "isAbnormalThreshold": 1000 + "isAbnormalThreshold": 1000, + "offendersTransformFn": function(offenders) { + return offenders.map(function(offender) { + var parts = /^"(.*)" appended to "(.*)"$/.exec(offender); + + return offendersHelpers.domPathToButton(parts[1]) + ' appended to ' + offendersHelpers.domPathToButton(parts[2]); + }); + } }, "DOMqueries": { "tool": "phantomas", diff --git a/lib/offendersHelpers.js b/lib/offendersHelpers.js index bbab2bf..24a523e 100644 --- a/lib/offendersHelpers.js +++ b/lib/offendersHelpers.js @@ -1,7 +1,6 @@ var OffendersHelpers = function() { - this.domPathToArray = function(str) { return str.split(/\s?>\s?/); @@ -60,6 +59,39 @@ var OffendersHelpers = function() { return this.domTreeToHTML(domTree); }; + this.domPathToButton = function(domPath) { + var domArray = this.domPathToArray(domPath); + var domTree = this.listOfDomPathsToHTML([domPath]); + + if (domArray[0] === 'html') { + return '
html
'; + } + if (domArray[0] === 'body') { + if (domArray.length === 1) { + return '
body
'; + } else { + return '
DOM element ' + domArray[domArray.length - 1] + '' + domTree + '
'; + } + } + if (domArray[0] === 'head') { + return '
head
'; + } + if (domArray[0] === 'DocumentFragment') { + if (domArray.length === 1) { + return '
Fragment
'; + } else { + return '
Fragment element ' + domArray[domArray.length - 1] + '' + domTree + '
'; + } + } + + // Not attached element, such as just created with document.createElement() + if (domArray.length === 1) { + return '
Created element ' + domPath + '
'; + } else { + return '
Created element ' + domArray[domArray.length - 1] + '' + domTree + '
'; + } + }; + }; module.exports = new OffendersHelpers(); \ No newline at end of file diff --git a/test/core/offendersHelpersTest.js b/test/core/offendersHelpersTest.js index 5c1a72c..30c2d15 100644 --- a/test/core/offendersHelpersTest.js +++ b/test/core/offendersHelpersTest.js @@ -80,4 +80,48 @@ describe('offendersHelpers', function() { }); + describe('domPathToButton', function() { + + it('should transform html', function() { + var result = offendersHelpers.domPathToButton('html'); + result.should.equal('
html
'); + }); + + it('should transform body', function() { + var result = offendersHelpers.domPathToButton('body'); + result.should.equal('
body
'); + }); + + it('should transform head', function() { + var result = offendersHelpers.domPathToButton('head'); + result.should.equal('
head
'); + }); + + it('should transform a standard in-body element', function() { + var result = offendersHelpers.domPathToButton('body > div#colorbox > div#cboxContent'); + result.should.equal('
DOM element div#cboxContent
body
div#colorbox
div#cboxContent
'); + }); + + it('should transform a domFragment element', function() { + var result = offendersHelpers.domPathToButton('DocumentFragment'); + result.should.equal('
Fragment
'); + }); + + it('should transform a domFragment element', function() { + var result = offendersHelpers.domPathToButton('DocumentFragment > div#colorbox > div#cboxContent'); + result.should.equal('
Fragment element div#cboxContent
DocumentFragment
div#colorbox
div#cboxContent
'); + }); + + it('should transform an not-attached element', function() { + var result = offendersHelpers.domPathToButton('div#sizcache'); + result.should.equal('
Created element div#sizcache
'); + }); + + it('should transform an not-attached element path', function() { + var result = offendersHelpers.domPathToButton('div > div#sizcache'); + result.should.equal('
Created element div#sizcache
div
div#sizcache
'); + }); + + }); + });