How to manage Page elements in Angular 19 in the right way?

I am trying to learn Angular 19. Every thing was pretty good until i started trying to manipulate the elements on the Page. I hope someone will help me to understand the idea of it in Angular.

Example

I have list on page and i just want to add and remove new items of this list

List of fruits +

  • apple x
  • banana x

On pressing + i want add new item to the end of the list (the name of item or another content does not matter, just add new item).

On pressing x i want to delete corresponding item from the list.

in JavaScript

If i need to change page structure using native JavaScript, i must use:

  • document.querySelector()
  • node.append()
  • node.remove()
  • and so on…
    this tools allow me to create, add, remove and change HTML elements.

So i must:

// this is simple example without using classes

let list = document.querySelector('.listOfFruits');
let newItem= document.createElement('li');
newItem.innerHTML = 'orange';

list.append(newItem);

//another code to remove item and so own

in Angular 19

What should i use?

I learned:

  • @if
  • @for
  • NgComponentOutlet
  • ViewContainerRef

But it is not seems to be the right way to do what i want to do. And i can not find any other information in Docs with full explanation how this kind of things has to be done in Angular.

Someone, please, give me full explanation.

Thank you.

How to use scrollTrigger in gsap to solve the problem of updating and converting to the initial state

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>
              <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 interact with the elements of website made in Reactjs?

I am trying to focus on a div with role textbox on a website made in reactjs but nothing is working.

I have tried this:

async function focusOnElement(selector) {
  let element = undefined;
  while (!element) {
    element = Array.from(document.querySelectorAll(selector)).at(-1);
    await delay(1000);
  }
  if (!element) {
    console.warn("Element not found for focusing.");
    return;
  }

  element.focus();
  
 
  const focusEvent = new Event("focus", { bubbles: true, cancelable: true });
  element.dispatchEvent(focusEvent);

  console.log(`Focused on element: ${selector}`);
}

But it didn’t work.
I have also tried this:

async function focusOnElement(selector) {
  let element = undefined;
  while (!element) {
    element = Array.from(document.querySelectorAll(selector)).at(-1);
    await delay(1000); // Wait for the element to exist
  }
  if (!element) {
    console.warn("Element not found for focusing.");
    return;
  }

  // Focus on the element explicitly
  element.focus();

  // Manually trigger React's synthetic focus event
  const reactKey = Object.keys(element).find(
    (key) =>
      key.startsWith("_reactProps$") || key.startsWith("_reactFiber$")
  );

  if (reactKey) {
    const props = element[reactKey];
    if (props && props.onFocus) {
      // Dispatch a synthetic focus event that React can handle
      props.onFocus({
        target: element,
        currentTarget: element,
        bubbles: true,
        cancelable: true,
      });
    }
  }

  console.log(`Focused on element: ${selector}`);
}

But still cant focus

Website is https://outlook.live.com/mail/0/options/mail/rules click on Add new rule and on condition select From and the div that i want to focus on will be visible

Javafx WebEngine javascript exception

In my JavaFX WebView application an upcall member is injected into the HTML document that will trigger an upcall to Java when certain SVG images are toggled by a mouse click.

 ( (JSObject)webEngine.executeScript( "window" ) )
            .setMember( "selector", this );

The document itself defines a script that toggles other SVG images on and off. This is called by

webEngine.executeScript("toggle(json)");

in response to the upcall.

The whole operation is invoked on the application thread. If I test the upcall by itself without invoking the script there is no problem. However, when invoking the script, the operation succeeds but a javascript error is generated to the effect that the upcall object is null. This seems to indicate an issue in WebView with having two javascript functions defined in the same file. Can anyone share experience with this issue?

JavaScript Canvas arc drawing behaves inconsistently

I’m struggling to have arcs drawn on a canvas as, to my eyes, the method context.arc appears to behave differently than what the specifications claim (or I understood from them).

Following is a piece of code I’m using to draw:

  1. A small dotted circle centered at the same coordinates the arc needs to be centered,
  2. An arc to cover 45 degrees (it does not!!)

In the picture included (after the code) the console part shows the printouts of the used values for the arc function.

    l_Context.moveTo(l_Arc_Center_X, l_Arc_Center_Y) ;
    l_Context.beginPath();
    l_Context.setLineDash([2,2])
    l_Context.arc(l_Arc_Center_X, l_Arc_Center_Y, 5 , 0 , 2 * G_PI , true);
    l_Context.stroke();
    l_Context.closePath() ;
    
    l_Context.beginPath();
    l_Context.setLineDash([])
    console.log("l_Arc_Center_X                          : " + l_Arc_Center_X)
    console.log("l_Arc_Center_Y                          : " + l_Arc_Center_Y)
    console.log("p_Radius [cm]                           : " + p_Radius      )
    console.log("l_Start_Angle                           : " + l_Start_Angle )
    console.log("F_Convert_Degrees_to_Rads(l_Start_Angle): " + F_Convert_Degrees_to_Rads(l_Start_Angle))
    console.log("l_End_Angle                             : " + l_End_Angle)
    console.log("F_Convert_Degrees_to_Rads(l_End_Angle)  : " + F_Convert_Degrees_to_Rads(l_End_Angle))
    console.log("l_CCW                                   : " + l_CCW)

    l_Context.arc(l_Arc_Center_X, l_Arc_Center_Y, F_Convert_Lengh_from_cm_to_Map(p_Radius) , F_Convert_Degrees_to_Rads(l_Start_Angle) , F_Convert_Degrees_to_Rads(l_End_Angle) , l_CCW);
    l_Context.stroke();
    l_Context.closePath() ;

Note: Functions like F_Convert_Degrees_to_Rads are used to convert from metric dimensions and degrees to canvas values.

