PushState() removes previous entries or creates doubles

Here’s my code:

$.ajax({
    url: link,
    type: 'get',
    data: { },
    success: function (res) {
        document.title = res.title;
        document.description = res.description;

        $('body').html(res.html);
        addToHistoryUrl(res, link);
    }
});

function addToHistoryUrl(res, url){
window.history.pushState({'title' : res.title, 'description' : res.description},"", url);}

Most of the time it works fine but sometimes pushstate() creates a double entries or removes some of them or even edit some entries.

I dont use onpopstate() handler, all navigation (back, forward) works by browser’s solutions.

Modal does not open when clicking the button – Javascript issue

I’m working on a website where I need to display a modal popup when a user clicks a button. However, the modal doesn’t open when the button is clicked. I’m using basic HTML, CSS, and JavaScript to implement the modal. I followed some tutorials online, but it still doesn’t seem to work.

The modal doesn’t open when I click the button (Erfahren Sie mehr über mich).

I’ve followed tutorials and checked the code, but the modal remains hidden.

I’m using basic JavaScript to manipulate the modal’s visibility.

The btn.onclick function should trigger the modal to appear, but it doesn’t seem to work.

What I’ve tried:
I’ve checked the console for errors, but there are none.

I made sure the IDs and classes match between HTML, CSS, and JavaScript.

I’ve also tried modifying the display property in different ways (using block, flex, etc.), but it still doesn’t work.

Any help would be greatly appreciated! I’ve been stuck on this for a while.

Additional Information:
Browser: Chrome (latest version)

I’m not using any frameworks or libraries, just pure HTML, CSS, and JavaScript.

### JavaScript-Code:
// Get the modal
var modal = document.getElementById("myModal");

// Get the button that opens the modal
var btn = document.getElementById("myBtn");

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks on the button, open the modal
btn.onclick = function() {
    modal.style.display = "block";
}

// When the user clicks on <span> (x), close the modal
span.onclick = function() {
    modal.style.display = "none";
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
    if (event.target == modal) {
        modal.style.display = "none";
    }
}
### CSS-Code:
.modal {
  display: none; 
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);
}

.modal-content {
  background-color: #fefefe;
  margin: 15% auto;
  padding: 20px;
  border: 1px solid #888;
  width: 80%;
}

.close {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
}


<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>In der Not für Sie da - Seniorenhilfe</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <div class="container">
            <h1>In der Not für Sie da</h1>
            <nav>
                <ul>
                    <li><a href="#services">Leistungen</a></li>
                    <li><a href="#contact">Kontakt</a></li>
                </ul>
            </nav>
        </div>
    </header>

    <section class="hero">
        <div class="container">
            <div class="hero-content">
                <div class="hero-text">
                    <h2>Arbenita </h2>
                    <p>Liebevolle Seniorenbetreuung mit Herz und Erfahrung</p>
                    <button id="myBtn">Erfahren Sie mehr über mich</button>
              
                    <div id="myModal" class="modal">
                        <div class="modal-content">
                            <span class="close">&times;</span>
                            <p>Mein Name ist Arbenita , ich bin 39 Jahre alt, Mutter von vier wunderbaren Kindern und seit über 15 Jahren als Pflege- und Haushaltshilfe tätig.</p>
                            <p>Es ist mir eine Herzensangelegenheit, älteren Menschen zu helfen und ihren Alltag durch liebevolle Unterstützung und Fürsorge zu erleichtern. Mit meiner langjährigen Erfahrung in der Branche setze ich mich mit viel Engagement und Empathie dafür ein, den Menschen ein würdevolles und angenehmes Leben zu ermöglichen.</p>
                            <img src="deine-mama.jpg" alt="Foto von Arbenita ">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <footer>
        <p>&copy; 2025 Seniorenhilfe | Alle Rechte vorbehalten</p>
    </footer>

    <script>
        // Get the modal
        var modal = document.getElementById("myModal");

        // Get the button that opens the modal
        var btn = document.getElementById("myBtn");

        // Get the <span> element that closes the modal
        var span = document.getElementsByClassName("close")[0];

        // When the user clicks on the button, open the modal
        btn.onclick = function() {
            modal.style.display = "block";
        }

        // When the user clicks on <span> (x), close the modal
        span.onclick = function() {
            modal.style.display = "none";
        }

        // When the user clicks anywhere outside of the modal, close it
        window.onclick = function(event) {
            if (event.target == modal) {
                modal.style.display = "none";
            }
        }
    </script>
