diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 182a804583313..6f887b3c33f13 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ----- * added information about orphaned events + * made the toolbar auto-update with info from ajax reponses when they set the + `Symfony-Debug-Toolbar-Replace header` to `1` 4.0.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 65bc491882f0a..58a6b5661cf28 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -83,6 +83,10 @@ if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) { stackElement.profilerUrl = ret[1]; } + if (ret = allHeaders.match(/^Symfony-Debug-Toolbar-Replace:\s+(.*)$/im)) { + stackElement.toolbarReplaceFinished = false; + stackElement.toolbarReplace = '1' === ret[1]; + } }; var successStreak = 4; @@ -179,6 +183,19 @@ if (!request.DOMNode) { return; } + + if (request.toolbarReplace && !request.toolbarReplaceFinished && request.profile) { + /* Flag as complete because finishAjaxRequest can be called multiple times. */ + request.toolbarReplaceFinished = true; + /* Search up through the DOM to find the toolbar's container ID. */ + for (var elem = request.DOMNode; elem && elem !== document; elem = elem.parentNode) { + if (elem.id.match(/^sfwdt/)) { + Sfjs.loadToolbar(elem.id.replace(/^sfwdt/, ''), request.profile); + break; + } + } + } + pendingRequests--; var row = request.DOMNode; /* Unpack the children from the row */ @@ -279,6 +296,8 @@ stackElement.statusCode = r.status; stackElement.profile = r.headers.get('x-debug-token'); stackElement.profilerUrl = r.headers.get('x-debug-token-link'); + stackElement.toolbarReplaceFinished = false; + stackElement.toolbarReplace = '1' === r.headers.get('Symfony-Debug-Toolbar-Replace'); finishAjaxRequest(idx); }, function (e){ stackElement.error = true; @@ -366,12 +385,15 @@ el.innerHTML = xhr.responseText; el.setAttribute('data-sfurl', url); removeClass(el, 'loading'); + var pending = pendingRequests; for (var i = 0; i < requestStack.length; i++) { startAjaxRequest(i); if (requestStack[i].duration) { finishAjaxRequest(i); } } + /* Revert the pending state in case there was a start called without a finish above. */ + pendingRequests = pending; (onSuccess || noop)(xhr, el); }, function(xhr) { (onError || noop)(xhr, el); }, @@ -383,6 +405,122 @@ return this; }, + loadToolbar: function(token, newToken) { + newToken = (newToken || token); + this.load( + 'sfwdt' + token, + '{{ path("_wdt", { "token": "xxxxxx" }) }}'.replace(/xxxxxx/, newToken), + function(xhr, el) { + + /* Evaluate embedded scripts inside the toolbar */ + var i, scripts = [].slice.call(el.querySelectorAll('script')); + + for (i = 0; i < scripts.length; ++i) { + eval(scripts[i].firstChild.nodeValue); + } + + el.style.display = -1 !== xhr.responseText.indexOf('sf-toolbarreset') ? 'block' : 'none'; + + if (el.style.display == 'none') { + return; + } + + if (getPreference('toolbar/displayState') == 'none') { + document.getElementById('sfToolbarMainContent-' + newToken).style.display = 'none'; + document.getElementById('sfToolbarClearer-' + newToken).style.display = 'none'; + document.getElementById('sfMiniToolbar-' + newToken).style.display = 'block'; + } else { + document.getElementById('sfToolbarMainContent-' + newToken).style.display = 'block'; + document.getElementById('sfToolbarClearer-' + newToken).style.display = 'block'; + document.getElementById('sfMiniToolbar-' + newToken).style.display = 'none'; + } + + /* Handle toolbar-info position */ + var toolbarBlocks = [].slice.call(el.querySelectorAll('.sf-toolbar-block')); + for (i = 0; i < toolbarBlocks.length; ++i) { + toolbarBlocks[i].onmouseover = function () { + var toolbarInfo = this.querySelectorAll('.sf-toolbar-info')[0]; + var pageWidth = document.body.clientWidth; + var elementWidth = toolbarInfo.offsetWidth; + var leftValue = (elementWidth + this.offsetLeft) - pageWidth; + var rightValue = (elementWidth + (pageWidth - this.offsetLeft)) - pageWidth; + + /* Reset right and left value, useful on window resize */ + toolbarInfo.style.right = ''; + toolbarInfo.style.left = ''; + + if (elementWidth > pageWidth) { + toolbarInfo.style.left = 0; + } + else if (leftValue > 0 && rightValue > 0) { + toolbarInfo.style.right = (rightValue * -1) + 'px'; + } else if (leftValue < 0) { + toolbarInfo.style.left = 0; + } else { + toolbarInfo.style.right = '0px'; + } + }; + } + addEventListener(document.getElementById('sfToolbarHideButton-' + newToken), 'click', function (event) { + event.preventDefault(); + + var p = this.parentNode; + p.style.display = 'none'; + (p.previousElementSibling || p.previousSibling).style.display = 'none'; + document.getElementById('sfMiniToolbar-' + newToken).style.display = 'block'; + setPreference('toolbar/displayState', 'none'); + }); + addEventListener(document.getElementById('sfToolbarMiniToggler-' + newToken), 'click', function (event) { + event.preventDefault(); + + var elem = this.parentNode; + if (elem.style.display == 'none') { + document.getElementById('sfToolbarMainContent-' + newToken).style.display = 'none'; + document.getElementById('sfToolbarClearer-' + newToken).style.display = 'none'; + elem.style.display = 'block'; + } else { + document.getElementById('sfToolbarMainContent-' + newToken).style.display = 'block'; + document.getElementById('sfToolbarClearer-' + newToken).style.display = 'block'; + elem.style.display = 'none' + } + + setPreference('toolbar/displayState', 'block'); + }); + renderAjaxRequests(); + addEventListener(document.querySelector('.sf-toolbar-block-ajax > .sf-toolbar-icon'), 'click', function (event) { + event.preventDefault(); + + toggleClass(this.parentNode, 'hover'); + }); + + var dumpInfo = document.querySelector('.sf-toolbar-block-dump .sf-toolbar-info'); + if (null !== dumpInfo) { + addEventListener(dumpInfo, 'sfbeforedumpcollapse', function () { + dumpInfo.style.minHeight = dumpInfo.getBoundingClientRect().height+'px'; + }); + addEventListener(dumpInfo, 'mouseleave', function () { + dumpInfo.style.minHeight = ''; + }); + } + }, + function(xhr) { + if (xhr.status !== 0) { + var sfwdt = document.getElementById('sfwdt' + token); + sfwdt.innerHTML = '\ +
\ + '; + sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); + } + }, + { maxTries: 5 } + ); + + return this; + }, + toggle: function(selector, elOn, elOff) { var tmp = elOn.style.display, el = document.getElementById(selector); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 8df2e844df4dd..e340d89f96b9e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -5,115 +5,6 @@Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: