Enable web browser’s microphone access automatically

  const checkMicrophoneAccess = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      stream.getTracks().forEach((track) => track.stop());
      localStorage.setItem("isMicAllowed", true);
    } catch (error) {
     console.log(error)
    }
  };

while trying to turn on automatically, getting error of “NotAllowedError: Permission denied”

How can I enable microphone access in a browser automatically from a React.js frontend application without showing the browser’s default pop-up? For example, the Google Meet web application uses its own custom pop-up to manage microphone access across all browsers like Chrome, Safari etc. I need a similar flow, ideally a silent enabling process.

Laravel validate index array of object

Is there anyway to validate the index array of objects in laravel with the validator?
Here is my post data:

[
    {
        "order_id": 601696,
        "is_delay": 0,
        "ship_date": null,
        "times": 1,
        "warehouse_id": 237,
        "ship_type": 1,
        "package": [
            {
                "sku": "JD-XL102",
                "order_item_id": 772447,
                "qty": 2
            }
        ]
    },
    {
        "order_id": 601696,
        "is_delay": 0,
        "ship_date": null,
        "times": 1,
        "warehouse_id": 251,
        "ship_type": 1,
        "package": [
            {
                "sku": "JD-D16",
                "order_item_id": 772447,
                "qty": 1
            },
            {
                "sku": "JD-D16-GC",
                "order_item_id": 772448,
                "qty": 1
            }
        ]
    }
]

Then i want to validate it like this :

public function rules()
{
    return [
        '*.*.order_id'      => 'required|integer',
        '*.*.is_delay'      => 'required|boolean',
        '*.*.ship_date'     => 'nullable|datetime',
        '*.*.times'         => 'required|integer|min:1',
        '*.*.warehouse_id'  => 'required|integer',
        '*.*.ship_type'     => 'required|integer',
        '*.*.package'       => 'required|array',
        '*.*.package.*.sku' => 'required|string',
        '*.*.package.*.qty' => 'required|integer|min:1',
    ];
}

Howevere it not works.
I know i can add a prefix field to fix it, but i just want to know if laravel support the index array to validate without the prefix key?

{
    "rows": [
        {...}
    ]
}
public function rules()
{
    return [
        'row'                 => 'required|array',
        'row.*.order_id'      => 'required|integer',
        'row.*.is_delay'      => 'required|boolean',
        'row.*.ship_date'     => 'nullable|datetime',
        'row.*.times'         => 'required|integer|min:1',
        'row.*.warehouse_id'  => 'required|integer',
        'row.*.ship_type'     => 'required|integer',
        'row.*.package'       => 'required|array',
        'row.*.package.*.sku' => 'required|string',
        'row.*.package.*.qty' => 'required|integer|min:1',
    ];
}

PHP version: v7.4.33

Laravel version: v6.20.44

there is a issue occurs while creating segment


 $response = $client->lists->createSegment("46ec78750d", [
    'name' => $request->name,
    'options' => [
        'match' => 'any',
        'conditions' => [
            [
                'condition_type' => 'EmailAddress',
                'field' => 'merge0',
                'op' => 'in',
                'value' => $emails
            ]
        ]
    ]
]);

I am trying to create a segment in Mailchimp using their API. Above’s the code I’m using

However, I encounter the following error:

Error creating segment: Client error: `POST https://us12.api.mailchimp.com/3.0/lists/46ec78750d/segments`resulted in a `400 Bad Request`response: {
    "type": "https://mailchimp.com/developer/marketing/docs/errors/",
    "title": "Invalid Resource",
    "status": 400,
    "detail": "The r (truncated...)

Multiple conditions in array for comparison?

I am trying to check conditions inside foreach for a dynamic array.

My Array:

Array
(
    [0] => Array
        (
            [type] => target_id
            [operator] => Equals
            [value] => 13
            [operation] => OR
        )
    [1] => Array
        (
            [type] => target_id
            [operator] => Equals
            [value] => 14
            [operation] => OR
        )
    [2] => Array
        (
            [type] => target_id
            [operator] => Equals
            [value] => 15
            [operation] => OR
        )
)

Say I have a variable:

$target_id = 14;

I want to check this way

$override = false;

foreach($array as $key => $value){
    if($value["type"] == "target_id" && $value["operator"] == "Equals"){
        if($target_id == $value["value"]){
            $override = true;
        }
    }
}

If I generate a filter string, it would look like: 13 == 14 OR 14 == 14 OR 14 == 15

So my logic would be if(13 == 14 OR 14 == 14 OR 14 == 15)

I am not sure how to add the operation condition inside foreach. Can anyone point me to the right direction please?

Is it possible to filter woocommerce product tags programmatically?

I am using tags for some product display filtering, grouping them into specific groups. At the same time I am displaying product tags on product pages for SEO purposes so I end up with a bunch of tags that are not that good looking for the customer. Is it possible to programmatically remove them before displaying for the customer?

ChatGPT is offering a filter that does not exist or I can not find documentation for it:

function exclude_specific_tags_from_display($tags, $product) {
    // Define tags to exclude
    $excluded_tags = array('shop-by-birthday-gift-tote-bag');
    
    // Filter out the excluded tags
    $tags = array_filter($tags, function($tag) use ($excluded_tags) {
        return !in_array($tag->slug, $excluded_tags);
    });

    return $tags;
}

add_filter('woocommerce_product_get_tags', 'exclude_specific_tags_from_display', 10, 2);

And this of course does not work as expected.

Route 404 in laravel11. Is there any rule to prioritize route in web.php

My issue is, even if I added route in web.php then also it gives me 404 not found.

My route file as below.

<?php

use IlluminateSupportFacadesRoute;
use AppHttpControllersStudentController;

Route::get('/students', [StudentController::class, 'index'])->name('students.index');
Route::get('students/export/excel', [StudentController::class, 'exportExcel'])->name('students.export.excel');
Route::get('students/export/pdf', [StudentController::class, 'exportPdf'])->name('students.export.pdf');
Route::get('students/{student}', [StudentController::class, 'show'])->name('students.show');
Route::get('/students/create', [StudentController::class, 'create'])->name('students.create');
Route::post('/students/store', [StudentController::class, 'store'])->name('students.store');

If I add my route
Route::get('/students/create', [StudentController::class, 'create'])->name('students.create');
below the route
Route::get('students/{student}', [StudentController::class, 'show'])->name('students.show');
it gives me 404 and if I add my route above the
Route::get('students/{student}', [StudentController::class, 'show'])->name('students.show');
it works fine.

How is it possible? Can anyone explain this or provide the some link so I can understand the how it works?

Thanks in Advance. 🙂

How to solve scrollTrigger update problem with code used from gsap

There is a problem in the following code.
When the user refreshes in the middle or bottom of the page, transform: translate(0px, 600px); has the hero class, but when the user scrolls from the bottom to the top, transform: translate(0px, 600px);
It will not update and will transform: translate(0px, 0px); does not convert In fact, the hero class cannot return to its initial values.
This mode only occurs when the user refreshes in the middle or bottom of the page.
It’s like gsap can’t tell if the user is at the beginning or the end of the page.
To implement it, I got help from the following site (https://www.greatwalstead.co.uk/). But this site has exactly the same problem.
Is there a way to solve it?

Initial values:

translate: none;
rotate: none;
scale: none;
left: 0px;
top: 0.001px;
margin: 0px;
max-width: 654px;
width: 654px;
max-height: 545px;
height: 545px;
padding: 0px;
box-sizing: border-box;
position: fixed;
transform: translate(0px, 0px);

Secondary values ​​after running gsap:

translate: none;
rotate: none;
scale: none;
inset: 0px auto auto 0px;
margin: 0px;
max-width: 654px;
width: 654px;
max-height: 545px;
height: 545px;
padding: 0px;
transform: translate(0px, 600.001px);

document.addEventListener("DOMContentLoaded", function (e) {
  gsap.registerPlugin(ScrollTrigger);
  var t,
    a = gsap.matchMedia();
  function n(e) {
    var t = arguments.length > 1 && void 0 !== arguments[1] && arguments[1],
      a = "power3";
    e.querySelectorAll(".gs-animate").forEach(function (e) {
      var n, r,i, o, l,s,c, d,g, u,
        m = null !== (n = e.dataset.animX) && void 0 !== n && n,
        p = null !== (r = e.dataset.animY) && void 0 !== r && r,
        v = null !== (i = e.dataset.animRotate) && void 0 !== i ? i : 0,
        y =
          (e.dataset.animOpacity,
          null !== (o = e.dataset.animScale) && void 0 !== o ? o : 1),
        f = e.dataset.animOpacity ? document.querySelector(f) : e,
        h = null !== (l = e.dataset.animScrub) && void 0 !== l && l,
        S = null !== (s = e.dataset.animStart) && void 0 !== s ? s : "top 75%",
        A = null !== (c = e.dataset.animEnd) && void 0 !== c ? c : "top 25%",
        T = null !== (d = e.dataset.animDuration) && void 0 !== d ? d : 1.5,
        j = null !== (g = e.dataset.animDelay) && void 0 !== g ? g : 0,
        q = null !== (u = e.dataset.animType) && void 0 !== u ? u : "from",
        x = {
          xPercent: m,
          yPercent: p,
          rotate: v,
          scale: y,
          ease: a,
          scrollTrigger: {
            trigger: f,
            start: S,
            end: A,
            scrub: h,
            containerAnimation: t,
          },
          delay: j,
          duration: T,
        };
      "to" == q ? gsap.to(e, x) : gsap.from(e, x);
    });
  }
  (t = document.querySelector(".gs-section-intro")),
    setTimeout(function () {
      gsap.to(".js-intro-line-wrap", { scaleX: 1, delay: 1.5 });
    }, 500),
    gsap.set(".js-intro-line-scroll", { autoAlpha: 0, scaleY: 0 }),
    gsap
      .timeline({
        scrollTrigger: {
          trigger: t,
          pin: !0,
          start: "top top",
          end: "+=600",
          scrub: 1,
        },
      })
      .to(".js-intro-line", { scaleX: 4, immediateRender: !1 })
      .set(".js-intro-line-scroll", { autoAlpha: 1, immediateRender: !1 })
      .set(".js-intro-line", { autoAlpha: 0, immediateRender: !1 })
      .to(".js-intro-line-scroll", { scaleY: 1 }),
    gsap.utils.toArray(".gs-section").forEach(function (e) {
      n(e);
    });
});
.hero {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--primary-color);
    background-image: url(../img/bg-green.jpg);
    background-repeat: no-repeat;
    background-size: cover;
    color: var(--baseLight-color);
    position: relative;
    overflow: hidden;
    margin-block-end: 0 !important;
    transform: translate(0px, 0px);
}

.hero--inner {
    width: 100%;
    position: relative;
    margin-block-end: 3rem;
}

.hero--content {
    width: 50%;
    margin-inline: auto;
}

.hero--content>picture>img {
    margin-inline: auto;
    display: block;
    width: 140px;
    height: 180px;
}


/* for animate line */
.hero--line__wrap {
    width: 100vw;
    height: 50vh;
    z-index: 10;
    position: absolute;
    left: 0;
    right: 0;
    top: 110%;
    overflow: hidden;
    transform-origin: center;
}

.hero--line {
    position: absolute;
    margin-left: auto;
    margin-right: auto;
    top: 0;
    left: 0;
    right: 0;
    display: block;
    height: 9px;
    width: 40%;
    overflow: hidden;
    transform-origin: center;
}

.hero--line:after {
    animation: moveline 3s linear infinite;
    background-image: url(../img/intro-line-sm.svg);
    background-repeat: repeat-x;
    background-size: 50% 100%;
    content: "";
    display: block;
    height: 100%;
    width: 200%;
}

.hero--line__bg {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    height: 100%;
    transform-origin: top;
    background-image: url(../img/intro-line.svg);
    background-position: top;
    background-size: 100% 100%;
    opacity: 0;
    visibility: hidden;
}

/* hero scroll */
.hero--scroll {
    position: absolute;
    left: 50%;
    bottom: 1rem;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
}

.hero--scroll__border {
    display: block;
    padding: .5rem;
    width: 2.5rem;
    height: 4rem;
    border: 2px solid #f6be56;
    border-radius: var(--border-radius30);
}


.hero--scroll__circle {
    display: block;
    margin-inline: auto;
    width: 1rem;
    height: 1rem;
    border-radius: 50%;
    background-color: #5f9893;
    animation: mouse 1000ms linear infinite;
    transition-timing-function: cubic-bezier(.33, 1, .68, 1);
}

.introduction {
    position: relative;
    padding-bottom: 10rem;
    background-color: var(--secondary-color);
}

.introduction::before {
    position: absolute;
    content: "";
    left: 20px;
    top: -100px;
    width: 250px;
    height: 182px;
    border: 1px solid green;
    background-image: url(/assets/img/vector-leaf.svg);
    background-repeat: no-repeat;
}

/* introduction--item */
ul li.introduction--item {
    overflow: hidden;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-block: 6rem;
}

ul li.introduction--item:nth-child(odd) {
    flex-direction: row;
}

ul li.introduction--item:nth-child(even) {
    flex-direction: row-reverse;
}

/* introduction--text */
.introduction--text {
    color: var(--text-color);
    position: relative;
    width: 45%;
    padding-inline: 5rem 0;
    position: relative;
}

.introduction--text .introduction--title {
    display: flex;
    align-items: center;
}

.introduction--text .introduction--title h3 {
    overflow: hidden;
    display: inline-block;
    overflow: hidden;
    line-height: var(--line-height140);
}

.introduction--text .introduction--title__line{
    width:85%;
    position: absolute;
    top: 20%;
    overflow: hidden;
}

.introduction--text .introduction--title__line::after {
    animation: moveline 3s linear infinite;
    background-image: url(../img/intro-line-sm-white.svg);
    background-repeat: repeat-x;
    background-size: 50% 100%;
    content: "";
    display: block;
    height: 9px;
    width: 200%;
}


.introduction--text>div {
    margin-block: 2.5rem 2rem;
    text-align: justify;
    font-weight: 500;
    line-height: var(--line-height140);
}

/* .introduction--video */
.introduction--video {
    width: 55%;
    position: relative;
}

ul li.introduction--item:nth-child(odd) .introduction--video {
    left: -10%;
}

ul li.introduction--item:nth-child(even) .introduction--video {
    right: -10%;
}

.introduction--video>.introduction--video__inner {
    position: relative;
    padding: 1.5rem;
}

ul li.introduction--item:nth-child(odd) .introduction--video>.introduction--video__inner {
    transform: rotate(-13deg);
}

ul li.introduction--item:nth-child(even) .introduction--video>.introduction--video__inner {
    transform: rotate(13deg);
}

ul li.introduction--item .introduction--video>.introduction--video__inner::after {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    background-image: url(/assets/img/border-video-white.svg);
    background-repeat: no-repeat;
    background-size: contain;
    z-index: -1;
}


.introduction--video>.introduction--video__inner video {
    border-radius: 50px;
    width: 100%;
    height: 100%;
}

.introduction--video>.introduction--video__inner .play--video {
    position: absolute;
    top: 82%;
    left: 50%;
    cursor: pointer;
    transform: translateX(-50%) rotate(10deg);
}

/* introduction--gif */
ul li.introduction--item .introduction--gif {
    display: block;
}

ul li.introduction--item:nth-child(odd) .introduction--gif {
    margin-inline-start: auto;
    margin-inline-end: 2rem;
}

ul li.introduction--item:nth-child(even) .introduction--gif {
    margin-inline-start: auto;
    margin-inline-end: 5rem;
}

.introduction--arrow {
    position: absolute;
    right: 45%;
    width: 10rem;
    transform-origin: right;
    bottom: 2rem;
}

.introduction--arrow>img {
    width: 100%;
}

/* vectors */
ul li.introduction--item:nth-child(1) .introduction--text::before {
    position: absolute;
    content: "";
    bottom: -50px;
    left: 50%;
    width: 90px;
    height: 93px;
    background-repeat: no-repeat;
    background-image: url(../img/vector-diamond.svg);
}

ul li.introduction--item:nth-child(1) .introduction--video::before {
    position: absolute;
    content: "";
    bottom: -20px;
    left: 75%;
    width: 214px;
    height: 100px;
    background-repeat: no-repeat;
    background-image: url(../img/vector-line.svg);
}

ul li.introduction--item:nth-child(2)::before {
    position: absolute;
    content: "";
    top: 0;
    right: -5px;
    width: 84px;
    height: 85px;
    background-repeat: no-repeat;
    background-image: url(../img/vector-star.svg);
}

ul li.introduction--item:nth-child(3)::before {
    position: absolute;
    content: "";
    top: 10px;
    left: 30px;
    width: 110px;
    height: 99px;
    background-repeat: no-repeat;
    background-image: url(../img/vector-circle-untidy.svg);
}
      <section class="gs-section-intro hero">
        <div class="hero--inner">
          <!-- hero content -->
          <div class="hero--content">
            <picture>
              <img src="/assets/img/logo-hero.svg" alt="" />
            </picture>
          </div>

          <!-- for animate line -->
          <div class="hero--line__wrap js-intro-line-wrap">
            <span class="hero--line js-intro-line"></span>
            <span class="hero--line__bg js-intro-line-scroll"></span>
          </div>
        </div>

        <!-- scroll down -->
        <div class="hero--scroll">
          <span class="hero--scroll__border">
            <span class="hero--scroll__circle"></span>
          </span>
        </div>

      </section>
      
      <section class="introduction gs-section" data-gs-type="items">
        <ul>
          <li class="introduction--item">
            <div
              class="introduction--text gs-animate"
              data-anim-x="150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--title">
                <img src="/assets/img/vector-title-white.svg" alt="" />
                </div>
              <span class="introduction--title__line"></span>

              <div>
...
              </div>
              <img
                src="/assets/img/GWS_hockey-girl.png"
                alt=""
                class="introduction--gif"
              />
            </div>

            <div
              class="introduction--video gs-animate"
              data-anim-x="-150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--video__inner">
               ...
              </div>              
            </div>
          </li>

          <li class="introduction--item">
            <div
              class="introduction--text gs-animate"
              data-anim-x="-150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--title">
                <img src="/assets/img/vector-title-white.svg" alt="" />
              </div>
              <span class="introduction--title__line"></span>

              <div>...</div>

              <a href="" class="btn btn--fill">درباره درخت دانش</a>

              <img
                src="/assets/img/GWS_football-boy.png"
                alt=""
                class="introduction--gif"
              />
            </div>

            <div
              class="introduction--video gs-animate"
              data-anim-x="150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--video__inner">...</div>
            </div>

            <div
              class="introduction--arrow gs-animate"
              data-anim-scale="0"
              data-anim-start="top bottom"
              data-anim-scrub="1"
            >
              <img
                src="/assets/img/icons/arrow-white-left.svg"
                alt="Arrow"
                loading="lazy"
              />
            </div>
          </li>

          <li class="introduction--item">
            <div
              class="introduction--text gs-animate"
              data-anim-x="150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--title">
                <img src="/assets/img/vector-title-white.svg" alt="" />
              </div>

              <span class="introduction--title__line"></span>

              <div> ...</div>

              <img
                src="/assets/img/kindergarten.png"
                alt=""
                class="introduction--gif"
              />
            </div>

            <div
              class="introduction--video gs-animate"
              data-anim-x="-150"
              data-anim-scrub="1"
              data-anim-start="top bottom"
            >
              <div class="introduction--video__inner"> ...</div>
            </div>
          </li>
        </ul>
      </section>

How to improve EventEmitter event notification function?

I wrote the following EventEmitter class, and it works great so far. But today I came across a scenario where if event listeners are created and destroyed frequently, and the off function is not used to remove the listener, there will be potential performance issues. How can I optimize this problem? Can anyone give me some ideas?

class EventEmitter {

    private listeners: Record<string, [Set<Function>, Set<Function>]> = {};

    existsEvent(eventName: string | number) {
        return !!this.listeners[eventName];
    }

    on(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            this.listeners[eventName] = [new Set(), new Set()];
        }
        this.listeners[eventName][0].add(listener);
    }

    once(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            this.listeners[eventName] = [new Set(), new Set()];
        }
        this.listeners[eventName][1].add(listener);
    }

    emit(eventName: string | number, ...args: any[]) {
        if (!this.listeners[eventName]) {
            return
        }

        this.listeners[eventName][0].forEach((listener: Function) => {
            listener(...args);
        });
        
        this.listeners[eventName][1].forEach((listener: Function) => {
            listener(...args);
        });
        this.listeners[eventName][1].clear();
    }

    off(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            return;
        }
        if (typeof listener === 'function') {
            this.listeners[eventName][0].delete(listener);
            this.listeners[eventName][1].delete(listener);
        } else {
            this.listeners[eventName][0].clear();
            this.listeners[eventName][1].clear();
        }
    }
}

