PageSourceSearch

https://www.discountbank.co.il/scripts/forms/init-dropzone.js?v=13.8.0

js discountbank.co.il collected 2026-10-01 12:09:49 UTC 11,558 bytes, 375 lines download raw bytes

1document.addEventListener("DOMContentLoaded", () => {
2  let notificationIndex = 0;
3
4  const showMessage = (message, element, delay = 5000) => {
5    const removeMessage = (notification) => {
6      const animation = notification.animate(
7        { opacity: [1, 0], transform: ["translate(0, 0)", "translate(0, 50px)"] },
8        { duration: 300, easing: "ease-in" },
9      );
10
11      animation.onfinish = () => {
12        notification.remove();
13      };
14    };
15
16    const notification = document.createElement("span");
17    notification.classList.add("drop-error");
18    notificationIndex += 1;
19    notification.innerText = message;
20
21    notification.animate(
22      { opacity: [0, 1], transform: ["translate(0, 50px)", "translate(0, 0)"] },
23      { duration: 300, easing: "ease-out" },
24    );
25
26    setTimeout(() => {
27      element.before(notification);
28
29      setTimeout(() => {
30        notificationIndex -= 1;
31        removeMessage(notification);
32      }, delay);
33    }, notificationIndex * 100);
34  };
35
36  const initOne = (field) => {
37    if (field) {
38      const dropArea = field.parentNode;
39      const button = dropArea.querySelector(".dropzone-btn");
40      const input = dropArea.querySelector("input[type='file']");
41      const hiddenInput = dropArea.querySelector("input[type='hidden']");
42      const filesList = dropArea.querySelector(".files-list");
43      const label = dropArea.querySelector("label");
44      const errorMessageEl = dropArea.querySelector(".field-validation-valid");
45      const tooltip = dropArea.querySelector(".help-text");
46
47      filesList?.querySelectorAll("li")?.forEach((container) => {
48        if (container.dataset.filePath) {
49          addPathToValue(container.dataset.filePath);
50        }
51
52        addRemoveHandler(container, null, null);
53      });
54
55      const rawFiles = (input.dataset?.files || "")
56        .split(",")
57        .map((s) => s.trim().toLowerCase())
58        .filter(Boolean);
59
60      const allowedExtensions = new Set();
61      const allowedExactMimes = new Set();
62      const allowedWildcardMimes = new Set();
63
64      rawFiles.forEach((token) => {
65        if (token.includes("/")) {
66          const [type, subtype] = token.split("/");
67          if (subtype === "*") {
68            allowedWildcardMimes.add(type);
69          } else {
70            allowedExactMimes.add(token);
71          }
72        } else {
73          const ext = token.startsWith(".") ? token.slice(1) : token;
74          if (ext) allowedExtensions.add(ext);
75        }
76      });
77
78      const options = {
79        allowedTypesRaw: rawFiles,
80        allowedExtensions,
81        allowedExactMimes,
82        allowedWildcardMimes,
83        maxSizeMB: +input.dataset?.maxSize || 10,
84        maxFileSizeBytes: +input.dataset?.maxFileSize || 10 * 1024 * 1024,
85        maxFiles: input.hasAttribute("multiple") ? +input.dataset?.maxFiles || null : 1,
86        isMultiple: input.hasAttribute("multiple"),
87      };
88
89      const getExtension = (name) => {
90        const idx = name.lastIndexOf(".");
91        return idx === -1 ? "" : name.slice(idx + 1).toLowerCase();
92      };
93
94      function isFileTypeAllowed(file) {
95        const mime = (file.type || "").toLowerCase();
96
97        if (mime) {
98          if (options.allowedExactMimes.has(mime)) return true;
99          const mt = mime.split("/")[0];
100          if (options.allowedWildcardMimes.has(mt)) return true;
101        }
102
103        const ext = getExtension(file.name);
104        if (ext && options.allowedExtensions.has(ext)) return true;
105
106        if (options.allowedTypesRaw.length === 0) return true;
107
108        return false;
109      }
110
111      function addPathToValue(path) {
112        if (!hiddenInput) return;
113
114        const values = hiddenInput.value ? hiddenInput.value.split(",") : [];
115
116        if (!values.includes(path)) {
117          values.push(path);
118        }
119
120        hiddenInput.value = values.join(",");
121      }
122
123      let error = false;
124
125      const parentForm = dropArea.closest("form");
126
127      if (parentForm) {
128        parentForm.addEventListener("reset", () => {
129          dropArea.classList.remove("active");
130          filesList.innerHTML = "";
131          input.value = "";
132          if (hiddenInput) hiddenInput.value = "";
133        });
134      }
135
136      button.onclick = () => {
137        if (!error) {
138          input.click();
139        }
140      };
141
142      label.addEventListener("click", (event) => {
143        event.preventDefault();
144      });
145
146      input.addEventListener("change", () => {
147        const files = Array.from(input.files);
148        handleFiles(files, dropArea);
149      });
150
151      dropArea.addEventListener("dragenter", (e) => {
152        e.preventDefault();
153        dropArea.classList.add("active");
154      });
155
156      dropArea.addEventListener("dragover", (e) => {
157        e.preventDefault();
158        dropArea.classList.add("active");
159      });
160
161      dropArea.addEventListener("dragleave", (e) => {
162        if (!e.relatedTarget || !dropArea.contains(e.relatedTarget)) {
163          dropArea.classList.remove("active");
164        }
165      });
166
167      dropArea.addEventListener("drop", (e) => {
168        e.preventDefault();
169        let files = Array.from(e.dataTransfer.files);
170
171        if (files.length) {
172          if (!options.isMultiple) {
173            files = files.slice(0, 1);
174          }
175
176          const dataTransfer = new DataTransfer();
177          files.forEach((file) => dataTransfer.items.add(file));
178
179          input.files = dataTransfer.files;
180
181          handleFiles(files, dropArea);
182        }
183      });
184
185      async function handleFiles(files, dropArea) {
186        if (!options.isMultiple) {
187          filesList.innerHTML = "";
188          if (hiddenInput) hiddenInput.value = "";
189        }
190
191        const existingFilesCount = options.isMultiple ? Array.from(filesList.children).length : 0;
192        const validFiles = [];
193
194        dropArea.classList.add("active");
195
196        for (const [index, file] of files.entries()) {
197          // File type check
198          if (!isFileTypeAllowed(file)) {
199            showMessage(
200              `הקובץ '${file.name}' אינו בפורמט נתמך. ניתן להעלות קבצים מסוג: ${options.allowedTypesRaw.join(
201                ", ",
202              )} בלבד.`,
203              errorMessageEl || tooltip || button,
204            );
205            continue;
206          }
207
208          // File size check
209          if (file.size > options.maxFileSizeBytes) {
210            showMessage(
211              `הקובץ '${file.name}' חורג מהגודל המותר (${options.maxSizeMB}MB), יש לבחור קובץ קטן יותר.`,
212              errorMessageEl || tooltip || button,
213            );
214            continue;
215          }
216
217          // Duplicate check
218          const existingFiles = Array.from(filesList.children).map((el) => ({
219            name: el.dataset.fileName,
220            lastModified: +el.dataset.lastModified,
221          }));
222
223          const isDuplicate =
224            existingFiles.some((f) => f.name === file.name && f.lastModified === file.lastModified) ||
225            validFiles.some((f) => f.name === file.name && f.lastModified === file.lastModified);
226
227          if (isDuplicate) {
228            showMessage(`קובץ כפול: ${file.name}`, errorMessageEl || tooltip || button);
229            continue;
230          }
231
232          // Сhecking the maximum number of files
233          const totalCount = existingFilesCount + validFiles.length;
234
235          if (options.maxFiles && totalCount >= options.maxFiles) {
236            showMessage(`מספר קבצים מקסימלי: ${options.maxFiles}`, errorMessageEl || tooltip || button);
237            continue;
238          }
239
240          const path = await uploadFile(file);
241
242          if (!path) continue;
243
244          validFiles.push(file);
245
246          // Make ui
247
248          const fileContainer = document.createElement("li");
249
250          fileContainer.setAttribute("role", "listitem");
251          fileContainer.setAttribute("data-file-path", path);
252          fileContainer.dataset.fileName = file.name;
253          fileContainer.dataset.lastModified = file.lastModified;
254
255          fileContainer.innerHTML = `
256                <span class="file-name">${file.name}</span>
257                <button type="button" class="remove-file" aria-label="Remove file"><span class="remove-icon"></span></button>
258              `;
259          filesList.append(fileContainer);
260          addRemoveHandler(fileContainer, file.name, file.lastModified);
261
262          fileContainer.animate(
263            {
264              opacity: [0, 1],
265              transform: ["translateY(50px)", "translateY(0)"],
266            },
267            {
268              duration: 400 + index * 100,
269              easing: "ease-out",
270            },
271          );
272        }
273
274        const updatedDT = new DataTransfer();
275        validFiles.forEach((file) => updatedDT.items.add(file));
276        input.files = updatedDT.files;
277      }
278
279      function addRemoveHandler(container, fileNameToRemove, fileLastModifiedToRemove) {
280        const removeBtn = container.querySelector(".remove-file");
281
282        removeBtn.onclick = async () => {
283          if (container.dataset.filePath) {
284            await removeUploadedFile(container.dataset.filePath);
285          }
286
287          container.animate(
288            { opacity: [1, 0], transform: ["translateY(0)", "translateY(50px)"] },
289            { duration: 300, easing: "ease-in" },
290          ).onfinish = () => container.remove();
291
292          if (!options.isMultiple) {
293            input.value = "";
294            if (hiddenInput) hiddenInput.value = "";
295            return;
296          }
297
298          if (!fileNameToRemove || !fileLastModifiedToRemove) {
299            return;
300          }
301
302          const updatedDT = new DataTransfer();
303          Array.from(input.files).forEach((f) => {
304            if (!(f.name === fileNameToRemove && f.lastModified === fileLastModifiedToRemove)) {
305              updatedDT.items.add(f);
306            }
307          });
308          input.files = updatedDT.files;
309        };
310      }
311
312      async function uploadFile(file) {
313        const formData = new FormData();
314        formData.append("file", file);
315        formData.append("fieldId", input.id);
316        formData.append("formId", input.dataset.formId);
317
318        try {
319          const response = await fetch("/umbraco/api/UploadApi/UploadFile", {
320            method: "POST",
321            body: formData,
322          });
323
324          if (!response.ok) {
325            throw new Error();
326          }
327
328          const data = await response.json();
329
330          if (data.filePath && hiddenInput) {
331            addPathToValue(data.filePath);
332          }
333
334          return data.filePath;
335        } catch (err) {
336          showMessage("העלאת הקובץ נכשלה", errorMessageEl || tooltip || button);
337          return null;
338        }
339      }
340
341      async function removeUploadedFile(path) {
342        try {
343          const response = await fetch(`/umbraco/api/UploadApi/RemoveUploadedFile?path=${encodeURIComponent(path)}`, {
344            method: "POST",
345          });
346
347          if (!response.ok) {
348            throw new Error();
349          }
350
351          if (!hiddenInput) {
352            return;
353          }
354
355          hiddenInput.value = hiddenInput.value
356            .split(",")
357            .filter((x) => x !== path)
358            .join(",");
359        } catch (err) {
360          showMessage("מחיקת הקובץ נכשלה", errorMessageEl || tooltip || button);
361        }
362      }
363    }
364  };
365
366  const initAll = () => {
367    const nodes = Array.from(document.querySelectorAll(".dropzone-input"));
368
369    nodes?.forEach((el) => {
370      initOne(el);
371    });
372  };
373
374  initAll();
375});

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.