vendor/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig line 1

Open in your IDE?
  1. {# This file is partially duplicated in TwigBundle/Resources/views/base_js.html.twig. If you
  2.    make any change in this file, verify the same change is needed in the other file. #}
  3. <script{% if csp_script_nonce is defined and csp_script_nonce %} nonce="{{ csp_script_nonce }}"{% endif %}>/*<![CDATA[*/
  4.     {# Caution: the contents of this file are processed by Twig before loading
  5.                 them as JavaScript source code. Always use '/*' comments instead
  6.                 of '//' comments to avoid impossible-to-debug side-effects #}
  7.     Sfjs = (function() {
  8.         "use strict";
  9.         if ('classList' in document.documentElement) {
  10.             var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); };
  11.             var removeClass = function(el, cssClass) { el.classList.remove(cssClass); };
  12.             var addClass = function(el, cssClass) { el.classList.add(cssClass); };
  13.             var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); };
  14.         } else {
  15.             var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); };
  16.             var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); };
  17.             var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } };
  18.             var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); };
  19.         }
  20.         var noop = function() {};
  21.         var profilerStorageKey = 'symfony/profiler/';
  22.         var request = function(url, onSuccess, onError, payload, options) {
  23.             var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  24.             options = options || {};
  25.             options.maxTries = options.maxTries || 0;
  26.             xhr.open(options.method || 'GET', url, true);
  27.             xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  28.             xhr.onreadystatechange = function(state) {
  29.                 if (4 !== xhr.readyState) {
  30.                     return null;
  31.                 }
  32.                 if (xhr.status == 404 && options.maxTries > 1) {
  33.                     setTimeout(function(){
  34.                         options.maxTries--;
  35.                         request(url, onSuccess, onError, payload, options);
  36.                     }, 1000);
  37.                     return null;
  38.                 }
  39.                 if (200 === xhr.status) {
  40.                     (onSuccess || noop)(xhr);
  41.                 } else {
  42.                     (onError || noop)(xhr);
  43.                 }
  44.             };
  45.             xhr.send(payload || '');
  46.         };
  47.         var getPreference = function(name) {
  48.             if (!window.localStorage) {
  49.                 return null;
  50.             }
  51.             return localStorage.getItem(profilerStorageKey + name);
  52.         };
  53.         var setPreference = function(name, value) {
  54.             if (!window.localStorage) {
  55.                 return null;
  56.             }
  57.             localStorage.setItem(profilerStorageKey + name, value);
  58.         };
  59.         var requestStack = [];
  60.         var extractHeaders = function(xhr, stackElement) {
  61.             /* Here we avoid to call xhr.getResponseHeader in order to */
  62.             /* prevent polluting the console with CORS security errors */
  63.             var allHeaders = xhr.getAllResponseHeaders();
  64.             var ret;
  65.             if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) {
  66.                 stackElement.profile = ret[1];
  67.             }
  68.             if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) {
  69.                 stackElement.profilerUrl = ret[1];
  70.             }
  71.         };
  72.         var successStreak = 4;
  73.         var pendingRequests = 0;
  74.         var renderAjaxRequests = function() {
  75.             var requestCounter = document.querySelector('.sf-toolbar-ajax-request-counter');
  76.             if (!requestCounter) {
  77.                 return;
  78.             }
  79.             requestCounter.textContent = requestStack.length;
  80.             var infoSpan = document.querySelector(".sf-toolbar-ajax-info");
  81.             if (infoSpan) {
  82.                 infoSpan.textContent = requestStack.length + ' AJAX request' + (requestStack.length !== 1 ? 's' : '');
  83.             }
  84.             var ajaxToolbarPanel = document.querySelector('.sf-toolbar-block-ajax');
  85.             if (requestStack.length) {
  86.                 ajaxToolbarPanel.style.display = 'block';
  87.             } else {
  88.                 ajaxToolbarPanel.style.display = 'none';
  89.             }
  90.             if (pendingRequests > 0) {
  91.                 addClass(ajaxToolbarPanel, 'sf-ajax-request-loading');
  92.             } else if (successStreak < 4) {
  93.                 addClass(ajaxToolbarPanel, 'sf-toolbar-status-red');
  94.                 removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading');
  95.             } else {
  96.                 removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading');
  97.                 removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red');
  98.             }
  99.         };
  100.         var startAjaxRequest = function(index) {
  101.             var tbody = document.querySelector('.sf-toolbar-ajax-request-list');
  102.             if (!tbody) {
  103.                 return;
  104.             }
  105.             var nbOfAjaxRequest = tbody.rows.length;
  106.             if (nbOfAjaxRequest >= 100) {
  107.                 tbody.deleteRow(nbOfAjaxRequest - 1);
  108.             }
  109.             var request = requestStack[index];
  110.             pendingRequests++;
  111.             var row = document.createElement('tr');
  112.             request.DOMNode = row;
  113.             var methodCell = document.createElement('td');
  114.             methodCell.textContent = request.method;
  115.             row.appendChild(methodCell);
  116.             var typeCell = document.createElement('td');
  117.             typeCell.textContent = request.type;
  118.             row.appendChild(typeCell);
  119.             var statusCodeCell = document.createElement('td');
  120.             var statusCode = document.createElement('span');
  121.             statusCode.textContent = 'n/a';
  122.             statusCodeCell.appendChild(statusCode);
  123.             row.appendChild(statusCodeCell);
  124.             var pathCell = document.createElement('td');
  125.             pathCell.className = 'sf-ajax-request-url';
  126.             if ('GET' === request.method) {
  127.                 var pathLink = document.createElement('a');
  128.                 pathLink.setAttribute('href', request.url);
  129.                 pathLink.textContent = request.url;
  130.                 pathCell.appendChild(pathLink);
  131.             } else {
  132.                 pathCell.textContent = request.url;
  133.             }
  134.             pathCell.setAttribute('title', request.url);
  135.             row.appendChild(pathCell);
  136.             var durationCell = document.createElement('td');
  137.             durationCell.className = 'sf-ajax-request-duration';
  138.             durationCell.textContent = 'n/a';
  139.             row.appendChild(durationCell);
  140.             var profilerCell = document.createElement('td');
  141.             profilerCell.textContent = 'n/a';
  142.             row.appendChild(profilerCell);
  143.             row.className = 'sf-ajax-request sf-ajax-request-loading';
  144.             tbody.insertBefore(row, tbody.firstChild);
  145.             renderAjaxRequests();
  146.         };
  147.         var finishAjaxRequest = function(index) {
  148.             var request = requestStack[index];
  149.             if (!request.DOMNode) {
  150.                 return;
  151.             }
  152.             pendingRequests--;
  153.             var row = request.DOMNode;
  154.             /* Unpack the children from the row */
  155.             var methodCell = row.children[0];
  156.             var statusCodeCell = row.children[2];
  157.             var statusCodeElem = statusCodeCell.children[0];
  158.             var durationCell = row.children[4];
  159.             var profilerCell = row.children[5];
  160.             if (request.error) {
  161.                 row.className = 'sf-ajax-request sf-ajax-request-error';
  162.                 methodCell.className = 'sf-ajax-request-error';
  163.                 successStreak = 0;
  164.             } else {
  165.                 row.className = 'sf-ajax-request sf-ajax-request-ok';
  166.                 successStreak++;
  167.             }
  168.             if (request.statusCode) {
  169.                 if (request.statusCode < 300) {
  170.                     statusCodeElem.setAttribute('class', 'sf-toolbar-status');
  171.                 } else if (request.statusCode < 400) {
  172.                     statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-yellow');
  173.                 } else {
  174.                     statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red');
  175.                 }
  176.                 statusCodeElem.textContent = request.statusCode;
  177.             } else {
  178.                 statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red');
  179.             }
  180.             if (request.duration) {
  181.                 durationCell.textContent = request.duration + 'ms';
  182.             }
  183.             if (request.profilerUrl) {
  184.                 profilerCell.textContent = '';
  185.                 var profilerLink = document.createElement('a');
  186.                 profilerLink.setAttribute('href', request.profilerUrl);
  187.                 profilerLink.textContent = request.profile;
  188.                 profilerCell.appendChild(profilerLink);
  189.             }
  190.             renderAjaxRequests();
  191.         };
  192.         var addEventListener;
  193.         var el = document.createElement('div');
  194.         if (!('addEventListener' in el)) {
  195.             addEventListener = function (element, eventName, callback) {
  196.                 element.attachEvent('on' + eventName, callback);
  197.             };
  198.         } else {
  199.             addEventListener = function (element, eventName, callback) {
  200.                 element.addEventListener(eventName, callback, false);
  201.             };
  202.         }
  203.         {% if excluded_ajax_paths is defined %}
  204.             if (window.fetch && window.fetch.polyfill === undefined) {
  205.                 var oldFetch = window.fetch;
  206.                 window.fetch = function () {
  207.                     var promise = oldFetch.apply(this, arguments);
  208.                     var url = arguments[0];
  209.                     var params = arguments[1];
  210.                     var paramType = Object.prototype.toString.call(arguments[0]);
  211.                     if (paramType === '[object Request]') {
  212.                         url = arguments[0].url;
  213.                         params = {
  214.                             method: arguments[0].method,
  215.                             credentials: arguments[0].credentials,
  216.                             headers: arguments[0].headers,
  217.                             mode: arguments[0].mode,
  218.                             redirect: arguments[0].redirect
  219.                         };
  220.                     } else {
  221.                         url = String(url);
  222.                     }
  223.                     if (!url.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) {
  224.                         var method = 'GET';
  225.                         if (params && params.method !== undefined) {
  226.                             method = params.method;
  227.                         }
  228.                         var stackElement = {
  229.                             error: false,
  230.                             url: url,
  231.                             method: method,
  232.                             type: 'fetch',
  233.                             start: new Date()
  234.                         };
  235.                         var idx = requestStack.push(stackElement) - 1;
  236.                         promise.then(function (r) {
  237.                             stackElement.duration = new Date() - stackElement.start;
  238.                             stackElement.error = r.status < 200 || r.status >= 400;
  239.                             stackElement.statusCode = r.status;
  240.                             stackElement.profile = r.headers.get('x-debug-token');
  241.                             stackElement.profilerUrl = r.headers.get('x-debug-token-link');
  242.                             finishAjaxRequest(idx);
  243.                         }, function (e){
  244.                             stackElement.error = true;
  245.                             finishAjaxRequest(idx);
  246.                         });
  247.                         startAjaxRequest(idx);
  248.                     }
  249.                     return promise;
  250.                 };
  251.             }
  252.             if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) {
  253.                 var proxied = XMLHttpRequest.prototype.open;
  254.                 XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
  255.                     var self = this;
  256.                     /* prevent logging AJAX calls to static and inline files, like templates */
  257.                     var path = url;
  258.                     if (url.substr(0, 1) === '/') {
  259.                         if (0 === url.indexOf('{{ request.basePath|e('js') }}')) {
  260.                             path = url.substr({{ request.basePath|length }});
  261.                         }
  262.                     }
  263.                     else if (0 === url.indexOf('{{ (request.schemeAndHttpHost ~ request.basePath)|e('js') }}')) {
  264.                         path = url.substr({{ (request.schemeAndHttpHost ~ request.basePath)|length }});
  265.                     }
  266.                     if (!path.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) {
  267.                         var stackElement = {
  268.                             error: false,
  269.                             url: url,
  270.                             method: method,
  271.                             type: 'xhr',
  272.                             start: new Date()
  273.                         };
  274.                         var idx = requestStack.push(stackElement) - 1;
  275.                         this.addEventListener('readystatechange', function() {
  276.                             if (self.readyState == 4) {
  277.                                 stackElement.duration = new Date() - stackElement.start;
  278.                                 stackElement.error = self.status < 200 || self.status >= 400;
  279.                                 stackElement.statusCode = self.status;
  280.                                 extractHeaders(self, stackElement);
  281.                                 finishAjaxRequest(idx);
  282.                             }
  283.                         }, false);
  284.                         startAjaxRequest(idx);
  285.                     }
  286.                     proxied.apply(this, Array.prototype.slice.call(arguments));
  287.                 };
  288.             }
  289.         {% endif %}
  290.         return {
  291.             hasClass: hasClass,
  292.             removeClass: removeClass,
  293.             addClass: addClass,
  294.             toggleClass: toggleClass,
  295.             getPreference: getPreference,
  296.             setPreference: setPreference,
  297.             addEventListener: addEventListener,
  298.             request: request,
  299.             renderAjaxRequests: renderAjaxRequests,
  300.             load: function(selector, url, onSuccess, onError, options) {
  301.                 var el = document.getElementById(selector);
  302.                 if (el && el.getAttribute('data-sfurl') !== url) {
  303.                     request(
  304.                         url,
  305.                         function(xhr) {
  306.                             el.innerHTML = xhr.responseText;
  307.                             el.setAttribute('data-sfurl', url);
  308.                             removeClass(el, 'loading');
  309.                             for (var i = 0; i < requestStack.length; i++) {
  310.                                 startAjaxRequest(i);
  311.                                 if (requestStack[i].duration) {
  312.                                     finishAjaxRequest(i);
  313.                                 }
  314.                             }
  315.                             (onSuccess || noop)(xhr, el);
  316.                         },
  317.                         function(xhr) { (onError || noop)(xhr, el); },
  318.                         '',
  319.                         options
  320.                     );
  321.                 }
  322.                 return this;
  323.             },
  324.             toggle: function(selector, elOn, elOff) {
  325.                 var tmp = elOn.style.display,
  326.                     el = document.getElementById(selector);
  327.                 elOn.style.display = elOff.style.display;
  328.                 elOff.style.display = tmp;
  329.                 if (el) {
  330.                     el.style.display = 'none' === tmp ? 'none' : 'block';
  331.                 }
  332.                 return this;
  333.             },
  334.             createTabs: function() {
  335.                 var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])');
  336.                 /* create the tab navigation for each group of tabs */
  337.                 for (var i = 0; i < tabGroups.length; i++) {
  338.                     var tabs = tabGroups[i].querySelectorAll('.tab');
  339.                     var tabNavigation = document.createElement('ul');
  340.                     tabNavigation.className = 'tab-navigation';
  341.                     for (var j = 0; j < tabs.length; j++) {
  342.                         var tabId = 'tab-' + i + '-' + j;
  343.                         var tabTitle = tabs[j].querySelector('.tab-title').innerHTML;
  344.                         var tabNavigationItem = document.createElement('li');
  345.                         tabNavigationItem.setAttribute('data-tab-id', tabId);
  346.                         if (j == 0) { addClass(tabNavigationItem, 'active'); }
  347.                         if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); }
  348.                         tabNavigationItem.innerHTML = tabTitle;
  349.                         tabNavigation.appendChild(tabNavigationItem);
  350.                         var tabContent = tabs[j].querySelector('.tab-content');
  351.                         tabContent.parentElement.setAttribute('id', tabId);
  352.                     }
  353.                     tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild);
  354.                 }
  355.                 /* display the active tab and add the 'click' event listeners */
  356.                 for (i = 0; i < tabGroups.length; i++) {
  357.                     tabNavigation = tabGroups[i].querySelectorAll('.tab-navigation li');
  358.                     for (j = 0; j < tabNavigation.length; j++) {
  359.                         tabId = tabNavigation[j].getAttribute('data-tab-id');
  360.                         document.getElementById(tabId).querySelector('.tab-title').className = 'hidden';
  361.                         if (hasClass(tabNavigation[j], 'active')) {
  362.                             document.getElementById(tabId).className = 'block';
  363.                         } else {
  364.                             document.getElementById(tabId).className = 'hidden';
  365.                         }
  366.                         tabNavigation[j].addEventListener('click', function(e) {
  367.                             var activeTab = e.target || e.srcElement;
  368.                             /* needed because when the tab contains HTML contents, user can click */
  369.                             /* on any of those elements instead of their parent '<li>' element */
  370.                             while (activeTab.tagName.toLowerCase() !== 'li') {
  371.                                 activeTab = activeTab.parentNode;
  372.                             }
  373.                             /* get the full list of tabs through the parent of the active tab element */
  374.                             var tabNavigation = activeTab.parentNode.children;
  375.                             for (var k = 0; k < tabNavigation.length; k++) {
  376.                                 var tabId = tabNavigation[k].getAttribute('data-tab-id');
  377.                                 document.getElementById(tabId).className = 'hidden';
  378.                                 removeClass(tabNavigation[k], 'active');
  379.                             }
  380.                             addClass(activeTab, 'active');
  381.                             var activeTabId = activeTab.getAttribute('data-tab-id');
  382.                             document.getElementById(activeTabId).className = 'block';
  383.                         });
  384.                     }
  385.                     tabGroups[i].setAttribute('data-processed', 'true');
  386.                 }
  387.             },
  388.             createToggles: function() {
  389.                 var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');
  390.                 for (var i = 0; i < toggles.length; i++) {
  391.                     var elementSelector = toggles[i].getAttribute('data-toggle-selector');
  392.                     var element = document.querySelector(elementSelector);
  393.                     addClass(element, 'sf-toggle-content');
  394.                     if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') {
  395.                         addClass(toggles[i], 'sf-toggle-on');
  396.                         addClass(element, 'sf-toggle-visible');
  397.                     } else {
  398.                         addClass(toggles[i], 'sf-toggle-off');
  399.                         addClass(element, 'sf-toggle-hidden');
  400.                     }
  401.                     addEventListener(toggles[i], 'click', function(e) {
  402.                         e.preventDefault();
  403.                         if ('' !== window.getSelection().toString()) {
  404.                             /* Don't do anything on text selection */
  405.                             return;
  406.                         }
  407.                         var toggle = e.target || e.srcElement;
  408.                         /* needed because when the toggle contains HTML contents, user can click */
  409.                         /* on any of those elements instead of their parent '.sf-toggle' element */
  410.                         while (!hasClass(toggle, 'sf-toggle')) {
  411.                             toggle = toggle.parentNode;
  412.                         }
  413.                         var element = document.querySelector(toggle.getAttribute('data-toggle-selector'));
  414.                         toggleClass(toggle, 'sf-toggle-on');
  415.                         toggleClass(toggle, 'sf-toggle-off');
  416.                         toggleClass(element, 'sf-toggle-hidden');
  417.                         toggleClass(element, 'sf-toggle-visible');
  418.                         /* the toggle doesn't change its contents when clicking on it */
  419.                         if (!toggle.hasAttribute('data-toggle-alt-content')) {
  420.                             return;
  421.                         }
  422.                         if (!toggle.hasAttribute('data-toggle-original-content')) {
  423.                             toggle.setAttribute('data-toggle-original-content', toggle.innerHTML);
  424.                         }
  425.                         var currentContent = toggle.innerHTML;
  426.                         var originalContent = toggle.getAttribute('data-toggle-original-content');
  427.                         var altContent = toggle.getAttribute('data-toggle-alt-content');
  428.                         toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
  429.                     });
  430.                     /* Prevents from disallowing clicks on links inside toggles */
  431.                     var toggleLinks = toggles[i].querySelectorAll('a');
  432.                     for (var j = 0; j < toggleLinks.length; j++) {
  433.                         addEventListener(toggleLinks[j], 'click', function(e) {
  434.                             e.stopPropagation();
  435.                         });
  436.                     }
  437.                     toggles[i].setAttribute('data-processed', 'true');
  438.                 }
  439.             }
  440.         };
  441.     })();
  442.     Sfjs.addEventListener(document, 'DOMContentLoaded', function() {
  443.         Sfjs.createTabs();
  444.         Sfjs.createToggles();
  445.     });
  446. /*]]>*/</script>