Svelte $effect behaving differently in runes mode

Component in svelte 4:

<script>
  let x = 1
  let y = "less than 10"

  function check(){
    if(x > 10){
      y = "more than 10"
    }
  }

  $: {
    check()
  }
</script>

<div>
not runes
<button onclick={() => x++ }>{x}</button>
{y}
</div>

Notice how the reactive statement calls a check function, so the reactive statement is never triggered because “x” is not directly called.

But in runes mode the $effect is triggered even if “x” does not directly appear in the effect body:

<script>
  let x = $state(1);
  let y = $state("less than 10");

  function check(){
    if(x > 10){
      y = "more than 10"
    }
  }

  $effect(() => {
    check()
  })
</script>
<div>
runes
<button onclick={() => x++ }>{x}</button>
{y}
</div>

I guess this is change in how svelte effects work from 4 to 5, but I was wondering how does svelte know when to run the effect, when in runes mode? Does it look into the function code and check of reactive vars? What if I have a deeply nested function call, with a reactive var in the deepest function, will the effect still detect it?

How with YouTube Data API v3 get created clips on own channel

Screenshot from https://www.youtube.com/feed/clips

How i can get a array of clips from this page “https://www.youtube.com/feed/clips” using YouTube Data API v3? Or tell me other solution for my problem, please.

I tried node.js using puppeteer, but I had some problems logging in to my Google account and waiting for the page to fully load in order to parse the information about the clips from the page.

this is an example of how I received information from the browser console.

contents = document.querySelector("#contents");
            listClipsHTML = contents.querySelectorAll("#dismissible")
            clips = [];
            listClipsHTML.forEach(clipHTML => {
                let clip = {};
                clip.img = clipHTML.querySelector("yt-image img").src;
                clip.link = clipHTML.querySelector("a#thumbnail").href;
                clip.lenght = clipHTML.querySelector("#time-status #text").innerText
                clip.viewed = clipHTML.querySelector("#metadata-line span:nth-child(1)").innerHTML
                clip.title = clipHTML.querySelector("#video-title").text
                clip.author = clipHTML.querySelector("#channel-name #text").title
                clip.createdAt = clipHTML.querySelector("#metadata-line span:nth-child(2)").innerHTML
                clips.push(clip);
            });

Zoom SDK – Keep Receiving ‘You are hosting another meeting’

Im trying to join a meet from HTML and JS using Zoom Meet SDK. But when I try to join, I keep getting ‘You are hosting another meeting. Do you want to end it and start this new meeting?’. The meeting room I first created using Zoom Workplace using a zoom account. And the signature I generate at https://developers.zoom.us/docs/meeting-sdk/auth/ . The console log that i get is {method: ‘join’, status: false, result: null, errorMessage: ‘Fail to join the meeting.’, errorCode: 1}. What should I do to make it successfully join the meeting I created from HTML?

Error Zoom

My Code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kiosk Video Call</title>

    <!-- Required Zoom CSS -->
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/3.1.0/css/bootstrap.css" />
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/3.1.0/css/react-select.css" />
        
    <style>
        body {
            background-color: rgb(63, 63, 63) !important;
            color: rgb(46, 46, 46);
            text-align: center;
        }
        #zmmtg-root {
            display: none; /* Initially hidden until Zoom starts */
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1000;
        }
        .controls {
            position: relative;
            z-index: 1001;
        }
        .btn {
            background-color: #007bff;
            border: none;
            color: white;
            padding: 15px 32px;
            font-size: 16px;
            cursor: pointer;
            margin-top: 20px;
        }
        .input-field {
            margin: 10px auto;
            padding: 8px;
            width: 80%;
            max-width: 400px;
            display: block;
        }
        .zoom-kiosk-title {
            font-size: 3rem;
            margin: 4rem;
            font-family: 'Epilogue', sans-serif;
            color: darkgray;
        }
    </style>
