German Umlauts cause incorrect code rendering

I’m facing an issue with highlight.js. When I include code containing German text with umlauts (e.g. “ö”), the code gets rendered incorrectly starting from the point where the umlaut appears.

setTimeout(Funktion, Verzögerung);

In this example, the umlaut “ö” in “Verzögerung” is displayed incorrectly, and the rest of the code is rendered differently from that point onward:

enter image description here

I’ve already tried converting the code to unicode (&ouml for ö).

The rendering is done using a typical setup:

hljs.highlightAll();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
</head>
<body>

<pre><code class="hljs language-javascript">
setTimeout(Funktion, Verzögerung);
</code></pre>

<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js"></script>

</body>
</html>

Does anyone have a solution to fix this issue?

Thanks in advance!

(javascript) Open site again on Unload?

I’m an art student and currently working on an interactive artpiece, which also is a website. The deadline is in two weeks, whereafter it’s gonna be shown in an art exhibit. Now, here’s the problem:

When show in the exhibition I’m scared of someone interacting with the site and closing the browser window. I need my website to open again when closed so I’m sure it’s going to be accesible for the whole duration of the exhibition. Is there a way i can get the site to open again with javascript?
I’m pretty new to coding, but i was thinking maybe Replay/onUnload ?

Another side note is that the site will run locally without any internet access, so an offline solution would be preferred, but I’m honestly happy for any help i can get.

I’m aware this kind of code probably only is used with ill intent by some very sketchy websites, but I swear I will only use it for this project, please help me I’m so lost
Thank you in advance

block scope, associating bindings to Declarative records

//global code: GC
const x=20; //BD_GC_X
{
//block code: BC
    console.log(x); //BC_X
    const x=10; //BD_BC_X
}

my understanding:

  • binding for x at BD_GC_X is associated by Global Execution Context’s Lexical
    Environment (say LE_GC) > Declarative Record (say DR_BC)
  • binding for x at BD_BC_X is associated by Global Execution Context’s
    Lexical Environment (say LE_GC) > Declarative Record (say DR_GC) //different one from DR_BC
  • Also Declarative Record DR_BC has its [[OuterEnv]] reference to
    Declarative Record DR_GC.

If my understanding is correct, when accessing X at BC_X, to resolve the binding would the JS start looking at DR_BC and then DR_GC? If so, how does JS keep track to look at DR_BC first?

Where to store answers in quiz app database or session

i’m building a quiz app. in app there will be question and answers.User does not need to login just should fill form (name,lastname etc). User will see questions in slides where he can get next page ar previous. after the last question user can submit the finish and will show his results. SO i want to know where should i store user’s answers to session or database ?

Media recorder API video chunk issue

I have a Vue JS2 app that uses MediaRecorder API for creating a Blob for video.

The basic functionality I have is record a video. user can pause a video and on pause user can delete the last recorded chunk. and record the video again.

So in recordcore.js file I manage the mediarecorder code.

videoInit() {
        const options = {
            mimeType: this.getMimeType(),
            videoBitsPerSecond: 5 * 1024 * 1024,
        }
        this.recordedChunks = [];
        this.mediaRecorder = new MediaRecorder(this.stream, options);

        let self = this;
        this.mediaRecorder.addEventListener('dataavailable', function (e) {
            if (e.data.size > 0) {
                self.currentSessionChunks.push(e.data);
            }
        });
}

startRecordVideo(slowModeFactor = false) {
        if (this.mediaRecorder) {
            this.currentSessionChunks = [];
            this.currentSlowModeFactor = slowModeFactor ? 0.25 : 1;
            this.mediaRecorder.start(100);
        }
    }

resumeRecordVideo(slowModeFactor = false) {
        if (this.mediaRecorder && this.mediaRecorder.state === 'paused') {
            this.currentSlowModeFactor = slowModeFactor ? 0.25 : 1;
            this.currentSessionChunks = [];
            this.mediaRecorder.resume();
        }
}

stopRecordVideo(callback) {
        if (!this.mediaRecorder) {
            return
        }
        let self = this;
        this.mediaRecorder.addEventListener('stop', function () {
            if (self.currentSessionChunks.length > 0) {
                self.recordedSessions.push({
                    chunks: [...self.currentSessionChunks],
                    slowModeFactor: this.currentSlowModeFactor
                });
            }

            const allChunks = self.recordedSessions.flatMap(session => session.chunks);
            console.log(allChunks);
            callback(new Blob(allChunks, {type: self.getMimeType()}))
        });
        this.mediaRecorder.stop()
}

pauseRecordVideo() {
        if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
            if (this.currentSessionChunks.length > 0) {
                console.log(this.currentSessionChunks);
                const endTime = performance.now();
                const durationMs = endTime - this.currentSessionStartTime;
                const actualDuration = durationMs / 1000;
                const adjustedDuration = actualDuration / this.currentSlowModeFactor;

                this.recordedSessions.push({
                    chunks: [...this.currentSessionChunks],
                    slowModeFactor: this.currentSlowModeFactor,
                    actualDuration,
                    adjustedDuration
                });

                this.currentSessionChunks = [];
            }
            this.mediaRecorder.pause();
        }
}

deleteLastSession() {
        if (this.recordedSessions.length > 0) {
            const lastSession = this.recordedSessions.pop();
            const lastSessionAdjustedDuration = lastSession.adjustedDuration || 0;
            const lastSessionActualDuration = lastSession.actualDuration;
            const recordedSessionsLength = this.recordedSessions.length;
            const isSlowMode = lastSession.slowModeFactor !== 1;

            return { lastSessionAdjustedDuration, lastSessionActualDuration, recordedSessionsLength, isSlowMode };
        }

        return { lastSessionAdjustedDuration: 0, lastSessionActualDuration: 0, recordedSessionsLength: 0, isSlowMode: false };
}

I have a slow mode feature but currently the issue focus is only on chunk issue in normal video mode.

So the issue is I recorded a 3 second video and paused. Resume it and record for 5 seconds and pause it. then deleted that last 5 seconds chunk. recorded again for 3 seconds and then stop the recording. the created blob video is of 11 seconds while it should be only 6 seconds. If I record, resume and delete and stop then no issue But if I record again after deleting a chunk its an issue

Please suggest here what causes the issue.

I console log into stopRecordVideo method and allChunks constant is also prepard correct.

Is there a vanilla javascript way to have two different elements be treated as the same for the purposes of hover state?

I’m working on a text highlight component, the idea is for paragraph of text, you might highlight a word or a sentence and this in the page margin some comment corresponding to that highlight will be displayed.

enter image description here

I’m now wanting to add some hover functionality, where if you mouse over the highlight, both the highlight and the comment will be emphasised, and vice versa.

For regular css, hover styling can easily be achieved with the :hover selector.

Currently I’m going down the path of adding onMouseEnter and onMouseLeave listeners to each of the highlight and the comment, and then using that do add a ‘.hover’ class that I’ll target.

Is there a much easier way to do this?

What I’m thinking of is how elements can similarly be bound, for example how the for attribute will allow clicking a label in one place to focus on a different element.

Set up Private mode and download path for Edge chromium in katalon

Hi i want to set up the Edge Chromium in to private mode and set up the download path in Katalon studio,but it does not work ,can anyone fix it

@BeforeTestCase
def sampleBeforeTestCaseEdge(TestCaseContext testCaseContext) {
    RunConfiguration.setWebDriverPreferencesProperty('args', [
        '--inprivate',
        '--no-sandbox',
        '--start-maximized',
        '--disable-extensions',
        '--disable-dev-shm-usage',
        '--safebrowsing-disable-extension-blacklist',
        '--safebrowsing-disable-download-protection',
        '--disable-features=DownloadBubble,DownloadBubbleV2'
    ])
    RunConfiguration.setWebDriverPreferencesProperty('edgeOptions.prefs', [
        'download.default_directory': GlobalVariable.downloadPath,
        'savefile.default_directory': GlobalVariable.downloadPath,
        'download.prompt_for_download': false,
        'download.extensions_to_open': 'application/xml',
        'safebrowsing.enabled': false
    ])
    WebUI.openBrowser('https://the-internet.herokuapp.com/')
}

