Skip to main content

max / makenotwork

7.8 KB · 214 lines History Blame Raw
1 // actions-tabs.js
2 // Delegated handler functions extracted from inline on* attributes in
3 // templates/partials/tabs/**, for CSP compliance (no script-src 'unsafe-inline').
4 // The dispatcher in the core module invokes each named function with `this` === the
5 // dispatching element and args drawn from data-arg / data-arg2. Bodies are the
6 // verbatim former inline handlers, adjusted only to read args from the element.
7
8 // --- item_overview.html ---
9 window.openInNewTab = function (url) {
10 window.open(url, '_blank');
11 };
12
13 window.copyItemLink = function (path) {
14 navigator.clipboard.writeText(window.location.origin + path).then(() => this.textContent = 'Copied!').catch(() => this.textContent = 'Failed');
15 };
16
17 window.openEmbedSection = function () {
18 var d = document.querySelector('details.content-section'); if (d) { d.open = true; d.scrollIntoView({ behavior: 'smooth' }); }
19 };
20
21 // --- item_embed.html ---
22 window.copyEmbedBtn = function () {
23 copyEmbed(this);
24 };
25
26 // --- project_settings.html ---
27 window.submitProjectInfo = function () {
28 saveProjectInfo({ preventDefault: function () {} }, this.getAttribute('data-project-id'));
29 };
30
31 window.submitProjectPricing = function () {
32 saveProjectPricing({ preventDefault: function () {} }, this.getAttribute('data-project-id'));
33 };
34
35 // --- item_pricing.html ---
36 window.togglePwywSettings = function () {
37 document.getElementById('pwyw-settings').classList.toggle('hidden', !this.checked);
38 };
39
40 window.toggleCustomLicense = function () {
41 document.getElementById('dash-custom-license').classList.toggle('hidden', this.value !== 'custom');
42 };
43
44 window.toggleLicenseKeys = function () {
45 document.getElementById('license-keys-section').classList.toggle('hidden', !this.checked);
46 };
47
48 // --- CSV export buttons (project_subscriptions, buyer_contacts, user_payments, user_creator) ---
49 window.exportCsvButton = function (url, filename) {
50 this.textContent = 'Exporting...'; this.disabled = true; var btn = this; fetch(url, { method: 'POST', headers: csrfHeaders() }).then(function (r) { return r.blob(); }).then(function (b) { var a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = filename; a.click(); btn.textContent = 'Export CSV'; btn.disabled = false; }).catch(function () { btn.textContent = 'Export CSV'; btn.disabled = false; showToast('Export failed'); });
51 };
52
53 // --- project_synckit.html / user_synckit.html ---
54 window.syncKitShowSlugFromBtn = function (appId) {
55 syncKitShowSlugForm(appId, this.dataset.slug);
56 };
57
58 window.syncKitDeleteFromBtn = function (appId) {
59 syncKitDeleteApp(appId, this.dataset.name);
60 };
61
62 // --- project_promotions.html ---
63 window.onPromoTypeChange = function () {
64 togglePromoFields(this.value);
65 };
66
67 window.syncTrialDays = function () {
68 document.getElementById('pc-trial-days').value = this.value;
69 };
70
71 // --- user_payments.html ---
72 window.submitOwnForm = function () {
73 this.form.requestSubmit();
74 };
75
76 // --- project_content.html ---
77 window.deselectAll = function () {
78 toggleSelectAll(false);
79 };
80
81 window.toggleSelectAllFromEl = function () {
82 toggleSelectAll(this.checked);
83 };
84
85 window.sortContent = function (colIndex, sortType) {
86 sortContentTable(parseInt(colIndex, 10), sortType);
87 };
88
89 // --- library_collections.html ---
90 window.slugifyCollName = function () {
91 document.getElementById('new-coll-slug').value = this.value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
92 };
93
94 // --- library_purchases.html ---
95 window.filterLibraryRows = function () {
96 (function (q) { var rows = document.querySelectorAll('#library-table tbody tr'); q = q.toLowerCase(); rows.forEach(function (r) { r.classList.toggle('hidden', r.textContent.toLowerCase().indexOf(q) === -1); }); })(this.value);
97 };
98
99 window.copyKeyCode = function (code) {
100 navigator.clipboard.writeText(code); this.textContent = 'Copied!'; setTimeout(() => this.textContent = code, 1500);
101 };
102
103 window.toggleContextMenuBtn = function (itemId) {
104 toggleContextMenu({ stopPropagation: function () {} }, itemId);
105 };
106
107 window.openCollectionPickerBtn = function (itemId) {
108 openCollectionPicker(itemId, this);
109 };
110
111 // --- user_profile.html ---
112 window.moveLinkUp = function () {
113 moveLink(this, -1);
114 };
115
116 window.moveLinkDown = function () {
117 moveLink(this, 1);
118 };
119
120 window.editLinkBtn = function () {
121 editLink(this);
122 };
123
124 window.saveLinkBtn = function () {
125 saveLink(this);
126 };
127
128 window.cancelLinkBtn = function () {
129 cancelLink(this);
130 };
131
132 window.copyElementText = function (id) {
133 navigator.clipboard.writeText(document.getElementById(id).textContent).then(() => { this.textContent = 'Copied'; setTimeout(() => this.textContent = 'Copy', 1500); });
134 };
135
136 window.copyFeedUrl = function () {
137 navigator.clipboard.writeText(document.getElementById('feed-url').value).then(() => { this.textContent = 'Copied!'; setTimeout(() => this.textContent = 'Copy URL', 2000); });
138 };
139
140 // --- user_media.html ---
141 window.onMediaFilesChange = function () {
142 mediaUploadFiles(this.files);
143 };
144
145 window.mediaFilterAll = function () {
146 mediaFilterFolder(null, this);
147 };
148
149 window.mediaFilterFolderBtn = function (folder) {
150 mediaFilterFolder(folder, this);
151 };
152
153 window.mediaDeleteFileBtn = function (id) {
154 mediaDeleteFile(id, this.dataset.filename);
155 };
156
157 // --- user_settings.html ---
158 window.setSettingsSectionBtn = function () {
159 setSettingsSection(this);
160 };
161
162 // --- item_details.html ---
163 window.onSearchTagsInput = function () {
164 searchTags(this.value);
165 };
166
167 window.syncItemHiddenFields = function () {
168 document.getElementById('hidden-title').value = document.getElementById('item-name').value; document.getElementById('hidden-desc').value = document.getElementById('item-description').value; document.getElementById('hidden-ai-tier').value = document.getElementById('ai_tier').value; document.getElementById('hidden-ai-disclosure').value = document.getElementById('ai_disclosure').value;
169 };
170
171 // --- user_creator.html ---
172 window.toggleTrialDetails = function () {
173 document.getElementById('trial-details').classList.toggle('hidden', !this.checked);
174 };
175
176 // --- Non-dispatcher delegated listeners ---
177 // The the core module dispatcher only covers click/change/input/submit. The handlers
178 // below cover drag-and-drop (user_media) and conditional submit (user_account),
179 // keyed on data attributes so the inline handlers can be removed.
180
181 // Media upload drop zone (user_media.html): former ondragover/ondragleave/ondrop.
182 document.addEventListener('dragover', function (e) {
183 var el = e.target.closest('[data-media-dropzone]');
184 if (!el) return;
185 e.preventDefault(); el.classList.add('user-media-upload--dragover');
186 });
187 document.addEventListener('dragleave', function (e) {
188 var el = e.target.closest('[data-media-dropzone]');
189 if (!el) return;
190 el.classList.remove('user-media-upload--dragover');
191 });
192 document.addEventListener('drop', function (e) {
193 var el = e.target.closest('[data-media-dropzone]');
194 if (!el) return;
195 mediaHandleDrop(e); el.classList.remove('user-media-upload--dragover');
196 });
197
198 // Conditional submit guard (user_account.html): a former onsubmit that returned
199 // false to block submission. Runs in capture phase so a false result can stop
200 // propagation before htmx's submit handler sees the event.
201 document.addEventListener('submit', function (e) {
202 var el = e.target.closest('[data-check-submit]');
203 if (!el) return;
204 var fn = window[el.getAttribute('data-check-submit')];
205 if (typeof fn === 'function') {
206 var r = fn.call(el, e);
207 if (r === false) { e.preventDefault(); e.stopPropagation(); }
208 }
209 }, true);
210
211 window.checkPasswordMatch = function () {
212 var np = document.getElementById('new-password').value, cp = document.getElementById('confirm-password').value; if (np !== cp) { var s = document.getElementById('password-status'); s.textContent = 'Passwords do not match'; s.classList.add('danger-text'); return false; }
213 };
214