</head>
<body>
    <div id="zmmtg-root"></div>

    <div class="controls">
        <h1 class="zoom-kiosk-title">Kiosk Video Call</h1>
        <input id="meetingNumber" class="input-field" type="text" placeholder="Enter Meeting Number">
        <input id="passWord" class="input-field" type="text" placeholder="Enter Meeting Password">
        <input id="userName" class="input-field" type="text" placeholder="Enter Your Name" value="Kiosk Client">
        <input id="sdkKey" class="input-field" type="text" placeholder="Enter SDK Key">
        <input id="signature" class="input-field" type="text" placeholder="Enter Signature">
        <button id="startSession" class="btn">Start Session</button>
    </div>

</body>

<!-- Add Lodash before Zoom SDK -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

<!-- Load Zoom SDK Dependencies -->
<script src="https://source.zoom.us/3.1.0/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/3.1.0/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/3.1.0/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/3.1.0/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/3.1.0/zoom-meeting-3.1.0.min.js"></script>
<script>
// Utility functions for debugging
const testTool = {
    parseQuery: () => {
        return {
            sdkKey: document.getElementById("sdkKey").value.trim(),
            meetingNumber: document.getElementById("meetingNumber").value.trim(),
            passWord: document.getElementById("passWord").value.trim(),
            userName: document.getElementById("userName").value.trim(),
            signature: document.getElementById("signature").value.trim(),
        };
    },
    detectOS: () => {
        const userAgent = navigator.userAgent.toLowerCase();
        if (userAgent.indexOf('win') > -1) return 'Windows';
        if (userAgent.indexOf('mac') > -1) return 'Mac';
        if (userAgent.indexOf('linux') > -1) return 'Linux';
        return 'Unknown OS';
    },
    getBrowserInfo: () => {
        const ua = navigator.userAgent;
        let tem;
        let M = ua.match(/(chrome|safari|firefox|msie|trident(?=/))/?s*(d+)/i) || [];
        return M[1] || "Unknown";
    }
};

// Main script
document.addEventListener('DOMContentLoaded', function () {
    if (typeof ZoomMtg === "undefined") {
        console.error("Zoom SDK failed to load.");
        return;
    }

    console.log("Zoom SDK Loaded");
    console.log(JSON.stringify(ZoomMtg.checkFeatureRequirements()));

    // Initialize Zoom SDK
    // ZoomMtg.setZoomJSLib('https://source.zoom.us/3.1.0/lib', '/av');
    ZoomMtg.setZoomJSLib('https://source.zoom.us/3.1.0/lib', '/av');
    ZoomMtg.preLoadWasm();
    ZoomMtg.prepareWebSDK();

    document.getElementById("startSession").addEventListener("click", function () {
        const meetingConfig = {
            sdkKey: document.getElementById("sdkKey").value.trim(),
            meetingNumber: document.getElementById("meetingNumber").value.trim(),
            passWord: document.getElementById("passWord").value.trim(),
            userName: document.getElementById("userName").value.trim(),
            signature: document.getElementById("signature").value.trim(),
        };

        if (!meetingConfig.meetingNumber || !meetingConfig.passWord || !meetingConfig.userName || !meetingConfig.sdkKey || !meetingConfig.signature) {
            alert("Please fill in all required fields.");
            return;
        }

        console.log("Meeting Config:", meetingConfig);
        console.log("Generated Signature:", meetingConfig.signature);

        // Initialize Zoom
        ZoomMtg.init({
            leaveUrl: 'https://localhost:8060/Default.html',
            isSupportAV: true,
            success: function () {
                document.querySelector(".controls").style.display = "none";
                console.log("Success init. Attempting to end any existing meeting...");
                // Try to end any existing meeting first
                proceedWithJoining();
                // ZoomMtg.leaveMeeting({
                //     success: function() {
                //         console.log("Successfully ended previous meeting");
                //         proceedWithJoining();
                //     },
                //     error: function(res) {
                //         console.log("No active meeting to end or error:", res);
                //         proceedWithJoining();
                //     }
                // });
            },
            error: function (res) {
                console.error("Zoom SDK Init Error:", res);
            }
        });

        // Function to handle the actual joining process
        function proceedWithJoining() {

            ZoomMtg.join({
                meetingNumber: meetingConfig.meetingNumber,
                userName: meetingConfig.userName,
                signature: meetingConfig.signature,
                sdkKey: meetingConfig.sdkKey,
                passWord: meetingConfig.passWord,
                success: function (res) {
                    console.log("Successfully joined meeting", res);
                },
                error: function (res) {
                    console.error("Error joining meeting:", res);
                }
            });
        }

        // Keep the event listeners for debugging
        ZoomMtg.inMeetingServiceListener("onUserJoin", function (data) {
            console.log("User joined:", data);
        });

        ZoomMtg.inMeetingServiceListener("onUserLeave", function (data) {
            console.log("User left:", data);
        });

        ZoomMtg.inMeetingServiceListener("onMeetingStatus", function (data) {
            console.log("Meeting status changed:", data);
        });
    });
});