Issue in compressing and uploading video using javascript.,jQuery and php

I am create a video upload program where we upload video, compress it using js/jquery and then upload it on server using php

I compressed the video successfully and preview the compressed video blob below and it works perfectly

<video id="videoPreview" controls="" src="blob:http://localhost/64f7b2ec-3fe0-4ede-a0eb-b655c7484cae" style="display: block;"></video>

And when i try to save the blob to server the audio inside the video is removed automatically

Here is my jquery code and PHP code

jQuery Code

$('#uploadBtn').on('click', function()
{
    if (!compressedBlob) return;
                
    const formData = new FormData();
    formData.append('compressedVideo', compressedBlob, 'compressed_' + originalFile.name.replace(/.[^/.]+$/, '') + '.mp4');
    
    $.ajax({
        url: '',
        type: 'POST',
        data: formData,
        processData: false,
        contentType: false,
        success: function(response)
        {
            alert("Uploaded");
        },
        error: function(xhr, status, error)
        {
            alert("Error");
        }
    });
});

PHP code

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['compressedVideo']))
{
    $uploadDir = 'uploads/';
    if (!file_exists($uploadDir)) mkdir($uploadDir, 0777, true);
    
    $fileName = uniqid() . '.mp4';
    $targetPath = $uploadDir . $fileName;
    
    if (move_uploaded_file($_FILES['compressedVideo']['tmp_name'], $targetPath))
    {
        echo json_encode(['success' => true, 'filePath' => $targetPath]);
    }
    else
    {
        echo json_encode(['success' => false, 'message' => 'Upload failed']);
    }
    exit;
}
?>

How to do this using javascript/jquery and php

Just to all you know this is my compression process using javascirpt

Compression code

$('#videoInput').on('change', function(e)
{
    preview_compress_video(e);
});
async function preview_compress_video(e)
{
    resetState();
    const file = e.target.files[0];
    if (!file) return;
    
    originalFile = file;

    // Setup video preview
    const video = $('#videoPreview')[0];
    video.src = URL.createObjectURL(file);
    video.style.display = 'block';
    
    
    video.onloadedmetadata = function()
    {
        originalDuration = video.duration;
    };
    
    // Compression handler
    if (!originalFile) return;
    
    // Use a hidden video element for processing
    const processingVideo = $('#hiddenVideo')[0];
    processingVideo.src = URL.createObjectURL(originalFile);

    // Wait for hidden video to load
    await new Promise((resolve) => {
        processingVideo.onloadedmetadata = resolve;
    });
    
    try
    {
        // Setup MediaRecorder with proper options
        const stream = processingVideo.captureStream();
        var bitrate="500000";
        const options = {
            audioBitsPerSecond: 128000,
            videoBitsPerSecond: bitrate,
            mimeType: 'video/mp4'
        };
        
        mediaRecorder = new MediaRecorder(stream, options);
        const chunks = [];
        
        // Event handlers
        mediaRecorder.ondataavailable = function(e) {
            if (e.data.size > 0) {
                chunks.push(e.data);
            }
        };
        
        mediaRecorder.onstop = function() {
            //compressedBlob = new Blob(chunks, { type: 'video/webm' });
            compressedBlob = new Blob(chunks, { type: 'video/mp4' });
            
            // Update preview with compressed version
            const compressedVideo = $('#videoPreview')[0];
            compressedVideo.src = URL.createObjectURL(compressedBlob);
            
            compressedVideo.onloadedmetadata = function()
            {
                $('#compressProgress').val(100);
            };
        };
        
        mediaRecorder.onerror = function(e) {
            $('#status').text('Compression error: ' + e.toString());
            resetState();
        };
        
        // Start recording
        mediaRecorder.start(100); // Collect data every 100ms
        
        // Progress tracking based on time
        const startTime = Date.now();
        recordingTimer = setInterval(() => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(100, (elapsed / (originalDuration * 1000)) * 100);
            $('#compressProgress').val(progress);
        }, 100);
        
        // Play the hidden video (muted)
        processingVideo.muted = true;
        processingVideo.currentTime = 0;
        await processingVideo.play();
        
        // Schedule recording stop after full duration
        setTimeout(() => {
            if (mediaRecorder && mediaRecorder.state === 'recording') {
                mediaRecorder.stop();
            }
            if (recordingTimer) clearInterval(recordingTimer);
        }, originalDuration * 1000);
        
    }
    catch (error)
    {
        $('#status').text('Error: ' + error.message);
        resetState();
    }
}

