暂无描述

exception.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig.
  2. If you make any change in this file, verify the same change is needed in the other file. */
  3. /*<![CDATA[*/
  4. if (typeof Sfjs === 'undefined') {
  5. Sfjs = (function() {
  6. "use strict";
  7. if ('classList' in document.documentElement) {
  8. var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); };
  9. var removeClass = function(el, cssClass) { el.classList.remove(cssClass); };
  10. var addClass = function(el, cssClass) { el.classList.add(cssClass); };
  11. var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); };
  12. } else {
  13. var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); };
  14. var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); };
  15. var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } };
  16. var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); };
  17. }
  18. var addEventListener;
  19. var el = document.createElement('div');
  20. if (!('addEventListener' in el)) {
  21. addEventListener = function (element, eventName, callback) {
  22. element.attachEvent('on' + eventName, callback);
  23. };
  24. } else {
  25. addEventListener = function (element, eventName, callback) {
  26. element.addEventListener(eventName, callback, false);
  27. };
  28. }
  29. return {
  30. addEventListener: addEventListener,
  31. createTabs: function() {
  32. var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])');
  33. /* create the tab navigation for each group of tabs */
  34. for (var i = 0; i < tabGroups.length; i++) {
  35. var tabs = tabGroups[i].querySelectorAll(':scope > .tab');
  36. var tabNavigation = document.createElement('ul');
  37. tabNavigation.className = 'tab-navigation';
  38. var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */
  39. for (var j = 0; j < tabs.length; j++) {
  40. var tabId = 'tab-' + i + '-' + j;
  41. var tabTitle = tabs[j].querySelector('.tab-title').innerHTML;
  42. var tabNavigationItem = document.createElement('li');
  43. tabNavigationItem.setAttribute('data-tab-id', tabId);
  44. if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; }
  45. if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); }
  46. tabNavigationItem.innerHTML = tabTitle;
  47. tabNavigation.appendChild(tabNavigationItem);
  48. var tabContent = tabs[j].querySelector('.tab-content');
  49. tabContent.parentElement.setAttribute('id', tabId);
  50. }
  51. tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild);
  52. addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active');
  53. }
  54. /* display the active tab and add the 'click' event listeners */
  55. for (i = 0; i < tabGroups.length; i++) {
  56. tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li');
  57. for (j = 0; j < tabNavigation.length; j++) {
  58. tabId = tabNavigation[j].getAttribute('data-tab-id');
  59. document.getElementById(tabId).querySelector('.tab-title').className = 'hidden';
  60. if (hasClass(tabNavigation[j], 'active')) {
  61. document.getElementById(tabId).className = 'block';
  62. } else {
  63. document.getElementById(tabId).className = 'hidden';
  64. }
  65. tabNavigation[j].addEventListener('click', function(e) {
  66. var activeTab = e.target || e.srcElement;
  67. /* needed because when the tab contains HTML contents, user can click */
  68. /* on any of those elements instead of their parent '<li>' element */
  69. while (activeTab.tagName.toLowerCase() !== 'li') {
  70. activeTab = activeTab.parentNode;
  71. }
  72. /* get the full list of tabs through the parent of the active tab element */
  73. var tabNavigation = activeTab.parentNode.children;
  74. for (var k = 0; k < tabNavigation.length; k++) {
  75. var tabId = tabNavigation[k].getAttribute('data-tab-id');
  76. document.getElementById(tabId).className = 'hidden';
  77. removeClass(tabNavigation[k], 'active');
  78. }
  79. addClass(activeTab, 'active');
  80. var activeTabId = activeTab.getAttribute('data-tab-id');
  81. document.getElementById(activeTabId).className = 'block';
  82. });
  83. }
  84. tabGroups[i].setAttribute('data-processed', 'true');
  85. }
  86. },
  87. createToggles: function() {
  88. var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');
  89. for (var i = 0; i < toggles.length; i++) {
  90. var elementSelector = toggles[i].getAttribute('data-toggle-selector');
  91. var element = document.querySelector(elementSelector);
  92. addClass(element, 'sf-toggle-content');
  93. if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') {
  94. addClass(toggles[i], 'sf-toggle-on');
  95. addClass(element, 'sf-toggle-visible');
  96. } else {
  97. addClass(toggles[i], 'sf-toggle-off');
  98. addClass(element, 'sf-toggle-hidden');
  99. }
  100. addEventListener(toggles[i], 'click', function(e) {
  101. e.preventDefault();
  102. if ('' !== window.getSelection().toString()) {
  103. /* Don't do anything on text selection */
  104. return;
  105. }
  106. var toggle = e.target || e.srcElement;
  107. /* needed because when the toggle contains HTML contents, user can click */
  108. /* on any of those elements instead of their parent '.sf-toggle' element */
  109. while (!hasClass(toggle, 'sf-toggle')) {
  110. toggle = toggle.parentNode;
  111. }
  112. var element = document.querySelector(toggle.getAttribute('data-toggle-selector'));
  113. toggleClass(toggle, 'sf-toggle-on');
  114. toggleClass(toggle, 'sf-toggle-off');
  115. toggleClass(element, 'sf-toggle-hidden');
  116. toggleClass(element, 'sf-toggle-visible');
  117. /* the toggle doesn't change its contents when clicking on it */
  118. if (!toggle.hasAttribute('data-toggle-alt-content')) {
  119. return;
  120. }
  121. if (!toggle.hasAttribute('data-toggle-original-content')) {
  122. toggle.setAttribute('data-toggle-original-content', toggle.innerHTML);
  123. }
  124. var currentContent = toggle.innerHTML;
  125. var originalContent = toggle.getAttribute('data-toggle-original-content');
  126. var altContent = toggle.getAttribute('data-toggle-alt-content');
  127. toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
  128. });
  129. /* Prevents from disallowing clicks on links inside toggles */
  130. var toggleLinks = toggles[i].querySelectorAll('a');
  131. for (var j = 0; j < toggleLinks.length; j++) {
  132. addEventListener(toggleLinks[j], 'click', function(e) {
  133. e.stopPropagation();
  134. });
  135. }
  136. toggles[i].setAttribute('data-processed', 'true');
  137. }
  138. },
  139. createFilters: function() {
  140. document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) {
  141. var filters = filter.closest('[data-filters]'),
  142. type = 'choice',
  143. name = filter.dataset.filter,
  144. ucName = name.charAt(0).toUpperCase()+name.slice(1),
  145. list = document.createElement('ul'),
  146. values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'),
  147. labels = {},
  148. defaults = null,
  149. indexed = {},
  150. processed = {};
  151. if (typeof values === 'string') {
  152. type = 'level';
  153. labels = values.split(',');
  154. values = values.toLowerCase().split(',');
  155. defaults = values.length - 1;
  156. }
  157. addClass(list, 'filter-list');
  158. addClass(list, 'filter-list-'+type);
  159. values.forEach(function (value, i) {
  160. if (value instanceof HTMLElement) {
  161. value = value.dataset['filter'+ucName];
  162. }
  163. if (value in processed) {
  164. return;
  165. }
  166. var option = document.createElement('li'),
  167. label = i in labels ? labels[i] : value,
  168. active = false,
  169. matches;
  170. if ('' === label) {
  171. option.innerHTML = '<em>(none)</em>';
  172. } else {
  173. option.innerText = label;
  174. }
  175. option.dataset.filter = value;
  176. option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows');
  177. indexed[value] = i;
  178. list.appendChild(option);
  179. addEventListener(option, 'click', function () {
  180. if ('choice' === type) {
  181. filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
  182. if (option.dataset.filter === row.dataset['filter'+ucName]) {
  183. toggleClass(row, 'filter-hidden-'+name);
  184. }
  185. });
  186. toggleClass(option, 'active');
  187. } else if ('level' === type) {
  188. if (i === this.parentNode.querySelectorAll('.active').length - 1) {
  189. return;
  190. }
  191. this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) {
  192. if (j <= i) {
  193. addClass(currentOption, 'active');
  194. if (i === j) {
  195. addClass(currentOption, 'last-active');
  196. } else {
  197. removeClass(currentOption, 'last-active');
  198. }
  199. } else {
  200. removeClass(currentOption, 'active');
  201. removeClass(currentOption, 'last-active');
  202. }
  203. });
  204. filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
  205. if (i < indexed[row.dataset['filter'+ucName]]) {
  206. addClass(row, 'filter-hidden-'+name);
  207. } else {
  208. removeClass(row, 'filter-hidden-'+name);
  209. }
  210. });
  211. }
  212. });
  213. if ('choice' === type) {
  214. active = null === defaults || 0 <= defaults.indexOf(value);
  215. } else if ('level' === type) {
  216. active = i <= defaults;
  217. if (active && i === defaults) {
  218. addClass(option, 'last-active');
  219. }
  220. }
  221. if (active) {
  222. addClass(option, 'active');
  223. } else {
  224. filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) {
  225. toggleClass(row, 'filter-hidden-'+name);
  226. });
  227. }
  228. processed[value] = true;
  229. });
  230. if (1 < list.childNodes.length) {
  231. filter.appendChild(list);
  232. filter.dataset.filtered = '';
  233. }
  234. });
  235. }
  236. };
  237. })();
  238. Sfjs.addEventListener(document, 'DOMContentLoaded', function() {
  239. Sfjs.createTabs();
  240. Sfjs.createToggles();
  241. Sfjs.createFilters();
  242. });
  243. }
  244. /*]]>*/