Javascript that toggles sub-menu also disabling sub-menu links

I’m using the code below to toggle the the sub-menu. The toggle works great, but it disables both the parent link (a good thing) and also the sub-menu links (definitely NOT a good thing).

What do I need to do with this piece of code to have the sub-menu links remain enabled?

jQuery(document).ready(function () {
   jQuery('#menubar ul.sub-menu').hide();
    if (jQuery('.menu-item-has-children').length > 0) {
        jQuery('.menu-item-has-children').click(
        function (event) {
            jQuery(this).addClass('toggled')
            if (jQuery(this).hasClass('toggled')) {
                jQuery(this).children('ul').toggle();
            }
            return false;
        });
    }
});

and here’s the menu structure:

<nav id-"menubar">
    <div class="menu-header">
        <ul id="nav" class="menu">
            <li class="menu-item"><a href="/">Home</a></li>
            <li class="menu-item menu-item-has-children">
                <a href="#">Page 2</a>
                <ul class="sub-menu">
                    <li><a href="#">A</a></li>
                    <li><a href="#">B</a></li>
                    <li><a href="#">c</a></li>
                </ul>
            </li>
        </ul>
    </div>
</nav>

JavaScript replace and replaceAll not working as expected [duplicate]

I’m having trouble with the replace and replaceAll functions in JavaScript. I have the following fragment, which is part of a Handlebars file:

<div class="default-nav-footer__social-media--responsive">
  {{#each socialNetworks}}
  <a href="{{url}}" target="_blank" class="header--custom-svg" rel="noopener noreferrer nofollow">
    {{> (concat 'icons/social_networks/' (lookup . 'name'))}}
  </a>
  {{/each}}
</div>

When I try to run:

str.replace('icons/social_networks/', 'icons/');

It doesn’t work. I also tried:

str.replace(new RegExp(`icons/social_networks/`, 'g'), 'icons/');

but that didn’t work either. Interestingly, if I use:

str.replace(new RegExp(`icons/social_networks/`, 'g'), match => {
  console.log(match);
});

It successfully logs all the matches it finds in the string, but no matter what I try, the actual string replacement is not happening as expected.

Why is replace not working, even though the matches are being found? How can I ensure that the strings are replaced correctly?

Edit: str refers to handlebar fragment shown above. I still expect replace to return a new string with the required replacements, but the result is exactly the same as the original string. We are not compiling the Handlebars template because it doesn’t matter for this case—I am handling it as plain text, not as Handlebars code. I mentioned the Handlebars syntax because it might look different from standard HTML, but that’s not relevant to the problem at hand.

How can I get the SVG to refresh in the browser after I’ve made changes with Javascript?

I have an SVG on the page which I am trying to edit. When I look at the element in the console after making the changes, I can see the source looks correct. Yet, it doesn’t upgrade in the browser. I’m suspecting this is some sort of caching issue? Otherwise I’m missing something basic. Here is the example:

<div class="svg">
    <svg id="svg" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 40" style="background-color: #333;">
        <line x1="10" x2="40" y1="40" y2="10" stroke="red"></line>
    </svg>
</div>
<script>
const svg = document.getElementById('svg');
const svgNS = svg.getAttribute('xmlns');
const line = document.createElementNS(svgNS, 'line');
line.setAttributeNS(svgNS, 'x1', '10');
line.setAttributeNS(svgNS, 'x2', '40');
line.setAttributeNS(svgNS, 'y1', '10');
line.setAttributeNS(svgNS, 'y2', '40');
line.setAttributeNS(svgNS, 'stroke', 'red');
svg.appendChild(line);
console.log(svg);
</script>

Very simply, the SVG comes up with one red slash and I’m trying to dynamically turn it into an X by adding a slash in the other direction. When I look in the console, I see this:

<svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 40" style="background-color: #333;">
    <line x1="10" x2="40" y1="40" y2="10" stroke="red"></line>
    <line x1="10" x2="40" y1="10" y2="40" stroke="red"></line>
</svg>

Yet the browser continues to just show the one slash. Most of the other similar questions have answers that say to specify the namespace when editing. I’m doing this. What am i missing?

How to log browser APIs called by a script in Puppeteer?

I am using Puppeteer with Chromium to execute JS scripts in headless mode and I am trying to find out what browser APIs a script is calling by executing it instead of statically analyzing it.

Does Puppeteer provide functionality to do that or will I have to modify Chromium’s source code to achieve that?

A simple example I would like would be visiting a site and logging any browser APIs that the site’s JavaScript calls.

Why can’t I build prodution build, but dev build works fine?

I have a project written in next js. The problem is that I’m trying to deploy it to vercel, but I can’t build the prodution build.

When trying to build a project, a bunch of errors like Error: connect ECONNREFUSED 127.0.0.1:3000 and many other incomprehensible errors occur. The Dev build starts and works fine. Link to project https://github.com/Dzhambulat-Kagermanov/protfolio-guestHouse

Here are some build errors:

[Error]: connect ECONNREFUSED 127.0.0.1:3000
at X.from (C:UsersДжамбулатDesktopПроектыHTMLPortfolioguest-house1.nextserverchunks712.js:11:11618)
at y. (C:UsersДжамбулатDesktopПроектыHTMLPortfolioguest-house1.nextserverchunks712.js:13:9607)
at y.emit (node:events:514:28)
at d. (C:UsersДжамбулатDesktopПроектыHTMLPortfolioguest-house1.nextserverchunks712.js:1:13572)
at ClientRequest.emit (node:events:514:28)
at Socket.socketErrorListener (node:_http_client:501:9)
at Socket.emit (node:events:514:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
at aM.request (C:UsersДжамбулатDesktopПроектыHTMLPortfolioguest-house1.nextserverchunks712.js:13:21562)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async j (C:UsersДжамбулатDesktopПроектыHTMLPortfolioguest-house1.nextserverchunks858.js:1:1622) {
port: 3000,
address: ‘127.0.0.1’,
syscall: ‘connect’,
code: ‘ECONNREFUSED’,
errno: -4078,

Error occurred prerendering page “/articles”

cause: Error: connect ECONNREFUSED 127.0.0.1:3000
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -4078,
code: ‘ECONNREFUSED’,
syscall: ‘connect’,
address: ‘127.0.0.1’,
port: 3000
},
digest: ‘1651881529’

Export encountered errors on following paths:
/about/page: /about
/articles/page: /articles
/page: /

iOS 18, Safari 18 has issues with setTimeout?

I have a simple web page that does an xhr (post) call every 5 seconds to an endpoint to fetch information and update the page. It was understood that mobile browsers usually throttle queued actions (setTimeout, setInterval) when the tab is no longer active. But the execution used to restart when the tab again became active. However, on iOS 18’s Safari, something has changed. The execution of setTimeout scripts do not continue immediately after the tab becomes active, at times it takes 40 seconds for the actions to resume and at other times it takes 120-150 seconds. I could not find anything in the Safari change log that alludes to this change. This is specifically occurring on iPhones.

Has anyone else noticed this?

JavaScript Script Issue for Dynamic Video Playback

I’m experiencing an issue with my JavaScript script that is supposed to manage video playback on my platform. Currently, the script works correctly for video elements already present on the page, but it does not account for new video elements that are dynamically loaded. None of the scripts work for these new elements.

Dynamic Loading: Videos are added to the page via AJAX when a user scrolls down.
Using IntersectionObserver: I’m attempting to start or stop video playback based on their visibility using the IntersectionObserver.

Problems Encountered

No Playback for New Elements: When new video elements are loaded, the script does not work for these.
Complete Script Non-Functional: None of the script seems to function for these new elements.

What can I do to ensure that the script also works for newly loaded video elements?
Are there best practices I should follow to correctly observe these new elements?

My JS:

document.addEventListener('DOMContentLoaded', () => {
        let currentVideo = null;  
        const pulseContainer = document.getElementById('pulse-container');
        let currentPage = 1;
        let loading = false;
        let visibleVideoCount = 0;

        function handleVideoPlayback(entries) {
            entries.forEach(entry => {
                const video = entry.target;
                if (entry.isIntersecting) {
                    if (currentVideo !== video) {
                        video.play();
                        video.loop = true;
                        if (currentVideo) {
                            currentVideo.pause();
                        }
                        currentVideo = video;
                    }
                    visibleVideoCount++;
                    console.log(visibleVideoCount);
                } else {
                    if (currentVideo === video) {
                        currentVideo = null;  
                    }
                    video.pause();
                }
            });
    
            // Vérifiez si le compteur de vidéos visibles atteint 5
            if (visibleVideoCount >= 5) {
                console.log('loadmore please');
                loadMoreContent(); // Charge plus de contenu
                visibleVideoCount = 0; // Réinitialise le compteur
            }
        }  
    
        const observer = new IntersectionObserver(handleVideoPlayback, {
            root: null,
            rootMargin: '0px',
            threshold: 0.5
        });
    
        const videos = document.querySelectorAll('.pulse-video');
        videos.forEach(video => {
            observer.observe(video);
            video.addEventListener('error', (e) => {
                console.error('Erreur de chargement de la vidéo:', e);
            });
            video.src = video.getAttribute('data-src');
            video.load();
           
        });
    
        function toggleGlobalSound() {
            const newMutedState = !Array.from(videos).some(video => video.muted);
            videos.forEach(video => {
                video.muted = newMutedState;
            });
            const globalSoundButtons = document.querySelectorAll('#global-sound-toggle i');
            globalSoundButtons.forEach(icon => {
                icon.classList.toggle('fa-volume-xmark', newMutedState);
                icon.classList.toggle('fa-volume-high', !newMutedState);
            });
        }
        
        const globalSoundButtons = document.querySelectorAll('#global-sound-toggle');
        globalSoundButtons.forEach(button => {
            button.addEventListener('click', toggleGlobalSound);
        });
    
        function setupVideoClickHandler() {
            const videos = document.querySelectorAll('.pulse-video'); // Récupère les vidéos à chaque appel
            videos.forEach(video => {
                video.addEventListener('click', () => {
                    video.paused ? video.play() : video.pause();
                    if (currentVideo && currentVideo !== video) {
                        currentVideo.pause();
                    }
                    currentVideo = video;
                });
            });
        }
    
        function handleVisibilityChange() {
            if (document.hidden && currentVideo) {
                currentVideo.pause();
            } else if (!document.hidden && currentVideo) {
                currentVideo.play();
            }
            
        }
        const artistContents = document.querySelectorAll('.artist-content');

        artistContents.forEach(content => {
            const toggleButton = content.querySelector('.toggle-description');

            if (toggleButton) {
                toggleButton.addEventListener('click', () => {
                    content.classList.toggle('open');
                });
            }
        });
        const allArtistElements = document.querySelectorAll('.all_artist'); // Pour plusieurs artistes
        
        allArtistElements.forEach(function(artistContent) {
            const toggleButton = artistContent.querySelector('.toggle-description');
            const descriptionContent = artistContent.querySelector('.description-content');
            
            // Fonction pour ajuster la hauteur de .all_artist.open
            function adjustHeight() {
                const descriptionHeight = descriptionContent.scrollHeight; // Hauteur réelle du contenu
                const additionalHeight = 0; // Hauteur supplémentaire pour que ça monte plus
                artistContent.style.height = `${descriptionHeight + additionalHeight}px`; // Ajuste la hauteur en fonction du contenu
                artistContent.style.transform = `translateY(-${descriptionHeight + additionalHeight}px)`; 
            }
            
            // Fonction pour ouvrir et fermer le contenu
            function toggleArtistContent() {
                artistContent.classList.toggle('open');
                if (artistContent.classList.contains('open')) {
                    descriptionContent.style.transform = 'translateY(0)'; // Annule le translateY
                    descriptionContent.style.opacity = '1'; // Affiche le contenu
                    descriptionContent.style.visibility = 'visible'; // Rend le contenu visible
                    adjustHeight(); // Ajuste la hauteur de .all_artist.open
                } else {
                    descriptionContent.style.transform = 'translateY(-50px)'; // Cache l'élément
                    descriptionContent.style.opacity = '0'; // Rend le contenu invisible
                    descriptionContent.style.visibility = 'hidden'; // Cache le contenu
                    artistContent.style.height = 'auto'; // Réinitialise la hauteur
                    artistContent.style.transform = `translateY(0)`; // Réinitialise la position
                }
            }
            
            // Écouteur d'événement sur le bouton pour basculer l'affichage
            toggleButton.addEventListener('click', toggleArtistContent);
        });
    
        document.addEventListener('visibilitychange', handleVisibilityChange);
    
        function adjustVideoSize() {
            videos.forEach(video => {
                video.style.width = '100%';
                video.style.height = '100%';
                video.style.objectFit = 'cover';
            });
        }
    
        function preloadVideos() {
            const videos = document.querySelectorAll('.pulse-video'); // Récupère les vidéos à chaque appel
            videos.forEach(video => {
                const rect = video.getBoundingClientRect();
                if (rect.top < window.innerHeight && rect.bottom > 0) {
                    if (video.src === '') {
                        video.src = video.getAttribute('data-src');
                        video.load();
                    }
                }
                observer.observe(video); // Assure-toi que chaque vidéo est observée
            });
        }
        const loadMoreUrl = '/pulses/load-more-pulses/';
        function loadMoreContent() {
            console.log('Trying to load more content...');
            if (loading) return;
            loading = true;
    
            const url = `/pulses/load-more-pulses/?page=${currentPage}`;
            fetch(url)
                .then(response => {
                    console.log('Response status:', response.status);
                    if (!response.ok) {
                        throw new Error('Network response was not ok');
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('Data received:', data);
                    if (data.pulse_data) {
                        data.pulse_data.forEach(pulse => {
                            pulseContainer.insertAdjacentHTML('beforeend', pulse.html);
                        });
                        currentPage++;
                        initializeNewElements()
                       
                    }
                })
                .catch(error => {
                    console.error('Error loading more content:', error);
                })
                .finally(() => {
                    loading = false;
                });
        }
    
        // Appelle les fonctions au chargement initial
        preloadVideos();
        
       
    
        function setupInteractionButtons() {
            const likeButtons = document.querySelectorAll('.like-button');
            const shareButtons = document.querySelectorAll('.share-button');
    
            likeButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const pulseId = button.dataset.pulseId;
                    fetch('{% url "pulses:toggle_like" %}', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'X-CSRFToken': getCookie('csrftoken')
                        },
                        body: new URLSearchParams({ 'pulse_id': pulseId })
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.error) {
                            alert(data.error);
                        } else {
                            button.querySelector('i').classList.toggle('fa-solid', data.liked);
                            button.querySelector('i').classList.toggle('fa-regular', !data.liked);
                            button.querySelector('i').style.color = data.liked ? '#d20000' : 'floralwhite';
                            button.querySelector('.like-count').textContent = data.like_count;
                        }
                    })
                    .catch(error => console.error('Error:', error));
                });
            });
    
            shareButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const pulseId = button.dataset.pulseId;
                    fetch('{% url "pulses:share_pulse" %}', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-CSRFToken': getCookie('csrftoken')
                        },
                        body: JSON.stringify({ pulse_id: pulseId })
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.success) {
                            document.querySelector(`.share-count[data-pulse-id="${pulseId}"]`).textContent = data.share_count;
                            navigator.clipboard.writeText(data.share_url)
                                .then(() => {
                                    alert('Lien copié!');
                                })
                                .catch(err => {
                                    console.error('Erreur lors de la copie du lien:', err);
                                });
                        }
                    })
                    .catch(error => console.error('Error:', error));
                });
            });
        }
    
        document.querySelectorAll('.toggle-comments').forEach(button => {
            button.addEventListener('click', () => {
                const commentsSection = button.closest('.pulse_item').querySelector('.comments-section');
                commentsSection.style.display = commentsSection.style.display === 'none' || commentsSection.style.display === '' ? 'flex' : 'none';
            });
        });
    
        setupVideoClickHandler();
        setupInteractionButtons();
        adjustVideoSize();
        preloadVideos();
    });
    
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let cookie of cookies) {
                cookie = cookie.trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }


    function loadScript(scriptUrl) {
        const script = document.createElement('script');
        script.src = scriptUrl;
        script.type = 'text/javascript';
        document.body.appendChild(script);
    }
    
    
    function initializeNewElements() {
        const videos = document.querySelectorAll('.pulse-video');
        if (!videos.length) return; // Vérification de la présence de vidéos
    
        videos.forEach(video => {
            observer.observe(video);
        });
        
        setupInteractionButtons(); // Ajouter les interactions aux nouveaux boutons
    }
 

My global HTML:

   <div class="all_pulse">
    <div class="pulse_title">Pulse</div>
    <div class="pulse_contains" id="pulse-container">
        {% for pulse in pulses %}
            {% include 'pages/partial-pulse.html' with pulse=pulse %}
        {% endfor %}
    </div>
    <div class="bar">
        <div class="bar-item">
            <a href="{% url 'content:index' %}" style="color:white;"><i class="fa-solid fa-house"></i></a>
            <a href="{% url 'beats:new_explore' %}" style="color:white;"><i class="fa-solid fa-magnifying-glass"></i></a>
            <a href="{% url 'pulses:pulse' %}" style="color:white;"><i class="fa-solid fa-compact-disc fa-lg" style="margin-top:5.5px;"></i></a>
            <a href="{% url 'accounts:conversations' %}" style="color:white;"><i class="fa-solid fa-message"></i></a>
            <a href="{% url 'accounts:profile' %}" style="color:white;"><i class="fa-solid fa-user"></i></a>
        </div>
    </div>
</div>   

My HTML which is implemented with ajax:

{% load static %}
<script src="{% static 'js/new_pulse.js' %}"></script>
<div class="pulse_item">
    <div class="video-wrapper">
        <video data-src="{{ pulse.video.url }}" class="pulse-video" src="{{ pulse.video.url }}"   muted playsinline></video>
        
    </div>
    <div class="comments-section" style="display: none;">
        <div class="comment-list">
            <h5 class="title_comments">Comments</h5>
            {% if pulse.comments.all %}
                {% for comment in pulse.comments.all %}
                    <div class="comment">
                        <strong>{{ comment.user.username }}:</strong>
                        <p>{{ comment.text }}</p>
                        <small style="color:grey;">{{ comment.created_at|date:"d M Y, H:i" }}</small>
                    </div>
                {% endfor %}
            {% else %}
                <p style="color:white;">Aucun commentaire</p>
            {% endif %}
         </div>
        <textarea class="comment-input" placeholder="Écrivez un commentaire..."></textarea>
        <button class="button-up" data-pulse-id="{{ pulse.id }}">Envoyer</button>
        
    </div>
    <div class="interacts">
        <div class="item-orga">
            
            <button class="like-button" data-pulse-id="{{ pulse.id }}" style="background-color:transparent;color:white;border:none;">
                <i class="fa-heart {% if pulse.liked %}fa-solid{% else %}fa-regular{% endif %} fa-xl" style="color: {% if pulse.liked %}#d20000{% else %}floralwhite{% endif %}; margin-right: 4px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"></i>
                <span class="like-count">{% if pulse.like_count %}{{ pulse.like_count }}{% else %}0{% endif %}</span>
            </button>
            <button class="share-button" data-pulse-id="{{ pulse.id }}" style="background-color:transparent;color:white;border:none;">
                <i class="fa-solid fa-share fa-xl" style="color:floralwhite;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"></i>
                <span class="share-count" data-pulse-id="{{ pulse.id }}">{% if pulse.share_count %}{{ pulse.share_count }}{% else %}0{% endif %} </span>
            </button>
            <button class="comments-button" data-pulse-id="{{ pulse.id }}" style="background-color:transparent;color:white;border:none;">
            <i class="fa-solid fa-comments fa-xl toggle-comments" style="color:floralwhite;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"></i>
            <span class="comments_count" data-pulse-id="{{ pulse.id }}">{% if pulse.comments %}{{ pulse.comments_count }}{% else %}0{% endif %} </span>
            </button>
            <button id="global-sound-toggle"><i class="fa-solid fa-volume-xmark" style="color:floralwhite;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"></i></button>
        </div>
    </div>
    
    <div class="data_artist">
        <div class="all_artist">
            <div class="artist-content">
                <div class="profile_picture_pulse">
                    {% if pulse.user.profile_picture %}
                        <img src="{{ pulse.user.profile_picture.url }}" class="img-fluid rounded-circle" style="min-width: 50px;max-width: 50px; height: 50px;" alt="Profile Picture">
                    {% else %}
                        <img src='/static/images/default_profile.png' class="img-fluid rounded-circle" style="width: 50px; height: 50px;" alt="Profile Picture">
                    {% endif %}
                </div>
                <div class="username_pulse">
                    <strong> <p id="superstrong" style="margin-bottom:0;">{{ pulse.user.username }} </p></strong>
                    
                    {% if request.user != pulse.user %}
                        <button id="sub_pulse"
                        class="follow-toggle-btn btn-style-2 {% if is_followed %}btn-yes{% else %}btn-no{% endif %}"
                            data-user-id="{{ pulse.user.id }}"
                        >
                            {% if is_followed %}Unfollow{% else %}Follow{% endif %}
                        </button>
                        <span style="margin-left:5px;" class="follower-count">{{ pulse.follower_count }}</span>
                        <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
                    {% endif %}
                    
                    <button class="toggle-description" aria-label="Show description">
                        <i class="fa-solid fa-chevron-down"></i>
                    </button>
                </div>
            </div>
            
            
            
            
            
            <div class="description-content">
                <p class="description-text">
                    {{ pulse.description }}<span class="more-text">{{ pulse.description|slice:"100:" }}</span>
                    {% for hashtag in pulse.hashtags.all %}
                    <a href="" alt="{{hashtag.name}}"style="text-decoration:none;">#{{hashtag}} </a>
                    {% endfor %}
                </p>
                
            </div>
        </div>
   

        
        <div class="song-content">
            <div class="song_pulse">
                <img src="/static/images/explore.webp" alt="Cover" class="square-image-x-fill beat-icon-beat_detail">
            </div>
        </div>
    </div>
    
</div>`

Axe Core Puppeteer Opening White browser with node JS

When I am trying to implement puppeteer plugin in node js blank browser is opening, I don’t want to open that white window when we are making headless as true.

Below is the code how I am implementing the puppeteer

const browser = await puppeteer.launch({
    headless: true,
    args: [
       '--no-sandbox', '--disabled-setuid-sandbox'
    ]
})

Word add-in: Show external API call response in Taskpane?

I’ve developed a simple Word Add-in which calls an external API with the selected text from the right-click menu. I can then insert the response on the Document, by I’d rather show the response on the taskpane.

I’ve tried adding a placeholder div on the taskpane, and then modifying the innerHtml from the commands.js function which calls the API, but it doesn’t work. It seems like commands.js (which holds the right click menu function) cannot directly modify the taskpane? How do I overcome this?

How do you persist the Paho MQTT client object in a React app?

I am using the Paho MQTT Javascript library in my React App to connect to an MQTT server. Everything is working fine but I would like to provide the user an option to manually disconnect from the server on clicking a button.

Give that the connect const client = new Paho.Client(...) is on one page and the button to call disconnect may be on another page, how can the client object be persisted and used in another page to call client.disconnect()?

I hope my question is clear. Everything else in the code is working as expected. Sharing the Redux code that I feel is relevant and not working as expected (if that is even the right approach).

I tried storing the client object in Redux after setting serializableCheck: false. But the client object is not getting saved in Redux, an empty object ({}) is stored. I am using Redux extensively and it is all working fine but I am not trying to store such an object anywhere else.

Here is the Redux function:

addConnectedMQTTClient: (state, action) => {
console.warn(action.payload.client); // This is showing the client as expected.
state.connected_mqtt_clients.push(action.payload.client);

The redux state shows:

"connected_mqtt_clients": [
    {
      "client": {}
    }
  ]

Upload tag video vimeo API

I can’t upload tags of video to vimeo

Can anyone help me, I have a problem uploading tags for videos, my syntax is below

const uploadTagsService = async (videoUri, tags) => {
  return new Promise((resolve, reject) => {
    client.request({
      method: 'PUT',
      path: `${videoUri}/tags`,
      query: {
        tags: tags
      }
    }, (error, body) => {
      if (error) {
        reject({ status: 500, message: error.message });
      } else {
        resolve({ status: 200, message: 'Video tags updated successfully', data: body });
      }
    });
  });
};

My tags be like:

tags = [
    { "name" : "tui1" },
    { "name": "tui2" }
]

Result is:


{
    "success": true,
    "data": {
        "total": 0,
        "page": 1,
        "per_page": 25,
        "paging": {
            "next": null,
            "previous": null,
            "first": "/videos/xxx/tags?page=1",
            "last": "/videos/xxx/tags?page=1"
        },
        "data": []
    },
    "message": "Video tags updated successfully"
}

Data will be null, I try to change

query: {
tags: tags
} 

by body, or data, it still not working

I need to know if there is a specific way to modify javascript [closed]

When I create userscripts(using tampermonkey) is there a certain way I need to write, that specifically changes what is on that website? Or do I just write the javascript as if I was making my own website, and tampermonkey just puts it over the website? This would help me a lot because I’m still not sure if i need to learn an entire other part of javascript that would take me more time.

I still haven’t tried anything, but I haven’t seen anyone say anything about specific type of javascript for changing websites.

How do I change the separator of the data table with Vuetify 3?

Hi everyone!

I’m studying Vue and Vuetify 3, and I want to style the data table, but it’s impossible. Haha. I want to figure out how to change the color or background of the separators in the table between the content and how to change the background of the table header. Thank you!

https://codepen.io/Vinicius-Ribeiro-the-typescripter/pen/QWeWXoG

`