Why isn’t my button’s click handler updating the text?

I’m new to JavaScript and I have a simple page with a button and a <div>. I want to change the div’s text when the button is clicked, but nothing happens.

var btn = document.getElementById('myButton');
var msg = document.getElementById('message');

btn.addEventListener('click', () => {
  console.log('clicked');
  msg.innerText = 'Button was clicked!';
});
<div id="message">Original text</div>
<button id="myButton">Click me</button>

and I never see “clicked” in my console.
so what am I missing that prevents the click handler from running? is there something wrong with how I’m selecting the elements or loading the script?

How can I capture and stream real-time audio from Google Meet via a Chrome Extension?

I’m building a Chrome extension that interacts with Google Meet, and I’m trying to capture and stream real-time audio from a meeting to a backend server for transcription and processing.

So far, my extension is able to detect when a user joins a Google Meet and notifies a backend service. My next step is to capture the audio and send it via WebSocket to the backend.

Here’s what I’ve tried or considered:

Using AudioWorklet within a content script or injected script

Exploring the chrome.tabCapture API

Setting up a WebSocket connection to ws://localhost:8080

My key question is:
What is the correct or feasible way to capture audio from Google Meet in real time using a Chrome extension, and stream it to a backend server for processing?

Are there any API limitations or security restrictions I should be aware of when trying to access the audio stream from the Meet tab?

Any guidance or code examples would be appreciated.

Javascript Assign same string to multiple Properties

I’m building a form where the user selects drop downs 1 – 5. Based on what they select for Drop Down 1, Drop Down 2 will display specific options, selecting Drop Down 2 will set Drop Down 3, etc.

Once you get to Drop Down 3, some of those options in Drop Down 3 use the same options for Drop Down 4.

Currently writing out an array of when you select a specific option, but instead of repeating the text for Drop Down 4 multiple times to go with each option of Drop Down 3, is there a way to write the strings once and apply them to multiple properties.

Here is how I have it for displaying options and want to write out the “Account Creation”, “Account Deletion” “Account Modification”, only once but have them apply to Choice 1, 2, 3, etc.

var DropDown3 = {
   "Choice 1": [
       " ";
       "Account Creation",
       "Account Deletion",
       "Account Modification",
   ],
   "Choice 2": [
       " ";
       "Account Creation",
       "Account Deletion",
       "Account Modification",
   ],
   "Choice 3": [
       " ";
       "Account Creation",
       "Account Deletion",
       "Account Modification",
   ],
}

This is my JavaScript that pulls those options:

function ChangeDropdown4(value) {
     if (value.length == ) document.getElementById("Tier4").innerHTML = "<option></option>";
        else {
           var Tier4Options = "";
           for (Tier4Id in Tier4ByTier3[value]) {
                Tier4Options += "<option>" + Tier4ByTier3[value][Tier4Id] + "</option";
           }
           document.getElementById("Tier4List").innherHTML = Tier4Options;
        }
}

Here is what the HTML looks like:

`<input type="text" list="Tier4List" id="Tier4" onChange="ChangeDropdown4(this.value);>`

Question about Cypress async handling issue

I’m a beginner currently trying to learn test automation on my own using Cypress.

The intended flow is: when the user clicks the “Confirm” button on the job posting page, it should navigate to the payment page. However, even after clicking the “Confirm” button, it doesn’t proceed to the payment page—possibly due to some asynchronous handling issue.

Additionally, the payment page seems to append a job post ID or some numeric value in the URL, and I’m having trouble handling this in my test code.