</body>
</html>


EventCalander – Stop overlapping event on load

I’m using this script https://github.com/vkurko/calendar to create an event calendar.
It seems to be working well, but I’m trying to work out how to stop an event being added if will overlap another event.

I’ve created a simple codepen, https://codepen.io/Tom_T/pen/emYjbJm

When you go to Week view there is one existing event. If you click load at the bottom of the page it adds a new event which overlaps the existing one. I want to stop this happening, if there is already an event then don’t add the new one.

The code I’m using to check if there is an existing event is:

newevent = data[i]

    var start = new Date(newevent.start);
    var end = new Date(newevent.end);
    console.log ( 'TEST: ' + start + ' --- ' + end );
    console.log ( ec.getEvents().filter(e => e.start < newevent.end && newevent.start < e.end ) )

If the result of the filter is > 0 then don’t add the event. At the moment it is only returning 0 so the event is added.

Does anyone know how I can filter the existing events to see if there are any clashing/overlapping entries ?

Thanks

Direct download link for Google Drive files on android without opening google drive

On my webpage, I am downloading google drive files via the following approach:

https://drive.google.com/uc?export=download&id=${fileId}

However, this only works on computers. On phones (such as an android), it opens up google drive instead of downloading the file.

On the other hand, if I paste the link on my phone’s browser, it downloads as expected instead of opening google drive.

One solution that seems to work even on phones is by using google drive api:

https://www.googleapis.com/drive/v3/files/FILE_ID?alt=media&key=YOUR_API_KEY

However, the name of the downloaded file is set to the file ID instead of the file name.

I’ve seen an answer which says to use Content-Disposition headers to set the file name, however, I do not have any server-side support, and apparently I will need expressjs to set content headers (Please tell me if I’m wrong) . My webpage has to be client-side only.

So how do I obtain a google drive download link that:

  1. Works everywhere without opening google drive (iPhone/iPads are an exception as they don’t allow downloads)
  2. Lets me keep or set the file name instead of setting the file id as the downloaded file name.

Is it possible to edit create an permanent editable textbox in html?

So I am trying to make an announcement website, but the people who actually set the announcements complain that announcements are too tricky to make (I literally give them the html file and they need to find the announcements div, create a new one using a tutorial I give them and then edit the text to their announcement). I understand that, but I literally have no idea how to change it. I went to google and looked it up. I think it has something to do with AJAX and JQuery, but I don’t know how that works. Here is about the website code but then like a sketch (the actual code has more decorations and is too long):

<!DOCTYPE html>
<html>
    <head>
        <style>
            .announcement{
                display: inline-block;
                font-size: 48px;
            }
        </style>
    </head>
    <body>
        <div id = 'announcement'>
            <a href = '/page.html'>
                <h1>Announcement here</h1>
            </a>
            <p>Announcement description</p>
        </div>
    </body>
</html>

Anyway, now there are no announcements until it is fixed and they use discord for now. It would really help if somebody helped me. Also, note that the edit announcement feature is only available with logging in.

Nested scrollable issue on react native

I am developing a book application, which supports both portrait and landscape modes. The pages of the book are svgs which are rendered inside a horizontal @shopify/flash-list. The Page component also has a vertical ScrollView which is enabled only in landscape mode.
The problem is that when in landscape mode I scroll vertically fast the ScrollView seems to be not rendered yet and the FlashList scroll is getting triggered, i.e page swipe instead of staying on the same page and scrolling down. If I wait for 1-2 sec. everything works fine and the indented scrollable is getting triggered

Tailwind navbar with nested sub menus