</script>
</html>

How to make an invisible title with Javascript

I’m working on my site, it has an animated title. I’m wondering how I can make the title empty for a moment for a kind of typing effect?

If you need to see the function the site is FykeLore

Here’s an example:

<DOCTYPE html> 
<html>
<head>
<!-- Not the actual code because it's a MESS -->
<title id="webTitle">&lrm;</title>
</head>
<body>
<script>
        let wordPool = ['F', 'Fy', 'Fyk', 'Fyke', 'FykeL', 'FykeLo', 'FykeLor', 'FykeLore', 'FykeLor', 'FykeLo', 'FykeL', 'Fyke', 'Fyk', 'Fy', 'F', ''];
let step = -1;

function runTitle(){
    step = step == (wordPool.length - 1) ? 0 : step + 1;
    webTitle.textContent = wordPool[step];
}

window.onload = function(){
    window.setInterval(runTitle, 500);
}
</script>
</body>
</html>

(Sorry if this is formatted wrong, I just got here 10 minutes ago ;-;)

I’ve tried using invisible letters, but it ended up showing up with text (Like how emojis would on some things) which is not what I was going for. I also tried just a plain ‘ol space, which also didn’t work, expectedly. The last thing I tried was ‎ and sadly I think that may only work in HTML.

Dynamically wrap and group headings in list items with Vue render functions

I want to create a Vue component <Steps></Steps that is an ordered list, but provides some flexibility in how the slots are passed in.

Each step, or <li>, is created when encountering a heading tag. It could be either an h2, h3, or h4.

Inside of the <Steps> component, each time a heading tag is found, that needs to create and wrap everything up to the next heading tag of the same heading level. I am running into problems also because if a an h4 is used after an h3 this should not create an extra <li>.

It seems the best way to solve this would be with Vue’s render h() function but I am really stuck on this one.

Input

<Steps>
  <h3>heading a</h3>
  <p>paragraph a<p>
  <div class="code-block"><pre>const x = 1</pre></div>
  <h4>this should not create an li</h4>
  <h3>heading b</h3>
  <p>paragraph b<p>
</Steps>

Output

<ol>
  <li>
    <h3>heading a</h3>
    <p>paragraph a<p>
    <div class="code-block"><pre>const x = 1</pre></div>
    <h4>this should not create an li</h4>
  </li>
  <li>
    <h3>heading b</h3>
    <p>paragraph b<p>
  </li>
</ol>

Load different header based on current url in php using twig or javascript

I have four domains – domain.com, domain.org, domain.africa and domain.net. All share the same user base from db and some content. Users can register and log in on any website. Works perfectly. The problem is each website has its own registration and login form, which means when something changes I have to edit each form for each website as they must all work with the same db.
What I am trying to achieve is to have one registration and one login form shared by all four domains. I have done that and its working, but I am struggling to load what is specific to each domain, depending on which domain the user is currently on – like the header and footer for that domain.

I am using php with twig (no framework) and have tried various ways to achieve what I want, mostly found online, but none seems to work. I am willing to use twig inside javascript, if necessary.
Tried twig inside javascript (if url contains):
<script type="text/javascript"> var siteName=document.URL; </script>

<script>
    if (siteName.indexOf("domain1")  != -1) 
      {document.write("include('domains/domain1/includes/header.html')" )}
    else if (siteName.indexOf("domain2")  != -1) 
      {document.write("include('domains/domain2/includes/header.html')")}
    else if (siteName.indexOf("domain3")  != -1) 
      {document.write("include('domains/domain3/includes/header.html')")}
    else if (siteName.indexOf("domain4")  != -1) 
      {document.write("include('domains/domain4/includes/header.html')")}
  </script>