Would anyone be willing to take a look at my poor attempt at a test and give me some guidance or suggestions?

I’ve tried adding a cy.wait() or retrying cy.url() assertions, but the issue persists.
Also tested clicking with { force: true } to ensure it’s not a visibility issue.

Thank you very much for taking the time to read this.

  • Error Message:
    Timed out retrying after 4000ms: expected ‘https://example-job-site.com/Company/RecruitRegist?registServiceCds=123&serviceNm=PremiumJobPost2Weeks’ to include ‘/Company/RecruitPayStd’

  • My Test Code:

describe('Automated test for paid job posting', () => {
  beforeEach(() => {
    cy.viewport(1280, 800);
    Cypress.on('uncaught:exception', (err) => {
      if (err.message.includes('$ is not defined')) return false;
      return true;
    });
  });

  it('Verifies redirection to the payment page after posting a job and extracting recruitCd', () => {
    cy.visit('https://example-login-site.com/Account/Login');
    cy.get('input[name="ID"]').type('sampleUser');
    cy.get('input[name="PW"]').type('samplePassword123');
    cy.get('button[type="submit"]').click();

    cy.origin('https://example-main-site.com', () => {
      cy.get('#gnb_wrap').contains('Product Info').click();
      cy.get('.btn-type.btn-primary-o').eq(0).click();
      cy.get('#btnRecruitPayAction').scrollIntoView().contains('Post Job').click({ force: true });
      cy.contains('Confirm').click({ force: true });
    });

    cy.origin('https://example-job-site.com', () => {
      const serviceCd = '123';
      const serviceNm = encodeURIComponent('PremiumJobPost2Weeks');
      const jobTitle = 'Test_PaidJob_0425';

      cy.visit(`https://example-job-site.com/Company/RecruitRegist?registServiceCds=${serviceCd}&serviceNm=${serviceNm}`);
      cy.url().should('include', '/Company/RecruitRegist');

      cy.get('input[type="text"][title="Job Title"]').type(jobTitle);
      cy.get('#same').check({ force: true });
      cy.get('select').eq(1).select('Position A');
      cy.get('select').eq(2).select('Department B');
      cy.get('select').eq(3).select('Specialty C');
      cy.contains('label', '0 Openings').click();
      cy.contains('label', 'No Experience Required').click();
      cy.get('select').eq(5).select('Associate Degree');
      cy.get('select[title="Salary Details"]').select('3600');
      cy.get('select[title="Working Days"]').select('5 Days a Week');
      cy.get('select[title="City"]').select('CityX');
      cy.get('select[title="District"]').select('DistrictY');
      cy.get('input[type="text"][title="Detailed Address"]').type('123 Example Street, Floor 2');
      cy.contains('button', '1 Month').click();
      cy.contains('Apply Entered Details').click();
      cy.get('button[title="Apply"]').click({ force: true });
      cy.get('input[type="text"][title="HR Department"]').type('HR Team');

      cy.get('button[type="submit"]').first().click({ force: true });
      cy.contains('Confirm').click({ force: true });

      cy.url().should('include', '/Company/RecruitPayStd').then((url) => {
        const recruitCd = url.split('/Company/RecruitPayStd/').pop();
        cy.log(`recruitCd: ${recruitCd}`);

        const payUrl = `https://example-main-site.com/Company/RecruitPayStd/${recruitCd}`;
        cy.visit(payUrl);
        cy.url().should('include', '/Company/RecruitPayStd');
      });

      cy.get('#recruitCd').then(($el) => {
        const recruitCd = $el.val();
        cy.log(`recruitCd (from input): ${recruitCd}`);

        const payUrl = `https://example-main-site.com/Company/RecruitPayStd/${recruitCd}`;
        cy.visit(payUrl);
        cy.url().should('include', '/Company/RecruitPayStd');
      });
    });
  });
});

CSS – Failed to separate the double-bordered divs inside table during printing in electron JS

This is my HTML structure of table I am printing out.

