How do I merge the range data of the highlighted cells of my grid’s ouput?

I am working on a game and I’ve come to the point where I am in need of an efficient collision detection system. At the moment, I am using a very heavy handed array of 1 and 0 to indicate a boundary.

I’ve written a crude grid creation tool that allows me to highlight the cells that I would like to indicate have a boundary however, I’m a bit lost in terms of how to simplify the output for quicker access.

Currently, my intention is to restructure the boundaries based on if there are consecutive highlighted cells and no entries when there are no highlighted cells. Hence the sparse matrix.

For example, assuming a cell size of 10
0,0
[_ _ ]- – -[ _ _]

I would expect my ouput to be

{ x: [0,30], y: [0,10] },
{ x: [60,90], y: [0,10] }

At the moment, I get an empty object for each cell..

This is the current iteration of my attempt to merge the range of the highlighted cells in to a single object to represent a boundary.

    function mergeConsecutiveCells(boundaries) {
        const mergedBoundaries = [];
       
        if (boundaries.length === 0) {
            return mergedBoundaries;
        }
       
        boundaries.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
       
        let currentBoundary = boundaries[0];
       
        for (let i = 1; i < boundaries.length; i++) {

            const nextBoundary = boundaries[i];
       
            if (
                currentBoundary[1] === nextBoundary[1] &&
                currentBoundary[2] === nextBoundary[2] &&
                currentBoundary[3] === nextBoundary[3] &&
                currentBoundary[0] + cellSize === nextBoundary[0]
            ) {

                // Consecutive cells, extend the range
                currentBoundary[0] = nextBoundary[0];
            } else {
               // Non-consecutive cells, add the current boundary to the result
               mergedBoundaries.push({
                   x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
                   y: { start: currentBoundary[1], end: currentBoundary[3] }
               });
               currentBoundary = nextBoundary;
            }
        }
        // Add the last boundary
        mergedBoundaries.push({
            x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
            y: { start: currentBoundary[1], end: currentBoundary[3] }
        });
        return mergedBoundaries;
    }

Further enhancing javascript code to retrieve video srcs

I am testing some javascript codes in the chrome console to retrieve videos src from an instagram post, that contains more than 2 videos.

I can retrieve the 2 srcs just fine using the code bellow, as it seems what’s loaded in DOM. However it doesn’t get the rest of the videos in that single post.

https://www.instagram.com/p/Cz45oeXJhj8/

for (const el of document.querySelectorAll('video')) {
  const src = el.getAttribute('src');
  if (src) {
    console.log(src);
  }
}

So I tried to implement some clicking logic to click the next button and retrieve more src links. It seems to be all over place, I can’t dial it in just to get the same amount of srcs based on the amount of the posts. I am not sure if this is even the correct way of doing it, it’s just for educational purposes, practicing javascript.

Here is the code that crawls the posts:

function extractVideoSources() {
  for (const video of document.querySelectorAll('video')) {
    const src = video.getAttribute('src');
    if (src) {
      console.log(src);
    }
  }
}

function clickNextButtonAndExtract() {
  const nextButton = document.querySelector('button[aria-label="Next"]');
  if (nextButton) {
    nextButton.click();

    setTimeout(() => {
      extractVideoSources();
      clickNextButtonAndExtract(); 
    }, 2000); 
  }
}
clickNextButtonAndExtract();

Any ideas how could I logically implement it? Also so it’s reliable. Does it also need to target the specific container?

Want buttons from vue component used for switching to be fixed in position?

I have vue component used for switching called UserAuthentication between signin and signup components. In this case I have buttons in the vue component for switching for signing and signup. I essentially want these buttons fixed on top of form-box from signin and signup component. Essentially want the button-field from user authentication to be fixed on top of signin.vue and signup.vue

signin.vue and signup.vue exact same just more fields in signup.vue:

<div class="container">
    <div class ="form-box">
        <h1 ref="title">Sign In</h1>
 
        <form @submit.prevent="handleSubmit" > 
       

            <div class = "input-group">



                <div class="input-field">
                    <input type = "email" v-model = "email" placeholder = "Email"> 
               
                </div>

                <div class="input-field">
                    <input type = "password"  v-model = "password"  placeholder = "Password"> 
                </div>

                
            </div>
        <div class = "btn-field">
                <button class= "invert" id="signupBtn" @click="signUp = !signUp">Sign In</button>
      
             
                </div>
         


        </form>


    </div>

