JAVASCRIPT 28
Toolbar.js Guest on 23rd April 2021 03:16:59 PM
  1. (function () {
  2.     'use strict';
  3.  
  4.     var findToolbar = function () {
  5.             return document.querySelector('#yii-debug-toolbar');
  6.         },
  7.         ajax = function (url, settings) {
  8.             var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  9.             settings = settings || {};
  10.             xhr.open(settings.method || 'GET', url, true);
  11.             xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  12.             xhr.setRequestHeader('Accept', 'text/html');
  13.             xhr.onreadystatechange = function () {
  14.                 if (xhr.readyState === 4) {
  15.                     if (xhr.status === 200 && settings.success) {
  16.                         settings.success(xhr);
  17.                     } else if (xhr.status !== 200 && settings.error) {
  18.                         settings.error(xhr);
  19.                     }
  20.                 }
  21.             };
  22.             xhr.send(settings.data || '');
  23.         },
  24.         url,
  25.         div,
  26.         toolbarEl = findToolbar(),
  27.         toolbarAnimatingClass = 'yii-debug-toolbar_animating',
  28.         barSelector = '.yii-debug-toolbar__bar',
  29.         viewSelector = '.yii-debug-toolbar__view',
  30.         blockSelector = '.yii-debug-toolbar__block',
  31.         toggleSelector = '.yii-debug-toolbar__toggle',
  32.         externalSelector = '.yii-debug-toolbar__external',
  33.  
  34.         CACHE_KEY = 'yii-debug-toolbar',
  35.         ACTIVE_STATE = 'active',
  36.  
  37.         animationTime = 300,
  38.  
  39.         activeClass = 'yii-debug-toolbar_active',
  40.         iframeActiveClass = 'yii-debug-toolbar_iframe_active',
  41.         iframeAnimatingClass = 'yii-debug-toolbar_iframe_animating',
  42.         titleClass = 'yii-debug-toolbar__title',
  43.         blockClass = 'yii-debug-toolbar__block',
  44.         ignoreClickClass = 'yii-debug-toolbar__ignore_click',
  45.         blockActiveClass = 'yii-debug-toolbar__block_active',
  46.         requestStack = [];
  47.  
  48.     if (toolbarEl) {
  49.         url = toolbarEl.getAttribute('data-url');
  50.  
  51.         ajax(url, {
  52.             success: function (xhr) {
  53.                 div = document.createElement('div');
  54.                 div.innerHTML = xhr.responseText;
  55.  
  56.                 toolbarEl.parentNode && toolbarEl.parentNode.replaceChild(div, toolbarEl);
  57.  
  58.                 showToolbar(findToolbar());
  59.  
  60.                 var event;
  61.                 if (typeof(Event) === 'function') {
  62.                     event = new Event('yii.debug.toolbar_attached', {'bubbles': true});
  63.                 } else {
  64.                     event = document.createEvent('Event');
  65.                     event.initEvent('yii.debug.toolbar_attached', true, true);
  66.                 }
  67.  
  68.                 div.dispatchEvent(event);
  69.             },
  70.             error: function (xhr) {
  71.                 toolbarEl.innerText = xhr.responseText;
  72.             }
  73.         });
  74.     }
  75.  
  76.     function showToolbar(toolbarEl) {
  77.         var barEl = toolbarEl.querySelector(barSelector),
  78.             viewEl = toolbarEl.querySelector(viewSelector),
  79.             toggleEl = toolbarEl.querySelector(toggleSelector),
  80.             externalEl = toolbarEl.querySelector(externalSelector),
  81.             blockEls = barEl.querySelectorAll(blockSelector),
  82.             blockLinksEls = document.querySelectorAll(blockSelector + ':not(.' + titleClass + ') a'),
  83.             iframeEl = viewEl.querySelector('iframe'),
  84.             iframeHeight = function () {
  85.                 return (window.innerHeight * (toolbarEl.dataset.height / 100) - barEl.clientHeight) + 'px';
  86.             },
  87.             isIframeActive = function () {
  88.                 return toolbarEl.classList.contains(iframeActiveClass);
  89.             },
  90.             resizeIframe = function(mouse) {
  91.                 var availableHeight = window.innerHeight - barEl.clientHeight;
  92.                 viewEl.style.height = Math.min(availableHeight, availableHeight - mouse.y) + "px";
  93.             },
  94.             showIframe = function (href) {
  95.                 toolbarEl.classList.add(iframeAnimatingClass);
  96.                 toolbarEl.classList.add(iframeActiveClass);
  97.  
  98.                 iframeEl.src = externalEl.href = href;
  99.                 iframeEl.removeAttribute('tabindex');
  100.  
  101.                 viewEl.style.height = iframeHeight();
  102.                 setTimeout(function () {
  103.                     toolbarEl.classList.remove(iframeAnimatingClass);
  104.                 }, animationTime);
  105.             },
  106.             hideIframe = function () {
  107.                 toolbarEl.classList.add(iframeAnimatingClass);
  108.                 toolbarEl.classList.remove(iframeActiveClass);
  109.                 iframeEl.setAttribute("tabindex", "-1");
  110.                 removeActiveBlocksCls();
  111.  
  112.                 externalEl.href = '#';
  113.                 viewEl.style.height = '';
  114.                 setTimeout(function () {
  115.                     toolbarEl.classList.remove(iframeAnimatingClass);
  116.                 }, animationTime);
  117.             },
  118.             removeActiveBlocksCls = function () {
  119.                 [].forEach.call(blockEls, function (el) {
  120.                     el.classList.remove(blockActiveClass);
  121.                 });
  122.             },
  123.             toggleToolbarClass = function (className) {
  124.                 toolbarEl.classList.add(toolbarAnimatingClass);
  125.                 if (toolbarEl.classList.contains(className)) {
  126.                     toolbarEl.classList.remove(className);
  127.                     [].forEach.call(blockLinksEls, function (el) {
  128.                         el.setAttribute('tabindex', "-1");
  129.                     });
  130.                 } else {
  131.                     [].forEach.call(blockLinksEls, function (el) {
  132.                         el.removeAttribute('tabindex');
  133.                     });
  134.                     toolbarEl.classList.add(className);
  135.                 }
  136.                 setTimeout(function () {
  137.                     toolbarEl.classList.remove(toolbarAnimatingClass);
  138.                 }, animationTime);
  139.             },
  140.             toggleStorageState = function (key, value) {
  141.                 if (window.localStorage) {
  142.                     var item = localStorage.getItem(key);
  143.  
  144.                     if (item) {
  145.                         localStorage.removeItem(key);
  146.                     } else {
  147.                         localStorage.setItem(key, value);
  148.                     }
  149.                 }
  150.             },
  151.             restoreStorageState = function (key) {
  152.                 if (window.localStorage) {
  153.                     return localStorage.getItem(key);
  154.                 }
  155.             },
  156.             togglePosition = function () {
  157.                 if (isIframeActive()) {
  158.                     hideIframe();
  159.                 } else {
  160.                     toggleToolbarClass(activeClass);
  161.                     toggleStorageState(CACHE_KEY, ACTIVE_STATE);
  162.                 }
  163.             };
  164.  
  165.         if (restoreStorageState(CACHE_KEY) === ACTIVE_STATE) {
  166.             var transition = toolbarEl.style.transition;
  167.             toolbarEl.style.transition = 'none';
  168.             toolbarEl.classList.add(activeClass);
  169.             setTimeout(function () {
  170.                 toolbarEl.style.transition = transition;
  171.             }, animationTime);
  172.         } else {
  173.             [].forEach.call(blockLinksEls, function (el) {
  174.                 el.setAttribute('tabindex', "-1");
  175.             });
  176.         }
  177.  
  178.         toolbarEl.style.display = 'block';
  179.  
  180.         window.onresize = function () {
  181.             if (toolbarEl.classList.contains(iframeActiveClass)) {
  182.                 viewEl.style.height = iframeHeight();
  183.             }
  184.         };
  185.  
  186.         toolbarEl.addEventListener("mousedown", function(e) {
  187.             if (isIframeActive() && (e.y - toolbarEl.offsetTop < 4 /* 4px click zone */)) {
  188.                 document.addEventListener("mousemove", resizeIframe, false);
  189.             }
  190.         }, false);
  191.  
  192.         document.addEventListener("mouseup", function(){
  193.             if (isIframeActive()) {
  194.                 document.removeEventListener("mousemove", resizeIframe, false);
  195.             }
  196.         }, false);
  197.  
  198.         barEl.onclick = function (e) {
  199.             var target = e.target,
  200.                 block = findAncestor(target, blockClass);
  201.  
  202.             if (block
  203.                 && !block.classList.contains(titleClass)
  204.                 && !block.classList.contains(ignoreClickClass)
  205.                 && e.which !== 2 && !e.ctrlKey // not mouse wheel and not ctrl+click
  206.             ) {
  207.                 while (target !== this) {
  208.                     if (target.href) {
  209.                         removeActiveBlocksCls();
  210.                         block.classList.add(blockActiveClass);
  211.                         showIframe(target.href);
  212.                     }
  213.                     target = target.parentNode;
  214.                 }
  215.  
  216.                 e.preventDefault();
  217.             }
  218.         };
  219.  
  220.         toggleEl.onclick = togglePosition;
  221.     }
  222.  
  223.     function findAncestor(el, cls) {
  224.         while ((el = el.parentElement) && !el.classList.contains(cls)) ;
  225.         return el;
  226.     }
  227.  
  228.     function renderAjaxRequests() {
  229.         var requestCounter = document.getElementsByClassName('yii-debug-toolbar__ajax_counter');
  230.         if (!requestCounter.length) {
  231.             return;
  232.         }
  233.         var ajaxToolbarPanel = document.querySelector('.yii-debug-toolbar__ajax');
  234.         var tbodies = document.getElementsByClassName('yii-debug-toolbar__ajax_requests');
  235.         var state = 'ok';
  236.         if (tbodies.length) {
  237.             var tbody = tbodies[0];
  238.             var rows = document.createDocumentFragment();
  239.             if (requestStack.length) {
  240.                 var firstItem = requestStack.length > 20 ? requestStack.length - 20 : 0;
  241.                 for (var i = firstItem; i < requestStack.length; i++) {
  242.                     var request = requestStack[i];
  243.                     var row = document.createElement('tr');
  244.                     rows.appendChild(row);
  245.  
  246.                     var methodCell = document.createElement('td');
  247.                     methodCell.innerHTML = request.method;
  248.                     row.appendChild(methodCell);
  249.  
  250.                     var statusCodeCell = document.createElement('td');
  251.                     var statusCode = document.createElement('span');
  252.                     if (request.statusCode < 300) {
  253.                         statusCode.setAttribute('class', 'yii-debug-toolbar__ajax_request_status yii-debug-toolbar__label_success');
  254.                     } else if (request.statusCode < 400) {
  255.                         statusCode.setAttribute('class', 'yii-debug-toolbar__ajax_request_status yii-debug-toolbar__label_warning');
  256.                     } else {
  257.                         statusCode.setAttribute('class', 'yii-debug-toolbar__ajax_request_status yii-debug-toolbar__label_error');
  258.                     }
  259.                     statusCode.textContent = request.statusCode || '-';
  260.                     statusCodeCell.appendChild(statusCode);
  261.                     row.appendChild(statusCodeCell);
  262.  
  263.                     var pathCell = document.createElement('td');
  264.                     pathCell.className = 'yii-debug-toolbar__ajax_request_url';
  265.                     pathCell.innerHTML = request.url;
  266.                     pathCell.setAttribute('title', request.url);
  267.                     row.appendChild(pathCell);
  268.  
  269.                     var durationCell = document.createElement('td');
  270.                     durationCell.className = 'yii-debug-toolbar__ajax_request_duration';
  271.                     if (request.duration) {
  272.                         durationCell.innerText = request.duration + " ms";
  273.                     } else {
  274.                         durationCell.innerText = '-';
  275.                     }
  276.                     row.appendChild(durationCell);
  277.                     row.appendChild(document.createTextNode(' '));
  278.  
  279.                     var profilerCell = document.createElement('td');
  280.                     if (request.profilerUrl) {
  281.                         var profilerLink = document.createElement('a');
  282.                         profilerLink.setAttribute('href', request.profilerUrl);
  283.                         profilerLink.innerText = request.profile;
  284.                         profilerCell.appendChild(profilerLink);
  285.                     } else {
  286.                         profilerCell.innerText = 'n/a';
  287.                     }
  288.                     row.appendChild(profilerCell);
  289.  
  290.                     if (request.error) {
  291.                         if (state !== "loading" && i > requestStack.length - 4) {
  292.                             state = 'error';
  293.                         }
  294.                     } else if (request.loading) {
  295.                         state = 'loading'
  296.                     }
  297.                     row.className = 'yii-debug-toolbar__ajax_request';
  298.                 }
  299.                 while (tbody.firstChild) {
  300.                     tbody.removeChild(tbody.firstChild);
  301.                 }
  302.                 tbody.appendChild(rows);
  303.             }
  304.             ajaxToolbarPanel.style.display = 'block';
  305.         }
  306.         requestCounter[0].innerText = requestStack.length;
  307.         var className = 'yii-debug-toolbar__label yii-debug-toolbar__ajax_counter';
  308.         if (state === 'ok') {
  309.             className += ' yii-debug-toolbar__label_success';
  310.         } else if (state === 'error') {
  311.             className += ' yii-debug-toolbar__label_error';
  312.         }
  313.         requestCounter[0].className = className;
  314.     }
  315.  
  316.     var proxied = XMLHttpRequest.prototype.open;
  317.  
  318.     XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
  319.         var self = this;
  320.  
  321.         // fix https://github.com/yiisoft/yii2-debug/issues/326
  322.         /* prevent logging AJAX calls to static and inline files, like templates */
  323.         if (url && url.substr(0, 1) === '/' && !url.match(new RegExp('{{ excluded_ajax_paths }}'))) {
  324.             var stackElement = {
  325.                 loading: true,
  326.                 error: false,
  327.                 url: url,
  328.                 method: method,
  329.                 start: new Date()
  330.             };
  331.             requestStack.push(stackElement);
  332.             this.addEventListener('readystatechange', function () {
  333.                 if (self.readyState === 4) {
  334.                     stackElement.duration = self.getResponseHeader('X-Debug-Duration') || new Date() - stackElement.start;
  335.                     stackElement.loading = false;
  336.                     stackElement.statusCode = self.status;
  337.                     stackElement.error = self.status < 200 || self.status >= 400;
  338.                     stackElement.profile = self.getResponseHeader('X-Debug-Tag');
  339.                     stackElement.profilerUrl = self.getResponseHeader('X-Debug-Link');
  340.                     renderAjaxRequests();
  341.                 }
  342.             }, false);
  343.             renderAjaxRequests();
  344.         }
  345.         proxied.apply(this, Array.prototype.slice.call(arguments));
  346.     };
  347.  
  348.     // catch fetch AJAX requests
  349.     if (window.fetch) {
  350.         var originalFetch = window.fetch;
  351.  
  352.         window.fetch = function (input, init) {
  353.             var method;
  354.             var url;
  355.             if (typeof input === 'string') {
  356.                 method = (init && init.method) || 'GET';
  357.                 url = input;
  358.             } else if (window.URL && input instanceof URL) { // fix https://github.com/yiisoft/yii2-debug/issues/296
  359.                 method = (init && init.method) || 'GET';
  360.                 url = input.href;
  361.             } else if (window.Request && input instanceof Request) {
  362.                 method = input.method;
  363.                 url = input.url;
  364.             }
  365.             var promise = originalFetch(input, init);
  366.  
  367.             /* prevent logging AJAX calls to static and inline files, like templates */
  368.             if (url && url.substr(0, 1) === '/' && !url.match(new RegExp('{{ excluded_ajax_paths }}'))) {
  369.                 var stackElement = {
  370.                     loading: true,
  371.                     error: false,
  372.                     url: url,
  373.                     method: method,
  374.                     start: new Date()
  375.                 };
  376.                 requestStack.push(stackElement);
  377.                 promise.then(function (response) {
  378.                     stackElement.duration = response.headers.get('X-Debug-Duration') || new Date() - stackElement.start;
  379.                     stackElement.loading = false;
  380.                     stackElement.statusCode = response.status;
  381.                     stackElement.error = response.status < 200 || response.status >= 400;
  382.                     stackElement.profile = response.headers.get('X-Debug-Tag');
  383.                     stackElement.profilerUrl = response.headers.get('X-Debug-Link');
  384.                     renderAjaxRequests();
  385.  
  386.                     return response;
  387.                 }).catch(function (error) {
  388.                     stackElement.loading = false;
  389.                     stackElement.error = true;
  390.                     renderAjaxRequests();
  391.  
  392.                     throw error;
  393.                 });
  394.                 renderAjaxRequests();
  395.             }
  396.  
  397.             return promise;
  398.         };
  399.     }
  400.  
  401. })();

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.