export const eventEmitter = new EventEmitter();

xterm.js generates full row of characters before writeln output

While experimenting with xterm.js I made the follwing fiddle.

const divTerm = document.querySelector("#term");

const xterm = new Terminal({
cols: 100,
rows: 80,
cursorBlink: true
});

xterm.open(divTerm);
xterm.writeln("Hello World");

jsfiddle output

As you can see, I am only writing “Hello World” to my terminal.
However, the “Hello World” String is only displayed on the second row of the terminal. The row above is filled with ‘d’s, and I don’t understand where they are coming from.

The weird thing is, when I did the same thing on my test site instead on jsfiddle, the behaviour was the same, except the first row was filled with ‘s’ characters.

What’s going on here?

How can we change a pie-doughnut chart into an arrow ring chart?

Currently I’ve below design in echarts apache

enter image description here

and i want as below pie doughnut chart with arrows inside

enter image description here

Here is my current code:

var data = [
  { name: 'Label 1 n', value: 16.67, },
  { name: 'Label 2 n', value: 16.67, },
  { name: 'Label 3 n', value: 16.67, },
  { name: 'Label 4 n', value: 16.67, },
  { name: 'Label 5 n', value: 16.67, },
  { name: 'Label 6 n', value: 16.67, },
];

option = {
  series: {
    type: "pie",
    radius: ['50%', '70%'],
    left:"center",
    data: data,
  }
};