</div>


</template>

<script>
  export default {
      name: 'signIn',

data(){

return {

email: '',
password: ''
}
},


methods:{
 handleSubmit(){

const data = {
email: this.email,
password: this.password
};
          console.log(data);
      }
  }

  }
</script>


<style>

.container{
    width : 100%;
    height: 100vh;  /*vh stands for viewable height */
    background-color: lightblue; /* can be image too*/
    position : relative;
    background-size: cover;
    background-position: center;
}


.form-box{
    width: 90%;
    max-width: 450px;  /*set a max width*/
   position: absolute; /*positioned relaitve to its position*/
    top: 30%;
    left: 30%;  /*middled using top and left*/
     transform: translate(-10%,-10%); /*translates box based on cordinates*/
    background : #fff;
     padding: 50px 60px 70px;    /*generate space around box*/
    text-align: center;       /*make sure text is centered*/

}

.form-box h1{
    font-size: 30px;
    margin-bottom: 60px; /*spaces it out from the fields*/
    color: #2da000;
    position: relative;

}

.form-box h1::after{  /*  */
    content: '';
    width: 30px;
    height: 4px;
    border-radius: 3px;
    background: #3c00a0;
    position: absolute;
    bottom: -12px;
    left: 50%;
    transform: translateX(-50%)
    ;

}

.input-field{   
  background: #eaeaea;
  margin: 15px 0;   /* create space around text between textboxes */
  border-radius: 3px;  /*closes in margin border*/
  display: flex; /*use flexbox for all items */
  align-items: center; /*center all items in the flexbox*/

  max-height:65px;
  transition: max-height 0.5s; /* provides transition */
  overflow:hidden;

}


input{
width: 100%;
background: transparent;
border: 0;
outline: 0;
padding: 18px 15px; /*make padding of input boxes wider*/
}



form p{
    text-align: left;
    font-size: 13px;
}


form p a {
    text-decoration: none;
    color: #3c00a0;
}


.btn-field{  /* add spaces between flex box buttons */
    width:100%;
    display: flex;
    justify-content: space-between;
}

.btn-field button{ /*provides length for flex button*/
    flex-basis:48% ;
    background: #3c00a0;
    color: #ffff;
    height: 40px; /*increase height of button*/
    border-radius: 20px; /*makes border go in more rounder shape*/
    border:0;   /*get rid of border surrounding button*/
    outline:0; 
    cursor: pointer;
    transition: background 1s;
}

.input-group{ /*add space between input field and button*/
    
    height: 280px;
}

.invert{
    background: #eaeaea;
    color: rgb(85, 85, 85);
}




</style>

UserAuthenticaion.vue

<template>
  <div class="user-authentication">
    <div class="auth-container">
      <div class="button-field">
        <button class="b1" @click="showSignIn">Sign-in</button>
        <button class="b2" @click="showSignUp">Sign-up</button>
      </div>
      <!-- Conditional rendering of components -->
      <SignIn v-if="currentComponent === 'sign-in'" class="sign-in"></SignIn>
      <SignUp v-else-if="currentComponent === 'sign-up'" class="sign-up">
        <div class="container">
          <div class="form-box">
            <!-- Content from SignUp.vue -->
            <!-- ... -->
          </div>
        </div>
      </SignUp>
    </div>
  </div>
</template>

<script>
import SignIn from './signIn.vue';
import SignUp from './signUp.vue';

export default {
  name: 'UserAuthentication',
  components: {
    SignIn,
    SignUp,
  },
  data() {
    return {
      currentComponent: 'sign-up',
    };
  },
  methods: {
    showSignIn() {
      this.currentComponent = 'sign-in';
    },
    showSignUp() {
      this.currentComponent = 'sign-up';
    },
  },
};
</script>

<style scoped>
/* Existing styles for user-authentication */
/* ... */



.auth-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column; /* Ensure vertical layout */
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
  z-index: 999; /* Ensure the container is on top */
}

