• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / blurts-server / c5f3d7b4-ee0c-44dd-8229-fb0a50cc276f

pending completion
c5f3d7b4-ee0c-44dd-8229-fb0a50cc276f

Pull #2987

circleci

Amri Toufali
add ESLint plugin for camelCase lint
Pull Request #2987: MNTOR-1171: Code Splitting

282 of 1663 branches covered (16.96%)

Branch coverage included in aggregate %.

12 of 12 new or added lines in 9 files covered. (100.0%)

959 of 4511 relevant lines covered (21.26%)

3.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/client/js/dialog.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
const main = document.querySelector('body > main')
×
6
const observer = new MutationObserver(handleMutation)
×
7
const triggerLinks = main.querySelectorAll('a[href*="dialog/"], button[data-dialog]')
×
8
let dialogEl
9

10
function init (links) {
11
  if (!dialogEl) {
×
12
    dialogEl = document.createElement('dialog')
×
13
    document.body.append(dialogEl)
×
14
  }
15

16
  links.forEach(link => link.addEventListener('click', handleEvent))
×
17
}
18

19
function handleMutation (mutationList) {
20
  for (const mutation of mutationList) {
×
21
    if (!mutation.addedNodes.length) continue // ignore removed-node mutations
×
22
    const triggerLink = mutation.target.querySelector('a[href*="dialog/"], button[data-dialog]')
×
23
    if (triggerLink) init([triggerLink])
×
24
  }
25
}
26

27
function handleEvent (e) {
28
  switch (true) {
×
29
    case e.target.matches('a[href*="dialog/"]'):
30
      e.preventDefault()
×
31
      openDialog(e.target.href)
×
32
      break
×
33
    case e.target.matches('button[data-dialog]'):
34
      openDialog(`dialog/${e.target.dataset.dialog}`)
×
35
      break
×
36
    case e.target.matches('dialog button.close'):
37
      dialogEl.close()
×
38
      break
×
39
  }
40
}
41

42
async function openDialog (path) {
43
  const partialName = path.substring(path.lastIndexOf('/') + 1)
×
44

45
  dialogEl.showModal() // provide immediate UI response by showing ::backdrop regardless of content load
×
46
  dialogEl.setAttribute('data-partial', partialName) // allow selector access, e.g. dialog[data-partial='addEmail']
×
47
  dialogEl.addEventListener('click', handleEvent)
×
48
  dialogEl.addEventListener('close', resetDialog)
×
49

50
  try {
×
51
    const res = await fetch(path, {
×
52
      headers: {
53
        Accept: 'text/html' // set to request localized response
54
      }
55
    })
56

57
    if (!res.ok) throw new Error('Bad fetch response')
×
58
    window.gtag('event', 'opened_closed_dialog', { action: 'open', result: 'success', page_location: location.href })
×
59

60
    const content = await res.text()
×
61
    dialogEl.insertAdjacentHTML('beforeend', content)
×
62

63
    try {
×
64
      const module = await import(`./partials/${partialName}.js`) // import module associated with dialog content
×
65
      module.default() // TODO: refactor filenames with camelCase to allow the filename as function name instead of default
×
66
    } catch (e) {
67
      console.log(`Dialog module "${partialName}.js" not found.`, e)
×
68
    }
69
  } catch (e) {
70
    dialogEl.close()
×
71
    window.gtag('event', 'opened_closed_dialog', { action: 'open', result: 'failed', page_location: location.href })
×
72
    console.error(`Could not load dialog content for ${partialName}.`, e)
×
73
  }
74
}
75

76
function resetDialog () {
77
  dialogEl.removeEventListener('click', handleEvent)
×
78
  dialogEl.removeEventListener('close', resetDialog)
×
79
  dialogEl.removeAttribute('data-partial')
×
80
  dialogEl.replaceChildren()
×
81
}
82

83
if (triggerLinks.length) init(triggerLinks) // adds event listeners for dialog links already in DOM
×
84
observer.observe(main, { attributes: false, childList: true, subtree: true }) // watches for new dialog links dynamically added to DOM
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc