Thymeleaf page not rendering correctly on iOS when using LIFF SDK

Now I am having a problem:
I am building a chat application, when from the LINE app click on the start chat button, it will transfer the user to the chat website dedicated to them. Currently when processing on Android, everything is still displayed normally, but when I build on iOS, nothing is displayed.

Regarding the technology used, I use spring boot, thymeleaf combined with jQuery + LIFF SDK.

The process when init the screen I am processing: When init the screen for the first time, the backend will check the isInit variable passed is null, then it will return the html of that screen.
My Server:

  public String init(
      @RequestParam(value = "liffChannelId") String liffChannelId,
      @RequestParam(value = "messageChannelId") String messageChannelId,
      @RequestParam(value = "isInit", required = false) String isInit,
      @RequestParam(value = "idToken", required = false) String idToken,
      HttpServletRequest request, Model model) {
    if (Objects.isNull(isInit)) {
      return "s2013_chat";
    }

    ChatForm form = chatHelper.init(liffChannelId, messageChannelId, idToken, page, request);

    return "s2013_chat";
  }

And in my js:

$(document).ready(function () {
  const urlParams = new URLSearchParams(window.location.search);
  const isInit = urlParams.get("isInit");
  if (!isInit) {
    initLiffApp();
  }
});

function initLiffApp() {
  const messageChannelId = new URLSearchParams(window.location.search).get("messageChannelId");
  if (!messageChannelId) {
    alert("MessageChannelId is missing");
    return;
  }

  const liffChannelId = new URLSearchParams(window.location.search).get("liffChannelId");
  if (!liffChannelId) {
    alert("LiffChannelId is missing");
    return;
  }

  const liffId = new URLSearchParams(window.location.search).get("liffId");
  if (!liffId) {
    alert("LiffId is missing");
    return;
  }

  liff
    .init({
      liffId: liffId
    })
    .then(() => {
      const idToken = liff.getIDToken();
      if (!idToken) {
        alert("Failed to get ID Token");
        return;
      }
      sendToServer(liffChannelId, messageChannelId, idToken);
    })
    .catch(err => {
      console.error("LIFF init error", err);
    });
}

function sendToServer(liffChannelId, messageChannelId, idToken) {
  const redirectUrl = `/counseling/chat/client?liffChannelId=${encodeURIComponent(liffChannelId)}&messageChannelId=${encodeURIComponent(messageChannelId)}&isInit=1&idToken=${encodeURIComponent(idToken)}`;
  window.location.href = redirectUrl;
}

When returning for the first time, in js make a call to the liff server to get idToken and at this time will call back to the server 1 more time with isInit is true. At this time the backend will start processing. However, when building on iOS, I noticed that when init for the first time, it returns the screen UI without displaying anything (I think it’s due to the processing when isInit is null, it returns without calling liff anymore).

I tried commenting out the isInit variable check, and now the UI is displayed but does not receive any css and js events.

//if (Objects.isNull(isInit)) {
//   return "s2013_chat";
//}

I used Web Inspector on Safari browser to check and saw that the css and js files were loaded successfully, but the console log is reporting an error as shown.

enter image description here
enter image description here
enter image description here

Please help me with this problem, I have been trying to solve it for 3 days but still don’t know the reason why?

displaying and filtering images with a click event vanillajs

I want to dynamically display images and list items. I then want to filter the images based on the list item(genre) that is clicked. There are 2 images per list item. The list items are displayed in the middle of the page with one image on either side of the page.
I’ve created this function that I know is wrong but I’m not exactly sure where I’m going wrong. I don’t necessarily need the answer but let me know if I’m going in the right direction and if not, what errors I am making.

HTML

    <div class="content-wrapper-2">
      <div class="image-container-1"></div>
      <ul id="genre-list"></ul>
      <div class="image-container-2"></div>
    </div>

JS

const imageContainer1 = document.querySelectorAll('.image-container-1');
const imageContainer2 = document.querySelectorAll('.image-container-2');
const genreList = document.getElementById('genre-list');
const albums = [
  {
    id: 1,
    genre: 'Rock',
    image1: '/images/album-covers/jimihindrix-areyouexperienced.jpg',
    image2: '/images/album-covers/thedoors.jpg',
  },
  {
    id: 2,
    genre: 'Jazz',
    image1: '/images/album-covers/somethinelse.jpg',
    image2: '/images/album-covers/MilesDavis-BitchesBrew.jpg',
  },
  {
    id: 3,
    genre: 'Hiphop',
    image1: '/images/album-covers/mfdoom-mmfood.jpg',
    image2: '/images/album-covers/nas-illmatic.jpg',
  },
  {
    id: 4,
    genre: 'Soul',
    image1: '/images/album-covers/aliciakeys-diary.jpeg',
    image2: '/images/album-covers/ettajames-tellmama.jpg',
  },
  {
    id: 5,
    genre: 'Electronic',
    image1: '/images/album-covers/burial-tunes.jpg',
    image2: '/images/album-covers/björk-homogenic.jpg',
  },
  {
    id: 6,
    genre: 'Classic',
    image1: '/images/album-covers/sparks-kimonomyhouse.jpg',
    image2: '/images/album-covers/chakakhan-rufus.jpg',
  },

  {
    id: 7,
    genre: 'Pop',
    image1: '/images/album-covers/beatles-sgtpeppers.jpg',
    image2: '/images/album-covers/prince-purplerain.png.webp',
  },
];

const handleClick = (e) => {
  const clickedElement = e.target.id;
  albums.map((album) => {
    genreList.innerHTML = `<li id=${album.genre}>${album.genre}</li>`;
  });
  document.getElementById(`${albums.genre}`).addEventListener('click', () => {
    albums.filter((p) => {
      if (p.name === clickedElement) {
        imageContainer1.innerHTML = `<img src=${p.image1}/>`;
        imageContainer2.innerHTML = `<img src=${p.image2}/>`;
        
      }
    });
  });
};

document.addEventListener('DOMContentLoaded', (e) => {
  handleClick(e);
});

To Do List JS project Saving Lists logic [closed]

I need help with my javaScript file in my To Do List project, I thought i could handle it but there is too much to think about in this type of project and i am overwhelmed, if someone could help with the list saving logic then reach me out and I will send the details of what I would like to implement.
project repo: https://github.com/Dudek10/To-Do-List-Advanced-Project

I have tried to implement the logic of renaming each list but it got too complicated and I don’t want to mess things up even more, I will additionaly send the JS file:

let tasks = [];

// Constants LocalStorage keys
const TASKS_KEY = 'tasks';
const CONTAINER_KEY = 'containerOpenState';
const TASK_INPUT_KEY = 'taskInputDraft';
const SAVED_LISTS_KEY = 'SavedLists';
const SAVE_LIMIT = 5;

// Constants for functions like 'addTask()' etc. 
const tasksDiv = document.getElementById("tasks");
const input = document.getElementById("TaskInput");
const addTaskButton = document.getElementById("AddTaskButton");

//main DOM content
document.addEventListener('DOMContentLoaded', () => {
  
  // the list cotainer logic
  const OpenListBtn = document.getElementById("OpenList");
  const DeleteAllTaskBtn = document.getElementById("TaskDelete");
  const NameForm = document.querySelector(".name-form");
  const Container = document.querySelector(".container");
  const SaveBtn = document.querySelector(".save-button");
  const IconClose = document.querySelector(".icon-close");

  // Checks whether container is open
  const savedState = localStorage.getItem(CONTAINER_KEY);
  if (Container && NameForm && SaveBtn) {
    if (savedState === 'open') {
      Container.classList.add('visible');
      NameForm.classList.add('visible');
      SaveBtn.classList.add('visible');
    } else {
      Container.classList.remove('visible');
      NameForm.classList.remove('visible');
      SaveBtn.classList.remove('visible');
    }
  }

  // Opens the list and sets the state to local storage
  if (OpenListBtn && Container && NameForm && SaveBtn) {
    OpenListBtn.addEventListener('click', () => {
      Container.classList.add('visible');
      NameForm.classList.add('visible');
      SaveBtn.classList.add('visible');
      localStorage.setItem(CONTAINER_KEY, 'open');

    });
  }
  if (IconClose && Container && NameForm && SaveBtn) {
    IconClose.addEventListener('click', () => {
      Container.classList.remove('visible');
      NameForm.classList.remove('visible');
      SaveBtn.classList.remove('visible');
      localStorage.setItem(CONTAINER_KEY, 'closed');
    });
  }
  
  // draft input retrieve
  const draft = localStorage.getItem(TASK_INPUT_KEY);
  if (draft !== null) input.value = draft;
  
  input.addEventListener('input', () => {
    localStorage.setItem(TASK_INPUT_KEY, input.value);
  });

  // Load tasks on startup
  loadTasks();

  renderSavedListsDropdown();

  // Saved list logic
  const SavedListBtn = document.getElementById("SavedLists");
  const SavedListsDropdown = document.querySelector('.saved-lists-dropdown');
  const ListSavingBtn = document.querySelector('.save-button');

  // Toggle dropdown visibility when clicking SavedLists button
  SavedListBtn.addEventListener('click', (e) => {
    e.stopPropagation();
    SavedListsDropdown.classList.toggle('show');
  });

  // Save the current tasks under the typed name
  ListSavingBtn.addEventListener('click', () => {
        //first we declare the things we want to save

        const nameInput = document.getElementById("NameBtn");
        const name = (nameInput?.value || '').trim();
        if (!name) return; // don’t save if no name
        if (tasks.length === 0) return; 

        //makes a map of all the elements
        const map = getSavedListsMap();

        //sets a variable for the names and then checks their number
        const existingNames = Object.keys(map);
        if (!map[name] && existingNames.length >= SAVE_LIMIT) {
            
            return;
        }
        
        map[name] = [...tasks];  // store a copy of tasks under given name 
        localStorage.setItem(SAVED_LISTS_KEY, JSON.stringify(map));
        
        //render the saved lists
        renderSavedListsDropdown();
        SavedListsDropdown.classList.add('show');
  })

  // Load a saved list when clicking its button in the dropdown
  SavedListsDropdown.addEventListener('click', (e) => {
        const btn = e.target.closest('.saved-list-button');
        if (!btn) return;
        const name = btn.dataset.name;
        const map = getSavedListsMap();

        // Show the list and fill the name field
        document.getElementById('NameBtn').value = name;
        tasks = map[name] ? [...map[name]] : [];

        Container.classList.add('visible');
        NameForm.classList.add('visible');
        SaveBtn.classList.add('visible');

        renderTasks(); // render loaded tasks
  });

  // Close dropdown when clicking outside
  document.addEventListener('click', (e) => {
    if (!SavedListBtn.contains(e.target) && !SavedListsDropdown.contains(e.target)) {
      SavedListsDropdown.classList.remove('show');
    }
  });

  // mobile toogle button for nav menu
  const toggleBtn = document.querySelector('.ToggleBtn');
  const dropdownMenu = document.querySelector('.DropdownMenu');
  const toggleBtnIcon = toggleBtn?.querySelector('i');
  let isOpen = false;
  
  // on button click change its icon to appropriate one
  if (toggleBtn && dropdownMenu && toggleBtnIcon) {
    toggleBtn.addEventListener('click', (e) => {
      e.stopPropagation();

      if (!isOpen) {
        dropdownMenu.classList.add('show');
        dropdownMenu.classList.remove('hide');
        toggleBtnIcon.className = 'fa-solid fa-xmark';
      } else {
        dropdownMenu.classList.add('hide');
        dropdownMenu.classList.remove('show');
        toggleBtnIcon.className = 'fa-solid fa-bars';
      }
      isOpen = !isOpen;
    });
  }
  

  // Delete all tasks
  if (DeleteAllTaskBtn) {
  DeleteAllTaskBtn.addEventListener('click', () => {
    const items = tasksDiv.querySelectorAll('.task');
    if (items.length === 0) return;

    let remaining = items.length;

    items.forEach((el, i) => {
      // set delay for each item
      el.style.transitionDelay = `${i * 0.3}s`;

      el.classList.add('erasing');
      el.addEventListener('transitionend', () => {
        remaining--;
        if (remaining === 0) {
          tasks.length = 0;
          renderTasks();
          saveTasks();
        }
      }, { once: true }); // the transition listener will only run once (the css have two transitions so it would double the iteration number)
    });
  });
  
}

  // Add task event
  addTaskButton.addEventListener('click', addTask);

});

//helper for saved lists
function getSavedListsMap() {
    try {
        return JSON.parse(localStorage.getItem(SAVED_LISTS_KEY)) || {};
    } catch {
        return {};
    }

}


function renderSavedListsDropdown() {
    const SavedListsDropdown = document.querySelector('.saved-lists-dropdown');
    const map = getSavedListsMap();
    SavedListsDropdown.innerHTML = ''; //clears the template buttons 
    Object.keys(map).forEach(name => {
        const btn = document.createElement('button');
        btn.className = 'saved-list-button';
        btn.textContent = name;
        btn.dataset.name = name;
        SavedListsDropdown.appendChild(btn);
    })
}

//tasks persistence
function loadTasks() {
    const oldTasks = localStorage.getItem(TASKS_KEY);
    if (oldTasks) {
        tasks = JSON.parse(oldTasks);
        renderTasks();
    }
}

function saveTasks() {
    localStorage.setItem(TASKS_KEY, JSON.stringify(tasks));
}

// tasks allingment and style
function renderTasks() {
    tasksDiv.innerHTML = "";
    tasks.forEach((task, idx) => {
        const div = document.createElement('div');
        div.classList.add('task');
        div.style.marginBottom = '10px';

        const text = document.createElement('p');
        text.textContent = task;
        Object.assign(text.style, {
            display: 'inline',
            marginRight: '10px',
            fontWeight: 'bold',
            fontSize: '1.3rem'
        });

        const button = document.createElement('button');
        button.innerHTML = '<ion-icon name="trash-outline" style="font-size: 1rem; color: white;"></ion-icon>';
        Object.assign(button.style, {
            backgroundColor: '#2F1E2E',
            color: '#ffffff',
            border: 'none',
            fontSize: '1.5rem',
            cursor: 'pointer',
            padding: '6px 8px',
            borderRadius: '8px',
            display: 'inline-flex',
            alignItems: 'center',
            justifyContent: 'center',
            height: '1.9rem'
        });

        button.addEventListener('mouseenter', () => button.style.backgroundColor = '#3C2E3B');
        button.addEventListener('mouseleave', () => button.style.backgroundColor = '#2F1E2E');
        
        // Trigger CSS animation and remove the task after the transition end
        button.onclick = () => {
            div.classList.add('erasing');
            div.addEventListener('transitionend', () => {
            removeTask(idx);
      }, { once: true }); // same case as for the delete all tasks button
    };

        div.appendChild(text);
        div.appendChild(button);
        tasksDiv.appendChild(div);
    });
}