<v-data-table

  :headers="headers"

  :items="items"

  :items-per-page="3" 

  :pagination.sync="pagination"

  class="elevation-0 ma-0"

  style="max-height: 400px; overflow-y: auto;"

></v-data-table>

`

https://codepen.io/Vinicius-Ribeiro-the-typescripter/pen/QWeWXoG

Helmet JS CSP configuration to allow external css and JS script – Where is the inline script?

I am relatively new to JavaScript and ExpressJS. I am trying to make a web application with a functional login page. I am trying to configure the helmet JS middle ware to allow for external css and scripts. However I am still receiving:
Content-Security-Policy: The page’s settings blocked an inline script (script-src-elem) from being executed because it violates the following directive: “script-src 'self'” .

I am not sure where the inline script is located in my html file.

Here is my folder structure:

-> public
    -> Login_Page_template
        - logo.jpg
        - login_page_client.js
        - static_login_page.html
        - static_login_styles.css
-> src
    -> routes
        - LOGIN_PAGE.js

- Entry_Point.js

Where Entry_Point.js is:

// Date Created: September 11 2024
// Date Last Updated: September 23 2024 

const express = require("express");
const ejs = require("ejs");
const cors = require("cors");
const fs = require("fs");
const https = require("https");
const helmet = require("helmet");

// Importing Routes
const getItems = require("./src/routes/DB_GET_ITEMS");
const login_page = require("./src/routes/LOGIN_PAGE");

const app = express();
// View engine setup 
app.set('view engine', 'ejs');

// Allows request from any IP (prevent any CORS error)
app.use(cors()); 

app.use(express.json({limit: "1mb"}));

// Enable parsing of URL-encoded data on all routes:
app.use(express.urlencoded({
   extended: true, // Whether to use algorithm that can handle non-flat data strutures
}));

// Define the Content Security Policy (from chatgpt)
const cspConfig = {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: [
        "'self'",         // Allows styles from your own domain
        'https://fonts.googleapis.com' // Allow Google Fonts, etc.
      ],
      scriptSrc: ["'self'"],
      fontSrc: [
        "'self'",
        'https://fonts.gstatic.com' // Allow fonts from Google Fonts
      ],
    },
  };
  

// added helmet as middleware
app.use(helmet({
    contentSecurityPolicy:true,
    directives: cspConfig.directives,
})); 

app.get("/",login_page.Send_login_page);
app.get("/params/",getItems.Router_DB_Params);

// made some self signed keys - not CA (not authorized by acceptable vendor)
const options = {
    key: fs.readFileSync(__dirname+"\config\cert\key.pem"),
    cert: fs.readFileSync(__dirname+"\config\cert\cert.pem")
};

https.createServer(options, app).listen(80, ()=>{
    console.log("https://localhost:80/");
});

LOGIN_PAGE.js is:

// Date Created: September 16 2024
// Date Last Updated: September 24 2024

const express = require("express");
const app = express();
const path = require('path');
const cors = require('cors');

app.use(cors()); // Allows request from any IP (prevent any CORS error)
app.use(express.static(path.join(__dirname, '../../public'))); // used to make it easier to reference static files such as certain .css and .html files

// Enable parsing of URL-encoded data on all routes:
app.use(express.urlencoded({
    extended: false, // Whether to use algorithm that can handle non-flat data strutures
 }));

function Send_login_page(req,res,next){
    const options = {root: path.join(__dirname,"../../public/")};
    res.sendFile("/Login_Page_template/static_login_page.html",options);
};

module.exports= {
    Send_login_page,
};

and the static_login_page.html is:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Portal</title>
    <link rel="stylesheet" src="./static_login_styles.css">

</head>
<body>    
    <div class="container">
        <div class="logo">
            <img src='./logo.jpg/' alt="Logo">
        </div>
        <div class="form">
            <form>
                <h1>Sign In?</h1>

                <input type="text"  id="username"  placeholder="Username" name="username">
                
                <input type="text"  id="password"  placeholder="Password" name="password">
                
                <input type="submit"  id="Submit_Login_btn"  value="Login">
            </form>
        </div>
        <div class="bypass">
            <a href="https://192.168.10.57:80/params/">
                <input type="button" name="Button" value="View">
            </a>
        </div>
    </div>
    <script type="text/script" src='./login_page_client.js'></script>
</body>
</html>

And Finally the login_page_client.js is:

// Date Created: July 23 2024
// Date Last Updated: August 26 2024

const login_form = document.querySelector('form');

login_form.addEventListener("submit", e => {
  e.preventDefault();

  var button = document.getElementById("Submit_Login_btn");
  var username_input = document.getElementById("username");
  var password_input = document.getElementById("password");

  const form_data = new FormData(login_form);

  const urlEncoded = new URLSearchParams(form_data).toString();
  
  const options = {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: urlEncoded
  };

  const response = fetch('/api/login-details',options);

  
});

Please note that when I append the styles using Fire Fox’s append style sheet option the styles load normally without error.