Following the below tutorial I can see how to use a Tailwind navbar to code a menu, with a single sub-menu:
https://webcrunch.com/posts/code-a-mega-menu-with-tailwind-css

Link to example via CodePen below:
https://codepen.io/webcrunchblog/pen/MWxGMdR?editors=1010

Code snippet:

document.addEventListener("DOMContentLoaded", () => {
  // Select all dropdown toggle buttons
  const dropdownToggles = document.querySelectorAll(".dropdown-toggle")

  dropdownToggles.forEach((toggle) => {
    toggle.addEventListener("click", () => {
      // Find the next sibling element which is the dropdown menu
      const dropdownMenu = toggle.nextElementSibling

      // Toggle the 'hidden' class to show or hide the dropdown menu
      if (dropdownMenu.classList.contains("hidden")) {
        // Hide any open dropdown menus before showing the new one
        document.querySelectorAll(".dropdown-menu").forEach((menu) => {
          menu.classList.add("hidden")
        })

        dropdownMenu.classList.remove("hidden")
      } else {
        dropdownMenu.classList.add("hidden")
      }
    })
  })

  // Clicking outside of an open dropdown menu closes it
  window.addEventListener("click", function (e) {
    if (!e.target.matches(".dropdown-toggle")) {
      document.querySelectorAll(".dropdown-menu").forEach((menu) => {
        if (!menu.contains(e.target)) {
          menu.classList.add("hidden")
        }
      })
    }
  })
  
  // Mobile menu toggle
  
  const mobileMenuButton = document.querySelector('.mobile-menu-button')
  const mobileMenu = document.querySelector('.navigation-menu')
  
  mobileMenuButton.addEventListener('click', () => {
    mobileMenu.classList.toggle('hidden')
  })
  
  
})
<script src="https://cdn.tailwindcss.com"></script>
​<nav class="bg-sky-600 text-white">
  <div class="container mx-auto px-4 md:flex items-center gap-6">
    <!-- Logo -->
    <div class="flex items-center justify-between md:w-auto w-full">
      <a href="#" class="py-5 px-2 text-white flex-1 font-bold">Webcrunch.com</a>

      <!-- mobile menu icon -->
      <div class="md:hidden flex items-center">
        <button type="button" class="mobile-menu-button">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
            <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12" />
          </svg>
        </button>
      </div>
    </div>

    <div class="hidden md:flex md:flex-row flex-col items-center justify-start md:space-x-1 pb-3 md:pb-0 navigation-menu">
      <a href="#" class="py-2 px-3 block">Home</a>
      <a href="#" class="py-2 px-3 block">About</a>
      <!-- Dropdown menu -->
      <div class="relative">
        <button type="button" class="dropdown-toggle py-2 px-3 hover:bg-sky-800 flex items-center gap-2 rounded">
          <span class="pointer-events-none select-none">Services</span>
          <svg class="w-3 h-3 pointer-events-none" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
            <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
          </svg>
        </button>
        <div class="dropdown-menu absolute hidden bg-sky-700 text-white rounded-b-lg pb-2 w-48">
          <a href="#" class="block px-6 py-2 hover:bg-sky-800">Web Design</a>
          <a href="#" class="block px-6 py-2 hover:bg-sky-800">Web Development</a>
          <a href="#" class="block px-6 py-2 hover:bg-sky-800">SEO</a>
                <!-- Dropdown menu -->
      <div class="relative">
        <button type="button" class="dropdown-toggle py-2 px-3 hover:bg-sky-800 flex items-center gap-2 rounded">
          <span class="pointer-events-none select-none">Test</span>
          <svg class="w-3 h-3 pointer-events-none" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
            <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
          </svg>
        </button>
        <div class="dropdown-menu absolute hidden bg-sky-700 text-white rounded-b-lg pb-2 w-48">
          <a href="#" class="block px-6 py-2 hover:bg-sky-800">Nested sub menu item</a>
        </div>
      </div>
        </div>
      </div>
      <a href="#" class="py-2 px-3 block">Contact</a>
    </div>
  </div>
</nav>

How can I modify this code to create a nested sub-menu. For example, trigger an additional sub-menu when clicking on a link within the existing sub-menu.

Attempts to do this by modifying the HTML results in the mainsub-menu closing when trying to trigger the nested sub-menu.

An example of the desired outcome is below:
enter image description here

Build a Table of Contents from HTML using Paged.js

I have read the documentation.

I have tried the sample code.

<!DOCTYPE html PUBLIC>
<html lang="en">

    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
        <meta http-equiv="Content-Style-Type" content="text/css"/>
        <title>Table of content</title>

        <script src="http://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
        <script src="toc.js"></script>

        <!-- config for the table of cntent -->
        <script>
            class handlers extends Paged
                .Handler {
                    constructor(chunker, polisher, caller) {
                        super(chunker, polisher, caller);
                    }

                    beforeParsed(content) {
                        createToc({content: content, tocElement: '#toc', titleElements: ['h1']});
                    }

                }
                Paged
                .registerHandlers(handlers);
        </script>

        <style>

            @media screen {
                .pagedjs_page {
                    box-shadow: 0 0 0 1px black;
                    margin: 2em auto;
                }
            }
            @media print {

                #toc li a::after {
                    content: target-counter(attr(href), page);
                    float: right;
                }
                section {
                    break-before: right;
                }
            }
        </style>

    </head>

    <body>
        <section id="toc">Table of content will be added here: if you see a toc, it works</section>
        <section class="chapter">
            <h1 class="title">title of the chapter 1 </h1>
        </section>
        <section class="chapter">
            <h1 class="title">title of the chapter 2 </h1>
        </section>
        <section class="chapter">
            <h1 class="title">title of the chapter 3 </h1>
        </section>
        <section class="chapter">
            <h1 class="title">title of the chapter 4 </h1>
        </section>
        <section class="chapter">
            <h1 class="title">title of the chapter 5</h1>
        </section>
    </body>
</html>

And the toc.js file is:

function createToc(config){
    const content = config.content;
    const tocElement = config.tocElement;
    const titleElements = config.titleElements;
    
    let tocElementDiv = content.querySelector(tocElement);
    let tocUl = document.createElement("ul");
    tocUl.id = "list-toc-generated";
    tocElementDiv.appendChild(tocUl); 

    // add class to all title elements
    let tocElementNbr = 0;
    for(var i= 0; i < titleElements.length; i++){
        
        let titleHierarchy = i + 1;
        let titleElement = content.querySelectorAll(titleElements[i]);  


        titleElement.forEach(function(element) {

            // add classes to the element
            element.classList.add("title-element");
            element.setAttribute("data-title-level", titleHierarchy);

            // add id if doesn't exist
            tocElementNbr++;
            idElement = element.id;
            if(idElement == ''){
                element.id = 'title-element-' + tocElementNbr;
            } 
            let newIdElement = element.id;

        });

    }

    // create toc list
    let tocElements = content.querySelectorAll(".title-element");  

    for(var i= 0; i < tocElements.length; i++){
        let tocElement = tocElements[i];

        let tocNewLi = document.createElement("li");

        // Add class for the hierarcy of toc
        tocNewLi.classList.add("toc-element");
        tocNewLi.classList.add("toc-element-level-" + tocElement.dataset.titleLevel);

        // Keep class of title elements
        let classTocElement = tocElement.classList;
        for(var n= 0; n < classTocElement.length; n++){
            if(classTocElement[n] != "title-element"){
                tocNewLi.classList.add(classTocElement[n]);
            }   
        }

        // Create the element
        tocNewLi.innerHTML = '<a href="#' + tocElement.id + '">' + tocElement.innerHTML + '</a>';
        tocUl.appendChild(tocNewLi);  
    }

}

The command I used to generate the TOC is pagedjs-cli index.html -o index.pdf

The pages and TOC both do not have page numbers.

What might be the solution here.

How to open the Gmail app on mobile instead of the browser using a mailto link?

How to open the Gmail app on mobile instead of the browser using a mailto link?