<body>
    <div class="tableFormat">
        <button onclick="window.print()">Print</button>
        <table>
            <tbody id="barcodeData">
                <tr>
                    <td>
                        <div class="eachBookCallNo">
                          <div class="callNo">
                              ၀၁၈၃၄၁ <br>
                                 -   <br>
                                 - 
                          </div>
                          <div class="barcode">
                             <img src="imagepath">၀၁၈၃၄၁</div>
                         </div>
                       </div>
                   </td>

                    <td>
                        <div class="eachBookCallNo">
                          <div class="callNo">
                               ၀၁၈၃၄၂ <br>
                                 -   <br>
                                 - 
                          </div>
                          <div class="barcode">
                             <img src="imagepath">၀၁၈၃၄၂</div>
                         </div>
                       </div>
                   </td>
  
                 </tr>

                 <!-- 12 rows -->
        </table>
    </div>

</body>

This is the CSS for that code


`.tableFormat table {
        border-spacing: 0.1in 0.1in;
        border-collapse: separate;
        border: none;
    }

.tableFormat table td{
        height: 0.95in;
        width: 33%;
        border: none;
    }
    
    .tableFormat table td div div{
        border: 1px double black;
        outline: 1px double black;
        outline-offset: 2px;
    }

    table td, table th {
        padding: 0; 
        margin: 0;
      }
    
    .eachBookCallNo{
        height: 100%;
        display: flex;
        box-sizing: border-box;
        cursor: pointer;
        gap: 0.05in;
    }

    .callNo{
        height: 100%;
        width: 40%;
        text-align: center;
        display: flex; 
        justify-content: center;
        align-items: center; 
        line-height: 25px;
        font-weight: bold;
        box-sizing: border-box;

    }

    .barcode{
        width: 60%; 
        height: 100%;
        display: flex; 
        justify-content: center;
        align-items: center; 
        flex-direction: column;
    }
    
    .barcode img{
        width: 98%;
        height: 60%;
        margin-right: 1px;
    }

    .barcode:nth-child(2){
        letter-spacing: 2.5cap;
        display: flex;
        align-items: flex-end;
        justify-content: center;
    }

@page {
      size: A4;
      margin: 0.75in 0.40in 0.75in 0.40in;
  }

  @media print {
    body {
      size: A4;
      font-family: Arial, sans-serif;
      font-size: 16px;
      font-weight: bold;
      color: #000;
      background: #fff;
      margin: 0;
    }

    .tableFormat table td div div{
        float:none;
        break-inside: avoid !important;
        break-after: always;
        margin: 4px 0px 4px 0px;
    }
    
    button{
        display: none;
    }
  }
`

Print as PDF screenshot

As I have attached an image, the first part of the double border is split before page break. Before the double borders, I have tried with single border and the page break works.

I do not have a physical printer so I used CutePDF Write to simulate as A4 printer. I searched for solutions like this (Avoid Page Break inside Row of table) but it does not work well with me. I need to completely separate the double border into another page.

How to prevent margin collapsing without altering margins?

I’m studying CSS margin collapsing rules and have some confusion regarding the W3C specification. The documentation states that margins collapse when adjacent elements meet these conditions:

  • “no line boxes, no clearance, no padding and no border separate them.”

My questions are:

  1. If I add a border to an element, does this technically make them non-adjacent (thus preventing margin collapse)?
  2. The spec also mentions:
  • “The top margin of an in-flow block element collapses with its first in-flow block-level child’s top margin if the element has no top border, no top padding, and the child has no clearance.”

What I need:

How can I prevent margin collapsing between box1 (parent) and box2 (child) without modifying their original margin values? Are there CSS properties other than border/padding that can achieve this?

.box {
  height: 100px;
  width: 100px;
  border: 1px solid red;
}

.box1 {
  background: blue;
  margin-bottom: 50px;
}

.box2 {
  background: green;
  margin-top: 50px;
}

.box3 {
  background: darkorange;
  margin-top: 50px;
}
<div class="container">
  <div class="box box1">box1</div>
  <div class="box box2">box1</div>
  <div class="box box3">box1</div>
</div>