.button-field {
  position: fixed;
  top: 90px; /* Adjust the top position as needed */
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  width: 200px; /* Set a specific width for the button container */
}

/* Other styles for SignUp component's structure */
.sign-up .container {
  position: relative;
  padding-top: 50px; /* Space for the fixed button-field */
}

.sign-up .form-box {
  /* Other styles */
}
</style>

Pwa notification with js

why my pwa don’t working? I need get notification.

 // Проверка поддержки и регистрация Service Worker
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/service-worker.js')
          .then(registration => {
            console.log('Service Worker зарегистрирован:', registration);
          })
          .catch(err => {
            console.error('Ошибка регистрации Service Worker:', err);
          });
      }
    
      let latestArticleId = 0;
    
      // Загрузка новостей при загрузке страницы и каждые 10 секунд
    document.addEventListener('DOMContentLoaded', () => {
        loadData();
        setInterval(loadData, 10000);
    
        // Обработчик нажатия на кнопку для запроса разрешения на уведомления
        const enableNotificationsButton = document.getElementById('enable-notifications');
        enableNotificationsButton.addEventListener('click', () => {
            Notification.requestPermission().then(permission => {
                if (permission === "granted") {
                    console.log("Разрешение на уведомления получено");
                    enableNotificationsButton.style.display = 'none'; // Скрыть кнопку после получения разрешения
                }
            });
        });
    });
    
    
    // Запрос новостей с сервера или из кеша
      function loadData() {
        fetch('/api/news')
          .then(response => {
            if (!response.ok) {
              throw new Error('Ошибка сетевого запроса');
            }
            return response.json();
          })
          .then(data => {
            if (data.items.length > 0) {
              updateNewsList(data.items);
              checkForNewArticle(data.items);
            }
          })
          .catch(error => {
            console.error('Ошибка при получении новостей:', error);
            loadFromCache();
          });
      }
    
      // Обновление списка новостей на странице
      function updateNewsList(articles) {
        const newsContainer = document.getElementById('news-container');
        newsContainer.innerHTML = '';
        articles.slice(0,10).forEach(article => {
          const articleElem = document.createElement('div');
          articleElem.className = 'news-article';
          articleElem.innerHTML = `<h3>${article.title}</h3><p>Опубликовано ${article.author} в ${article.publicationDate}</p>`;
          newsContainer.appendChild(articleElem);
        });
      }
    
      // Проверка наличия новых статей
      function checkForNewArticle(articles) {
        if (articles[0].id > latestArticleId) {
          latestArticleId = articles[0].id;
          if (document.hidden) {
            showNotification(articles[0].title);
          }
        }
      }
    
      // Отображение уведомлений
      function showNotification(title) {
        if (Notification.permission === "granted") {
          new Notification("Новая статья!", {
            body: title,
            icon: '/icons/icon-192x192.png'
          });
        } else if (Notification.permission !== "denied") {
          Notification.requestPermission().then(permission => {
            if (permission === "granted") {
              new Notification("Новая статья!", {
                body: title,
                icon: '/icons/icon-192x192.png'
              });
            }
          });
        }
      }
    
      // Загрузка новостей из кеша
      function loadFromCache() {
        if (!navigator.serviceWorker) {
          console.log('Service Worker не поддерживается этим браузером.');
          return;
        }
    
        navigator.serviceWorker.controller.postMessage({ type: 'get-cached-news' });
    
        navigator.serviceWorker.onmessage = event => {
          if (event.data.type === 'cached-news' && event.data.articles) {
            updateNewsList(event.data.articles);
          }
        };
      }

its my code, why I don't get message for accept notification/ its pwa for get 10 last news from server, and when server pushing new news, I need get notification from browser or pwa app. its my code, why I don't get message for accept notification/ its pwa for get 10 last news from server, and when server pushing new news, I need get notification from browser or pwa app.

ResolverFn in Angula 17

idk what is happening, but call a function in the ResolveFn and it calls that the method is not a function

Resolver