function addTask() {
    const value = input.value.trim();
    const OriginalPlaceholder = input.placeholder;

    // Helper: show placeholder error messages briefly
    const ShowPlaceholderWarning = (msg) => {
        input.value = "";
        input.placeholder = msg;

        // clear previous timer
        if (input._phTimer) clearTimeout(input._phTimer);

        // Restore original placeholder when user is typing
        const onType = () => {
            input.placeholder = OriginalPlaceholder;
            input.removeEventListener('input', onType);
            if (input._phTimer) {
            clearTimeout(input._phTimer);
            input._phTimer = null;
            }
        };

        input.addEventListener('input', onType, { once: true });

        //restore after 2s
        input._phTimer = setTimeout(() => {
            input.placeholder = OriginalPlaceholder;
            input.removeEventListener('input', onType);
            input._phTimer = null;
        }, 2000);
        };

    // validations
    if (!/^[a-zA-Z0-9 ]*$/.test(value)) return ShowPlaceholderWarning("Task contains invalid characters!");
    if (!value) return ShowPlaceholderWarning("Please enter a task!");
    if (value.length > 45) return ShowPlaceholderWarning("Task exceeds 45 characters!");
    if (tasks.includes(value)) return ShowPlaceholderWarning("Task already exists!");
    if (tasks.length >= 9) return ShowPlaceholderWarning("Maximum number of tasks reached");

    tasks.push(value);
    renderTasks();
    input.value = "";
    localStorage.removeItem(TASK_INPUT_KEY);
    saveTasks();
}

function removeTask(idx) {
    tasks.splice(idx, 1);
    renderTasks();
    saveTasks();

}


// input events
input.addEventListener('keyup', (event) => {
    if (event.key === 'Enter') addTask();
});

What are the biggest obstacles companies face when adopting AI Software Development, and how can they overcome them successfully? [closed]

Many companies are eager to adopt AI Software Development Services because of the potential to improve efficiency, decision-making, and automation. But in practice, adoption is not straightforward. Businesses often struggle with issues such as poor-quality data, unclear objectives, integration with legacy systems, limited in-house expertise, and fears about cost or complexity. These obstacles can delay or even derail AI projects.

What I tried:
We started exploring AI Software Development Services to automate processes and improve efficiency. The plan included testing predictive models with existing business data and integrating them into our legacy systems.
**
What I expected:**
I expected the models to provide clean insights, integrate smoothly, and improve decision-making with minimal setup.

What actually happened:
We ran into poor data quality, integration issues with older systems, and a lack of in-house expertise to fine-tune the models. Instead of smoother operations, we got delays and inconsistent results.

Tabulator Spreadsheet Paste Multiple Rows

The attached example allows for copying multiple rows but only pastes a single row. I would like to copy multiple rows and paste multiple rows.
jsfiddle : https://jsfiddle.net/8Lof1m3g/

Steps to reproduce:

  1. select multiple rows in the spreadsheet and press ctrl+c
  2. select an empty row and press ctrl+v

The result will be only one of the rows getting pasted.

Tabulator documentation: https://tabulator.info/examples/6.3#spreadsheet-clipboard

//define an array of sheet definitions
var sheets = [
  {
    title: "First Sheet",
    key: "first",
    rows: 20,
    columns: 20,
    data: [
      [9937, "", "", 7749, 9816, 4355, 8279, "", ""],
      [2380, "", 6977, 8896, 4012, 3803, 5408, 3415, 3056],
      [9180, "", 39, 9445, 3917, "", 18, 5239, 2516],
      [1924, 8734, 1819, 1838, 2330, 7921, 9219, "", 3537],
    ],
  },
  {
    title: "Second Sheet",
    key: "second",
    data: [
      [2380, "", 6977, 8896, 4012, 3803, 5408, 3415, 3056],
      [9180, "", 39, 9445, 3917, "", 18, 5239, 2516],
      [1924, 8734, 1819, 1838, 2330, 7921, 9219, "", 3537],
      ["", 8665, 5875, 9732, 1926, "", 9743, 8388, ""],
      [7040, 4861, 2988, 5584, 2344, 9749, 8872, 9177, 6246],
      [6334, 1674, 2967, "", 9353, 396, 6006, 8572, ""],
      [6359, "", 2580, 5723, 9801, 554, 1044, 5266, 8532],
    ],
  },
  {
    title: "Third Sheet",
    key: "third",
    rows: 5,
    columns: 5,
    data: [
      [1924, 8734, 1819, 1838, 2330, 7921, 9219, "", 3537],
      ["", 8665, 5875, 9732, 1926, "", 9743, 8388, ""],
      [7040, 4861, 2988, 5584, 2344, 9749, 8872, 9177, 6246],
      [6334, 1674, 2967, "", 9353, 396, 6006, 8572, ""],
      [6359, "", 2580, 5723, 9801, 554, 1044, 5266, 8532],
      [7278, 6971, 2232, 5720, 5665, 7231, 1165, "", 168],
    ],
  },
]

