From 54fc973c4fe5dd3289f619d28c285200de96b856 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 17 May 2020 16:13:14 -0700 Subject: [PATCH] Load JavaScript as ES6 modules JavaScript modules have been supported by the spec since ES6 (2015) and the feature is available in all modern, supported browsers. Using JavaScript modules offers advantages: - All scripts are loaded in strict mode, reducing unexpected edge cases from "sloppy mode". - Scripts run in isolation and no longer pollute the global namespace. This allows removing the IIFE from all JavaScript. - Browsers can optimize loading of modules. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules --- .../static/debug_toolbar/js/toolbar.js | 539 +++++++++--------- .../static/debug_toolbar/js/toolbar.timer.js | 80 ++- .../templates/debug_toolbar/base.html | 2 +- .../templates/debug_toolbar/redirect.html | 2 +- 4 files changed, 310 insertions(+), 313 deletions(-) diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.js b/debug_toolbar/static/debug_toolbar/js/toolbar.js index c9ffb4fc8..2b852815a 100644 --- a/debug_toolbar/static/debug_toolbar/js/toolbar.js +++ b/debug_toolbar/static/debug_toolbar/js/toolbar.js @@ -1,309 +1,308 @@ -(function () { - const $$ = { - on: function(root, eventName, selector, fn) { - root.addEventListener(eventName, function(event) { - const target = event.target.closest(selector); - if (root.contains(target)) { - fn.call(target, event); - } - }); - }, - show: function(element) { - element.style.display = 'block'; - }, - hide: function(element) { - element.style.display = 'none'; - }, - toggle: function(element, value) { - if (value) { - $$.show(element); - } else { - $$.hide(element); +const $$ = { + on: function(root, eventName, selector, fn) { + root.addEventListener(eventName, function(event) { + const target = event.target.closest(selector); + if (root.contains(target)) { + fn.call(target, event); } - }, - visible: function(element) { - const style = getComputedStyle(element); - return style.display !== 'none'; - }, - executeScripts: function(scripts) { - scripts.forEach(function(script) { - const el = document.createElement('script'); - el.src = script; - el.async = true; - document.head.appendChild(el); - }); - }, - }; + }); + }, + show: function(element) { + element.style.display = 'block'; + }, + hide: function(element) { + element.style.display = 'none'; + }, + toggle: function(element, value) { + if (value) { + $$.show(element); + } else { + $$.hide(element); + } + }, + visible: function(element) { + const style = getComputedStyle(element); + return style.display !== 'none'; + }, + executeScripts: function(scripts) { + scripts.forEach(function(script) { + const el = document.createElement('script'); + el.type = 'module'; + el.src = script; + el.async = true; + document.head.appendChild(el); + }); + }, +}; - const onKeyDown = function(event) { - if (event.keyCode === 27) { - djdt.hide_one_level(); +const onKeyDown = function(event) { + if (event.keyCode === 27) { + djdt.hide_one_level(); + } +}; + +const ajax = function(url, init) { + init = Object.assign({credentials: 'same-origin'}, init); + return fetch(url, init).then(function(response) { + if (response.ok) { + return response.json(); + } else { + const win = document.querySelector('#djDebugWindow'); + win.innerHTML = '
»

'+response.status+': '+response.statusText+'

'; + $$.show(win); + return Promise.reject(); } - }; + }); +}; - const ajax = function(url, init) { - init = Object.assign({credentials: 'same-origin'}, init); - return fetch(url, init).then(function(response) { - if (response.ok) { - return response.json(); - } else { - const win = document.querySelector('#djDebugWindow'); - win.innerHTML = '
»

'+response.status+': '+response.statusText+'

'; - $$.show(win); - return Promise.reject(); +const djdt = { + handleDragged: false, + init: function() { + const djDebug = document.querySelector('#djDebug'); + $$.show(djDebug); + $$.on(djDebug.querySelector('#djDebugPanelList'), 'click', 'li a', function(event) { + event.preventDefault(); + if (!this.className) { + return; } - }); - }; - - const djdt = { - handleDragged: false, - init: function() { - const djDebug = document.querySelector('#djDebug'); - $$.show(djDebug); - $$.on(djDebug.querySelector('#djDebugPanelList'), 'click', 'li a', function(event) { - event.preventDefault(); - if (!this.className) { - return; - } - const current = djDebug.querySelector('#' + this.className); - if ($$.visible(current)) { - djdt.hide_panels(); - } else { - djdt.hide_panels(); + const current = djDebug.querySelector('#' + this.className); + if ($$.visible(current)) { + djdt.hide_panels(); + } else { + djdt.hide_panels(); - $$.show(current); - this.parentElement.classList.add('djdt-active'); + $$.show(current); + this.parentElement.classList.add('djdt-active'); - const inner = current.querySelector('.djDebugPanelContent .djdt-scroll'), - store_id = djDebug.dataset.storeId; - if (store_id && inner.children.length === 0) { - let url = djDebug.dataset.renderPanelUrl; - const url_params = new URLSearchParams(); - url_params.append('store_id', store_id); - url_params.append('panel_id', this.className); - url += '?' + url_params.toString(); - ajax(url).then(function(data) { - inner.previousElementSibling.remove(); // Remove AJAX loader - inner.innerHTML = data.content; - $$.executeScripts(data.scripts); - }); - } + const inner = current.querySelector('.djDebugPanelContent .djdt-scroll'), + store_id = djDebug.dataset.storeId; + if (store_id && inner.children.length === 0) { + let url = djDebug.dataset.renderPanelUrl; + const url_params = new URLSearchParams(); + url_params.append('store_id', store_id); + url_params.append('panel_id', this.className); + url += '?' + url_params.toString(); + ajax(url).then(function(data) { + inner.previousElementSibling.remove(); // Remove AJAX loader + inner.innerHTML = data.content; + $$.executeScripts(data.scripts); + }); } + } + }); + $$.on(djDebug, 'click', 'a.djDebugClose', function(event) { + event.preventDefault(); + djdt.hide_one_level(); + }); + $$.on(djDebug, 'click', '.djDebugPanelButton input[type=checkbox]', function() { + djdt.cookie.set(this.dataset.cookie, this.checked ? 'on' : 'off', { + path: '/', + expires: 10 }); - $$.on(djDebug, 'click', 'a.djDebugClose', function(event) { - event.preventDefault(); - djdt.hide_one_level(); - }); - $$.on(djDebug, 'click', '.djDebugPanelButton input[type=checkbox]', function() { - djdt.cookie.set(this.dataset.cookie, this.checked ? 'on' : 'off', { - path: '/', - expires: 10 - }); - }); + }); - // Used by the SQL and template panels - $$.on(djDebug, 'click', '.remoteCall', function(event) { - event.preventDefault(); + // Used by the SQL and template panels + $$.on(djDebug, 'click', '.remoteCall', function(event) { + event.preventDefault(); - const ajax_data = {}; + const ajax_data = {}; - if (this.tagName === 'BUTTON') { - const form = this.closest('form'); - ajax_data.url = this.formAction; + if (this.tagName === 'BUTTON') { + const form = this.closest('form'); + ajax_data.url = this.formAction; - if (form) { - ajax_data.body = new FormData(form); - ajax_data.method = form.method.toUpperCase(); - } + if (form) { + ajax_data.body = new FormData(form); + ajax_data.method = form.method.toUpperCase(); } + } - if (this.tagName === 'A') { - ajax_data.url = this.href; - } + if (this.tagName === 'A') { + ajax_data.url = this.href; + } - ajax(ajax_data.url, ajax_data).then(function(data) { - const win = djDebug.querySelector('#djDebugWindow'); - win.innerHTML = data.content; - $$.show(win); - }); + ajax(ajax_data.url, ajax_data).then(function(data) { + const win = djDebug.querySelector('#djDebugWindow'); + win.innerHTML = data.content; + $$.show(win); }); + }); - // Used by the cache, profiling and SQL panels - $$.on(djDebug, 'click', 'a.djToggleSwitch', function(event) { - event.preventDefault(); - const self = this; - const id = this.dataset.toggleId; - const open_me = this.textContent === this.dataset.toggleOpen; - const name = this.dataset.toggleName; - const container = this.closest('.djDebugPanelContent').querySelector('#' + name + '_' + id); - container.querySelectorAll('.djDebugCollapsed').forEach(function(e) { - $$.toggle(e, open_me); - }); - container.querySelectorAll('.djDebugUncollapsed').forEach(function(e) { - $$.toggle(e, !open_me); - }); - this.closest('.djDebugPanelContent').querySelectorAll('.djToggleDetails_' + id).forEach(function(e) { - if (open_me) { - e.classList.add('djSelected'); - e.classList.remove('djUnselected'); - self.textContent = self.dataset.toggleClose; - } else { - e.classList.remove('djSelected'); - e.classList.add('djUnselected'); - self.textContent = self.dataset.toggleOpen; - } - const switch_ = e.querySelector('.djToggleSwitch'); - if (switch_) { - switch_.textContent = self.textContent; - } - }); + // Used by the cache, profiling and SQL panels + $$.on(djDebug, 'click', 'a.djToggleSwitch', function(event) { + event.preventDefault(); + const self = this; + const id = this.dataset.toggleId; + const open_me = this.textContent === this.dataset.toggleOpen; + const name = this.dataset.toggleName; + const container = this.closest('.djDebugPanelContent').querySelector('#' + name + '_' + id); + container.querySelectorAll('.djDebugCollapsed').forEach(function(e) { + $$.toggle(e, open_me); }); - - djDebug.querySelector('#djHideToolBarButton').addEventListener('click', function(event) { - event.preventDefault(); - djdt.hide_toolbar(true); + container.querySelectorAll('.djDebugUncollapsed').forEach(function(e) { + $$.toggle(e, !open_me); }); - djDebug.querySelector('#djShowToolBarButton').addEventListener('click', function(event) { - event.preventDefault(); - if (!djdt.handleDragged) { - djdt.show_toolbar(); + this.closest('.djDebugPanelContent').querySelectorAll('.djToggleDetails_' + id).forEach(function(e) { + if (open_me) { + e.classList.add('djSelected'); + e.classList.remove('djUnselected'); + self.textContent = self.dataset.toggleClose; + } else { + e.classList.remove('djSelected'); + e.classList.add('djUnselected'); + self.textContent = self.dataset.toggleOpen; + } + const switch_ = e.querySelector('.djToggleSwitch'); + if (switch_) { + switch_.textContent = self.textContent; } }); - let startPageY, baseY; - const handle = document.querySelector('#djDebugToolbarHandle'); - const onHandleMove = function(event) { - // Chrome can send spurious mousemove events, so don't do anything unless the - // cursor really moved. Otherwise, it will be impossible to expand the toolbar - // due to djdt.handleDragged being set to true. - if (djdt.handleDragged || event.pageY !== startPageY) { - let top = baseY + event.pageY; + }); - if (top < 0) { - top = 0; - } else if (top + handle.offsetHeight > window.innerHeight) { - top = window.innerHeight - handle.offsetHeight; - } + djDebug.querySelector('#djHideToolBarButton').addEventListener('click', function(event) { + event.preventDefault(); + djdt.hide_toolbar(true); + }); + djDebug.querySelector('#djShowToolBarButton').addEventListener('click', function(event) { + event.preventDefault(); + if (!djdt.handleDragged) { + djdt.show_toolbar(); + } + }); + let startPageY, baseY; + const handle = document.querySelector('#djDebugToolbarHandle'); + const onHandleMove = function(event) { + // Chrome can send spurious mousemove events, so don't do anything unless the + // cursor really moved. Otherwise, it will be impossible to expand the toolbar + // due to djdt.handleDragged being set to true. + if (djdt.handleDragged || event.pageY !== startPageY) { + let top = baseY + event.pageY; - handle.style.top = top + 'px'; - djdt.handleDragged = true; + if (top < 0) { + top = 0; + } else if (top + handle.offsetHeight > window.innerHeight) { + top = window.innerHeight - handle.offsetHeight; } - }; - djDebug.querySelector('#djShowToolBarButton').addEventListener('mousedown', function(event) { + + handle.style.top = top + 'px'; + djdt.handleDragged = true; + } + }; + djDebug.querySelector('#djShowToolBarButton').addEventListener('mousedown', function(event) { + event.preventDefault(); + startPageY = event.pageY; + baseY = handle.offsetTop - startPageY; + document.addEventListener('mousemove', onHandleMove); + }); + document.addEventListener('mouseup', function (event) { + document.removeEventListener('mousemove', onHandleMove); + if (djdt.handleDragged) { event.preventDefault(); - startPageY = event.pageY; - baseY = handle.offsetTop - startPageY; - document.addEventListener('mousemove', onHandleMove); - }); - document.addEventListener('mouseup', function (event) { - document.removeEventListener('mousemove', onHandleMove); - if (djdt.handleDragged) { - event.preventDefault(); - localStorage.setItem('djdt.top', handle.offsetTop); - setTimeout(function () { - djdt.handleDragged = false; - }, 10); - } - }); - const show = localStorage.getItem('djdt.show') || djDebug.dataset.defaultShow; - if (show === 'true') { - djdt.show_toolbar(); - } else { - djdt.hide_toolbar(); + localStorage.setItem('djdt.top', handle.offsetTop); + setTimeout(function () { + djdt.handleDragged = false; + }, 10); } - }, - hide_panels: function() { - const djDebug = document.getElementById('djDebug'); - $$.hide(djDebug.querySelector('#djDebugWindow')); - djDebug.querySelectorAll('.djdt-panelContent').forEach(function(e) { - $$.hide(e); - }); - djDebug.querySelectorAll('#djDebugToolbar li').forEach(function(e) { - e.classList.remove('djdt-active'); - }); - }, - hide_toolbar: function() { - djdt.hide_panels(); + }); + const show = localStorage.getItem('djdt.show') || djDebug.dataset.defaultShow; + if (show === 'true') { + djdt.show_toolbar(); + } else { + djdt.hide_toolbar(); + } + }, + hide_panels: function() { + const djDebug = document.getElementById('djDebug'); + $$.hide(djDebug.querySelector('#djDebugWindow')); + djDebug.querySelectorAll('.djdt-panelContent').forEach(function(e) { + $$.hide(e); + }); + djDebug.querySelectorAll('#djDebugToolbar li').forEach(function(e) { + e.classList.remove('djdt-active'); + }); + }, + hide_toolbar: function() { + djdt.hide_panels(); - const djDebug = document.getElementById('djDebug'); - $$.hide(djDebug.querySelector('#djDebugToolbar')); + const djDebug = document.getElementById('djDebug'); + $$.hide(djDebug.querySelector('#djDebugToolbar')); - const handle = document.querySelector('#djDebugToolbarHandle'); - $$.show(handle); - // set handle position - let handleTop = localStorage.getItem('djdt.top'); - if (handleTop) { - handleTop = Math.min(handleTop, window.innerHeight - handle.offsetHeight); - handle.style.top = handleTop + 'px'; - } + const handle = document.querySelector('#djDebugToolbarHandle'); + $$.show(handle); + // set handle position + let handleTop = localStorage.getItem('djdt.top'); + if (handleTop) { + handleTop = Math.min(handleTop, window.innerHeight - handle.offsetHeight); + handle.style.top = handleTop + 'px'; + } - document.removeEventListener('keydown', onKeyDown); + document.removeEventListener('keydown', onKeyDown); - localStorage.setItem('djdt.show', 'false'); - }, - hide_one_level: function() { - const djDebug = document.getElementById('djDebug'); - if ($$.visible(djDebug.querySelector('#djDebugWindow'))) { - $$.hide(djDebug.querySelector('#djDebugWindow')); - } else if (djDebug.querySelector('#djDebugToolbar li.djdt-active')) { - djdt.hide_panels(); - } else { - djdt.hide_toolbar(true); + localStorage.setItem('djdt.show', 'false'); + }, + hide_one_level: function() { + const djDebug = document.getElementById('djDebug'); + if ($$.visible(djDebug.querySelector('#djDebugWindow'))) { + $$.hide(djDebug.querySelector('#djDebugWindow')); + } else if (djDebug.querySelector('#djDebugToolbar li.djdt-active')) { + djdt.hide_panels(); + } else { + djdt.hide_toolbar(true); + } + }, + show_toolbar: function() { + document.addEventListener('keydown', onKeyDown); + const djDebug = document.getElementById('djDebug'); + $$.hide(djDebug.querySelector('#djDebugToolbarHandle')); + $$.show(djDebug.querySelector('#djDebugToolbar')); + localStorage.setItem('djdt.show', 'true'); + }, + cookie: { + get: function(key){ + if (document.cookie.indexOf(key) === -1) { + return null; } - }, - show_toolbar: function() { - document.addEventListener('keydown', onKeyDown); - const djDebug = document.getElementById('djDebug'); - $$.hide(djDebug.querySelector('#djDebugToolbarHandle')); - $$.show(djDebug.querySelector('#djDebugToolbar')); - localStorage.setItem('djdt.show', 'true'); - }, - cookie: { - get: function(key){ - if (document.cookie.indexOf(key) === -1) { - return null; - } - const cookieArray = document.cookie.split('; '), - cookies = {}; + const cookieArray = document.cookie.split('; '), + cookies = {}; - cookieArray.forEach(function(e){ - const parts = e.split('='); - cookies[ parts[0] ] = parts[1]; - }); + cookieArray.forEach(function(e){ + const parts = e.split('='); + cookies[ parts[0] ] = parts[1]; + }); - return cookies[ key ]; - }, - set: function(key, value, options){ - options = options || {}; + return cookies[ key ]; + }, + set: function(key, value, options){ + options = options || {}; - if (typeof options.expires === 'number') { - const days = options.expires, t = options.expires = new Date(); - t.setDate(t.getDate() + days); - } + if (typeof options.expires === 'number') { + const days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } - document.cookie = [ - encodeURIComponent(key) + '=' + String(value), - options.expires ? '; expires=' + options.expires.toUTCString() : '', - options.path ? '; path=' + options.path : '', - options.domain ? '; domain=' + options.domain : '', - options.secure ? '; secure' : '' - ].join(''); + document.cookie = [ + encodeURIComponent(key) + '=' + String(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join(''); - return value; - } - }, - }; - window.djdt = { - show_toolbar: djdt.show_toolbar, - hide_toolbar: djdt.hide_toolbar, - init: djdt.init, - close: djdt.hide_one_level, - cookie: djdt.cookie, - }; + return value; + } + }, +}; +window.djdt = { + show_toolbar: djdt.show_toolbar, + hide_toolbar: djdt.hide_toolbar, + init: djdt.init, + close: djdt.hide_one_level, + cookie: djdt.cookie, +}; - if (document.readyState !== 'loading') { - djdt.init(); - } else { - document.addEventListener('DOMContentLoaded', djdt.init); - } -})(); +if (document.readyState !== 'loading') { + djdt.init(); +} else { + document.addEventListener('DOMContentLoaded', djdt.init); +} diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.timer.js b/debug_toolbar/static/debug_toolbar/js/toolbar.timer.js index a4625d607..fe8ee7310 100644 --- a/debug_toolbar/static/debug_toolbar/js/toolbar.timer.js +++ b/debug_toolbar/static/debug_toolbar/js/toolbar.timer.js @@ -1,43 +1,41 @@ -(function () { - const timingOffset = performance.timing.navigationStart, - timingEnd = performance.timing.loadEventEnd, - totalTime = timingEnd - timingOffset; - function getLeft(stat) { - return ((performance.timing[stat] - timingOffset) / (totalTime)) * 100.0; - } - function getCSSWidth(stat, endStat) { - let width = ((performance.timing[endStat] - performance.timing[stat]) / (totalTime)) * 100.0; - // Calculate relative percent (same as sql panel logic) - width = 100.0 * width / (100.0 - getLeft(stat)); - return (width < 1) ? "2px" : width + "%"; - } - function addRow(stat, endStat) { - const row = document.createElement('tr'); - if (endStat) { - // Render a start through end bar - row.innerHTML = '' + stat.replace('Start', '') + '' + - '
 
' + - '' + (performance.timing[stat] - timingOffset) + ' (+' + (performance.timing[endStat] - performance.timing[stat]) + ')'; - row.querySelector('strong').style.width = getCSSWidth(stat, endStat); - } else { - // Render a point in time - row.innerHTML = '' + stat + '' + - '
 
' + - '' + (performance.timing[stat] - timingOffset) + ''; - row.querySelector('strong').style.width = '2px'; - } - row.querySelector('.djDebugLineChart').style.left = getLeft(stat) + '%'; - document.querySelector('#djDebugBrowserTimingTableBody').appendChild(row); +const timingOffset = performance.timing.navigationStart, + timingEnd = performance.timing.loadEventEnd, + totalTime = timingEnd - timingOffset; +function getLeft(stat) { + return ((performance.timing[stat] - timingOffset) / (totalTime)) * 100.0; +} +function getCSSWidth(stat, endStat) { + let width = ((performance.timing[endStat] - performance.timing[stat]) / (totalTime)) * 100.0; + // Calculate relative percent (same as sql panel logic) + width = 100.0 * width / (100.0 - getLeft(stat)); + return (width < 1) ? "2px" : width + "%"; +} +function addRow(stat, endStat) { + const row = document.createElement('tr'); + if (endStat) { + // Render a start through end bar + row.innerHTML = '' + stat.replace('Start', '') + '' + + '
 
' + + '' + (performance.timing[stat] - timingOffset) + ' (+' + (performance.timing[endStat] - performance.timing[stat]) + ')'; + row.querySelector('strong').style.width = getCSSWidth(stat, endStat); + } else { + // Render a point in time + row.innerHTML = '' + stat + '' + + '
 
' + + '' + (performance.timing[stat] - timingOffset) + ''; + row.querySelector('strong').style.width = '2px'; } + row.querySelector('.djDebugLineChart').style.left = getLeft(stat) + '%'; + document.querySelector('#djDebugBrowserTimingTableBody').appendChild(row); +} - // This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param) - addRow('domainLookupStart', 'domainLookupEnd'); - addRow('connectStart', 'connectEnd'); - addRow('requestStart', 'responseEnd'); // There is no requestEnd - addRow('responseStart', 'responseEnd'); - addRow('domLoading', 'domComplete'); // Spans the events below - addRow('domInteractive'); - addRow('domContentLoadedEventStart', 'domContentLoadedEventEnd'); - addRow('loadEventStart', 'loadEventEnd'); - document.querySelector('#djDebugBrowserTiming').classList.remove('djdt-hidden'); -})(); +// This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param) +addRow('domainLookupStart', 'domainLookupEnd'); +addRow('connectStart', 'connectEnd'); +addRow('requestStart', 'responseEnd'); // There is no requestEnd +addRow('responseStart', 'responseEnd'); +addRow('domLoading', 'domComplete'); // Spans the events below +addRow('domInteractive'); +addRow('domContentLoadedEventStart', 'domContentLoadedEventEnd'); +addRow('loadEventStart', 'loadEventEnd'); +document.querySelector('#djDebugBrowserTiming').classList.remove('djdt-hidden'); diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html index 4281ad623..d8080db91 100644 --- a/debug_toolbar/templates/debug_toolbar/base.html +++ b/debug_toolbar/templates/debug_toolbar/base.html @@ -1,7 +1,7 @@ {% load i18n %}{% load static %} - +
Django Debug Toolbar Redirects Panel: {{ status_line }} - +

{{ status_line }}