I want to create a feature where clicking a link opens the Gmail app on mobile devices (instead of the browser). The link should pre-fill the recipient’s email, subject, and body.

I tried using a basic mailto link:

<a href="mailto:[email protected]?subject=Test%20Subject&body=This%20is%20a%20test%20email">Send Email</a>

This works, but on some devices, it opens the browser instead of the Gmail app.

For Android, I tried using an intent link:

<a href="intent://[email protected]&subject=Test%20Subject&body=This%20is%20a%20test%20email#Intent;scheme=mailto;package=com.google.android.gm;end;">Send Email</a>

However, this doesn’t seem to work consistently across devices.

Was expecting when the user clicks on it in mobile devices it should take him to his app rather than web

How to Programmatically Add a Required Signature Field in an Adobe PDF Using Python, R or etc

I am trying to programmatically add a required signature field to a PDF using both pymupdf (PyMuPDF) and pyhanko. My goal is to ensure that Adobe Acrobat recognizes the field as a required signature field.

I have two different implementations:

Using PyHanko (append_signature_field):

I can successfully add a signature field that appears in Adobe Acrobat, but I am unable to make it required.

Adobe allows me to sign the field, but it does not enforce the requirement.

Using PyMuPDF (Widget):

I can add a signature field with field_flags = 0, which should allow modifications.

However, Adobe Acrobat treats the PDF as already signed, preventing further edits.

import fitz  # PyMuPDF

def add_signature_field_pymupdf(input_pdf, output_pdf):
    doc = fitz.open(input_pdf)
    page = doc[0]  # First page
    page_height = page.rect.height

    # Define coordinates for the signature field
    x1, y1, x2, y2 = 100, 600, 300, 650
    y1_pdf, y2_pdf = page_height - y2, page_height - y1  # Flip Y-coordinates

    # Create a signature widget
    w = fitz.Widget()
    w.field_name = "AdobeSignHere"
    w.field_label = "Please Sign Here"
    w.field_value = None
    w.text_font = "TiRo"
    w.text_fontsize = 12
    w.rect = fitz.Rect(x1, min(y1_pdf, y2_pdf), x2, max(y1_pdf, y2_pdf))
    w.field_type = fitz.PDF_WIDGET_TYPE_SIGNATURE
    w.field_flags = 2  # Set as required

    page.add_widget(w)

    doc.save(output_pdf, pretty=True)
    print(f"Signature field added: {output_pdf}")

# Run function
output_pdf_pymupdf = "signed_pymupdf.pdf"
add_signature_field_pymupdf(pdf_path, output_pdf_pymupdf)


from pyhanko.sign.fields import append_signature_field, SigFieldSpec
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter

def add_signature_field_pyhanko(input_pdf, output_pdf):
    with open(input_pdf, "rb") as pdf_in:
        w = IncrementalPdfFileWriter(pdf_in)

        # Define signature field specifications
        sig_field_spec = SigFieldSpec(
            sig_field_name="AdobeSignHere",
            on_page=0,  # First page
            box=(100, 600, 300, 650),  # Position
            empty_field_appearance=True,  # Adobe requires a visible field
            combine_annotation=True,  # Keep annotation and field together
            readable_field_name="Please Sign Here"  # Tooltip for the field
        )

        append_signature_field(w, sig_field_spec)

        with open(output_pdf, "wb") as pdf_out:
            w.write(pdf_out)

    print(f"Signature field added using PyHanko: {output_pdf}")

# Run function
output_pdf_pyhanko = "signed_pyhanko.pdf"
add_signature_field_pyhanko(pdf_path, output_pdf_pyhanko)

This creates a signature field, but when opening the PDF in Adobe Acrobat, it thinks the document is already signed and prevents modifications.

I suspect the issue might be with the field flags or signature field setup, but I can’t find the correct combination to make the field required and still signable.

What I’ve Tried:
Setting w.field_flags = 2 (read-only), which prevents signing.

Using w.is_signed = False, but PyMuPDF does not allow manually setting this.

Changing fonts (times-roman, TiRo), but no effect.

Comparing field properties with an Adobe-created required signature field, but I couldn’t match it exactly.

Expected Outcome:
The PDF should contain a signature field that is marked as required in Adobe Acrobat.

The field should allow a user to sign it.

The document should remain editable until signed.

Question:
How can I correctly define a required but signable signature field using PyMuPDF or PyHanko so that Adobe Acrobat enforces the requirement but does not lock the PDF before signing?

Why does “finally” delays the execution of “then” attached to it?

In this example:

const foo = async () => {
    const a = await (Promise.resolve(1).then(v => console.log(v)));
    console.log('foo');
    return 1;
}

const value = foo();

value
    .then(a => a + 1)
    .then(a => console.log('then 1', a));

value
    .finally(() => 'finally') 
    .then(a => console.log('then after finally'));

value 
    .then(a => a + 2)
    .then(a => console.log('then 2', a));

The output is:

1
foo
then 1 2
then 2 3
then after finally

What I don’t get is why does “then after finally” runs after “then 2 3”? And not after “then 1 2”? Why is it places at the very end of a microtask queue?
As far as I understand all tree “branches” of value are independent, but it seems like the “finally” waits until all “then”s (1st and 2nd branch) are executed.

But if I add some more “then”s like this:

value
    .then(a => a + 1)
    .then(a => console.log('then 1', a))
    .then(a => console.log('then 3', a))
    .then(a => console.log('then 5', a))
    .then(a => console.log('then 7', a));

value
    .finally(() => 'finally') 
    .then(a => console.log('then after finally'));

value 
    .then(a => a + 2)
    .then(a => console.log('then 2', a))
    .then(a => console.log('then 4', a))
    .then(a => console.log('then 6', a))
    .then(a => console.log('then 8', a));

it doesn’t seem like “finally” waits for anything:

1
foo
then 1 2
then 2 3
then 3 undefined
then 4 undefined
then 5 undefined
then after finally
then 6 undefined
then 7 undefined
then 8 undefined

Can someone please explain how it all works in this example?

Repeat ir signal for NEC (button hold)

I want to send the infrared signal of the remote control to the CD player, and I am making an application for Android. The problem is that the button holding function does not work. This button has a dual function. When pressed once, it switches the track of the LG CD player, and when you hold the button, it rewinds the track. I am doing this for the NEC protocol. Here is my code. I would be very grateful for your help!
PS. There is not much information about this
https://catedu.github.io/rover-marciano-alphabot/5-control-remoto/51-como-funciona.html