As the code shows, I’m drawing a small dotted circle whose center coincides with that of the arc I’m attempting to draw.

The following picture shows the result along with the console where the values of the parameters (to the “arc” function) are presented.

enter image description here

So, instead of getting a 45 degrees arc (from 45 to 90 degrees) I’m getting what remains to complete a whole circle and at the wrong angles (i.e. the complement of what I wish).

What am I doing wrong?

Thanks.

Inconsistent CSS animation using JavaScript in response to a click event listener

I’m working on a routine that reorders a set of div on an HTML page using JavaScript. The re-ordering is working correctly.

To add some visual feedback when the div moves, I’m using a CSS animation (and keyframes) class that gets added

Each div has an up and down arrow with an event listener.

The “Up” functionality works every time. The “Down” functionality works exactly once, unless the Up button is used, in which case the Down functionality is reset and works just once again.

The entire experiment is in a self-contained PHP file:

<?php
    ini_set('display_errors', 1);
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <title>Reorder List</title>
    <style>
        .component {
            margin-bottom: 4px;
            font-size: 16px;
            border: 1px solid black;
            border-radius: 5px;
        }

        .component button {
            margin: 2px;
            padding: 2px;
            border-radius: 5px;
            border: 1px solid grey;
            font-size: 24px;
        }

        .component span {
            margin-left: 10px;
        }

        .container {
            border: 1px solid red;
            padding: 5px;
            border-radius: 5px;
        }

        .internal {
            clear: both;
            display: block;
            margin-left: 15px;
        }

        .fade-in {
            animation: fadeIn 1s ease-in-out;
        }

        @keyframes fadeIn {
            from {
                opacity: 0;
            }
            to {
                opacity: 1;
            }
        }

    </style>
</head>
<body>

<p>[<a href="/experiments/">Experiments Home</a>]</p>

<p>This page demonstrates: </p>

<ol>
    <li>Reordering child divs of a parent div using JavaScript.</li>
    <li>The order set by JavaScript is retained in a POST request.</li>
</ol>

<?php

$colors = [
    "red" => "RED",
    "green" => "GREEN",
    "cyan" => "CYAN",
    "darkmagenta" => "DARK MAGENTA",
    "blue" => "BLUE",
    "darksalmon" => "DARK SALMON",
    "lightcoral" => "LIGHT CORAL",
    "mediumspringgreen" => "MEDIUM SPRING GREEN",
    "indigo" => "INDIGO"
];

if ( $_POST ) {
    $colorlist = $_POST;
} else {
    $colorlist = $colors;
} // end else

?>

    <form method="post" action="reorder_list.php">
    <div class="container" id="list">

    <?php
    $i = 0;
    foreach ($colorlist as $key => $value) {
        $i++;
    ?>

        <div class="component">
            <button class="up material-icons">arrow_upward</button>
            <button class="down material-icons">arrow_downward</button>
            <input type="hidden" name="<?= $key ?>" value="<?= $value ?>">
            <p class="internal" style="color: <?= $key ?>"><?= $i . ". " . $value ?></p>
            <p class="internal">Here is another paragraph</p>
            <p class="internal"><label for="name">Here is a form element</label> <input type="text" id="name" name="name"></p>
            <p class="internal">And yet another paragraph</p>
        </div>
    <?php
    } // end foreach  ?>
    </div>

    <p><input type="submit"></p>
    </form>


<script>
    document.querySelectorAll('.up').forEach(button => {
        button.addEventListener('click', function(event) {
            once: true;
            event.preventDefault();
            const el = button.parentElement;
            const prevEl = el.previousElementSibling;
            if (prevEl) {
                el.parentNode.insertBefore(el, prevEl);
                //el.classList.remove('fade-in');
                el.classList.add('fade-in');
                //setTimeout(el.classList.remove('fade-in'), 3000);
            }
        });
    });

    document.querySelectorAll('.down').forEach(button => {
        button.addEventListener('click', function(event) {
            once: true;
            event.preventDefault();
            const el = button.parentElement;
            const nextEl = el.nextElementSibling;
            if (nextEl) {
                el.parentNode.insertBefore(nextEl, el);
                //el.classList.remove('fade-in');
                el.classList.add('fade-in');
                //setTimeout(el.classList.remove('fade-in'), 3000);
            }
        });
    });
</script>


<h1>Original Order</h1>
<ul id="list">
<?php
$i = 0;
foreach ($colors as $key => $value) {
    $i++;
?>
    <li class="list-item"><span style="color: <?= $key; ?>"><?= $i . ". " . $value ?></span></li>
<?php
}
?>

</ul>

</body>
</html>

I have tried using setTimeOut to remove the animation class which disables the Up and Down functionally completely. (You can see the attempt commented out in the code)

I also tried removing the animation class before adding it back in.

I tried adding once: true to the event

The goal is to get both Up and Down functionality working consistently.

Why useParams and useNavigate in react router does unnecessary re-renders?

I would like to ask for your assistance in understanding why I am experiencing unnecessary re-rendering of the component every time I click on the same link. This issue seems to be caused by the use of the useParams and useNavigate hooks. I’m just worry it can cause app performance cuz re-render happen in parent component

here a short case demonstration

Parent component:

export const Conversation = () => {
    // const { id } = useParams() as { id: string };
    
    const setChat = useChat((state) => state.actions.setChat);
    // const navigate = useNavigate();
    
    const { isLoading, isError, isRefetching, refetch, data } = useQuery(({ signal }) => conversationApi.get('67096041d913474deb2ea5bc', signal), {
        keys: [],
        retry: 5,
        retryDelay: 2000,
        onSelect: ({ messages, ...data }) => data,
        onSuccess: ({ messages }) => {
            setChat({
                messages,
                params: {
                    id: '67096041d913474deb2ea5bc',
                    type: SourceRefPath.CONVERSATION,
                    query: { recipientId: '67096041d913474deb2ea5bc', session_id: useSocket.getState().session_id }
                }
            });
        },
    });

    if (isLoading) return <ChatSkeleton />;

    if (isError) {
        return (
            <OutletError
                title='Something went wrong'
                description='Cannot load conversation'
                callToAction={
                    <Button onClick={refetch} className='mt-5' disabled={isRefetching}>
                        {isRefetching ? <Loader2 className='w-6 h-6 animate-spin' /> : 'try again'}
                    </Button>
                }
            />
        );
    }

    return (
        // <ConversationProvider conversation={data}>
            <Content />
        // </ConversationProvider>
    );
};

Content:

export const Content = () => {
    // const { _id, isInitiatorBlocked, isRecipientBlocked, recipient, isRecipientTyping, handleTypingStatus } = useConversation(useShallow(contentSelector));

    const showDetails = useChat((state) => state.showDetails);
    // const description = getConversationDescription({ data: { recipient, isInitiatorBlocked, isRecipientBlocked }, isRecipientTyping });
console.log('rerender')
    return (
        <OutletContainer>
            test
            {/* <div className='flex-1 flex flex-col'>
                <OutletHeader
                    name={recipient.name}
                    isOfficial={recipient.isOfficial}
                    description={description}
                    dropdownMenu={<ConversationDDM />}
                />
                <MessagesList getPreviousMessages={(id, cursor) => conversationApi.getPreviousMessages(id, cursor)} />
                <SendMessage
                    handleTypingStatus={handleTypingStatus()}
                    restrictMessaging={[
                        {
                            reason: !!(isInitiatorBlocked || isRecipientBlocked),
                            message: isRecipientBlocked ? `You blocked ${recipient.name}` : `${recipient.name} has restricted incoming messages`
                        },
                        {
                            reason: !_id && recipient.isPrivate,
                            message: `${recipient.name} does not accept new messages`
                        }
                    ]}
                />
            </div>
            {showDetails && (
                <OutletDetails
                    title='User Info'
                    name={recipient.name}
                    avatarUrl={recipient.avatar?.url}
                    description={description}
                    info={[
                        { data: recipient.status, type: OutletDetailsTypes.BIO },
                        { data: recipient.login, type: OutletDetailsTypes.LOGIN },
                    ]}
                />
            )} */}
        </OutletContainer>
    );
};

NavLink i use to navigate:

export const ConversationItem = ({ feedItem: { item } }: { feedItem: ExctactLocalFeedItem<FeedTypes.CONVERSATION> }) => {
    const recipient = item.recipient;
    const draft = useLayout((state) => state.drafts).get(recipient._id);

    return (
        <li>
            <NavLink
                to={`/conversation/${recipient._id}`}
                className={({ isActive }) =>
                    cn(
                        'flex items-center gap-5 p-2 rounded-lg transition-colors duration-200 ease-in-out',
                        isActive
                            ? 'dark:bg-primary-dark-50 bg-primary-gray/10'
                            : 'dark:hover:bg-primary-dark-50/30 hover:bg-primary-gray/5'
                    )
                }
            >
                {recipient.avatar ? (
                    <span className='relative w-[50px] h-[50px]'>
                        <Image
                            src={recipient.avatar.url}
                            skeleton={<AvatarByName name={recipient.name} size='lg' />}
                            className='object-cover object-center min-w-[50px] max-w-[50px] h-[50px] rounded-full'
                        />
                        {recipient.presence === PRESENCE.ONLINE && <ProfileIndicator />}
                    </span>
                ) : (
                    <AvatarByName name={recipient.name} size='lg' isOnline={recipient.presence === PRESENCE.ONLINE} />
                )}
                <div className='flex flex-col items-start w-full overflow-hidden'>
                    <Typography
                        as='h2'
                        weight='medium'
                        className='flex w-full items-center'
                    >
                        {recipient.name}
                        {recipient.isOfficial && (
                            <Typography className='ml-2'>
                                <Verified className='w-5 h-5' />
                            </Typography>
                        )}
                        {!!item.unreadMessages && (
                            <span className='text-primary-dark-200 font-semibold text-sm flex items-center justify-center ml-auto size-5 rounded-full bg-primary-white'>
                                {item.unreadMessages}
                            </span>
                        )}
                    </Typography>
                    {!!item.participantsTyping?.length ? (
                        <Typography as='p' variant='secondary' className='line-clamp-1'>
                            typing...
                        </Typography>
                    ) : draft?.state === 'send' ? (
                        <Typography as='p' variant='secondary' className='line-clamp-1 break-all'>
                            <Typography as='span' variant='error'>
                                Draft:&nbsp;
                            </Typography>
                            {draft.value}
                        </Typography>
                    ) : (
                        !!item.lastMessage && (
                            <div className='flex items-center w-full gap-5'>
                                <Typography className='break-all dark:text-primary-white/30 text-primary-gray line-clamp-1'>
                                    {item.lastMessage?.text}
                                </Typography>
                                <Typography className='ml-auto' variant='secondary'>
                                    {new Date(item.lastMessage.createdAt).toLocaleTimeString(navigator.language, {
                                        hour: 'numeric',
                                        minute: 'numeric'
                                    })}
                                </Typography>
                            </div>
                        )
                    )}
                </div>
            </NavLink>
        </li>
    );
};

Failed to redirecter to a page after submitting a html formular

sorry it’s me again, I’ve been trying to use PHP to redirect the user to home.html after submitting a form, but instead of being redirected, I’m getting a blank page. The two files (.php and .html) are in the same directory, so I don’t understand why the redirection isn’t working as expected.