//Build Tabulator
var table = new Tabulator("#example-table", {
  height: "311px",

  spreadsheet: true,
  spreadsheetRows: 50,
  spreadsheetColumns: 50,
  spreadsheetColumnDefinition: { editor: "input", resizable: "header" },
  spreadsheetSheets: sheets,
  spreadsheetSheetTabs: true,

  rowHeader: {
    field: "_id",
    hozAlign: "center",
    headerSort: false,
    frozen: true,
  },

  editTriggerEvent: "dblclick", //change edit trigger mode to make cell navigation smoother
  editorEmptyValue: undefined, //ensure empty values are set to undefined so they arent included in spreadsheet output data

  //enable range selection
  selectableRange: 1,
  selectableRangeColumns: true,
  selectableRangeRows: true,
  selectableRangeClearCells: true,

  //configure clipboard to allow copy and paste of range format data
  clipboard: true,
  clipboardCopyStyled: false,
  clipboardCopyConfig: {
    rowHeaders: false,
    columnHeaders: false,
  },
  clipboardCopyRowRange: "range",
  clipboardPasteParser: "range",
  clipboardPasteAction: "range",
})

jQuery not grabbing form setup in chart.js loadCallback function

I have a form appearing in a popup, this loads in the content section of chart.js new Popup function. I’m utilizing the loadCallback as described in their documentation to set up actions based on input in the content.

When the button is clicked, the event is registering and hitting my code, however when I go to serialize the form to acquire its data, it reports blank. If I console.log the variable I’ve saved the form too, I do get the elements of the form.

So it appears to grab the elements, but my serializeObject function isn’t getting any data or references. I was curious if this is an issue with how I’m utilizing jQuery, or perhaps an issue with something else all together.

Edit: upon further playing around with this, I found that its jQuery’s serializeArray() function which isn’t returning any data on the form which my serializeObject() requires. Not sure why, I use it this way in every other script with forms.

const handleUserForm = function(document) {
    console.log(document);

    myPopup = new Popup({
        id: "popup",
        title: "Download Form",
        content: '<div class="row">' +
            '<form id="user-registration-form">' +
            '<div class="row">' +
            '<div class="col"><label for="fname" hidden>First Name</label><input type="text" placeholder="First Name" id="fname"></div>' +
            '<div class="col"><label for="lname" hidden>Last Name</label><input type="text" placeholder="Last Name" id="lname"></div> ' +
            '</div>' +
            '<div class="row">' +
            '<div class="col"><label for="email" hidden>Email</label><input type="email" placeholder="[email protected]"></div>' +
            '<div class="col"><label for="organization" hidden>Organization</label><input type="text" placeholder="Organization Name"></div>' +
            '</div>' +
            '<div class="row">' +
            '<div class="col"><label for="state" hidden>State</label><select id="state"></select></div>' +
            '<div class="col"><label for="zip" hidden>Zip Code</label><input id="zip" type="text"></div> ' +
            '</div>' +
            '<div class="row">' +
            '<a class="btn btn-secondary" type="submit" id="registrationFormSubmit" style="color: white;">Submit</a>' +
            '</div>' +
            '</form> ' +
            '</div>',
        loadCallback: () => {
            $('#registrationFormSubmit').on('click', function (e) {
                e.preventDefault();

                let $reg = $('#user-registration-form');

                console.log($reg);
                console.log($reg.serializeObject());
            })
        },
    });

    myPopup.show();
}

jQuery.fn.serializeObject = function () {
    let arrayData, objectData;
    arrayData = this.serializeArray();
    objectData = {};

    console.log('serializeObject');
    console.log(arrayData);

    $.each(arrayData, function () {
        let value;

        console.log(value);

        if (this.value != null) {
            value = this.value;
        } else {
            value = '';
        }

        if (objectData[this.name] != null) {
            if (!objectData[this.name].push) {
                objectData[this.name] = [objectData[this.name]];
            }

            objectData[this.name].push(value);
        } else {
            objectData[this.name] = value;
        }
    });

    return objectData;
};

Even though there are no errors in the frontend or backend, something in my Angular app is still preventing the pages from rendering

I am working on an Angular application, but currently all the pages are showing up as blank. There are no errors reported in the frontend console or in the backend, and the API calls are working correctly. I suspect that something in the app’s structure or routing configuration is blocking the rendering of the components. I have checked the modules and components, but the issue persists

I have tried checking all my Angular modules, components, and routing configuration. I also verified that there are no errors in the console and that all backend APIs are working correctly. I expected the pages to render normally, with each route displaying its corresponding component, but instead the application shows only a blank page.

How can I run JavaScript code in VS Code?

I’m learning JavaScript and I’m using Visual Studio Code as my editor.

I wrote a simple file, script.js:

console.log("Hello, world!");

But when I try to run it inside VS Code, nothing happens.

  • Do I need to install something extra?

  • Should I run it in the terminal, or is there a built-in way in VS Code to execute JavaScript files?

  • What’s the simplest way to run and see the output of my JS code in VS Code?

I’m on Windows 11.

How do services like Otter.ai programmatically join Google Meet without browser automation?

Context & Current Situation

We’re building an educational analytics platform and need to access individual participant video streams from Google Meet sessions. After hitting walls with official APIs (Meet API, Add-ons SDK), we’re exploring bot-based approaches.

The Documentation & Visibility Problem

The core issue: There’s zero official documentation on how to build Google Meet bots, yet companies like Otter.ai, Read.ai, and numerous others have seamless implementations.