import { of } from 'rxjs';
import { Inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { Livro } from '../models/livro';
import { LivrosService } from '../services/livros.service';

export const livrosResolver: ResolveFn<Livro> = (route, state) => {

  if(route.params?.['id']){
    return Inject(LivrosService).loadById(route.params['id'])
  }

  return of({_id: Number(null), name: '', desc: ''});
};

Services

import { Livro } from './../models/livro';
import { tap, first } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';


@Injectable({
  providedIn: 'root'
})
export class LivrosService {

  private readonly API = 'api/livros'

  constructor(
    private httpClient: HttpClient,

    ) {
  }

  list(){
    return this.httpClient.get<Livro[]>(this.API)
    .pipe(
      first(),
      tap(formulas => console.log(formulas))
      )
    }

  loadById(id: number){
    return this.httpClient.get<Livro>(`${this.API}/${id}`)
  }

  save(livro: Partial<Livro>){
    return this.httpClient.post<Livro>(this.API, livro);
  }


}

Model

export interface Livro {
    _id: number;
    name: string;
    desc: string;
}

Routing Module

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LivrosComponent } from './containers/livros/livros.component';
import { LivroFormComponent } from './containers/livro-form/livro-form.component';
import { livrosResolver } from './guards/livros.resolver';


const routes: Routes = [
  { path: '', component: LivrosComponent},
  { path: 'new', component: LivroFormComponent, resolve: {livro:livrosResolver}},
  { path: 'edit/:id', component: LivroFormComponent, resolve: {livro:livrosResolver}}
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class LivrosRoutingModule { }

Component

import { Component, OnInit } from '@angular/core';
import { LivrosService } from '../../services/livros.service';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { MatDialog } from '@angular/material/dialog';
import { ErrorDialogComponent } from '../../../shared/components/error-dialog/error-dialog.component';
import { Livro } from '../../models/livro';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-livros',
  templateUrl: './livros.component.html',
  styleUrl: './livros.component.scss'
})
export class LivrosComponent {

  livros$: Observable<Livro[]>

    constructor(
      private livrosServices: LivrosService,
      public dialog: MatDialog,
      private router: Router,
      private route: ActivatedRoute

    )

    {
      this.livros$ = this.livrosServices.list()
    .pipe(
      catchError(error =>{
        this.onError('Erro ao carregar as Fórmulas')
        return of([])
      })
      )
    }

    onError(errorMsg: string) {
      this.dialog.open(ErrorDialogComponent, {
        data: errorMsg
      });
    }


    onAdd(){
      this.router.navigate(['new'], {relativeTo: this.route})
    }

    onEdit(livro: Livro){

      this.router.navigate(['edit', livro._id], {relativeTo: this.route})
    }


}

The Error

ERROR TypeError: Inject(...).loadById is not a function
    at livrosResolver (livros.resolver.ts:10:34)
    at resolve_data.ts:109:42
    at R3Injector.runInContext (r3_injector.ts:235:14)
    at getResolver (resolve_data.ts:109:23)
    at resolve_data.ts:92:18
    at doInnerSub (mergeInternals.ts:71:15)
    at outerNext (mergeInternals.ts:53:58)
    at OperatorSubscriber2._this._next (OperatorSubscriber.ts:70:13)
    at Subscriber2.next (Subscriber.ts:75:12)
    at Observable2._subscribe (innerFrom.ts:78:18)

For me using a resolver is a better method to get this data from the Server. But i don’t know why this won’t work, i do what they explain in the documentation and simply don’t work

I want to learn how to create an app to input data and create an report in pdf. What would be the better learning path to create that?

I want to create am app similar to the next link:
https://www.geobrugg.com/portal/app/ruvolum/
In this web you can input data and the web process and make some calculations. After that, it is created a report with the steps and even some graphics. In addition, you can download the report in pdf.

I would like to create something similar but I don’t know if it’s better to use JavaScript and web apps or flutter multiple devices apps? Which technology is better and has more resources to this kind of app? Also, which is easy to learn?

I’m getting into coding world and I don’t know how to start.

Drag and draw a line between two divs

I would like to be able to draw a line between two divs, the left would be the inputs and the right the outputs. That line will start to be drawn on a mousedown until the target mouseup

Here’s an example:
enter image description here

I am unable to find an existing library that would do such a thing, do you have any recommandations or custom implementations you did yourselves?