I believe my code is correct, but I’m not sure why it’s still not working. I need to fix this issue for a project I’m working on, so I would really appreciate any help.

Here’s what I’ve tried:
Form HTML: The HTML form is designed to collect user data like name, email, password, etc. It uses POST to send the data to a PHP script (which is the current page).

PHP Script (Processing Form): In my PHP script, after processing the form and checking for errors (such as missing fields or incorrect password confirmation), I attempt to redirect the user to home.html using header(‘Location: home.html’);.

Problem: Instead of being redirected to home.html, the browser shows a blank page. The form is processed, but no redirection occurs. sorry for asking the same question 2 times in a row ,but i need it for my homework,and i am a newbie as you can see, so yeah i don’t know what to do anymore.

I’m using header(‘Location: home.html’); after checking the form data, but it’s not redirecting properly.
I’ve checked that the PHP script is in the same folder as home.html, so path issues shouldn’t be the problem.
I’ve tried calling exit(); after the header() function, but it still doesn’t work.
There’s no output before the header() call, as I make sure to only send the header first before any HTML content.
Here is the html form:

<form method="post" action="procesare_formular.php">
    <div>
        <label for="nume">Name</label>
        <input type="text" name="nume" id="nume" placeholder="Enter name" required>
    </div>
    <div>
        <label for="prenume">Surname</label>
        <input type="text" name="prenume" id="prenume" placeholder="Enter surname" required>
    </div>
    <div>
        <label for="email">Email</label>
        <input type="email" name="email" id="email" placeholder="Enter email" required>
    </div>
    <div>
        <label for="telefon">Phone</label>
        <input type="tel" name="telefon" id="telefon" placeholder="Enter phone number" required>
    </div>
    <div>
        <label for="password">Password</label>
        <input type="password" name="password" id="password" placeholder="Enter password" required>
    </div>
    <div>
        <label for="confirmparola">Confirm Password</label>
        <input type="password" name="confirmparola" id="confirmparola" placeholder="Confirm password" required>
    </div>
    <input type="submit" class="submitregister" value="Create account">
</form>
and here is the php script:
<?php
    if($_SERVER['REQUEST_METHOD']==="POST")
    {
        $nume = trim($_POST['nume']);
        $prenume = trim($_POST['prenume']);
        $email = trim($_POST['email']);
        $password = trim($_POST['password']);
        $confirmparola = trim($_POST['confirmparola']);
        $telefon = trim($_POST['telefon']);
        $mesaje = [];
        
        // Check if all fields are filled
        if(empty($nume) || empty($prenume) || empty($email) || empty($password) || empty($confirmparola) || empty($telefon))
        {
            $mesaje[] = "All fields must be filled!";
        }
        
        // Check if passwords match
        if($password !== $confirmparola)
        {
            $mesaje[] = "Password must be typed exactly the same twice for confirmation";    
        }
        
        // Check if password is strong enough
        if(strlen($password) <= 5 || $password == "password")
        {
            $mesaje[] = "Password must be longer than five characters";
        }
        
        // If there are errors, display them
        if(!empty($mesaje))
        {
            echo "<h3>Errors:</h3><ul>";
            foreach($mesaje as $mesaj)
            {
                echo "<li>$mesaj </li>";
            }
            echo "</ul>";
            exit;
        }

        // Redirect to the home page if no errors
        header("Location:home.html");
        exit;
    }   
    else
    {
        echo "Request is not valid.";
    }
    ?>  

Error : Cannot Find native module ‘ExpoSQLite’

Hello guys I am just trying to do simple crud operations in React-Native using SQLite database but I am encountering:

(NOBRIDGE) ERROR Error: Cannot find native module ‘ExpoSQLite’ [Component Stack]
(NOBRIDGE) WARN Route “./_layout.jsx” is missing the required default export. Ensure a React component is exported as default. [Component Stack]

Error again and again

I am using Expo SDK 52 as the framework and react native version 0.76

here are my _layout.jsx and index.jsx files

index.jsx file

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import * as Sqlite from 'expo-sqlite';


const db = Sqlite.openDatabaseSync('trial1.db');


const SignupScreen = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const setTable = () => {
    try {
      db.transaction((tx) => {
        tx.executeSql(
          "CREATE TABLE IF NOT EXISTS trial (id INTEGER PRIMARY KEY AUTOINCREMENT, email VARCHAR(20),password VARCHAR(20));",
          [],
          () => {
            console.log("Table created successfully.");
          },
          (error) => {
            console.error("Error creating table: ", error);
          }
        );
      });
    } catch (error) {
      console.error("Error setting up database: ", error);
    }
  };
  const saveData = () => {
    // Handle signup logic here
    try{
      db.transaction( tx =>{
        tx.executeSql("INSERT INTO trial(email,password) VALUES(?,?)",[email,password],
          (txObj,res) => {
            console.log(res);
          },
          (txObj,error) =>{
            console.log(error);
          }
        );
      });
    }catch(error){
      console.log(error);
    }
  };
  useEffect(() => {
    setTable();
  }, []);


  return (
    <View style={styles.container}>
      <Text style={styles.title}>Create an Account</Text>
      <TextInput
        style={styles.input}
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
        placeholderTextColor="#aaa"
      />
      <TextInput
        style={styles.input}
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
        placeholderTextColor="#aaa"
      />
      <TextInput
        style={styles.input}
        placeholder="Confirm Password"
        value={confirmPassword}
        onChangeText={setConfirmPassword}
        secureTextEntry
        placeholderTextColor="#aaa"
      />
      <TouchableOpacity style={styles.button}>
        <Text style={styles.buttonText}>Sign Up</Text>
      </TouchableOpacity>
      <Text style={styles.footerText}>
        Already have an account? <Text style={styles.link}>Log In</Text>
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f8f8',
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    color: '#333',
  },
  input: {
    width: '100%',
    height: 50,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    paddingHorizontal: 10,
    marginBottom: 15,
    backgroundColor: '#fff',
  },
  button: {
    width: '100%',
    height: 50,
    backgroundColor: '#6200ea',
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8,
    marginTop: 10,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
  footerText: {
    marginTop: 20,
    color: '#666',
  },
  link: {
    color: '#6200ea',
    fontWeight: 'bold',
  },
});