The above only loads domain1 header for all domains.
Using twig only:

{% if 'domain1' in url %}
{{ include('domains/domain1/includes/header.html') }}
{% endif %}

AND

{% if url == "https://domain.africa" %}
    {% include('domain/location/includes/site.header.html') %}
  {% endif %}

Twig gets no result.
In javascript method when I add a string like “domain1” and “domain2”, etc for each domain, instead of the twig include function, I get the correct output for each domain I visit. But the moment I add the twig include function the headers, I get the domain1 header loaded for all domains

Wrong list indentions with trumbowyg

I tried to use trumbowyg in my code but when I click on the “indent” button within the selected texts are an ordinal list. It directly puts the ul tag in the parent ul instead of putting it in il tag before.

For example:

<ul>
    <ul>
        <li><u>EDVA activities: </u></li>
        <ul>
            <li>&nbsp;3 flights this week:  1 gold flight.</li
        </ul>
        <li>&nbsp;8 shuttles</li>
    </ul>
</ul>
   

Instead of:

<ul>
    <li>
        <ul>
            <li><u>EDVA activities: </u></li>
            <li>
                <ul>
                    <li>&nbsp;3 flights this week:  1 gold flight.</li>
                </ul>
            </li>
            <li>&nbsp;8 shuttles</li>
        </ul>
    </li>
</ul>

How can I solve this problem?

How to specify the types of a function so that the function can accept an object strictly only of type A or strictly only of type B

For example I have such function:

type A = {
    propA1: string
    propA2: string
}

type B = {
    propB1: string
    propB2: string
}

const f = (arg: A | B) => { }

then It can be used like this:

f({propA1: 'val', propA2: 'val', propB1: 'val'})

But I need an error in this case. I would like possibility passed argument with type only A, or only B, without mixing.

Playground

Transloco Language Switch Works but Pipe Doesn’t Update URL in Angular

I’m using the @jsverse/transloco library in my Angular application to manage language translation. When I switch languages using a button, the translations are updated correctly in the template (for example, “en title” becomes “es title”). However, the link in my template doesn’t change accordingly.

The link is constructed using a custom lang pipe that attaches the current language to the URL. Below is the code for my LangPipe and the switchLang method:

import { Component, inject, Injectable, isDevMode, Pipe } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import {
  provideTransloco,
  Translation,
  TranslocoLoader,
  TranslocoModule,
  TranslocoService,
} from '@jsverse/transloco';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { provideRouter, RouterModule } from '@angular/router';

console.clear();

@Injectable({ providedIn: 'root' })
export class TranslocoHttpLoader implements TranslocoLoader {
  private http = inject(HttpClient);

  getTranslation(lang: string) {
    return this.http.get<Translation>(`/assets/i18n/${lang}.json`);
  }
}

@Pipe({
  name: 'lang',
})
export class LangPipe {
  transloco = inject(TranslocoService);

  transform(value: string) {
    console.log({ value });
    return `${this.transloco.getActiveLang()}/${value}`.replace(////g, '/');
  }
}

@Component({
  selector: 'app-root',
  imports: [TranslocoModule, CommonModule, LangPipe],
  template: `
    in app!
    <ng-container *transloco="let t">
      <p>{{ t('title') }}</p>

      <button (click)="switchLang()">switch lang</button>
      <a [href]="'/products/1' | lang">goto to some link</a>
    </ng-container>
  `,
})
export class App {
  name = 'Angular';
  transloco = inject(TranslocoService);

  switchLang() {
    if (this.transloco.getActiveLang() === 'en') {
      this.transloco.setActiveLang('es');
    } else {
      this.transloco.setActiveLang('en');
    }
  }
}

bootstrapApplication(App, {
  providers: [
    provideHttpClient(),
    provideTransloco({
      config: {
        availableLangs: ['en', 'es'],
        defaultLang: 'en',
        reRenderOnLangChange: true,
        prodMode: !isDevMode(),
      },
      loader: TranslocoHttpLoader,
    }),
  ],
});
  • The language is switching successfully in the template (en becomes es), but the URL (generated by the lang pipe) does not update with the new language.
  • The pipe transforms the URL as expected, but it doesn’t seem to react to the language change when it’s triggered by the switchLang method.

What I’ve tried:

  • I’ve verified that the language changes correctly with the transloco.getActiveLang() method.
  • I’ve also checked the lang pipe, and it correctly transforms the link based on the active language, but it does not update dynamically when the language is switched.

If Transloco has a better built-in way to handle this scenario and update the URL correctly based on the active language, I would happily use that approach instead of the custom pipe.

How can I ensure that the URL updates correctly when the language is switched?

stackblitz demo

Google Apps Script for OTP Generation

I tried using a google apps script attached to a google form to generate OTP.

The script intends to make the respondent fill out the email id, leaving the OTP field blank. The submit button triggers the otp generation and will be sent to the email id keyed in. Then the respondent edits the response and keys in the otp and then submits. The latter submission triggers vefirication of otp and displays the success/failure message.

Could enyone help?

how to get file MD5 from FileReader readAsArrayBuffer()

anyone know how to get file MD5 from Filereader readAsArrayBuffer() ?

my current solution is using CryptoJS

  1. convert arraybuffer to base64
  2. decode base64 to binary string.
  3. use CryptoJS.MD5(p_str).toString(CryptoJS.enc.Hex).toUpperCase();

this method get me correct MD5 but I hope to skip the part decode the base64.
the suggestions I found is using readAsBinaryString() which deprecated function.

Special caracters in string in global variable read by JSON in Node-RED (variable names are in naitive language)

I have a template in Node-RED in which I read 3 global variables, one of these is a string that often contains the “>” symbol. tho after this template, whith output “parsed JSON”, it doesn’t show “>” but “&gt”

this is my code:

{"stsGestart": "{{global.stsGestart}}", "lvlTank": "{{global.lvlTank}}", "stsTank": "{{global.StatusTank}}"}

I have debuged every step of the proces it happens right after the template

how can i fix my issue

reddit recomended this:

let result = { "stsGestart": stsGestart, "lvlTank": lvlTank, "stsTank": StatusTank } return JSON.stringify(result)
but “let” is an “invalid symbol”

Angular Signal not Recomputing

In the Angular (v18) code below, a static list of 3 allTasks is filtered by user id when the component renders and displays (for userId u3) 2 tasks via the computed tasks property.

There is an event which calls onCompleteTask() which successfully removes the task from allTasks. The length of allTasks is logged as being reduced from 3 to 2. We expect the tasks() property to now return 1 instead of 2 filtered tasks.

However, the component does not re-render – the computed tasks function is never called even though allTasks has been updated – indeed with a new reference.

Why is tasks not updated when allTasks changes?

import { Component, input, computed } from '@angular/core';
//import { NgIf } from '@angular/common';

import { TaskComponent } from './task/task.component';

import { Task } from './task.model';

@Component({
  selector: 'app-task-list',
  standalone: true,
  templateUrl: './tasks.component.html',
  imports: [TaskComponent],
  styleUrls: ['./tasks.component.css'],
})
export class TaskListComponent {
  userId = input<string>();
  userName = input<string>();
  allTasks: Task[] = [
    {
      id: 't1',
      userId: 'u1',
      title: 'Master Angular',
      summary: 'Learn all the basic and advanced features of Angular & how to apply them.',
      dueDate: '2025-12-31',
    },
    {
      id: 't2',
      userId: 'u3',
      title: 'Build first prototype',
      summary: 'Build a first prototype of the online shop website',
      dueDate: '2024-05-31',
    },
    {
      id: 't3',
      userId: 'u3',
      title: 'Prepare issue template',
      summary: 'Prepare and describe an issue template which will help with project management',
      dueDate: '2024-06-15',
    },
  ];
  tasks = computed<Task[]>(() => {
    console.log('Computing tasks for user', this.userId());
    return this.allTasks.filter((task) => task.userId === this.userId());
  });

  constructor() {}

  onCompleteTask(id: string) {
    let newTasks = this.allTasks.filter((task) => task.id !== id);
    this.allTasks = newTasks;
    console.log('Completed task', id, this.allTasks.length);
  }
}