forked from FOSSpel/qr-code-generator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
371 lines (317 loc) · 12.7 KB
/
Copy pathscript.js
File metadata and controls
371 lines (317 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
document.addEventListener("DOMContentLoaded", () => {
const qrOptions = {
width: 300,
height: 300,
type: "svg",
data: "https://fosspel.github.io/qr-code-generator/",
image: "",
dotsOptions: { color: "#000000", type: "square" },
backgroundOptions: { color: "#ffffff" },
imageOptions: { crossOrigin: "anonymous", margin: 10 }
};
const qrCode = new QRCodeStyling(qrOptions);
qrCode.append(document.getElementById("qr-code-container"));
const qrText = document.getElementById("qr-text");
const qrSize = document.getElementById("qr-size");
const qrSizeValue = document.getElementById("qr-size-value");
const qrColor = document.getElementById("qr-color");
const qrBgColor = document.getElementById("qr-bg-color");
const dotStyle = document.getElementById("dot-style");
const logoUpload = document.getElementById("logo-upload");
const removeLogoBtn = document.getElementById("remove-logo");
const downloadBtn = document.getElementById("download-btn");
// Modal management elements
const modalOverlay = document.getElementById("modal-overlay");
const savePresetModal = document.getElementById("save-preset-modal");
const managePresetsModal = document.getElementById("manage-presets-modal");
const savePresetModalBtn = document.getElementById("save-preset-modal-btn");
const managePresetsModalBtn = document.getElementById("manage-presets-modal-btn");
console.log("Modal elements found:", {
modalOverlay: !!modalOverlay,
savePresetModal: !!savePresetModal,
managePresetsModal: !!managePresetsModal,
savePresetModalBtn: !!savePresetModalBtn,
managePresetsModalBtn: !!managePresetsModalBtn
});
// Modal form elements
const modalPresetNameInput = document.getElementById("modal-preset-name");
const modalPresetSelect = document.getElementById("modal-preset-select");
const modalLoadPresetBtn = document.getElementById("modal-load-preset");
const modalDeletePresetBtn = document.getElementById("modal-delete-preset");
const modalExportPresetsBtn = document.getElementById("modal-export-presets");
const modalImportPresetsInput = document.getElementById("modal-import-presets");
// Modal constants
const PRESET_STORAGE_KEY = "qr-presets";
const MAX_PRESETS = 50;
// Preset management functions
const getAllPresets = () => {
try {
const presets = localStorage.getItem(PRESET_STORAGE_KEY);
return presets ? JSON.parse(presets) : {};
} catch (error) {
console.error("Error loading presets:", error);
return {};
}
};
const saveAllPresets = (presets) => {
try {
localStorage.setItem(PRESET_STORAGE_KEY, JSON.stringify(presets));
return true;
} catch (error) {
console.error("Error saving presets:", error);
alert("Failed to save presets. LocalStorage might be full.");
return false;
}
};
const savePreset = (name) => {
if (!name.trim()) {
alert("Please enter a preset name.");
return false;
}
const presets = getAllPresets();
if (Object.keys(presets).length >= MAX_PRESETS) {
alert(`Maximum of ${MAX_PRESETS} presets allowed. Please delete some presets first.`);
return false;
}
const presetData = {
text: qrText.value,
color: qrColor.value,
bgColor: qrBgColor.value,
dotStyle: dotStyle.value,
size: qrSize.value,
logo: qrCode._options.image || "",
createdAt: new Date().toISOString()
};
presets[name] = presetData;
return saveAllPresets(presets);
};
const loadPreset = (name) => {
const presets = getAllPresets();
const preset = presets[name];
if (!preset) {
alert("Preset not found.");
return false;
}
qrText.value = preset.text || "";
qrColor.value = preset.color || "#000000";
qrBgColor.value = preset.bgColor || "#ffffff";
dotStyle.value = preset.dotStyle || "square";
qrSize.value = preset.size || "300";
qrSizeValue.textContent = `${qrSize.value}px`;
if (preset.logo) {
qrCode.update({ image: preset.logo });
removeLogoBtn.classList.remove("hidden");
logoUpload.value = ""; // Clear file input since we're loading from data URL
} else {
qrCode.update({ image: "" });
removeLogoBtn.classList.add("hidden");
logoUpload.value = "";
}
updateQRCode();
return true;
};
const deletePreset = (name) => {
if (!confirm(`Are you sure you want to delete the preset "${name}"?`)) {
return false;
}
const presets = getAllPresets();
delete presets[name];
return saveAllPresets(presets);
};
const updatePresetSelect = (selectElement = modalPresetSelect) => {
const presets = getAllPresets();
selectElement.innerHTML = '<option value="">Choose a preset...</option>';
Object.keys(presets).sort().forEach(name => {
const option = document.createElement("option");
option.value = name;
option.textContent = name;
selectElement.appendChild(option);
});
};
const exportPresets = () => {
const presets = getAllPresets();
if (Object.keys(presets).length === 0) {
alert("No presets to export.");
return;
}
const dataStr = JSON.stringify({
version: "1.0",
exportedAt: new Date().toISOString(),
presets: presets
}, null, 2);
const dataBlob = new Blob([dataStr], { type: "application/json" });
const url = URL.createObjectURL(dataBlob);
const link = document.createElement("a");
link.href = url;
link.download = `qr-presets-backup-${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
};
const importPresets = (file) => {
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = JSON.parse(e.target.result);
if (!data.presets || typeof data.presets !== 'object') {
throw new Error("Invalid preset file format.");
}
const currentPresets = getAllPresets();
const importedPresets = data.presets;
// Merge presets (imported take precedence for conflicts)
const mergedPresets = { ...currentPresets, ...importedPresets };
// Check if we exceed the limit
if (Object.keys(mergedPresets).length > MAX_PRESETS) {
alert(`Import would exceed the maximum of ${MAX_PRESETS} presets. Please delete some presets first.`);
return;
}
if (saveAllPresets(mergedPresets)) {
updatePresetSelect();
alert(`Successfully imported ${Object.keys(importedPresets).length} preset(s).`);
}
} catch (error) {
console.error("Error importing presets:", error);
alert("Failed to import presets. Please check the file format.");
}
};
reader.readAsText(file);
};
// Modal management functions
const openModal = (modal) => {
console.log("Opening modal:", modal.id);
modalOverlay.classList.remove("hidden");
modal.classList.remove("hidden");
document.body.style.overflow = "hidden"; // Prevent background scrolling
console.log("Modal overlay classes:", modalOverlay.className);
console.log("Modal classes:", modal.className);
};
const closeModal = () => {
modalOverlay.classList.add("hidden");
savePresetModal.classList.add("hidden");
managePresetsModal.classList.add("hidden");
document.body.style.overflow = ""; // Restore scrolling
// Clear form inputs
modalPresetNameInput.value = "";
modalPresetSelect.value = "";
};
const openSavePresetModal = () => {
openModal(savePresetModal);
modalPresetNameInput.focus();
};
const openManagePresetsModal = () => {
updatePresetSelect();
openModal(managePresetsModal);
};
const updateQRCode = () => {
const size = parseInt(qrSize.value, 10);
qrCode.update({
width: size,
height: size,
data: qrText.value.trim() === "" ? " " : qrText.value,
dotsOptions: { color: qrColor.value, type: dotStyle.value },
backgroundOptions: { color: qrBgColor.value }
});
};
qrText.addEventListener("input", updateQRCode);
qrSize.addEventListener("input", () => {
qrSizeValue.textContent = `${qrSize.value}px`;
updateQRCode();
});
qrColor.addEventListener("input", updateQRCode);
qrBgColor.addEventListener("input", updateQRCode);
dotStyle.addEventListener("change", updateQRCode);
logoUpload.addEventListener("change", (e) => {
if (e.target.files && e.target.files[0]) {
const reader = new FileReader();
reader.onload = (event) => {
qrCode.update({ image: event.target.result });
removeLogoBtn.classList.remove("hidden");
};
reader.readAsDataURL(e.target.files[0]);
}
});
removeLogoBtn.addEventListener("click", () => {
qrCode.update({ image: "" });
logoUpload.value = "";
removeLogoBtn.classList.add("hidden");
});
downloadBtn.addEventListener("click", () => {
qrCode.download({ name: "qrcode", extension: "png" });
});
// Modal event listeners
savePresetModalBtn.addEventListener("click", () => {
console.log("Save preset button clicked");
openSavePresetModal();
});
managePresetsModalBtn.addEventListener("click", () => {
console.log("Manage presets button clicked");
openManagePresetsModal();
});
// Modal close buttons
document.getElementById("close-save-modal").addEventListener("click", closeModal);
document.getElementById("close-manage-modal").addEventListener("click", closeModal);
document.getElementById("cancel-save-preset").addEventListener("click", closeModal);
document.getElementById("close-manage-modal-btn").addEventListener("click", closeModal);
// Modal backdrop click to close
modalOverlay.addEventListener("click", (e) => {
if (e.target === modalOverlay) {
closeModal();
}
});
// ESC key to close modal
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && !modalOverlay.classList.contains("hidden")) {
closeModal();
}
});
// Save preset modal actions
document.getElementById("confirm-save-preset").addEventListener("click", () => {
const name = modalPresetNameInput.value.trim();
if (savePreset(name)) {
updatePresetSelect();
closeModal();
alert(`Preset "${name}" saved successfully!`);
}
});
// Enter key to save preset
modalPresetNameInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
document.getElementById("confirm-save-preset").click();
}
});
// Manage presets modal actions
modalLoadPresetBtn.addEventListener("click", () => {
const selectedPreset = modalPresetSelect.value;
if (!selectedPreset) {
alert("Please select a preset to load.");
return;
}
if (loadPreset(selectedPreset)) {
closeModal();
alert(`Preset "${selectedPreset}" loaded successfully!`);
}
});
modalDeletePresetBtn.addEventListener("click", () => {
const selectedPreset = modalPresetSelect.value;
if (!selectedPreset) {
alert("Please select a preset to delete.");
return;
}
if (deletePreset(selectedPreset)) {
updatePresetSelect();
alert(`Preset "${selectedPreset}" deleted successfully!`);
}
});
modalExportPresetsBtn.addEventListener("click", exportPresets);
modalImportPresetsInput.addEventListener("change", (e) => {
if (e.target.files && e.target.files[0]) {
importPresets(e.target.files[0]);
e.target.value = ""; // Reset file input
}
});
// Initialize preset system
updatePresetSelect();
updateQRCode();
});