PageSourceSearch

https://korzh.com/assets/js/index.js

js korzh.com collected 2026-09-25 15:12:51 UTC 26,696 bytes, 581 lines download raw bytes

1document.addEventListener("DOMContentLoaded", () => {
2
3    const reCaptchaSiteKey = "6LeNDYMsAAAAALRDQNC4MOiETC9uD8gIj8AdRNjd";
4
5    // ==========================================
6    // EasyQuery Logic (from easyquery.html)
7    // ==========================================
8
9    const eqAction = window.location.href.split("#")[1];
10
11    const mobileDialogStyle = document.createElement("style");
12    mobileDialogStyle.innerHTML = `
13        @media screen and (max-width: 768px) {
14            .eq-mobile-fullscreen {
15                width: 100vw !important;
16                height: 100vh !important;
17                max-width: 100vw !important;
18                max-height: 100vh !important;
19                margin: 0 !important;
20                top: 0 !important;
21                left: 0 !important;
22                transform: none !important;
23                border-radius: 0 !important;
24                overflow-x: hidden !important;
25                overflow-y: auto !important;
26                border: none !important;
27            }
28        }
29    `;
30    document.head.appendChild(mobileDialogStyle);
31
32    if (eqAction === 'get-trial') {
33        getTrial();
34    } else {
35        const editions = ['asp-core-edition', 'asp-net-edition', 'winforms-edition', 'silverlight-edition', 'wpf-edition', 'delphi-edition'];
36        if (editions.includes(eqAction)) {
37            const licensingEl = document.getElementById("licensing");
38            if (licensingEl) {
39                licensingEl.scrollIntoView();
40            }
41            if (typeof $ !== 'undefined' && typeof Metro !== 'undefined') {
42                Metro.getPlugin("#license-price", 'tabs').open(editions.indexOf(eqAction) + 1);
43            }
44        }
45    }
46
47    // Attach click handler to "Get Trial" button
48    const getTrialBtn = document.getElementById("btn-get-trial");
49    if (getTrialBtn) {
50        getTrialBtn.addEventListener("click", (e) => {
51            e.preventDefault();
52            getTrial();
53        });
54    }
55
56    if (typeof $ !== 'undefined') {
57        $("body").on("click", "a[slow-loading]", function () {
58            showLoadIndicator();
59        });
60    }
61
62    function trialChangeOptions(val) {
63        if (typeof $ !== 'undefined') {
64            $(".trial-sub-options > form").hide();
65            $("#trial-option-" + val).show();
66        }
67    }
68
69    function getTrial() {
70        if (typeof Metro === 'undefined') return;
71
72        Metro.dialog.create({
73            title: "<span class='mif-magic-wand fg-primary pr-2'></span> Get EasyQuery Trial",
74            content: `
75            <h4 class="text-bold">Select your application type</h4>
76            <div class="mb-4 text-leader2" style="font-size: 1.1rem; line-height: 1.6;">
77                EasyQuery framework can be used on different platforms and with different types of applications. So, to give you the most relevant installation instructions we need to know more about your project first.
78            </div>
79            <select id="select-apptype" class="mt-4 mb-4" data-role="select" data-filter="false">
80                <option value="asp-net-core-razor">ASP.NET Core + MVC or Razor pages</option>
81                <option value="asp-net-core-spa">ASP.NET Core + SPA Frontend (Angular, Razor, Vue, etc)</option>
82                <option value="asp-net-4-mvc">ASP.NET 4 MVC</option>
83                <option value="asp-net-4-webforms">ASP.NET 4 WebForms</option>
84                <option value="net-winforms">.NET (Core) Windows Forms</option>
85                <option value="net-wpf">.NET (Core) WPF</option>
86                <option value="webapp-other">Web application on other platform (Java, Node.js, PHP, Python, etc) </option>
87                <option value="other">Any other type of application</option>
88            </select>
89            <div class="trial-sub-options">
90                <form id="trial-option-asp-net-core-razor" class="trial-option p-4 border bd-default mb-4">
91                    <input type="radio" data-role="radio" name="viewEngine" data-caption="MVC" value="mvc" checked/>
92                    <input type="radio" data-role="radio" name="viewEngine" data-caption="Razor Pages" value="razor-pages"/>
93                </form>
94                <form id="trial-option-asp-net-core-spa" name="trial-option-asp-net-core-spa" class="trial-option p-4 border bd-default mb-4">
95                    <input type="radio" data-role="radio" name="frontend" data-caption="Angular" value="angular"/>
96                    <input type="radio" data-role="radio" name="frontend" data-caption="React" value="react"/>
97                    <input type="radio" data-role="radio" name="frontend" data-caption="Vue" value="vue"/>
98                    <input type="radio" data-role="radio" name="frontend" data-caption="Other" value="other" checked/>
99                </form>
100                <form id="trial-option-asp-net-4-mvc" class="trial-option"></form>
101                <form id="trial-option-asp-net-4-webforms" class="trial-option"></form>
102                <form id="trial-option-net-winforms" class="trial-option"></form>
103                <form id="trial-option-net-wpf" class="trial-option"></form>
104                <form id="trial-option-webapp-other" class="trial-option p-4 border bd-default mb-4">
105                    <input type="text" data-role="input" name="backend" data-label="Please, specify:"/>
106                </form>
107                <form id="trial-option-other" class="trial-option p-4 border bd-default mb-4">
108                    <input type="text" data-role="input" name="apptype" data-label="Please, specify:"/>
109                </form>
110            </div>
111
112            <h4 class="text-bold mt-4">Enter your email <span class="text-muted text-normal">(optional)</span></h4>
113            <div class="mb-4 text-leader2" style="font-size: 1.1rem; line-height: 1.6;">
114                We will provide the detailed instructions on how to get the things worked.
115            </div>
116            <input id="trial-email" type="email" placeholder="[email protected]" data-role="input" data-prepend="<span class='mif-envelop'></span>" name="email"/>
117        `,
118            clsDialog: "eq-mobile-fullscreen",
119            closeButton: true,
120            defaultActions: false,
121            overlay: true,
122            overlayClickClose: false,
123            customButtons: [
124                {
125                    id: "get-trial-btn-in-dialog",
126                    text: "Get Trial",
127                    cls: "info rounded px-6 js-get-trial-action-btn",
128                    onclick: async function () {
129                        const app = document.getElementById("select-apptype").value;
130                        const email = document.getElementById("trial-email").value;
131
132                        closeDialogs();
133
134                        setTimeout(() => {
135                            if (typeof Metro !== 'undefined') {
136                                Metro.dialog.create({
137                                    title: "",
138                                    clsDialog: "eq-processing-dialog shadow-large eq-mobile-fullscreen",
139                                    content: `
140                                        <div style="position: relative;">
141                                            <!-- Ghost container to pre-stretch the dialog to exact destination size -->
142                                            <div style="visibility: hidden; pointer-events: none; opacity: 0; padding-top: 2rem; padding-bottom: 1rem;">
143                                                <div class="mx-auto" style="max-width: 400px; padding: 1rem; margin-bottom: 1.5rem; border: none;">
144                                                    <h3 class="text-bold">Your download will start shortly in <span class="fg-green text-leader">5</span> seconds...</h3>
145                                                    <h3 class="mt-2 text-muted">If your download does not start automatically, click here.</h3>
146                                                </div>
147                                            </div>
148
149                                            <div id="eq-processing-state" class="text-center" style="position: absolute; top:0; left:0; right:0; bottom:0; display:flex; flex-direction:column; justify-content:center; align-items:center; z-index: 2;">
150                                                <div class="mb-4">
151                                                    <div data-role="activity" data-type="cycle" data-style="color" style="margin: 0 auto; transform: scale(1.5);"></div>
152                                                </div>
153                                                <h3 class="text-light mt-4 mb-0">Assembling a sample project for you...</h3>
154                                            </div>
155
156                                            <div id="eq-result-state" style="position: absolute; top:0; left:0; right:0; bottom:0; z-index: 3; display:flex; flex-direction:column; justify-content:center; opacity: 0; pointer-events: none; visibility: hidden;"></div>
157                                        </div>
158                                    `,
159                                    closeButton: true,
160                                    defaultActions: false,
161                                    overlay: true,
162                                    overlayClickClose: false,
163                                    customButtons: [
164                                        {
165                                            text: "Close",
166                                            cls: "js-dialog-close flat fg-gray",
167                                            onclick: function () {
168                                            }
169                                        }
170                                    ],
171                                    onOpen: function () {
172                                        if (typeof grecaptcha !== 'undefined') {
173                                            grecaptcha.ready(function () {
174                                                grecaptcha
175                                                    .execute(reCaptchaSiteKey, { action: "eq_trial" })
176                                                    .then(function (token) {
177                                                        return processTrialRequest
177(app, email, token);
178                                                    })
179                                                    .catch(function (error) {
180                                                        console.error("reCAPTCHA error:", error);
181                                                        closeDialogs();
182                                                    });
183                                            });
184                                        } else {
185                                            console.warn("grecaptcha is not defined");
186                                            processTrialRequest(app, email, "dummy_token");
187                                        }
188                                    }
189                                });
190                            }
191                        }, 50);
192                    }
193                },
194                {
195                    text: "Cancel",
196                    cls: "js-dialog-close flat fg-gray",
197                    onclick: function () {
198                    }
199                }
200            ],
201            onOpen: function () {
202                const selectApptype = document.getElementById("select-apptype");
203                if (selectApptype) {
204                    selectApptype.addEventListener("change", function () {
205                        trialChangeOptions(this.value);
206                    });
207                    trialChangeOptions(selectApptype.value);
208                }
209            }
210        });
211    }
212
213    function closeDialogs() {
214        if (typeof document !== 'undefined') {
215            const existingDialogs = document.querySelectorAll('.dialog');
216            existingDialogs.forEach(d => {
217                if (typeof Metro !== 'undefined') {
218                    const instance = Metro.getPlugin(d, 'dialog');
219                    if (instance && typeof instance.close === 'function') {
220                        instance.close();
221                        return;
222                    }
223                }
224                d.remove();
225                const overlay = document.querySelector('.overlay');
226                if (overlay) overlay.remove();
227            });
228        }
229    }
230
231    async function processTrialRequest(apptype, email, token) {
232        const url = `https://account.korzh.com/api/account/register`;
233
234        let nextHref = 'https://korzh.com/easyquery/docs/getting-started';
235        let downloadUrl = null;
236        switch (apptype) {
237            case 'asp-net-core-razor':
238                downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNetCore-Razor-Mvc.zip';
239                break;
240            case 'asp-net-core-spa':
241                const form = document.forms["trial-option-asp-net-core-spa"];
242                if (form && form.elements.frontend) {
243                    const spaType = form.elements.frontend.value;
244                    switch (spaType) {
245                        case 'angular':
246                            downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNetCore-Angular.zip';
247                            break;
248                        case 'react':
249                            downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNetCore-React.zip';
250                            break;
251                        case 'vue':
252                            downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNetCore-Vue3.zip';
253                            break;
254                        case 'other':
255                            break;
256                    }
257                }
258                break;
259            case 'asp-net-4-mvc':
260                downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNet4-Mvc.zip';
261                break;
262            case 'asp-net-4-webforms':
263                downloadUrl = 'https://cdn.korzh.com/dot-net-samples/AspNet4-WebForms.zip';
264                break;
265            case 'net-winforms':
266                downloadUrl = 'https://cdn.korzh.com/dot-net-samples/WinForms.zip';
267                break;
268            case 'net-wpf':
269                downloadUrl = 'https://cdn.korzh.com/dot-net-samples/Wpf.zip';
270                break;
271            case 'webapp-other':
272            case 'other':
273                break;
274        }
275
276        const trialData = {
277            email,
278            captchaToken: token,
279            data: {
280                intent: "get-trial",
281                apptype
282            }
283        };
284
285        try {
286            const response = await fetch(url, {
287                method: 'POST',
288                headers: {
289                    'Content-Type': 'application/json'
290                },
291                body: JSON.stringify(trialData)
292            });
293
294            if (!response.ok) {
295                console.error("[EQ] Server error: " + response.status);
296                closeDialogs();
297                if (typeof Metro !== 'undefined' && Metro.toast && typeof Metro.toast.create === 'function') {
298                    Metro.toast.create("Verification failed. Please try again.", {
299                        clsToast: "alert",
300                        position: "top"
301                    });
302                } else {
303                    alert("Verification failed. Please try again.");
304                }
305                return;
306            }
307        } catch (error) {
308            console.error("[EQ] API error:", error);
309        }
310
311        let dialogContent = '';
312
313        if (downloadUrl) {
314            dialogContent += `
315                <div class="mx-auto">
316                    <div class="p-4 bd-default mb-6">
317                        <h3 id="download-countdown-text" class="text-bold text-center">
318                            The sample project download will start in <span id="download-countdown" class="fg-green text-leader">5</span> seconds...
319                        </h3>
320                        <h4  class="mt-2 text-muted text-center" style="line-height: 1.5;">
321                            <span id="manual-download-text">If the download does not start automatically,</span> <a href="${downloadUrl}" id="manual-download-link" class="fg-primary">click here</a>.
322                        </h4>
323                    </div>
324                </div>
325            `;
326        }
327
328        dialogContent += `
329                <div class="mt-2 text-left">
330                    <a href="https://korzh.com/easyquery/docs/getting-started/from-sample-to-your-own-project" target="_blank" class="fg-primary">
331                        <span class="mif-books pr-2"></span> Getting started with the sample
332                    </a>
333                </div>
334                <div class="mt-2 text-left">
335                    <a href="${nextHref}" target="_blank" class="fg-primary">
336                        <span class="mif-books pr-2"></span> EasyQuery documentation
337                    </a>
338                </div>
339        `;
340
341        const processingState = document.getElementById("eq-processing-state");
342        const resultState = document.getElementById("eq-result-state");
343        let downloadInterval = null;
344
345        if (processingState) processingState.style.display = "none";
346
347        if (resultState) {
348            resultState.innerHTML = dialogContent;
349            resultState.style.opacity = "1";
350            resultState.style.pointerEvents = "auto";
351            resultState.style.visibility = "visible";
352
353            if (downloadUrl) {
354                let count = 5;
355
356                const manualLink = document.getElementById('manual-download-link');
357                if (manualLink) {
358                    manualLink.addEventListener('click', () => {
359                        if (downloadInterval) clearInterval(downloadInterval);
360                        const countdownText = document.getElementById('download-countdown-text');
361                        if (countdownText) countdownText.style.display = 'none';
362                    });
363                }
364
365                downloadInterval = setInterval(() => {
366                    if (!document.getElementById('eq-result-state')) {
367                        clearInterval(downloadInterval);
368                        return;
369                    }
370
371                    count--;
372                    const counterEl = document.getElementById('download-countdown');
373                    if (counterEl) counterEl.innerText = count;
374                    if (count <= 0) {
375                        clearInterval(downloadInterval);
376                        const countdownText = document.getElementById('download-countdown-text');
377                        if (countdownText) countdownText.style.display = 'none';
378                        const manualDownloadText = document.getElementById('manual-download-text');
379                        if (manualDownloadText) manualDownloadText.innerText = 'The sample project download should have started automatically.\nIf not,';
380                        window.location.href = downloadUrl;
381                    }
382                }, 1000);
383            }
384        }
385    }
386
387    window.addEventListener("pageshow", function (event) {
388        if (event.persisted) {
389            window.location.reload();
390        }
391    });
392
393    function showLoadIndicator() {
394        if (typeof Metro !== 'undefined' && Metro.activity) {
395            Metro.activity.open({
396                type: "cycle",
397                overlayColor: "#fff",
398                overlayAlpha: .6,
399                text: '<div class="mt-2 text-small">Loading...</div>'
400            });
401        }
402    }
403
404
405    // ==========================================
406    // ERSK Logic (from easy-report-starter-kit.html)
407    // ==========================================
408
409    let getCommunityDialog = null;
410
411    const btnGetErskCommunity = document.getElementsByClassName("get-ersk-community-btn");
412    if (btnGetErskCommunity.length > 0) {
413        Array.from(btnGetErskCommunity).forEach(btn => {
414            btn.addEventListener("click", getERSKCommunity);
415        });
416    }
417
418    function getERSKCommunity() {
419        if (typeof Metro === 'undefined') return;
420
421        getCommunityDialog = Metro.dialog.create({
422            title: "Get ERSK Community",
423            content: `
424              <div>
425                  <p>When you download ERSK Community Edition, you'll get access to:</p>
426                  <ul class="unstyled-list">
427                      <li><span class="mif-checkmark fg-green mr-1"></span> Report Management</li>
428                      <li><span class="mif-checkmark fg-green mr-1"></span> User Management</li>
429                      <li><span class="mif-checkmark fg-green mr-1"></span> Report Sharing</li>
430                      <li><span class="mif-checkmark fg-green mr-1"></span> Data visualization with tables</li>
431                  </ul>
432                  <p class="mt-4">You can optionally provide your email to receive setup instructions and updates.</p>
433              </div>
434              <form id="ersk-community-edition-form">
435                  <div class="ersk-community-edition box">
436                      <label>Email (optional):</label>
437                      <input
438                          type="email"
439                          name="email"
440                          id="ersk-email-input"
441                          data-role="input"
442                          data-validate="email"
443                          placeholder="Enter your email..."
444                      >
445                  </div>
446                  <div class="form-actions mt-4 d-flex flex-justify-right gap-2">
447                      <button type="button" class="button js-dialog-close">Cancel</button>
448                      <button
449                          type="button"
450                          id="ersk-download-btn"
451                          class="button info"
452                      >Download ERSK Community</button>
453                  </div>
454              </form>
455          `,
456            clsDialog: "get-community-dialog shadow-large",
457            closeButton: true,
458            defaultActions: false,
459            customButtons: [],
460            onOpen: function () {
461                const downloadBtn = document.getElementById("ersk-download-btn");
462                if (downloadBtn) {
463                    downloadBtn.addEventListener("click", handleERSKDownload);
464                }
465            }
466        });
467    }
468
469    function setErskButtonState(state) {
470        const button = document.getElementById("ersk-download-btn");
471        if (!button) return;
472        if (state === "loading") {
473            button.disabled = true;
474            button.textContent = "Processing...";
475        } else {
476            button.disabled = false;
477            button.textContent = "Download ERSK Community";
478        }
479    }
480
481    function handleERSKDownload() {
482        const emailInput = document.getElementById("ersk-email-input");
483        const email = emailInput?.value.trim() || "";
484        const downloadUrl = "https://cdn.korzh.com/download/ersk_community.zip";
485
486        // Перевірка валідності email
487        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
488        if (email && !emailRegex.test(email)) {
489            if (typeof Metro !== 'undefined' && Metro.toast) {
490                Metro.toast.create("Please enter a valid email address", null, 3000, "alert");
491            }
492            return;
493        }
494
495        const btn = document.getElementById("ersk-download-btn");
496        const originalText = btn ? btn.textContent : "Download ERSK Community";
497
498        // Блокуємо кнопку під час обробки
499        setErskButtonState("loading");
500
501        // Викликаємо reCAPTCHA v3
502        if (typeof grecaptcha !== 'undefined') {
503            grecaptcha.ready(function () {
504                grecaptcha
505                    .execute(reCaptchaSiteKey, { action: "download_ersk" })
506                    .then(function (token) {
507                        console.log("OK");
508                        return submitERSKData(email, token, downloadUrl);
509                    })
510                    .catch(function (error) {
511                        console.error("reCAPTCHA error:", error);
512                        if (btn) {
513                            btn.disabled = false;
514                            btn.textContent = originalText;
515                        }
516                    });
517            });
518        } else {
519            console.warn("grecaptcha is not defined");
520            submitERSKData(email, "dummy_token", downloadUrl);
521        }
522    }
523
524    async function submitERSKData(email, recaptchaToken, downloadUrl) {
525        const nextUrl = "https://korzh.com/easy-report-starter-kit/docs/setup-first-launch";
526        const apiAuthoring = "https://account.korzh.com/api/account/register";
527
528        const data = {
529            email,
530            captchaToken: recaptchaToken, //The token of the Google CAPTCHA
531            data: {
532                intent: "get-perk", //register | get-trial | get-perk
533                ptag: "ERSK", //The unique identifier of the product the user interested in.
534                apptype: "ersk-community", //The type of the application the user going to use. 
535            },
536        };
537
538        try {
539            const response = await fetch(apiAuthoring, {
540                method: "POST",
541                headers: {
542                    "Content-Type": "application/json",
543                },
544                body: JSON.stringify(data),
545            });
546
547            if (!response.ok) {
548                console.error("[ERSK] Server error: " + response.status);
549                return;
550            }
551
552            const result = await response.json();
553
554            if (result?.status === 21) {
555                // user already registered
556            } else {
557                if (typeof Metro !== 'undefined' && Metro.toast) {
558                    Metro.toast.create("Your account has ben created! Thank you for using our products!", {
559                        clsToast: "success",
560                        position: "top",
561                    });
562                }
563            }
564
565            if (getCommunityDialog && typeof Metro !== 'undefined') {
566                Metro.dialog.close(getCommunityDialog);
567            }
568        } catch (error) {
569            console.error("[ERSK] API error:", error);
570        }
571
572        // Відкриваємо завантаження в новому вікні
573        window.open(downloadUrl, "_blank");
574        setTimeout(() => {
575            window.location.href = nextUrl;
576        }, 100);
577
578        return null;
579    }
580
581});

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.