1import { BASE_URL } from "config"; 2import { loginRegisterHandler_ } from "api-auth"; 3import { loginTemplate, registerTemplate } from "panel-pages-auth-template"; 4import { menuGenerator } from "components-section-menu-generator"; 5 6// ! ---------- Variables ---------- 7export const modal = jQuery("#modal"); 8export const modalTitle = modal.find(".modal-title"); 9export const modalBody = modal.find(".modal-body"); 10export const modalFooter = modal.find(".modal-footer"); 11export const regExpEmail = /^[a-zA-Z][a-zA-Z0-9_\.]*@[a-zA-Z0-9\.]*\.[a-zA-Z]{2,4}$/; 12export const regExpPhone = /^09\d{2}\s*?\d{3}\s*?\d{4}$/; 13 14// ? ========== Effect ========== 15jQuery.fn.shake = function (interval = 100) { 16 this.addClass("shaking"); 17 this.css("transition", "all " + (interval / 100).toString() + "s"); 18 setTimeout(() => { 19 this.css("transform", "translateX(-50%)"); 20 }, interval * 0); 21 setTimeout(() => { 22 this.css("transform", "translateX(50%)"); 23 }, interval * 1); 24 setTimeout(() => { 25 this.css("transform", "translateX(-25%)"); 26 }, interval * 2); 27 setTimeout(() => { 28 this.css("transform", "translateX(25%)"); 29 }, interval * 3); 30 setTimeout(() => { 31 this.css("transform", "translateX(-7%)"); 32 }, interval * 4); 33 setTimeout(() => { 34 this.css("transform", "translateX(0%)"); 35 }, interval * 5); 36 this.removeClass("shaking"); 37}; 38 39// ? ========== Separate Number ========== 40export const separate = (Number) => { 41 Number += ""; 42 Number = Number.replace(",", ""); 43 Number = Number.replace(",", ""); 44 Number = Number.replace(",", ""); 45 Number = Number.replace(",", ""); 46 Number = Number.replace(",", ""); 47 Number = Number.replace(",", ""); 48 let x = Number.split("."); 49 let y = x[0]; 50 let z = x.length > 1 ? "." + x[1] : ""; 51 let rgx = /(\d+)(\d{3})/; 52 while (rgx.test(y)) y = y.replace(rgx, "$1" + "," + "$2"); 53 return y + z; 54}; 55 56// ? ========== Short number display ========== 57export const shortNumberDisplay = (number) => { 58 return number >= 1000 ? (number / 1000) + "K" : number; 59}; 60 61// ? ========== Random number generator between min and max number ========== 62export const randomNumberGenerator = ({max, min}) => { 63 return Math.floor(Math.random() * (max - min + 1)) + min; 64}; 65 66// ? ========== Paste ========== 67export const paste = async (input) => { 68 const text = await navigator.clipboard.readText(); 69 input.value = text; 70}; 71 72// ? ========== Copy To Clipboard ========== 73export const copyToClipboard = (text, callback = null) => { 74 var elem = jQuery(`<textarea class="textarea-copy">${text}</textarea>`); 75 jQuery(document.body).append(elem); 76 elem.select(); 77 document.execCommand("copy"); 78 elem.remove(); 79 80 if (callback) callback(text); 81 82 if (jQuery.Toast()) { 83 jQuery(".toast-item-wrapper").remove(); 84 jQuery.Toast("Ù ÙÙÙÛØª Ø¢Ù ÛØ²", `<b>${text}</b> با Ù ÙÙÙÛØª Ú©Ù¾Û Ø´Ø¯`, "success"); 85 } 86}; 87 88// ? ========== Enter Character Convert To List ========== 89export const enterConvertToList = (desc) => { 90 if (desc.match(/\n/) && !desc.includes("<ul")) { 91 let listDesc = desc.split("\r\n"); 92 let list = ""; 93 94 for (let i = 0; i < listDesc.length; i++) { 95 // console.log(listDesc[i].replaceAll('\t', '')); 96 if (listDesc[i] != "") { 97 list += `<li>${listDesc[i]}</li>`; 98 } 99 } 100 return `<ul>${list}</ul>`; 101 } else { 102 return `<span>${desc}</span>`; 103 } 104}; 105 106// ? ========== Handle Button Loading ========== 107export const handleBtnLoading = (btn, time = 5) => { 108 var counter = time; 109 jQuery(btn).addClass("btn-loading"); 110 jQuery(btn).attr("disabled", true); 111 jQuery(btn).css("cursor", "not-allowed"); 112 var myInterval = setInterval(function () { 113 --counter; 114 if (counter <= 1) { 115 jQuery(btn).removeClass("btn-loading"); 116 jQuery(btn).attr("disabled", false); 117 jQuery(btn).css("cursor", "pointer"); 118 clearInterval(myInterval); 119 counter = 10; 120 } 121 }, 1000); 122}; 123 124// ? ========== Modal ========== 125// Show Modal 126export const showModal = (display, title, closableOverlay = true) => { 127 if (display == "show") { 128 jQuery(".overlay-modal").show(); 129 modal.css("display", "flex");
130 modal.find(".modal-title").text(title); 131 modalBody.html(""); 132 } 133 if (display == "hide") { 134 jQuery(".overlay-modal").hide(); 135 modal.hide(); 136 modalBody.html(""); 137 } 138 139 jQuery(".overlay-modal").click(function () { 140 jQuery(".modal-content").css("animation", "1s ease pulseEffect"); 141 142 if (closableOverlay) { 143 closeModal(); 144 } 145 }); 146 147 jQuery(".modal .close").click(closeModal); 148}; 149 150// Close Modal 151export const closeModal = () => { 152 jQuery(".go-back").addClass("d-none"); 153 jQuery(".overlay-modal").hide(); 154 showModal("hide", ""); 155}; 156 157// ? ========== Services Page Link ========== 158export const handleServicePageLink = (tag) => { 159 tag = String(tag).toLowerCase(); 160 let serviceLink = `${BASE_URL}/buy-`; 161 switch (tag) { 162 // ---------- Instagram ---------- 163 case "ig-follower": 164 serviceLink += "instagram-follower"; 165 break; 166 case "ig-like": 167 serviceLink += "instagram-like"; 168 break; 169 case "instagram-comment": 170 serviceLink += "instagram-comment"; 171 break; 172 case "ig-video-view": 173 serviceLink += "instagram-video-view"; 174 break; 175 case "instagram-comment-igtv": 176 serviceLink += "igtv-comments"; 177 break; 178 case "view-igtv-instagram": 179 serviceLink += "igtv-views"; 180 break; 181 // case 'instagram-like-igtv': 182 // serviceLink += 'igtv-like'; 183 // break; 184 // case 'ig-story': 185 // serviceLink += 'instagram-story'; 186 // break; 187 case "buy-instagram-impression": 188 serviceLink += "instagram-impression"; 189 break; 190 case "like-instagram-comment": 191 serviceLink += "instagram-comment-likes"; 192 break; 193 case "buy-instagram-save": 194 serviceLink += "instagram-save"; 195 break; 196 case "shares-instagram": 197 serviceLink += "instagram-sharing-posts"; 198 break; 199 case "ig-live-instagram": 200 serviceLink += "instagram-live-views"; 201 break; 202 case "instagram-highlight-view": 203 serviceLink += "instagram-higlight-views"; 204 break; 205 case "buy-instagram-view-story": 206 serviceLink += "instagram-story"; 207 break; 208 case "instagram-story-left": 209 serviceLink += "instagram-story-poll-votes"; 210 break; 211 case "instagram-story-right": 212 serviceLink += "instagram-story-poll-votes"; 213 break; 214 215 // ---------- Telegram ---------- 216 case "tlg-group-member": 217 serviceLink += "telegram-group-member"; 218 break; 219 case "tlg-channel-member": 220 serviceLink += "telegram-channel-member"; 221 break; 222 case "telegram-post-view": 223 serviceLink += "telegram-view"; 224 break; 225 226 // ---------- Aparat ---------- 227 case "buy-aparat-view": 228 serviceLink += "aparat-view"; 229 break; 230 231 // ---------- Clubhouse ---------- 232 case "follower-club-house": 233 serviceLink += "clubhouse-followers"; 234 break; 235 default: 236 serviceLink = BASE_URL; 237 break; 238 } 239 return serviceLink; 240}; 241 242// ? ========== Check Social Link ========== 243export const handleCheckSocialLink = (link) => { 244 if (link.indexOf("http") != -1 || link.indexOf("https") != -1 || link.indexOf("www") != -1) { 245 return link; 246 } 247 return null; 248}; 249 250// ? ========== Handle Slider ========== 251export const handleSlider = (element, count = 4) => { 252 // console.log(count); 253 if (count > 4) { 254 count = 4; 255 } else if (count == 4) { 256 count = 3; 257 } else if (count <= 3) { 258 count = 2; 259 } else if (count <= 2) { 260 count = 1; 261 } 262 263 jQuery(element).slick({ 264 dots : false, 265 infinite : true, 266 speed : 300, 267 rtl : true, 268 slidesToShow : count, 269 centerMode : true, 270 centerPadding: "55px", 271 responsive : [ 272 { 273 breakpoint: 1300, 274 settings : { 275 slidesToShow : 3, 276 infinite : true, 277 centerMode : true, 278 centerPadding: "55px" 279 } 280 }, 281 { 282 breakpoint: 1230, 283 settings : { 284 slidesToShow : 2, 285 infinite : true, 286 centerMode : false, 287 centerPadding: "0px" 288 } 289 }, 290 { 291 breakpoint: 660, 292 settings : { 293 slidesToShow : 1, 294 infinite : true, 295 centerMode : true, 296 centerPadding: "45px" 297 } 298 }, 299 { 300 breakpoint: 500, 301 settings : { 302 slidesToShow : 1, 303 infinite : true, 304 centerMode : true, 305 centerPadding: "30px" 306 } 307 }, 308 { 309 breakpoint: 430, 310 settings : { 311 slidesToShow : 1, 312 infinite : true, 313 centerMode : true, 314 centerPadding: "30px" 315 } 316 } 317 ] 318 }); 319}; 320
321// ? ========== Timer Counter ========== 322export const timerCounter = (duration, cb) => { 323 let timer = parseInt(duration); 324 let hours, minutes, seconds; 325 let interval = setInterval(function () { 326 hours = parseInt(timer / 60 / 60, 10); 327 minutes = parseInt(timer / 60, 10); 328 seconds = parseInt(timer % 60, 10); 329 330 hours = hours < 10 ? "0" + hours : hours; 331 minutes = minutes < 10 ? "0" + minutes : minutes; 332 seconds = seconds < 10 ? "0" + seconds : seconds; 333 334 if (duration > 3600) 335 jQuery(".box-remaining-time").text(hours + ":" + minutes + ":" + seconds); 336 else 337 jQuery(".box-remaining-time").text(minutes + ":" + seconds); 338 339 if (--timer < 0) { 340 timer = 0; 341 clearInterval(interval); 342 343 jQuery(".free-timer-block").html(` 344 <div> 345 <div class="alert-box alert-info"> 346 Ø¨Ø±Ø§Û Ø§Ø³ØªÙØ§Ø¯Ù از اÛ٠سرÙÛØ³ ÙØ·Ùا رÙÛ Ø¯Ú©Ù Ù Ø²ÛØ± Ú©ÙÛÚ© Ú©ÙÛØ¯ 347 </div> 348 349 <button onclick="location.reload();"> 350 <span class="fa fa-refresh"></span> 351 <span>Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û Ù Ø¬Ø¯Ø¯</span> 352 </button> 353 </div> 354 `); 355 356 cb(); 357 358 // location.reload(); 359 } 360 }, 1000); 361}; 362 363// ? ========== Countdown timer ========== 364export const countdownTimer = (duration, target, callback) => { 365 duration = (duration * 1000) + new Date().getTime(); 366 367 let x = setInterval(() => { 368 let now = new Date().getTime(); 369 let distance = duration - now; 370 371 let days = Math.floor(distance / (1000 * 60 * 60 * 24)); 372 let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); 373 let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); 374 let seconds = Math.floor((distance % (1000 * 60)) / 1000); 375 376 days = days < 10 ? `0${days}` : days; 377 hours = hours < 10 ? `0${hours}` : hours; 378 minutes = minutes < 10 ? `0${minutes}` : minutes; 379 seconds = seconds < 10 ? `0${seconds}` : seconds; 380 381 if (distance <= 0) { 382 clearInterval(x); 383 return callback(); 384 } 385 386 if (days > 0) { 387 jQuery(target).text([days, hours, minutes, seconds].join(":")); 388 } else if (hours > 0) { 389 jQuery(target).text([hours, minutes, seconds].join(":")); 390 } else { 391 jQuery(target).text([minutes, seconds].join(":")); 392 } 393 }, 1000); 394 395 return x; 396}; 397 398// ? ========== Handle File Attachment ========== 399export const handleFileAttachment = (element) => { 400 jQuery(element).bind("change", function () { 401 let filename = jQuery(element).val(); 402 if (/^\s*$/.test(filename)) { 403 jQuery(".file-upload").removeClass("active"); 404 jQuery("#noFile").text("ÙÛÚ ÙØ§ÛÙÛ Ø§ÙØªØ®Ø§Ø¨ ÙØ´Ø¯Ù است..."); 405 } else { 406 jQuery(".file-upload").addClass("active"); 407 jQuery("#noFile").text(filename.replace("C:\\fakepath\\", "")); 408 } 409 }); 410}; 411 412// ? ========== limitStringToCharacter ========== 413export const limitStringToCharacter = ({str, limit = 20}) => { 414 if (str.length >= limit) return str.substring(0, limit) + "..."; 415 return str; 416}; 417 418// ? ========== Show more box area ========== 419export const boxAreaExpander = ({target, max, screen, btnShow = "Ø¨ÛØ´ØªØ±", btnHide = "ک٠تر"}) => { 420 let box_area = jQuery(".box-area"); 421 let target_element = jQuery(box_area).find(target); 422 423 if (jQuery(target_element).outerHeight() >= max.mobile || jQuery(target_element).outerHeight() >= max.desktop) { 424 jQuery(target_element).addClass("box-hide"); 425 426 if (jQuery(target_element).find(`#expander`).length == 0) { 427 jQuery(target_element).parent().append(` 428 <div id="expander" class="text-center"> 429 <button class="btn btn-primary btn-more">${btnShow}</button> 430 </div> 431 `); 432 } 433 } 434 435 // if (jQuery(window).width() >= screen.mobile) 436 // jQuery('.box-hide').css('height', `${max.desktop}px`); 437 // else 438 // jQuery('.box-hide').css('height', `${max.mobile}px`); 439 440 jQuery(target_element).parent().find(`#expander button`).click(function () { 441 if (jQuery(target_element).hasClass("box-hide")) { 442 jQuery(target_element).removeClass("box-hide"); 443 jQuery(this).text(btnHide); 444
445 // if (jQuery(window).width() >= screen.mobile) 446 // jQuery(target_element).css('margin-bottom', `${max.desktop}px`); 447 // else 448 // jQuery(target_element).css('margin-bottom', `${max.mobile}px`); 449 450 } else { 451 jQuery(target_element).addClass("box-hide"); 452 jQuery(this).text(btnShow); 453 454 // jQuery(target_element).css('margin-bottom', `0`); 455 } 456 }); 457}; 458 459// ? ========== Scroll To ========== 460/* 461export const scrollTo = (target, {offset = 100, delay = 400}) => { 462 // Scroll to services 463 jQuery("html, body").animate({scrollTop: jQuery(target).offset().top - offset}, delay); 464}; 465*/ 466 467export const scrollTo = (target, {offset = 100, delay = 400}) => { 468 const $target = jQuery(target); 469 if (!$target.length) { 470 // console.error(`Invalid target element: ${target}`); 471 return; 472 } 473 474 // Scroll to target 475 jQuery("html, body").animate({scrollTop: $target.offset().top - offset}, delay); 476}; 477 478// ? ========== Go to back URL ========== 479export const goToBackUrl = (target_url = null) => { 480 const params = new URLSearchParams(window.location.search); 481 482 if (params.get("backUrl")) { 483 window.location = BASE_URL + params.get("backUrl"); 484 } else { 485 window.location = BASE_URL + (target_url ? target_url : `/my-account/`); 486 } 487}; 488 489// ? ========== Logout ========== 490export const logout = () => { 491 localStorage.removeItem("mobile"); 492 localStorage.removeItem("email"); 493 localStorage.removeItem("uwt"); 494 495 if (location.href.includes("/my-account")) { 496 location.href = BASE_URL; 497 } else { 498 // window.location = BASE_URL + location.pathname + location.hash + location.search; 499 location.reload(); 500 } 501}; 502 503// ? ========== IsEnterEvent ========== 504export const isEnterEvent = (e) => { 505 return (e.keyCode == 13 || e.which == 13 || e.key == "Enter"); 506}; 507 508// ? ========== isAuthenticated ========== 509export const isAuthenticated = (e) => { 510 return (localStorage.getItem("mobile") && localStorage.getItem("uwt")); 511}; 512 513// ? ========== isNotAuthenticated ========== 514export const isNotAuthenticated = (e) => { 515 return (!localStorage.getItem("mobile") || !localStorage.getItem("uwt")); 516}; 517 518// ? ========== getUserToken ========== 519export const getUserToken = () => { 520 return localStorage.getItem("uwt") || null; 521}; 522 523// ? ========== Login register popup ========== 524export const loginRegisterPopup = (callback) => { 525 showModal("show", "ÙØ±Ùد Ø¨Ù ØØ³Ø§Ø¨ کاربرÛ", false); 526 modalBody.append(loginTemplate.apply({})); 527 // jQuery("#btn-close-modal").click(() => closeModal()); 528 529 loginRegisterHandler_(function () { 530 closeModal(); 531 menuGenerator("vn"); 532 // if (location.href.includes("https://followeran.com/vn")) 533 // menuGenerator("vn"); 534 // else 535 // menuGenerator("sm"); 536 537 callback(); 538 }); 539 540 // Render reCaptcha 541 /*window.reCaptachLoginCallback = () => { 542 grecaptcha.render('recaptcha_login', { 543 'sitekey': RECAPTCHA_SITE_KEY, 544 'callback': (reCaptchaToken) => window.reCaptchaLoginToken = reCaptchaToken, 545 }); 546 };*/ 547}; 548 549export const loginPopup = (callback) => { 550 showModal("show", "ÙØ±Ùد Ø¨Ù ØØ³Ø§Ø¨ کاربرÛ", false); 551 modalBody.append(loginTemplate.apply({})); 552 553 loginRegisterHandler_(function () { 554 closeModal(); 555 menuGenerator("vn"); 556 // if (location.href.includes("https://followeran.com/vn")) 557 // menuGenerator("vn"); 558 // else 559 // menuGenerator("sm"); 560 561 callback(); 562 }); 563}; 564 565export const registerPopup = (callback) => { 566 showModal("show", "ثبت ÙØ§Ù ", false); 567 modalBody.append(registerTemplate.apply({})); 568 569 loginRegisterHandler_(function () { 570 closeModal(); 571 menuGenerator("vn"); 572 // if (location.href.includes("https://followeran.com/vn")) 573 // menuGenerator("vn"); 574 // else 575 // menuGenerator("sm"); 576 577 callback(); 578 }); 579}; 580 581// ? ========== Tab handler ========== 582export const tabHandler = ({tabItem, tabContent}, cb = () => {}) => { 583 jQuery(tabItem).on("click", function () { 584 let that = this; 585 586 // Active tab item 587 jQuery(tabItem).removeClass("active"); 588 jQuery(that).addClass("active"); 589 590 if (jQuery(that).hasClass("active")) { 591 jQuery(tabContent).each(function (i, item) { 592 jQuery(item).removeClass("active"); 593 594 if (jQuery(this).attr("id") == jQuery(that).data("target")) { 595 // Active tab content 596 jQuery(this).addClass("active"); 597 } 598 }); 599 } 600 }); 601 602 jQuery(`${tabItem}:first`).click(); 603 cb(tabItem); 604}; 605// ? ========== Tab handler ========== 606export const tabHandler2 = ({tabItem, tabContent}, cb = () => {}) => { 607 jQuery(tabItem).on("click", function () { 608 let that = this; 609 610 // Active tab item 611 jQuery(tabItem).removeClass("active"); 612 jQuery(that).addClass("active"); 613 614 if (jQuery(that).hasClass("active")) { 615 jQuery(tabContent).each(function (i, item) { 616 jQuery(item).removeClass("active"); 617 618 if (jQuery(this).attr("id") == jQuery(that).data("target")) { 619 // Active tab content 620 jQuery(this).addClass("active"); 621 cb(that); 622 } 623 }); 624 } 625 }); 626 627 jQuery(`${tabItem}:first`).click(); 628}; 629 630// ? ========== Is page check ========== 631export const isPage = (url = location.href == "https://followeran.com/" || location.href == "https://followeran.com") => { 632 return url; 633}; 634 635// ========== Highlight change ========== 636export const highlightChange = (target) => {
637 let color = jQuery(target).css("color"); 638 let background = jQuery(target).css("background-color"); 639 640 jQuery(target).css("background-color", "#ffff00").css("color", "#000"); 641 642 setTimeout(() => { 643 jQuery(target).css("background-color", background).css("color", color); 644 }, 2000); 645}; 646 647// ========== Check internet ========== 648export const checkInternet = () => { 649 return navigator.onLine; 650}; 651/** 652 * Converts a number to its Persian representation with comma separators for thousands. 653 * 654 * @param {number} number The number to convert 655 * @return {string} The Persian representation of the number 656 */ 657export const convertToPersianNumber = (number) => { 658 const formatter = new Intl.NumberFormat("fa", { 659 useGrouping: true, 660 style : "decimal" 661 }); 662 return formatter.format(number); 663};
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.