Thanks!

How to best implement a Typesense-style search for a website in JavaScript

I’m not sure if this already exists in some other library, but what I am trying to do is implement a typesense-style search that gives you results as you type in your search term.

The source is a json object that will be fetched by the client when the window loads. It will have approximately 10K keys that I want to search through. For example: https://redditstatsbot.com/json/alphabetbot.json

What I don’t want to do is have to type in the full key. The user must be able to get their unique ID by typing in the first few letters of their ID.

For example, typing in “str” would yield all keys that start with “str”, ["stranger", "strongman", "stranded", ... ] and then the user can select from the returned smaller list, whith the returned list growing or shrinking depending on the typed search term.

So basically, I don’t think that a full-blown Typesense implementation is necessary for my needs, because this is not a massive database, but I’m not really sure what my other options are.

When an unqualified global variable is undefined, where was it searched?

Question

In my project, when pluralize—a global variable—is used like this pluralize.plural(templateName), it errors with “pluralize is not defined”. Where did the runtime look for pluralize? i.e., local scope, globalThis.pluralize, global.pluralize, a window.pluralize, and/or somewhere else?

I’m not looking for a general rule of thumb or a best practice. I want to print all the places pluralize was searched before the runtime determined it was undefined.

Example answer

function verboseGlobalVariableSearch(globalVariableName: string) {
  // Your code here
}

verboseGlobalVariableSearch("pluralize");
pluralize.plural(templateName);

Example output:

Searched for "pluralize" in local scope... local scope pluralize not found.
Searched for "pluralize" in globalThis... globalThis.pluralize not found.
Searched for "pluralize" in window... window.pluralize not found.
Giving up. Returning undefined.
Error: pluralize is not defined
  stack trace line 1
  stack trace line 2

The above tells me that an assignment to local scope, globalThis.pluralize, or window.pluralize will fix the error, but an assignment to global.pluralize won’t. It also tells me the search precedence. First local scope, then globalThis, then window.

What code will print this information?

Context

I’ve written a Node.JS test that uses JSDOM to parse my project’s HTML/JS/CSS. This project code normally runs in the browser, so I’m using JSDOM to create a browser-like environment. The benefit of using JSDOM for this instead of Selenium, Puppet, etc. is the tests run much faster than firing up a real browser.

Unfortunately, when I run my test I get this error: “pluralize is not defined”. This does not occur in production. Therefore, my JSDOM environment isn’t emulating the browser environment correctly, and I’m trying to find the difference.

I’ve proven this is the line that causes the error: pluralize.plural(templateName). Now I need to fix it, but I’m not sure how. For example, is that line of code looking for a globalThis.pluralize, global.pluralize, a window.pluralize, or something else?

Normally this is straightforward:

  1. Does your code run in node.js? Then globalThis.pluralize and global.pluralize as a fallback (I think).
  2. Does your code run in the browser? Then globalThis.pluralize and window.pluralize as a fallback (I think).

But when Node.JS, JSDOM, globalThis, global, window, and your code share the environment, <x> is not defined errors are difficult to reason able. For me, it’s even more complicated than that: that line of code may run within a direct eval, too.

React js – Block scrolling in the upwards direction

In my application, I have a List component where as a user scrolls up, more data is loaded. When the user has reached the end of the list and there is no more data, I set the scrollBlocked state variable to true meaning a user shouldn’t be able to scroll up further.

I have an onScroll event on my List, which calls the function disable everytime a user scrolls.

List Component:

<List onScroll={(e) => disable(e)} />

Disable function:

  function disable(e) {
    const newScrollPosition = e.target.scrollTop;
    if (!scrollBlocked) {
      setScrollPosition(newScrollPosition);
    }

    // Code to completely stop a user scrolling in any direction. 
    //Here is where I want to implement logic to allow scrolling downwards, however disable scrolling upwards
    if (scrollBlocked) {
      e.target.scrollTo({
        top: scrollPosition,
        left: 0
      });
    }
}

This code blocks the user scrolling in any direction if scrollBlocked has been set to true. However, I would still like a user to be able to scroll down if scrollBlocked is true, so they can see the previous data. How could I accomplish only disabling scrolling upwards, and allowing a user to still scroll downwards if scrollBlocked has been set to true? Thanks.

