PageSourceSearch

https://nightshade.gg/services/ModalService.js

js nightshade.gg collected 2026-10-08 23:35:22 UTC 3,418 bytes, 130 lines download raw bytes

1export class ModalService {
2  static createModal({ title, content, onClose }) {
3    const overlay = document.createElement('div');
4    overlay.id = 'modalOverlay';
5    overlay.className = 'modal-overlay';
6    
7    const modal = document.createElement('div');
8    modal.className = 'preset-modal';
9    
10    const header = document.createElement('div');
11    header.className = 'modal-header';
12    
13    const titleElement = document.createElement('h2');
14    titleElement.textContent = title;
15    
16    const closeButton = document.createElement('button');
17    closeButton.className = 'close-modal';
18    closeButton.innerHTML = '×';
19    closeButton.onclick = () => {
20      this.closeModal(overlay);
21      if (onClose) onClose();
22    };
23    
24    header.appendChild(titleElement);
25    header.appendChild(closeButton);
26    
27    const contentContainer = document.createElement('div');
28    contentContainer.className = 'modal-content';
29    
30    if (typeof content === 'string') {
31      contentContainer.innerHTML = content;
32    } else if (content instanceof Element) {
33      contentContainer.appendChild(content);
34    }
35    
36    modal.appendChild(header);
37    modal.appendChild(contentContainer);
38    overlay.appendChild(modal);
39    
40    // Close on overlay click
41    overlay.addEventListener('click', (e) => {
42      if (e.target === overlay) {
43        this.closeModal(overlay);
44        if (onClose) onClose();
45      }
46    });
47    
48    // Close on escape key
49    document.addEventListener('keydown', (e) => {
50      if (e.key === 'Escape') {
51        this.closeModal(overlay);
52        if (onClose) onClose();
53      }
54    });
55    
56    return overlay;
57  }
58  
59  static showModal(options) {
60    const modal = this.createModal(options);
61    document.body.appendChild(modal);
62    return modal;
63  }
64  
65  static closeModal(modal) {
66    if (modal && modal.parentElement) {
67      modal.parentElement.removeChild(modal);
68    }
69  }
70  
71  static showError(message, duration = 5000) {
72    const errorModal = this.createModal({
73      title: 'Error',
74      content: `<div class="error-message">${message}</div>`
75    });
76    
77    document.body.appendChild(errorModal);
78    
79    if (duration > 0) {
80      setTimeout(() => this.closeModal(errorModal), duration);
81    }
82    
83    return errorModal;
84  }
85  
86  static showSuccess(message, duration = 3000) {
87    const successModal = this.createModal({
88      title: 'Success',
89      content: `<div class="success-message">${message}</div>`
90    });
91    
92    document.body.appendChild(successModal);
93    
94    if (duration > 0) {
95      setTimeout(() => this.closeModal(successModal), duration);
96    }
97    
98    return successModal;
99  }
100  
101  static showConfirm({ title, message, onConfirm, onCancel }) {
102    const content = document.createElement('div');
103    content.className = 'confirm-dialog';
104    content.innerHTML = `
105      <p>${message}</p>
106      <div class="confirm-actions">
107        <button class="btn-confirm">Confirm</button>
108        <button class="btn-cancel">Cancel</button>
109      </div>
110    `;
111    
112    const modal = this.showModal({
113      title,
114      content,
115      onClose: onCancel
116    });
117    
118    content.querySelector('.btn-confirm').onclick = () => {
119      this.closeModal(modal);
120      if (onConfirm) onConfirm();
121    };
122    
123    content.querySelector('.btn-cancel').onclick = () => {
124      this.closeModal(modal);
125      if (onCancel) onCancel();
126    };
127    
128    return modal;
129  }
130} 

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.