What We’re Struggling With:
Complete lack of official guidance – No Google documentation on bot development for Meet

Technical implementation mysteries – How are these companies actually joining meetings programmatically?

Reliability vs. hackiness – Our Puppeteer attempts are fragile and break frequently

Detection avoidance – What techniques prevent Google from blocking bot access?

Core Questions:

How do established companies achieve rock-solid reliability? Their bots join seamlessly every time

What’s the actual technical architecture? Are they using undocumented APIs, special browser automation, or something else entirely?

I would appreciate real technical insights from developers who’ve solved this. Anyone with actual implementation experience or insights into how this ecosystem really works?

Is this a valid JavaScript approach for sorting large arrays of unique integers efficiently?

I’m experimenting with sorting large arrays of unique integers in JavaScript and came up with a simple approach. I’m curious if it’s a recognized pattern or if there are potential pitfalls I might be missing.

Here’s the code I’m using:

function sortArr(arr) {
    const sorted = [];
    arr.forEach(el => sorted[el] = el);
    return sorted.filter(el => el);
}

function getRandomArray(length, max = length * 10) {
    const set = new Set();
    while (set.size < length) {
        set.add(Math.floor(Math.random() * max) + 1);
    }
    return [...set];
}

const arr = getRandomArray(100000);
console.log(sortArr(arr));

How it works:

Each number from the array is placed at the index equal to its value in a new array.

Then they are filtered out of empty slots to get the sorted array.

Questions:

  1. Are there potential performance or memory issues with this approach in JavaScript, especially with large arrays or large maximum values?

  2. Would this be practical for production code, or is it more of a coding experiment?

Any feedback or references to similar approaches would be appreciated!

I was trying to sort a large array of unique integers efficiently in JavaScript. I wanted to see if placing each element at its index in a new array and then filtering empty slots would produce a correctly sorted array, and whether this approach is efficient compared to built-in sort or counting sort.
I expected the code to return a sorted array in ascending order. I also expected it to run relatively fast for large arrays and use a reasonable amount of memory.

Keeping the current chosen option from marker passed from Django

I’m currently trying to create a website/webapp for my portfolio’s bank using Django 5.2/HTML/CSS/JS. I got stuck on one small part of creating bank statement subpage.
The issue I have encountered is: When user is setting how he wants his statement to be ordered the option of both select tags is reverting back to it’s default state.

Please keep in mind I’m currently focusing on learning Django as part of my Python learning plan and I’m practically a noob in JS. I do however understand a lot since I’ve done basics of Python(I passed PCEP and PCAP) and apart from semanthic changes most of the rules seems to be similar in OOP.

Here is my current code from statement.html:

{% extends "bank_accounts.html" %}
{% block title %} Statement {% endblock %}
<script type="text/javascript">

function change_order(o, o2) {
    document.getElementById(o).selected=True;
    document.getElementById(o2).selected=True;
}
</script>
{% block main %}
<p>{{ order }} {{ order2 }}</p>
<h1>STATEMENT</h1>
<h3> Below you can see statement from current month for your account({{ acc }}):</h3>
<form method="POST" onload="change_order('{{ order }}', '{{ order2 }}');">{% csrf_token %}Sort by:
<select name="order-by" id="order-by">
    <option id="date" value="date">Date</option>
    <option id="from" value="from">From</option>
    <option id="to" value="to">To</option>
    <option id="type" value="type">Type</option>
    <option id="sum" value="sum">Sum</option>

</select>

<select name="order-by2" id="order-by2">

    <option id="asc" value="asc">Ascending</option>
    <option id="desc" value="desc">Descending</option>

</select>
<table id="state-tb">
<tr>
    <th class="state-t"> Date and time </th>
    <th class="state-t"> From </th>
    <th class="state-t"> To </th>
    <th class="state-t"> Type </th>
    <th class="state-t"> Sum </th>
    <th class="state-t"> Reference </th>
    <th class="state-t"> Saldo after transaction </th>
</tr>

{% for x in history %}
    {% if x.type == "IN" %}
    <tr class="in">
    <td class="state-t">{{ x.date|date:"d/m/Y" }} {{ x.date|time:"h:i:s A" }}</td>
    <td class="state-t">{{ x.sender }}</td>
    <td class="state-t">{{ x.recipient }}</td>
    <td class="state-t">{{ x.t`your text`ype }} </td>
    <td class="state-t">{{ x.amount }}</td>
    <td class="state-t">{{ x.trans_ref }}</td>
    <td class="state-t">{{ x.after_saldo }}</td>
    </tr>
    {% else %}
    <tr class="out">
    <td class="state-t">{{ x.date|date:"d/m/Y" }} {{ x.date|time:"h:i:s A" }}</td>
    <td class="state-t">{{ x.sender }}</td>
    <td class="state-t">{{ x.recipient }}</td>
    <td class="state-t">{{ x.type }} </td>
    <td class="state-t">{{ x.amount }}</td>
    <td class="state-t">{{ x.trans_ref }}</td>
    <td class="state-t">{{ x.after_saldo }}</td>
    </tr>


    {% endif %}
{% endfor %}

