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 f70bfc01c3983..859b7b2f28ab5 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
@@ -5,7 +5,7 @@
them as JavaScript source code. Always use '/*' comments instead
of '//' comments to avoid impossible-to-debug side-effects #}
-if (typeof Sfjs === 'undefined') {
+if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') {
Sfjs = (function() {
"use strict";
diff --git a/src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js b/src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js
index 8cc7b5318449a..0720a3a358aac 100644
--- a/src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js
+++ b/src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js
@@ -1,279 +1,280 @@
/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig.
If you make any change in this file, verify the same change is needed in the other file. */
/* .tab');
- var tabNavigation = document.createElement('ul');
- tabNavigation.className = 'tab-navigation';
-
- var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */
- for (var j = 0; j < tabs.length; j++) {
- var tabId = 'tab-' + i + '-' + j;
- var tabTitle = tabs[j].querySelector('.tab-title').innerHTML;
-
- var tabNavigationItem = document.createElement('li');
- tabNavigationItem.setAttribute('data-tab-id', tabId);
- if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; }
- if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); }
- tabNavigationItem.innerHTML = tabTitle;
- tabNavigation.appendChild(tabNavigationItem);
-
- var tabContent = tabs[j].querySelector('.tab-content');
- tabContent.parentElement.setAttribute('id', tabId);
- }
+if (typeof Sfjs === 'undefined') {
+ Sfjs = (function() {
+ "use strict";
+
+ if ('classList' in document.documentElement) {
+ var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); };
+ var removeClass = function(el, cssClass) { el.classList.remove(cssClass); };
+ var addClass = function(el, cssClass) { el.classList.add(cssClass); };
+ var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); };
+ } else {
+ var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); };
+ var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); };
+ var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } };
+ var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); };
+ }
- tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild);
- addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active');
- }
+ var addEventListener;
+
+ var el = document.createElement('div');
+ if (!('addEventListener' in el)) {
+ addEventListener = function (element, eventName, callback) {
+ element.attachEvent('on' + eventName, callback);
+ };
+ } else {
+ addEventListener = function (element, eventName, callback) {
+ element.addEventListener(eventName, callback, false);
+ };
+ }
- /* display the active tab and add the 'click' event listeners */
- for (i = 0; i < tabGroups.length; i++) {
- tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li');
+ return {
+ addEventListener: addEventListener,
- for (j = 0; j < tabNavigation.length; j++) {
- tabId = tabNavigation[j].getAttribute('data-tab-id');
- document.getElementById(tabId).querySelector('.tab-title').className = 'hidden';
+ createTabs: function() {
+ var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])');
- if (hasClass(tabNavigation[j], 'active')) {
- document.getElementById(tabId).className = 'block';
- } else {
- document.getElementById(tabId).className = 'hidden';
+ /* create the tab navigation for each group of tabs */
+ for (var i = 0; i < tabGroups.length; i++) {
+ var tabs = tabGroups[i].querySelectorAll(':scope > .tab');
+ var tabNavigation = document.createElement('ul');
+ tabNavigation.className = 'tab-navigation';
+
+ var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */
+ for (var j = 0; j < tabs.length; j++) {
+ var tabId = 'tab-' + i + '-' + j;
+ var tabTitle = tabs[j].querySelector('.tab-title').innerHTML;
+
+ var tabNavigationItem = document.createElement('li');
+ tabNavigationItem.setAttribute('data-tab-id', tabId);
+ if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; }
+ if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); }
+ tabNavigationItem.innerHTML = tabTitle;
+ tabNavigation.appendChild(tabNavigationItem);
+
+ var tabContent = tabs[j].querySelector('.tab-content');
+ tabContent.parentElement.setAttribute('id', tabId);
}
- tabNavigation[j].addEventListener('click', function(e) {
- var activeTab = e.target || e.srcElement;
+ tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild);
+ addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active');
+ }
- /* needed because when the tab contains HTML contents, user can click */
- /* on any of those elements instead of their parent '
' element */
- while (activeTab.tagName.toLowerCase() !== 'li') {
- activeTab = activeTab.parentNode;
- }
+ /* display the active tab and add the 'click' event listeners */
+ for (i = 0; i < tabGroups.length; i++) {
+ tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li');
- /* get the full list of tabs through the parent of the active tab element */
- var tabNavigation = activeTab.parentNode.children;
- for (var k = 0; k < tabNavigation.length; k++) {
- var tabId = tabNavigation[k].getAttribute('data-tab-id');
+ for (j = 0; j < tabNavigation.length; j++) {
+ tabId = tabNavigation[j].getAttribute('data-tab-id');
+ document.getElementById(tabId).querySelector('.tab-title').className = 'hidden';
+
+ if (hasClass(tabNavigation[j], 'active')) {
+ document.getElementById(tabId).className = 'block';
+ } else {
document.getElementById(tabId).className = 'hidden';
- removeClass(tabNavigation[k], 'active');
}
- addClass(activeTab, 'active');
- var activeTabId = activeTab.getAttribute('data-tab-id');
- document.getElementById(activeTabId).className = 'block';
- });
- }
-
- tabGroups[i].setAttribute('data-processed', 'true');
- }
- },
+ tabNavigation[j].addEventListener('click', function(e) {
+ var activeTab = e.target || e.srcElement;
- createToggles: function() {
- var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');
+ /* needed because when the tab contains HTML contents, user can click */
+ /* on any of those elements instead of their parent '' element */
+ while (activeTab.tagName.toLowerCase() !== 'li') {
+ activeTab = activeTab.parentNode;
+ }
- for (var i = 0; i < toggles.length; i++) {
- var elementSelector = toggles[i].getAttribute('data-toggle-selector');
- var element = document.querySelector(elementSelector);
+ /* get the full list of tabs through the parent of the active tab element */
+ var tabNavigation = activeTab.parentNode.children;
+ for (var k = 0; k < tabNavigation.length; k++) {
+ var tabId = tabNavigation[k].getAttribute('data-tab-id');
+ document.getElementById(tabId).className = 'hidden';
+ removeClass(tabNavigation[k], 'active');
+ }
- addClass(element, 'sf-toggle-content');
+ addClass(activeTab, 'active');
+ var activeTabId = activeTab.getAttribute('data-tab-id');
+ document.getElementById(activeTabId).className = 'block';
+ });
+ }
- if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') {
- addClass(toggles[i], 'sf-toggle-on');
- addClass(element, 'sf-toggle-visible');
- } else {
- addClass(toggles[i], 'sf-toggle-off');
- addClass(element, 'sf-toggle-hidden');
+ tabGroups[i].setAttribute('data-processed', 'true');
}
+ },
- addEventListener(toggles[i], 'click', function(e) {
- e.preventDefault();
+ createToggles: function() {
+ var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');
- if ('' !== window.getSelection().toString()) {
- /* Don't do anything on text selection */
- return;
- }
+ for (var i = 0; i < toggles.length; i++) {
+ var elementSelector = toggles[i].getAttribute('data-toggle-selector');
+ var element = document.querySelector(elementSelector);
- var toggle = e.target || e.srcElement;
+ addClass(element, 'sf-toggle-content');
- /* needed because when the toggle contains HTML contents, user can click */
- /* on any of those elements instead of their parent '.sf-toggle' element */
- while (!hasClass(toggle, 'sf-toggle')) {
- toggle = toggle.parentNode;
+ if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') {
+ addClass(toggles[i], 'sf-toggle-on');
+ addClass(element, 'sf-toggle-visible');
+ } else {
+ addClass(toggles[i], 'sf-toggle-off');
+ addClass(element, 'sf-toggle-hidden');
}
- var element = document.querySelector(toggle.getAttribute('data-toggle-selector'));
+ addEventListener(toggles[i], 'click', function(e) {
+ e.preventDefault();
- toggleClass(toggle, 'sf-toggle-on');
- toggleClass(toggle, 'sf-toggle-off');
- toggleClass(element, 'sf-toggle-hidden');
- toggleClass(element, 'sf-toggle-visible');
+ if ('' !== window.getSelection().toString()) {
+ /* Don't do anything on text selection */
+ return;
+ }
- /* the toggle doesn't change its contents when clicking on it */
- if (!toggle.hasAttribute('data-toggle-alt-content')) {
- return;
- }
+ var toggle = e.target || e.srcElement;
- if (!toggle.hasAttribute('data-toggle-original-content')) {
- toggle.setAttribute('data-toggle-original-content', toggle.innerHTML);
- }
+ /* needed because when the toggle contains HTML contents, user can click */
+ /* on any of those elements instead of their parent '.sf-toggle' element */
+ while (!hasClass(toggle, 'sf-toggle')) {
+ toggle = toggle.parentNode;
+ }
- var currentContent = toggle.innerHTML;
- var originalContent = toggle.getAttribute('data-toggle-original-content');
- var altContent = toggle.getAttribute('data-toggle-alt-content');
- toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
- });
+ var element = document.querySelector(toggle.getAttribute('data-toggle-selector'));
+
+ toggleClass(toggle, 'sf-toggle-on');
+ toggleClass(toggle, 'sf-toggle-off');
+ toggleClass(element, 'sf-toggle-hidden');
+ toggleClass(element, 'sf-toggle-visible');
- /* Prevents from disallowing clicks on links inside toggles */
- var toggleLinks = toggles[i].querySelectorAll('a');
- for (var j = 0; j < toggleLinks.length; j++) {
- addEventListener(toggleLinks[j], 'click', function(e) {
- e.stopPropagation();
+ /* the toggle doesn't change its contents when clicking on it */
+ if (!toggle.hasAttribute('data-toggle-alt-content')) {
+ return;
+ }
+
+ if (!toggle.hasAttribute('data-toggle-original-content')) {
+ toggle.setAttribute('data-toggle-original-content', toggle.innerHTML);
+ }
+
+ var currentContent = toggle.innerHTML;
+ var originalContent = toggle.getAttribute('data-toggle-original-content');
+ var altContent = toggle.getAttribute('data-toggle-alt-content');
+ toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
});
- }
- toggles[i].setAttribute('data-processed', 'true');
- }
- },
-
- createFilters: function() {
- document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) {
- var filters = filter.closest('[data-filters]'),
- type = 'choice',
- name = filter.dataset.filter,
- ucName = name.charAt(0).toUpperCase()+name.slice(1),
- list = document.createElement('ul'),
- values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'),
- labels = {},
- defaults = null,
- indexed = {},
- processed = {};
- if (typeof values === 'string') {
- type = 'level';
- labels = values.split(',');
- values = values.toLowerCase().split(',');
- defaults = values.length - 1;
- }
- addClass(list, 'filter-list');
- addClass(list, 'filter-list-'+type);
- values.forEach(function (value, i) {
- if (value instanceof HTMLElement) {
- value = value.dataset['filter'+ucName];
- }
- if (value in processed) {
- return;
+ /* Prevents from disallowing clicks on links inside toggles */
+ var toggleLinks = toggles[i].querySelectorAll('a');
+ for (var j = 0; j < toggleLinks.length; j++) {
+ addEventListener(toggleLinks[j], 'click', function(e) {
+ e.stopPropagation();
+ });
}
- var option = document.createElement('li'),
- label = i in labels ? labels[i] : value,
- active = false,
- matches;
- if ('' === label) {
- option.innerHTML = '(none)';
- } else {
- option.innerText = label;
+
+ toggles[i].setAttribute('data-processed', 'true');
+ }
+ },
+
+ createFilters: function() {
+ document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) {
+ var filters = filter.closest('[data-filters]'),
+ type = 'choice',
+ name = filter.dataset.filter,
+ ucName = name.charAt(0).toUpperCase()+name.slice(1),
+ list = document.createElement('ul'),
+ values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'),
+ labels = {},
+ defaults = null,
+ indexed = {},
+ processed = {};
+ if (typeof values === 'string') {
+ type = 'level';
+ labels = values.split(',');
+ values = values.toLowerCase().split(',');
+ defaults = values.length - 1;
}
- option.dataset.filter = value;
- option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows');
- indexed[value] = i;
- list.appendChild(option);
- addEventListener(option, 'click', function () {
- if ('choice' === type) {
- filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
- if (option.dataset.filter === row.dataset['filter'+ucName]) {
- toggleClass(row, 'filter-hidden-'+name);
+ addClass(list, 'filter-list');
+ addClass(list, 'filter-list-'+type);
+ values.forEach(function (value, i) {
+ if (value instanceof HTMLElement) {
+ value = value.dataset['filter'+ucName];
+ }
+ if (value in processed) {
+ return;
+ }
+ var option = document.createElement('li'),
+ label = i in labels ? labels[i] : value,
+ active = false,
+ matches;
+ if ('' === label) {
+ option.innerHTML = '(none)';
+ } else {
+ option.innerText = label;
+ }
+ option.dataset.filter = value;
+ option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows');
+ indexed[value] = i;
+ list.appendChild(option);
+ addEventListener(option, 'click', function () {
+ if ('choice' === type) {
+ filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
+ if (option.dataset.filter === row.dataset['filter'+ucName]) {
+ toggleClass(row, 'filter-hidden-'+name);
+ }
+ });
+ toggleClass(option, 'active');
+ } else if ('level' === type) {
+ if (i === this.parentNode.querySelectorAll('.active').length - 1) {
+ return;
}
- });
- toggleClass(option, 'active');
- } else if ('level' === type) {
- if (i === this.parentNode.querySelectorAll('.active').length - 1) {
- return;
- }
- this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) {
- if (j <= i) {
- addClass(currentOption, 'active');
- if (i === j) {
- addClass(currentOption, 'last-active');
+ this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) {
+ if (j <= i) {
+ addClass(currentOption, 'active');
+ if (i === j) {
+ addClass(currentOption, 'last-active');
+ } else {
+ removeClass(currentOption, 'last-active');
+ }
} else {
+ removeClass(currentOption, 'active');
removeClass(currentOption, 'last-active');
}
- } else {
- removeClass(currentOption, 'active');
- removeClass(currentOption, 'last-active');
- }
- });
- filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
- if (i < indexed[row.dataset['filter'+ucName]]) {
- addClass(row, 'filter-hidden-'+name);
- } else {
- removeClass(row, 'filter-hidden-'+name);
- }
+ });
+ filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
+ if (i < indexed[row.dataset['filter'+ucName]]) {
+ addClass(row, 'filter-hidden-'+name);
+ } else {
+ removeClass(row, 'filter-hidden-'+name);
+ }
+ });
+ }
+ });
+ if ('choice' === type) {
+ active = null === defaults || 0 <= defaults.indexOf(value);
+ } else if ('level' === type) {
+ active = i <= defaults;
+ if (active && i === defaults) {
+ addClass(option, 'last-active');
+ }
+ }
+ if (active) {
+ addClass(option, 'active');
+ } else {
+ filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) {
+ toggleClass(row, 'filter-hidden-'+name);
});
}
+ processed[value] = true;
});
- if ('choice' === type) {
- active = null === defaults || 0 <= defaults.indexOf(value);
- } else if ('level' === type) {
- active = i <= defaults;
- if (active && i === defaults) {
- addClass(option, 'last-active');
- }
- }
- if (active) {
- addClass(option, 'active');
- } else {
- filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) {
- toggleClass(row, 'filter-hidden-'+name);
- });
+
+ if (1 < list.childNodes.length) {
+ filter.appendChild(list);
+ filter.dataset.filtered = '';
}
- processed[value] = true;
});
-
- if (1 < list.childNodes.length) {
- filter.appendChild(list);
- filter.dataset.filtered = '';
- }
- });
- }
- };
-})();
-
-Sfjs.addEventListener(document, 'DOMContentLoaded', function() {
- Sfjs.createTabs();
- Sfjs.createToggles();
- Sfjs.createFilters();
-});
-
+ }
+ };
+ })();
+
+ Sfjs.addEventListener(document, 'DOMContentLoaded', function() {
+ Sfjs.createTabs();
+ Sfjs.createToggles();
+ Sfjs.createFilters();
+ });
+}
/*]]>*/