visibilitychange not firing on app switch on macOS

visibilitychange event is not fired when switching between apps when the window is not maximized.

I have pasted this code block in the console. While this is working on tab change, it is not triggering on app switch ( not maximised )

window.addEventListener('visibilitychange', () => console.log('triggered'), {capture:true});

Dispatch event not working during page route

I’m working on a Angular 14 application in which on a specific scenario where the page load gets the current date (selected from a datepicker) and pass it to the backend to get the data .

In this case the I trigger the datachange event manually in ngOnInit which works on page load or refresh but the event doesn’t get fired when the internal navigation/route happens.

//HTML
<input type="date" id="bookedDate" formControlName="bookedDate" [min]="getToday" (change)="changeDate($event)" />
    
//Typescript
ngOnInit(): void{
const inputElement = document.getElementId('bookedDate) as HTMLInputElement;
if(inputElement){
    this.ngZone.runOutsideAngular(() => {
    setTimeout(() => {
      const event = new Event(çhange', {bubbles: true});
      //this gets fired in pagerefresh or navigation
      inputElement.dispatchEvent(event);
      });
    });
  }
}
    
changeDate(e:any){
  // this event not firing on page navigation
}

Tried multiple options using ngAfterViewInit, Router/Route events subscription but nothing helped.

Where am i wrong?

How to force instagram to redirect a link from instagram app to safari using javascript

I am trying to force instagram to redirect a link to safari using Javascript.

I have depployed the below code on netlify and using the hosted link on my instagram bio. Would want the appclip to open on safari from the instagram web-view.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Redirecting...</title>
    <script>
        document.addEventListener("DOMContentLoaded", () => {
            const userAgent = navigator.userAgent || navigator.vendor || window.opera;
            console.log("User Agent:", userAgent);
            
            const url = "https://xplr.live/p2bdafhuw";
            const playstore = "https://play.google.com/store/apps/details?id=com.xircular.xplorecampaign&campaignId=043a10ed-79c6-4b3d-8c16-7ab9d72e96d8&launch=true";
            const appcliplink = "https://appclip.apple.com/id?p=com.xircular.XplorePromote.Clip&campaignId=043a10ed-79c6-4b3d-8c16-7ab9d72e96d8";

            if (/Instagram/i.test(userAgent)) {
                if (/android/i.test(userAgent)) {
                    // Redirect for Android using intent scheme
                    window.location.href = intent:${playstore}#Intent;package=com.android.chrome;end;
                } else if (/iPhone|iPad|iPod/i.test(userAgent)) {
                    // Attempt to open the App Clip link directly in Safari
                    setTimeout(() => {
                        window.location.href = appcliplink;
                    }, 100);
                } else {
                    // Handle other platforms
                    alert("Other platform detected.");
                    window.location.href = url;
                }
            } else {
                // Redirect to the URL directly for non-Instagram browsers
                window.location.href = url;
            }
        });
    </script>
</head>
<body>
    <h1>Redirecting...</h1>
    <h2>I should not see this screen</h2>
</body>
</html>

Sync vs Async function execution time confusion [duplicate]

I am struggling to understand why an asynchronous function with some calculations takes such a long time to execute. I have simplified my code like so:

const syncCalc = () => {
    let v = 0;
    for (let i = 1; i < 10000000; i++) {
        //emtpy loop
        v += i
    }
    return v;
}

const asyncCalc = () =>
    new Promise(resolve => {
        let v = 0;
        for (let i = 1; i < 10000000; i++) {
            //emtpy loop
            v += i
        }
        resolve(v);
    })


console.time('syncCalc');
console.log("Result:", syncCalc());
console.timeEnd('syncCalc');

console.log('------------')

console.time('asyncCalc');
asyncCalc().then(v => console.log("Result:", v));
console.timeEnd('asyncCalc');

The result of the above code run in node is:

Result: 49999995000000
syncCalc: 27.659ms
------------
asyncCalc: 14.152ms
Result: 49999995000000

The first part (i.e. 27 ms) makes perfect sense. It takes a while for the calculation to finish in a synchronous environment.

What I don’t get is why it takes 14 ms to get past the asyncCalc function. Shouldn’t the jump from console.time('asyncCalc'); to console.timeEnd('asyncCalc'); be instant as we DO NOT wait for the asyncCalc().then(... to execute?

Why, then, does this take under a millisecond to get from time to timeEnd?

const asyncTimeout = () =>
    new Promise(resolve => {
        setTimeout(() => resolve(49999995000000), 1000)
    })

console.time('asyncCalc');
asyncTimeout().then(v => console.log("Result:", v));
console.timeEnd('asyncCalc');

// asyncCalc: 0.962ms
// Result: 49999995000000


Can someone explain this to me please?

How to synchronize two or more graphics with converFromPixel in same echarts.instance?

I have two dot graphics (scatter) and I need to move the mouse (mousemove) over one of them and pass the tooltip effect to the other. That is, when I move the mouse over series[0], the tooltip must also appear in series[1] and vice versa. I tried synchronizing the charts with chartUSe.getZr().on(...) but I couldn’t get it to work. Also, it wouldn’t be interesting to use echarts.connect to do this, as I need the charts to be in the same instance.

Code:

document.addEventListener('DOMContentLoaded', function() {

    // system
    const chartSystem = () => {

        const dfInit = () => {
            
            const groups = ['group1', 'group2', 'group3'];

            const data = [];

            for (let i = 0; i < 30; i++) {
                data.push(
                    [
                        (Math.random() * 101) | 0,
                        (Math.random() * 101) | 0,
                        groups[(Math.random() * groups.length) | 0]
                    ]
                )
            }
            return data;
        }

        return {
            "source": {
                "first": dfInit()
            }
        };

    }

    // send
    let pullDataset = [];

    const chartSend = () => {

        const { first } = chartSystem().source;

        pullDataset.push(
            {
                source: [
                    ["x1", "x2", "groups"],
                    ...first
                ]
            }
        )

    }

    chartSend();

    // frames
    const chartUse = echarts.init(document.getElementsByClassName('chart')[0]);

    function chartFrameSwitch0 () {

        const title0 = [
            {
                text: "convertFromPixel in same instance (chartUse)",
                left: 'center',
                textStyle: {
                    fontSize: 30,
                    color: "#242832"
                }
            }
        ];

        const tooltip0 = {
            trigger: "axis"
        };

        const grid0 = [
            {
                left: '5%',
                top: '12%',
                width: '40%',
                height: '35%'
            },
            {
                right: '5%',
                top: '12%',
                width: '40%',
                height: '35%'
            }
        ];

        const xAxis0 = [
            {
                type: 'value',
                gridIndex: 0
            },
            {
                type: 'value',
                gridIndex: 1
            }
        ];

        const yAxis0 = [
            {
                type: 'value',
                gridIndex: 0
            },
            {
                type: 'value',
                gridIndex: 1
            }
        ];

        const series0 = [
            {
                type: 'scatter',
                datasetIndex: 0,
                xAxisIndex: 0,
                yAxisIndex: 0,
                encode: {
                    x: 0,
                    y: 1
                }
            },
            {
                type: 'scatter',
                datasetIndex: 0,
                xAxisIndex: 1,
                yAxisIndex: 1,
                encode: {
                    x: 0,
                    y: 1
                }
            }
        ];

        const option = {
            title: title0,
            tooltip: tooltip0,
            grid: grid0,
            dataset: [pullDataset[0]],
            xAxis: xAxis0,
            yAxis: yAxis0,
            series: series0
        };

        chartUse.setOption(option);

    }

    chartFrameSwitch0();

    // Charts synchronize 
    chartUse.getZr().on('mousemove', function(params) {

        // Catch mousemove event
        let pointInGrid = [params.offsetX, params.offsetY];

        // series 0 interaction
        if (params.seriesIndex === 0) {

            let index = chartUse.convertFromPixel({ seriesIndex: 0 }, pointInGrid)[0];

            // Checks if the index is within the data range
            if (index >= 0 && index < pullDataset[0].source.length) {

                chartUse.dispatchAction({
                    type: 'showTip',
                    seriesIndex: 1,
                    dataIndex: index
                });

            }

        } 
        
        // series 1 interaction
        else if (params.seriesIndex === 1) {

            let index = chartUse.convertFromPixel({ seriesIndex: 1 }, pointInGrid)[0];

            // Checks if the index is within the data range
            if (index >= 0 && index < pullDataset[0].source.length) {

                chartUse.dispatchAction({
                    type: 'showTip',
                    seriesIndex: 0,
                    dataIndex: index
                });

            }

        }
        
    });


});
<head>
    <script src='https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js'></script>
</head>
    
<div class='chart' style='width: 100%; height: 100vh;'></div>