public class MainActivity extends Activity {
    private ConsumerIrManager irManager;
    private Handler handler = new Handler();
    private boolean isHolding = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        irManager = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);

        // Устанавливаем обработчики для всех кнопок
        setupButton(R.id.powerButton, 0x08087887, false);
        setupButton(R.id.sleepButton, 0x080843BC, false);
        setupButton(R.id.eqButton, 0x080802FD, false);
        setupButton(R.id.upButton, 0x080848B7, false);
        setupButton(R.id.downButton, 0x0808C837, false);
        setupButton(R.id.bandButton, 0x08089A65, false);
        setupButton(R.id.playPauseButton, 0x080820DF, false);
        setupButton(R.id.stopButton, 0x0808A05F, false);
        setupButton(R.id.progButton, 0x0808B24D, false);
        setupButton(R.id.prevButton, 0x0808609F, false);
        setupButton(R.id.nextButton, 0x0808E01F, true);
        setupButton(R.id.repeatButton, 0x0808728D, false);
        setupButton(R.id.volUpButton, 0x08086897, true);
        setupButton(R.id.volDownButton, 0x0808E817, true);
    }

    private void setupButton(int buttonId, final int necCode, boolean isHoldable) {
        Button button = findViewById(buttonId);
        if (button != null) {
            button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        sendIrSignal(necCode);
                    }
                });

            if (isHoldable) {
                button.setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, android.view.MotionEvent event) {
                            switch (event.getAction()) {
                                case android.view.MotionEvent.ACTION_DOWN:
                                    isHolding = true;
                                    sendIrSignal(necCode);  // Первая передача при нажатии
                                    startHoldingSignal(necCode);  // Запуск повторных сигналов при удержании
                                    return true;

                                case android.view.MotionEvent.ACTION_UP:
                                    isHolding = false;
                                    handler.removeCallbacksAndMessages(null);  // Остановка повторных сигналов
                                    return true;
                            }
                            return false;
                        }
                    });
            }
        }
    }

    private void startHoldingSignal(final int necCode) {
        handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isHolding) {
                        sendHoldingSignal();  // Отправка повторного сигнала
                        handler.postDelayed(this, 110);  // Повтор через 110 мс
                    }
                }
            }, 110);  // Начало через 110 мс после первого сигнала
    }

    private void sendIrSignal(int necCode) {
        irManager.transmit(38000, encodeNEC(necCode));  // Первая передача сигнала
    }

    private void sendHoldingSignal() {
        // Передача повторного сигнала (9мс, 2.25мс, 0.5625мс)
        int[] signal = new int[] {9000, 2250, 562};  // Импульс 9 мс, пауза 2.25 мс, импульс 0.5625 мс
        irManager.transmit(38000, signal);  // Отправка повторного сигнала
    }

    private int[] encodeNEC(int necCode) {
        int[] encodedSignal = new int[68];
        int i = 0;

        // Начало сигнала (9 мс, 4.5 мс пауза)
        encodedSignal[i++] = 9000;  // 9 мс
        encodedSignal[i++] = 4500;  // 4.5 мс пауза

        // Адрес и инверсия (27 мс для каждого бита)
        for (int bit = 31; bit >= 0; bit--) {
            if ((necCode & (1 << bit)) != 0) {
                encodedSignal[i++] = 560;  // 27 мс для бита 1
                encodedSignal[i++] = 1690; // 27 мс для бита 1
            } else {
                encodedSignal[i++] = 560;  // 27 мс для бита 0
                encodedSignal[i++] = 560;  // 27 мс для бита 0
            }
        }

        // Конец сигнала (широкая пауза)
        encodedSignal[i++] = 560;
        encodedSignal[i++] = 39416;  // Пауза на завершение

        return encodedSignal;
    }
}

Fabric.js Inline Image Cropping Using Control Dots (mt, mb, mr, ml)

I am working with Fabric.js and need to implement inline image cropping using control dots (mt, mb, mr, ml). My goal is to achieve the following behavior:

Horizontal Resizing (mr, ml) → Instead of stretching, the image should zoom and crop from the top and bottom.

Vertical Resizing (mt, mb) → Instead of stretching, the image should zoom and crop from the left and right.

Essentially, the image should scale while maintaining aspect ratio, and cropping should be applied dynamically as the controls are adjusted.

How can I achieve this effect using Fabric.js? Any guidance or examples would be appreciated!

enter image description here

ReferenceError: normalizedWhisper is not defined in whisper update test

Explain what you’re working on and what problems you’re facing in detail
I’m currently learning about testing with Jest, and there’s one test in an ‘it’ block that’s failing. The issue happens when I try to update a task, but the task doesn’t have an ID (it’s null).
Explain what you’ve done so far and what you want to achieve
I’m working on testing the to-do list endpoint for updating tasks, but it’s not working because it can’t find a valid ID. What I want to achieve is being able to update the task using a valid ID.
https://github.com/prabowo-sakti/fullstack-todo/tree/main/back-end
Thanks in advance for taking the time to help answer this.
Here’s my env file:

JWT_SECRET=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
MONGODB_URI=mongodb://sakti26:[email protected]:27017/whispering-database?authSource=admin
PORT=3000
MONGO_INITDB_ROOT_USERNAME=sakti26
MONGO_INITDB_ROOT_PASSWORD=testing123

How to run the code:

  1. Download MongoDB
  2. Download Mongosh
  3. Download Mongosh
  4. Install dependencies using pnpm i or if you use npm, you can delete the pnpm-lock.yaml file and then run npm i
  5. Run the command pnpm infra:start && pnpm start