export default SignupScreen

_layout.jsx file

import { Stack } from "expo-router";
import { SQLiteProvider } from "expo-sqlite";

export default function RootLayout() {
  return (
    
      <Stack>
        <SQLiteProvider databaseName="trial1.db">
        </SQLiteProvider>
      </Stack>

  );
}

Error: Cannot find native module ‘ExpoSQLite’ [Component Stack] in Expo React-Native App

Tried debugging several times using ORM but still didn’t work.

How to properly retrieve image from database using Node.JS?

When I extract the base64 image stored in the database, and convert it to a temporary file like this :

        // Send the formatted text and image to Telegram
        const channelId = process.env.CHANNEL_ID;
        const form = new FormData();
        form.append('chat_id', channelId);
        form.append('caption', formattedProgrammeDetails);

        // Create a temporary file and write the image data to it
        const { path: tempFilePath } = await tmp.file();
        await fs.promises.writeFile(tempFilePath, programme.ProgrammePicture);

        // Append the temporary file to the form data
        form.append('photo', fs.createReadStream(tempFilePath), {
        filename: 'announcement.jpg',
        contentType: 'image/jpeg'
        });

        const base64Image = programme.ProgrammePicture ? `data:image/jpeg;base64,${programme.ProgrammePicture.toString("base64")}` : null;
        form.append('photo', base64Image, {
          filename: 'announcement.jpg',
          contentType: 'image/jpeg'
        });

        await axios.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendPhoto`, form, {
            headers: {
                ...form.getHeaders()
            },
            timeout: 60000 // 60 seconds
        });

I get an error saying that the file is corrupted, im unable to send the image through telegram bot API, although I can send the image if im using an image i uploaded in my folder (locally). When i try to open the corrupted image, there’s nothing.

I’m using Railway Free Trial Database (MySQL)

I tried asking ChatGPT whats the issue but it kept giving me similar code.

firestore Vector Save of, “what the best bet…”, matches retrieval for, “foo”

Either I’ve set this up wrong or I’m misunderstanding the vector database.

I have the phrase, “What’s the best bet on the table”, I’m embedding it to get the vector, then savings to firestore as a vector. My intention is to match sentences like, “What’s the BEST bet on the table” with a phrase like, “What’s the TOP bet on the table”.

Here is my save code:

require('dotenv').config({ path: __dirname + '/.env' })

const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore, FieldValue } = require('firebase-admin/firestore');
const serviceAccount = require('./secrets/crapsai-72b89-firebase-adminsdk-pnqva-e321c8eecb.json');

const { gemini15Flash, googleAI } = require('@genkit-ai/googleai');
const { textEmbeddingGecko001 } = require('@genkit-ai/googleai');

const { genkit } = require('genkit');

const ai = genkit({
    plugins: [
        googleAI({
            apiKey: process.env.GOOGLE_GENAI_API_KEY
        })
    ],
    model: gemini15Flash
});

const app = initializeApp({
    credential: cert(serviceAccount)
});

const firestore = getFirestore(app);

var question = "What's the best bet on the table";

(async () => {
    try {

        const embedding = await ai.embed({
            embedder: textEmbeddingGecko001,
            content: question
        });

        console.log("Got the embeddings");
        console.log(embedding);

        await firestore.collection("questions").add({
            "question": question,
            "embedding": FieldValue.vector(embedding),
            "confirmed": true
        });

        console.log("DONE");
        process.exit(0);
    } catch (e) {
        console.log("Error", e);
        process.exit(1);
    };
})();

Here is what that looks like in firestore

enter image description here

Here is the retrieval code:

require('dotenv').config({ path: __dirname + '/.env' })

const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const serviceAccount = require('./secrets/crapsai-72b89-firebase-adminsdk-pnqva-e321c8eecb.json');

const { gemini15Flash, googleAI, textEmbeddingGecko001 } = require('@genkit-ai/googleai');

const { defineFirestoreRetriever } = require('@genkit-ai/firebase');

const { genkit } = require('genkit');

const ai = genkit({
    plugins: [
        googleAI({
            apiKey: process.env.GOOGLE_GENAI_API_KEY
        })
    ],
    model: gemini15Flash
});

const app = initializeApp({
    credential: cert(serviceAccount)
});

const firestore = getFirestore(app);

const retriever = defineFirestoreRetriever(ai, {
    name: 'questionRetriever',
    firestore,
    collection: 'questions',
    contentField: 'question',
    vectorField: 'embedding',
    embedder: textEmbeddingGecko001,
    distanceMeasure: 'COSINE'
});

var question = "foo";

(async () => {
    try {
        const docs = await ai.retrieve({
            retriever,
            query: question,
            options: {
                limit: 5,
                where: { confirmed: true }
            },
        });

        docs.forEach(doc => {
            console.log(doc);
        })

        console.log("DONE");
        process.exit(0);
    } catch (e) {
        console.log("Error", e);
        process.exit(1);
    };
})();

Then when I run the code for retrieval based on the question, ‘foo’ expecting to NOT get a match. I get a match.

SO either I’ve set this up wrong or I’m misunderstanding the vector db.

Here is my index in firestore
enter image description here

Missing tamagui config

Context

I created a new tamagui project using their template (which included expo-router and some other libs).

It worked great until, I started encountering an issue randomly yesterday when I tried running the project on the android simulator. Up till that point I had not encountered any issues.

Problem

I’m getting the following error when running yarn android, the simulator is showing a “Rendor Error”

Missing tamagui config, you either have a duplicate config,
or haven’t set it up. Be sure createTamagui is called before
rendering. Also, make sure all of your tamagui dependencies
are on the same version (‘tamagui’, ‘@tamagui/package-name’, etc.)
not just in your package.json, but in your lockfile.

What I’ve done

  1. The tamagui.config.ts is set at the root directory of the project and it exports the config file
  2. I’m importing the config to app/Provider.tsx and I’m passing the config to the <TamaguiProvider config={config} ...
  3. I’ve logged the config in the file mentioned previously and it’s properly set.
  4. The libraries are all set at the same version 1.120.0 (in package.json + yarn.lock file, only thing I’ve noticed is that the @tamagui/core library is set to 1.120.2)
  5. I’ve rm -rf node_modules android + yarn cache clean and reinstalled everything without success.

Question

How do I resolve the error mentioned previously? Why was it working the other day and all of a sudden it no longer works?

Code

note: i’m aware that I’m exporting the config twice, one as a named export and the other as default. I’ve played around with both and it doesn’t change anything.

// tamagui.config.ts

import { createTamagui } from "tamagui";
import { config as defaultConfig } from "@tamagui/config/v3";

export type Conf = typeof config;

declare module "tamagui" {
  interface TamaguiCustomConfig extends Conf {}
}

const colors = {
  // colors here and used in createTamagui config
};

const config = createTamagui({
  // Stuff here
});

export type TamaguiConfig = typeof config;
export default config;
// app/Provider.tsx

import { useColorScheme } from "react-native";
import { TamaguiProvider, type TamaguiProviderProps } from "tamagui";
import { ToastProvider, ToastViewport } from "@tamagui/toast";
import { CurrentToast } from "./CurrentToast";
import config from "../tamagui.config";
import { ParentHeightProvider } from "./providers/ParentHeightContext";

export function Provider({
  children,
  ...rest
}: Omit<TamaguiProviderProps, "config">) {
  const colorScheme = useColorScheme();

  return (
    <TamaguiProvider
      config={config}
      defaultTheme={colorScheme === "dark" ? "dark" : "light"}
      {...rest}
    >
      <ParentHeightProvider>
        <ToastProvider
          swipeDirection="horizontal"
          duration={6000}
          native={
            [
              /* uncomment the next line to do native toasts on mobile. NOTE: it'll require you making a dev build and won't work with Expo Go */
              // 'mobile'
            ]
          }
        >
          {children}
          <CurrentToast />
          <ToastViewport top="$8" left={0} right={0} />
        </ToastProvider>
      </ParentHeightProvider>
    </TamaguiProvider>
  );
}

Footer overlapping with content on mobile version

I have a problem on the main page of the site. On the desktop version everything looks good, but on the mobile version the footer is not at the very bottom and covers the elements. How to fix this? I will be very grateful for every answer.

I think the problem is in the mobile styles (from line 704 to line 928)

Website: https://gta-fandom.com/home

Mobile Version

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="google-adsense-account" content="ca-pub-9285651055717731">
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9285651055717731"
     crossorigin="anonymous"></script>

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NK8M80SQWB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-NK8M80SQWB');
</script>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GTA 6 Wiki</title>
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:[email protected]&display=swap" rel="stylesheet">
<link rel="icon" href="favicon.png" type="image/x-icon">
<link rel="stylesheet" href="style.css">
<meta name="description" content="Welcome to GTA 6 Wiki! Here you can find all the information about GTA 6, including a comprehensive wiki, the latest news, and a gallery of the game's best moments.">
<script src="script.js" defer></script>

<style>




/* Общие стили для мобильной версии */
@media (max-width: 768px) {
    



    main {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 0 !important;
        flex-grow: 1;
        margin-left: -10px !important;
        margin-right: -10px !important;
        height: auto !important;
    }

    .welcome-box {
        width: 100%;
        margin-bottom: 0px !important;
        padding: 0px;
        box-sizing: border-box;
        border-radius: 8px;
    margin-top: 20px !important;
    padding: 15px !important;
    text-align: center;
    width: 130%; /* Ширина центрального окна */
    height: 160px !important;
    align-items: center !important;
    justify-items: center !important;
    }

    #article-count {
        font-size: 16px;
        word-wrap: break-word;
        margin-top: 10px;
    }

    #last-activity {
        font-size: 12px;
        margin-top: 10px;
    }

    .section-container {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 5px;
        margin: 0 5px;
        align-items: center;
        justify-items: center;
        width: 100%;
    }

    .section {
        height: 160px;
        padding: 5px;
        width: 140px;
        box-sizing: border-box;
        text-align: center;
    }

    .section img {
        height: 80px;
        margin-bottom: 5px;
    }

    .section h2 {
        font-size: 12px;
        margin-bottom: 5px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .section p {
        font-size: 10px;
        line-height: 1.2;
        margin-bottom: 5px;
        padding: 0 5px;
    }

    .left-sidebar,
    .right-sidebar {
        width: 90%;
        margin-bottom: 20px;
        padding: 15px;
        box-sizing: border-box;
    }

    .news-box,
    .recommendations-box {
        width: 100%;
        padding: 10px;
        margin-bottom: 20px;
    }

    .information-buttons button,
    .random-buttons button {
        padding: 10px;
        font-size: 14px;
    }

    .latest-news-item img {
        height: 100px;
    }

    .recommended-item {
        width: calc(50% - 5px);
        margin: 5px;
    }

    .recommended-item img {
        height: 70px;
    }

    

    .main-content h1{
        font-size: 20px !important;
        margin-bottom: 30px;
    }

    .main-content h2{
        font-size: 19px !important;
        margin-bottom: 30px;
    }


    .main-content #article-count{
        font-size: 15px !important;
        line-height: 1.3;

    }

    .main-content #last-activity{
        font-size: 11px !important;
    }

    .section-container {
        display: grid;
        grid-template-columns: repeat(2, 1fr); /* Два окошка в ряд */
        gap: 10px !important; /* Уменьшаем отступы между секциями */
        align-items: center !important;
        margin-left: 10px !important; /* Расстояние до левого края */
        margin-right: 10px !important;
        justify-items: center ; /* Центрируем карточки по горизонтали */
        gap: 5px !important;
        margin-top: 0px !important;
        margin-bottom: 50px;
        
    }

    .section {
        height: 210px; /* Ещё уменьшаем высоту секций */
        padding: 8px; /* Уменьшаем внутренние отступы */
        width: 160px; /* Секция занимает всю ширину колонки */
    }

    .section img {
        height: 100px; /* Уменьшаем высоту изображений */
        margin-bottom: 10px; /* Уменьшаем отступ от изображения до текста */
    }

    .section h2 {
        font-size: 14px; /* Ещё уменьшаем заголовки */
        margin-bottom: 0px !important; /* Уменьшаем отступ после заголовка */
    }

    .section p {
        font-size: 11px; /* Уменьшаем текст описания */
        line-height: 1.2;
        margin-bottom:20px !important;
        padding: 5px;
    }
    

  
    html, body {
    height: 100%;
    margin: 0;
    display: flex;
    flex-direction: column;
}

.footer {
    margin-top: auto !important; /* автоматически перемещается вниз */
    height: auto !important;
}

.content {
    margin-top: 50px;
    padding: 0 0px;
    margin: 0 auto;
    text-align: center;
    height: auto !important;

}


.right-sidebar .random-buttons{
    margin-bottom: 100px !important;
}

body {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
}
main {
      flex: 1 1 auto !important;  /*grow vertically*/
}
main {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}
.footer {
    position:static;
    bottom: 0;
    width: 100%;
    background-color: #1b1b1b;
    color: #ffffff;
    text-align: center !important;
    padding: 10px ;
    justify-content: end !important;
    align-items: end !important;
    margin-top: 500px !important;
    height: 300px !important;
}

.header{
    height: 300px !important;
}

   
}








</style>
</head>
<body>
<header class="header" >
    <div class="logo">
        <img src="photos/logo.png" alt="GTA 6 Wiki">
    </div>
    <nav class="nav">
        <a href="index.html">Home</a>
        <a href="explore.html">Explore</a>
        <a href="trailers.html">Trailers</a>
        <a href="news.html">News</a>
        <a href="gallery.html">Gallery</a>
        <a href="donate.html">Donate</a>
    </nav>
    <div class="search-container">
        <input type="text" id="searchQuery" placeholder="Search...">
        <button id="searchButton"></button>
    </div>
</header>

<main style="position: relative; margin-bottom: 200px;" >
    <div class="left-sidebar">
        <div class="news-box">
            <h3>Latest News</h3>
            <div id="latest-news" >
                <!-- Новости будут добавлены динамически -->
            </div>
        </div>
        <div class="information-buttons" style="margin-top: 30px;">
            <h3 style="align-items: center !important ; text-align:center !important ;">Information</h3>
            <button onclick="window.location.href='/privacy-policy.html'">Privacy Policy</button>
            <button onclick="window.location.href='/about.html'">About GTA 6 Wiki</button>
            <button onclick="window.location.href='/contact.html'">Contact Us</button>
        </div>
    </div>

    <div class="main-content" style="align-items: center !important; ">
        <div class="welcome-box">
            <h1>Welcome to GTA 6 Wiki</h1>
            <p id="article-count"><span>Currently, there are </span><a href="explore.html" id="article-number">xxx</a> about the world of GTA 6</p>
            <p id="last-activity">Last update: December 28, 2024 1:05</p>
        </div>
        <h2>Explore GTA 6 World</h2>
        <div class="section-container" style="align-items: center !important; justify-content: center !important;">
            <a href="explore/characters.html" class="section">
                <img src="assets/bonny.jpg" alt="GTA 6 Characters">
                <h2>Characters</h2>
                <p>Explore all the characters from the world of GTA 6.</p>
            </a>
            <a href="explore/vehicles.html" class="section">
                <img src="explore/img/Vehicles.png" alt="GTA 6 Vehicles">
                <h2>Vehicles</h2>
                <p>Explore all vehicles featured in the world of GTA 6.</p>
            </a>
            <a href="explore/locations.html" class="section">
                <img src="explore/img/buildings.png" alt="GTA 6 Locations">
                <h2>Locations</h2>
                <p>Explore all the locations from the world of GTA 6.</p>
            </a>
            <a href="explore/weapons.html" class="section">
                <img src="explore/img/weapons.jpg" alt="GTA 6 Weapons">
                <h2>Weapons</h2>
                <p>Explore all the types of weapons featured in GTA 6.</p>
            </a>
        </div>
    </div>

    <div class="right-sidebar" style="margin-top: 200px;" >
        <div class="recommendations-box" style="margin-top: 15px !important;"style="height: auto !important;">
            <h3>Recommended</h3>
            <div id="recommended-articles" style="gap: 10px !important; ">
                <!-- Рекомендованные статьи будут вставляться сюда -->
            </div>
        </div>
        <div class="random-buttons" style="height: auto !important;" >
            <h3>Random Choice</h3>
            <button id="random-article">Random Article</button>
            <button id="random-news">Random News</button>
        </div>
    </div>
</main>



<footer class="footer">
    <p >&copy; 2024 GTA 6 Wiki. All rights reserved.</p>
    <p>This is an unofficial fan site, not affiliated with Rockstar Games. <span class="mobile-br"></span>GTA 6 and related assets are trademarks of Rockstar Games.</p>
</footer>
<script>
    // Загрузка статей и подсчёт их количества
    fetch('/pages.json')
        .then(response => response.json())
        .then(data => {
            const articles = data; // Массив статей из pages.json
            const articleCount = articles.length; // Подсчёт количества статей
    
            // Обновляем текст с количеством статей
            document.getElementById('article-number').innerText = `${articleCount} articles`;
        })
        .catch(error => console.error('Error fetching pages.json:', error));
    
    // Загрузка статей и отображение рекомендованных
    fetch('/pages.json')
        .then(response => response.json())
        .then(data => {
            const articles = data; // Массив статей из pages.json
    
            // Находим статью с названием "State of Leonida"
            const leonidaArticle = articles.find(article => article.title === "State of Leonida");
    
            if (leonidaArticle) {
                const recommendedContainer = document.getElementById('recommended-articles');
    
                // Очищаем контейнер на случай перезаписи
                recommendedContainer.innerHTML = '';
    
                // Добавляем карточку "State of Leonida" первой
                const leonidaElement = document.createElement('div');
                leonidaElement.classList.add('recommended-item');
                leonidaElement.innerHTML = `
                    <img src="${leonidaArticle.photo}" alt="${leonidaArticle.title}" class="recommended-item-img">
                    <h3>${leonidaArticle.title}</h3>
                `;
                leonidaElement.addEventListener('click', () => {
                    window.location.href = leonidaArticle.link;
                });
                recommendedContainer.appendChild(leonidaElement);
    
                // Убираем "State of Leonida" из общего списка
                const otherArticles = articles.filter(article => article.title !== "State of Leonida");
    
                // Добавляем ровно 2 случайные статьи
                const randomArticles = getRandomArticles(otherArticles, 2);
                randomArticles.forEach(article => {
                    const articleElement = document.createElement('div');
                    articleElement.classList.add('recommended-item');
                    articleElement.innerHTML = `
                        <img src="${article.photo}" alt="${article.title}" class="recommended-item-img">
                        <h3>${article.title}</h3>
                    `;
                    articleElement.addEventListener('click', () => {
                        window.location.href = article.link;
                    });
                    recommendedContainer.appendChild(articleElement);
                });
            } else {
                console.error('State of Leonida article not found in pages.json');
            }
        })
        .catch(error => console.error('Error fetching pages.json:', error));
    
    // Функция для выбора случайных статей
    function getRandomArticles(articles, count) {
        return articles
            .sort(() => 0.5 - Math.random()) // Перемешиваем статьи
            .slice(0, count); // Берём первые `count` элементов
    }
    
    // Загрузка и отображение новостей
    fetch('/articles.json')
        .then(response => response.json())
        .then(data => {
            // Сортируем новости по дате (от самых новых к старым)
            const sortedNews = data.sort((a, b) => new Date(b.date) - new Date(a.date));
            const latestNews = sortedNews.slice(0, 3); // Берем три самых новых новости
    
            const newsContainer = document.getElementById('latest-news');
            latestNews.forEach(news => {
                const newsItem = document.createElement('div');
                newsItem.classList.add('latest-news-item');
    
                newsItem.innerHTML = `
                    <img src="${news.image}" alt="${news.title}">
                    <h4>${news.title}</h4>
                    <p>${news.date}</p>
                `;
    
                // Добавляем ссылку на новость
                newsItem.addEventListener('click', () => {
                    window.location.href = news.link; // Перенос на страницу новости
                });
    
                newsContainer.appendChild(newsItem);
            });
        })
        .catch(error => console.error('Error fetching articles.json:', error));
    
    // Событие для случайной статьи
    document.getElementById('random-article').addEventListener('click', function() {
        fetch('/pages.json')
            .then(response => response.json())
            .then(data => {
                const randomArticle = data[Math.floor(Math.random() * data.length)];
                window.location.href = randomArticle.link;
            });
    });
    
    // Событие для случайной новости
    document.getElementById('random-news').addEventListener('click', function() {
        fetch('/articles.json')
            .then(response => response.json())
            .then(data => {
                const randomNews = data[Math.floor(Math.random() * data.length)];
                window.location.href = randomNews.link;
            });
    });

    document.addEventListener('DOMContentLoaded', function () {
            if (window.innerWidth <= 768) {
                const mainContent = document.querySelector('.main-content');
                const exploreSection = document.querySelector('.section-container');
                const leftSidebar = document.querySelector('.left-sidebar');
                const rightSidebar = document.querySelector('.right-sidebar');
    
                const main = document.querySelector('main');
                main.innerHTML = '';
    
                main.appendChild(mainContent);
                main.appendChild(exploreSection);
                main.appendChild(leftSidebar);
                main.appendChild(rightSidebar);
            }
        });





    
    </script>
    
    

    
</body>
</html>

I tried to solve this problem using Chat GPT, but everything it suggested did not help me.
I tried to fix some styles, but everything I tried didn’t help either.

Back button issue with 401 unauthorized access error

The back button functionality using window.history.back() works fine for navigating forward and backward on clicking of backButton. However, there’s a specific page (abc page) where an AJAX call is used for video response. When this page gets load initially, it gives a 401 unauthorized access error. As a result, navigating to the page ABC and clicking the back button doesn’t work unless clicked quickly twice.
Removing the ajax call changes from page ABC fixes the back button issue. Any suggestions would be appreciated.