</table>

    <h4>Below you can specify dates for your statement</h4>
    <input type="date" name="date_min" value="{{ date_val1 }}" min="{{ min_date }}">
    <input type="date" name="date_max" value="{{ date_val2 }}" max="{{ max_date }}">
    <button type="submit">Apply</button>

</form>
</div>

{% endblock %}

I’m not adding my views.py code as I checked wether context variables are passed by adding a p tag and displaying both of them in this part :

{% block main %}
<p>{{ order }} {{ order2 }}</p>
<h1>STATEMENT</h1>

I’ve tried a couple solutions:
1.First one was the same as above but without changing selected to True but just leaving it at .selected to maybe add that attribute to the proper <option>
2.In the second one I tried to change the .value of the <select> option by id and it looked like this:

<form method="POST">{% csrf_token %}Sort by:
<select name="order-by" id="order-by" onload="get.ElementById('order-by').value='{{ order }}';">

    <option id="date" value="date">Date</option>
    <option id="from" value="from">From</option>
    <option id="to" value="to">To</option>
    <option id="type" value="type">Type</option>
    <option id="sum" value="sum">Sum</option>

</select>

<select name="order-by2" id="order-by2" onload="get.ElementById('order-by').value='{{ order2 }}';">

    <option id="asc" value="asc">Ascending</option>
    <option id="desc" value="desc">Descending</option>

   </select>

I’ve tried few other solutions, mostly changing the "on event"(onload, onselect, onchange and even onclick) and placing it in different tags of my subpage.

Let me just add that:

  1. The “ordering-by” feature works perfectly for both selects.
  2. There are two date-type fields on the bottom of this site that let you specify the daterange for your statement and they work perfectly as well.
  3. The date-type fields get their default value from context variables that are passed from views.py and they retain the chosen date as I pass chosen dates as context variables to the value Attribute.
<h4>Below you can specify dates for your statement</h4>
    <input type="date" name="date_min" value="{{ date_val1 }}" min="{{ min_date }}">
    <input type="date" name="date_max" value="{{ date_val2 }}" max="{{ max_date }}">

Values of {{ order }} and {{ order2 }} ARE 100% within one of the options from the select tag.

Does anyone have any idea how to resolve this?
Also This is my first time posting on this site so apologies if I have done something wrong.

Calculated font size returns smaller than div height

I am trying to fit some long text into a div, and I use the following Javascript function to calculate the required font size. The container is the actual div that will display, and the measurer is a temporary div that has taken all the properties of the container, so same margins, padding, etc.

However, the measurer returns a smaller font size but a correct div height.

The irregularity is, when the page loads, it displays this smaller font. But performing a soft reload (Ctrl-R) displays the correctly sized font perfectly fitting in the div. Doing a hard reload (Ctrl-Shift-R) reloads the smaller font again.

What could be causing this strange behavior?

const measurer = document.createElement("div");
const containerStyles = getComputedStyle(container);

for (let prop of containerStyles) {
  measurer.style[prop] = containerStyles.getPropertyValue(prop);
}

measurer.style.display = "hidden";
measurer.style.position = "absolute";
measurer.style.height = "auto";
measurer.innerHTML = text;
document.body.appendChild(measurer);

while (measurer.offsetHeight == 0 || measurer.offsetHeight >= container.offsetHeight) {
  measurer.style.fontSize = (fontSize--) + "px";
  measurer.innerHTML = "";
  measurer.innerHTML = text;
}

document.body.removeChild(measurer);

Child window window.open not returning to the base memory of parent

I Have a app in app we have a widget we want to open this widget into new window
when i open window i communicate to parent window open in child when child is closed i communicate to parent child closed so parent open this widget in parent
memory increase
problem is when i open it takes alot of memory to open
i research on this and people saying it takes
so when i close widget it should return to base memory

export const openWidgetInNewWindow = ({
  widgetId,
  rowData,
  width = 900,
  height = 600,
  data,
  onCloseCallback = null,
}) => {
  // Get the name of the widget based on the ID

  const widgetName = Object.keys(allWidgetIDs).find(
    (key) => allWidgetIDs[key]?.id === widgetId,
  )

  // Calculate center position for the child window
  const left = window.screenX + (window.outerWidth - width) / 2
  const top = window.screenY + (window.outerHeight - height) / 2
  const url = `/widget/${widgetId}/${widgetName}`

  // Open the child window with specified dimensions and position

  childWindow = window.open(
    url,
    '_blank',
    `width=${width},height=${height},top=${top},left=${left}`,
  )

  // Store the window reference using its ID
  openWindows[widgetId] = childWindow

  if (childWindow) {
    childWindow.focus()

    // Set the widget as open in Redux
    store.dispatch.boards.addWidget({
      boardId: rowData,
      widget: { id: widgetId, name: widgetName },
      childOpen: true,
    })

    // Getting the latest current Board after dispatching so that can be used throughout the app
    const updatedCurrentBoard = getCurrentBoard()

    // Event handler to handle messages from child window (like closure)
    const closeTimeouts = {}

    const handleMessage = (event) => {
      if (event.data?.type === 'childClosed') {
        const widgetId = event?.data?.widgetId
        const data = event.data?.closed

        if (closeTimeouts[widgetId]) {
          clearTimeout(closeTimeouts[widgetId])
        }

        closeTimeouts[widgetId] = setTimeout(() => {
          if (data) {
            updateWidgetChildOpen(widgetId, false)
            if (onCloseCallback) onCloseCallback()
          }

          delete closeTimeouts[widgetId]
        }, 10)
      }
    }

    // Listen for messages from the child window
    window.addEventListener('message', handleMessage)

    // Cleanup listener on component unmount
    const cleanup = () => {
      window.removeEventListener('message', handleMessage)
    }
    window.reduxStore = updatedCurrentBoard

    return { childWindow, cleanup }
  } else {
    console.error('Failed to open child window')
    return null
  }
}