Network Error Fetching Resource in Axum Server During Video Download Task

I’m developing a web application using Rust’s Axum framework and have encountered a network error when trying to implement a video download feature. The issue arises when my server-side function, which handles video downloads, is called. Removing this function resolves the error, suggesting the issue is related to how the function operates.

Environment:

  • Rust with Axum framework
  • JavaScript (client-side)

Problem:
When I trigger a video download from the client side (using JavaScript fetch to send a POST request), the server (Axum in Rust) throws a “network error fetching resource.” This error does not occur when I remove the video download handling function on the server.

Server-side code snippet:

use axum::{
    response::{Response, IntoResponse},
    http::{StatusCode, header::HeaderMap},
    Json,
};
use reqwest::header;
use serde::Deserialize;

use crate::utils::youtube::download_youtube;

#[derive(Deserialize)]
pub struct VideoRequest {
    site: String,
    url: String,
}

pub async fn download_video(Json(payload): Json<VideoRequest>) -> impl IntoResponse {
    let response_body = match payload.site.as_str() {
        "youtube" => {
            format!("Processing youtube with URL: {}", payload.url)
        },
        "type2" => format!("Processing type2 with URL: {}", payload.url),
        _ => format!("Unknown type: {}", payload.site),
    };

    let mut headers = HeaderMap::new();
    headers.insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());

    Response::builder()
    .status(StatusCode::OK)
    .header(header::CONTENT_TYPE, "text/plain")
    .body(response_body)
    .unwrap()
}

Client-side code snippet:

document.addEventListener('DOMContentLoaded', () => {
    const downloadButton = document.getElementById('downloadButton');
    if (downloadButton) {
        downloadButton.addEventListener('click', function(e) {
            e.preventDefault(); // Prevent the default button click action

            const videoUrl = document.getElementById('videoUrl').value;
            fetch('http://127.0.0.1:3000/api/v1/download', {
                method: 'POST',
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ site: "youtube", url: videoUrl })
            })
            .then(response => console.log(response.status))
            .catch(error => {
                console.error('Error:', error);
            });
        })
    }
});

Attempts to resolve:

  • Checked CORS settings on the server (seem to be configured correctly).
  • The server works fine for other routes and functionalities.

Questions:

  1. What could be causing the network error specifically when the video download function is active?
  2. Are there any best practices for handling long-running tasks like video downloads in Axum to avoid blocking or timeouts?
  3. Could this be related to async handling in Rust, and if so, how can I better structure my async function to prevent such issues?

Any insights or suggestions on how to troubleshoot or resolve this would be greatly appreciated!

Does any knows how to control an Odysee embedded video?

Can I keep track of the time the Odysee’s embedded video? I can embbed the video but I’d like to play where the user left off next time the page is opened. But I didn’t tind any offical Odysee’s API nor how I can do that usin g pure Javascript, due to cross-origin. I have no code to show because I didn’t find any workaround. Are there any? any help is very appreciated.

insert before pre tag

I need to insert from javascript some text into a pre tag. I tried the following:

<!DOCTYPE html>
<html>

<body>
  
  <pre id='test'> some
text</pre>

  <script>
    // Create a "span" element:
    const newNode = document.createElement("span");
    // Create a text node:
    const textNode = document.createTextNode(" Water ");
    // Append text node to "span" element:
    newNode.appendChild(textNode);

    // Insert before existing child:
    const list = document.getElementById("test");
    list.insertBefore(newNode, list.children[0]);
  </script>

</body>

</html>

but my output is:

 some
text water

but I need:

 water some
text

Divider stretches at the top but not at the bottom of the page

 <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" 
rel="stylesheet" integrity="sha384- 
 T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" 
   crossorigin="anonymous">



  </nav>    

  <div class="divider py-1  bg-purple"></div><br>
  <!--The divider above works.  It stretches across the whole page-->


</table>
</div>

 &nbsp; <!--sapaces-->

<div class="divider py-1  bg-purple " ></div><br>

The same divider here just beneath the table only stretches the length of the table. It does not stretch across the whole page. I am not sure why this is happening.