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.