This is child window

function OrderEntry(props) {
  const { defaultSettings, widgetId, rowData } = props
  const boardId = rowData

  return (
    <Box
      onClick={() =>
        openWidgetInNewWindow({
          widgetId,
          rowData: boardId,
          width: 346,
          height: 400,
          onCloseCallback: () => {
            console.log('Widget closed')
          },
        })
      }
    >
      Childwindow open
    </Box>
  )
}

OrderEntry.propTypes = {
  defaultSettings: propTypes.object.isRequired,
  widgetId: propTypes.any,
  rowData: propTypes.string,
}

export default memo(OrderEntry)
  useEffect(() => {
// Initialize global event listeners
console.log('Initializing global event listeners')
const cleanupFns = initializeGlobalEventListeners({
  messageHandler: (event) => handleWidgetCommunication(event),
  unloadHandler: () => console.log('Window unloaded'),
  widgetId: widgetId,
})

// Apply zoom reset
function applyZoomReset() {
  const r = window.devicePixelRatio || 1
  document.documentElement.style.zoom = 1 / r
}
window.addEventListener('resize', applyZoomReset)
applyZoomReset()

// Cleanup both on unmount
return () => {
  cleanupFns.forEach((cleanupFn) => cleanupFn())
  window.removeEventListener('resize', applyZoomReset)
}

}, [])

Error: Cannot find module ‘../lightningcss.win32-x64-msvc.node’ ADRIAN [duplicate]

Require stack:

  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopnode_moduleslightningcssnodeindex.js
  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopdistcss-to-rnindex.js
  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopdistmetroindex.js
  • D:codebility_projectsSubTracknode_modulesnativewinddistmetroindex.js
  • D:codebility_projectsSubTrackmetro.config.js
  • D:codebility_projectsSubTracknode_modulescosmiconfignode_modulesimport-freshindex.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistloaders.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistcreateExplorer.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistindex.js
  • D:codebility_projectsSubTracknode_modulesmetro-configsrcloadConfig.js
  • D:codebility_projectsSubTracknode_modulesmetro-configsrcindex.js
  • D:codebility_projectsSubTracknode_modules@expometrometro-configindex.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartservermetroinstantiateMetro.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartservermetroMetroBundlerDevServer.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartserverDevServerManager.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartstartAsync.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartindex.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildbincli
  • D:codebility_projectsSubTracknode_modulesexpobincli
    Error: Cannot find module ‘../lightningcss.win32-x64-msvc.node’
    Require stack:
  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopnode_moduleslightningcssnodeindex.js
  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopdistcss-to-rnindex.js
  • D:codebility_projectsSubTracknode_modulesreact-native-css-interopdistmetroindex.js
  • D:codebility_projectsSubTracknode_modulesnativewinddistmetroindex.js
  • D:codebility_projectsSubTrackmetro.config.js
  • D:codebility_projectsSubTracknode_modulescosmiconfignode_modulesimport-freshindex.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistloaders.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistcreateExplorer.js
  • D:codebility_projectsSubTracknode_modulescosmiconfigdistindex.js
  • D:codebility_projectsSubTracknode_modulesmetro-configsrcloadConfig.js
  • D:codebility_projectsSubTracknode_modulesmetro-configsrcindex.js
  • D:codebility_projectsSubTracknode_modules@expometrometro-configindex.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartservermetroinstantiateMetro.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartservermetroMetroBundlerDevServer.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartserverDevServerManager.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartstartAsync.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildsrcstartindex.js
  • D:codebility_projectsSubTracknode_modulesexponode_modules@expoclibuildbincli
  • D:codebility_projectsSubTracknode_modulesexpobincli
    at Function._resolveFilename (node:internal/modules/cjs/loader:1383:15)
    at defaultResolveImpl (node:internal/modules/cjs/loader:1025:19)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1030:22)
    at Function._load (node:internal/modules/cjs/loader:1192:37)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:237:24)
    at Module.require (node:internal/modules/cjs/loader:1463:12)
    at require (node:internal/modules/helpers:147:16)
    at Object. (D:codebility_projectsSubTracknode_modulesreact-native-css-interopnode_moduleslightningcssnodeindex.js:21:22)
    at Module._compile (node:internal/modules/cjs/loader:1706:14)

SOLUTION: just download this “https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170”