Call to eventChange event

I’m using FullCalendar 6.1 with rrule plugin. I have set editable:true so that I can drag existing events. I’m not planing on dropping external events. The documentation says evenChange is called after eventDrop and eventResize, so I’m guessing I need to make ajax call in eventChange to update database. After the Ajax call to update database, how do I render calendar? I looked around but I cannot seem to find an example that uses eventChange. I was wondering how definition of function looks like e.g

eventChange: function (info) {
...
}

How to call dispatch function in same useEffect in order to avoid Maximum update depth exceeded

I have component that looks like this

const TrainingProgressBar = ({ id }) => {
  const { classes } = useStyles();
  const dispatch = useDispatch();

  const { success } = useSelector(state => state.app.contents).statusById[id];
  const content = useSelector(state => selectContent(state, { id }));
  const { notStarted, started, completed } = content.trainingProgress || {};

  const refic = useRef();

  useEffect(() => {
    if (success || JSON.stringify(refic.current) !== JSON.stringify(content)) {
     dispatch(getContent({
       id,
       query: {
         calculateTrainingProgress: true,
         management: true
       }
     }));
     refic.current = content;
    }
  }, [dispatch, id, success, content]);

  const total = notStarted + started + completed;
  const totalPercentage = Math.round((completed / total) * 100) || 0;

  return (
    <>
      some code
    </>
  );
};

Where content depends on the ID that is passed to this component. I’m trying to achieve that dispatch is called when content is loaded, success is true, and content is changed. In the second case, success is not changed. The problem I have is that the Maximum update depth is exceeded. It’s caused by content in the dependency array, but if I don’t put it in there, dispatch will not be called if the content is changed. What am I doing wrong?

Bcrypt returns false

Bcrypt.compare returns false. I checked about 10 questions in here, but still couldn’t figure it out. My user model doesn’t trim passwords. Mongodb used to store hashed password. Implemented step by step checks. Hashed password is returned correctly. Ensured that the correct password is used as an input. Consulted with genAI with no success. Please help.

    userLogin: async (parent, { email, password }, context) => {
  try {
    // Check if the rate limit has been exceeded
    if (context.req.rateLimit && context.req.rateLimit.remaining <= 0) {
      // Log rate limit exceeded
      logWarn(`Rate limit exceeded for email: ${email}`);
      // Throw an error if the rate limit has been exceeded
      throw new Error('Too many login attempts, please try again later.');
    }

    // Find the user by email
    const user = await User.findOne({ email });

    // Log the user object
    logInfo(`User found: ${JSON.stringify(user)}`);

    // Check if the user exists
    if (!user) {
      // Log failed login attempt
      logError(`Failed login attempt for email: ${email}`);
      // Throw an error if the user does not exist
      throw new Error('User not found');
    }

    // Log the hashed password stored in the database
    logInfo(`Hashed password from database: ${user.password}`);

    // Log the provided password
    logInfo(`Provided password: ${password}`);

    // Check if the provided password matches the hashed password stored in the database
    const isMatch = await bcrypt.compare(password, user.password);

    // Log the password comparison result
    logInfo(`Password match: ${isMatch}`);

    if (!isMatch) {
      // Log failed login attempt
      logError(`Failed login attempt for email: ${email}`);
      // Throw an error if the password is incorrect
      throw new Error('Invalid email or password');
    }

    // Generate a JWT token
    const token = jwt.sign({ userId: user._id }, 'your_jwt_secret_here', {
      expiresIn: '1h',
    });

    // Log successful login
    logInfo(`User logged in: ${user.email}`);

    // Return the token and the user ID
    return {
      token,
      userId: user._id,
    };
  } catch (error) {
    // Log the error
    logError(`Error during login: ${error.message}`);
    throw error;
  }
},

Can’t figure a way to save ‘textarea’ content that can be lost when perplexity.ai trigger a Cloudfare captcha

I try to save the content of ‘textarea’ for perplexity.ai.

The website can trigger a Cloudfare captcha when you submit, then you loose what you have written in the box.

I tried this, which is wrong, there’s nothing restored by example when I refresh the page.

// ==UserScript==
// @name         Sauvegarde Textarea
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Sauvegarde le contenu d'un textarea et le restaure après un rafraîchissement de la page.
// @match        https://www.perplexity.ai/search/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Sélectionner le textarea
    const textareas = document.querySelectorAll('textarea');
    let textarea;

    // Vérifier si des textareas existent
    if (textareas.length > 0) {
        // Choisir le bon textarea (ajuster selon la structure de la page)
        textarea = textareas.length === 3 ? textareas[2] : textareas[0];
    } else {
        console.error("Aucun textarea trouvé.");
        return;
    }

    // Charger le contenu sauvegardé depuis le localStorage
    const savedContent = localStorage.getItem('textareaContent');
    if (savedContent) {
        textarea.value = savedContent; // Restaurer le contenu sauvegardé
    }

    // Fonction pour sauvegarder le contenu dans localStorage
    function saveContent() {
        localStorage.setItem('textareaContent', textarea.value);
    }

    // Écouter les événements de changement sur le textarea
    textarea.addEventListener('input', saveContent);

    // Écouter l'événement de perte de focus pour sauvegarder une dernière fois
    textarea.addEventListener('blur', saveContent);

    // Écouter l'événement de déchargement de la page pour sauvegarder une dernière fois
    window.addEventListener('beforeunload', saveContent);
})();

How can I display/hide divs when corresponding images are clicked? (vanilla JS)

I’ve been teaching myself some coding basics by creating a spoof social media site with HTML/CSS and vanilla Javascript. Currently, I’m trying to toggle post descriptions when post images are clicked.

I’ve cobbled together an ugly and janky (but working!) list of functions with if/else statements. It’s REALLY horrible; I know there are much cleaner solutions using arrays and for loops. I’d like to find out how to store my post descriptions and post images in two const variables (as nodelists, then turn them into arrays?), then use a loop to toggle the correct post description to “display: block” when its corresponding image is clicked.

As it stands, my code functions, but extremely poorly. Here is the fiddle: https://jsfiddle.net/x9abz658/3/#&togetherjs=hFzS5u7I9y

And here is the first function as an example:

function showPostOne() {
    var a = document.getElementById("postone");
    var b = document.getElementById("posttwo");
    var c = document.getElementById("postthree");
    var d = document.getElementById("postfour");
    var e = document.getElementById("postfive");
    var f = document.getElementById("postsix");
    var g = document.getElementById("postseven");

    if (a.style.display === "none")
         {a.style.display = "block";}

    else {
        a.style.display = "none";
    }

    if (b.style.display === "block")
        {b.style.display = "none";}

    if (c.style.display === "block")
        {c.style.display = "none";}

    if (d.style.display === "block")
        {d.style.display = "none";}

    if (e.style.display === "block")
        {e.style.display = "none";}

    if (f.style.display === "block")
        {f.style.display = "none";}

    if (g.style.display === "block")
        {g.style.display = "none";}
    }

Every image activates a function onclick, which displays its specific description by manually setting every other description to display: none. Like I said, horrible.

Currently, I’m using document.getElementById to assign a unique variable to every post, then specifically designating which post to display while hiding the others. I’ve tried to make the variables global by using const and moving them out of the functions, but everything stops working. Not only is the code janky, but I have to declare the same variables inside each function.

I’ve scoured the web for solutions using loops and nodelists/arrays, such as this one:

const pics = document.getElementsByClassName("pix");
const posts = document.getElementsByClassName("post");

for (let ii = 0; ii < pics.length; ii++) {
    pics[ii].addEventListener("click", function() {
    
        for (let aa = 0; aa < posts.length; aa++) {
            posts[aa].style.display = "none";
        }
        posts[ii].style.display = "block";
    });
}

I’m getting more familiar with for loops, and I broadly understand this code, but it doesn’t work with the HTML/CSS that I already have; the variable and class names are correct, as far as I’m aware. The “pix” class has only been assigned to <img> elements; I tried to enclose each image in a div and assign those to the variable “pics”, thinking that might help, but it only made things worse.

Any advice is appreciated.

How to Properly Configure Vite to Compile data-src Attributes for Lazy Loading Images?

I am working on a project using Vite and trying to implement lazy loading for images. I have the following HTML structure for my images:

html

<img
  class="lazy"
  src="./src/images/lazy/note.webp"
  data-src="./src/images/note.webp"
  alt="Image of a book"
  class="bookImage"
/>

after build the html looks like this

 <img
   class="lazy"
   src="/assets/note-BK5rAaOe.webp"
   data-src="./src/images/note.webp"
   alt="Image of a book"
   class="bookImage"
 />

Problem:
The issue I am facing is that during the Vite build, the data-src attributes for my images are not being processed. As a result, lazy loading does not work as expected as the location is wrong

To achieve lazy loading, I’m using the following JavaScript:

document.addEventListener('DOMContentLoaded', function () {
  const lazyImages = document.querySelectorAll('.lazy');

  const lazyLoad = (entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.classList.add('loaded'); // Add loaded class for the animation
        observer.unobserve(img); // Stop observing the image once it's loaded
      }
    });
  };

  const observer = new IntersectionObserver(lazyLoad, {
    root: null,
    rootMargin: '0px',
    threshold: 0.1,
  });

  lazyImages.forEach(img => observer.observe(img));
});

Additionally, here is my vite.config.js file:

import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        // Use the modern API
        api: 'modern-compiler', // or "modern"
      },
    },
  },
});

How can I configure Vite to compile the data-src attributes properly?
Do I need to manually add images to achieve lazy loading, or is there a way to automate this process?
I also tried building the same setup using Parcel, but I encountered the same issue with the data-src attributes not being compiled.
Any guidance or suggestions on how to resolve this issue would be greatly appreciated!

compileSdkVersion is not specified during configuration of project ‘expo-camera’

When building my expo react-native app I get the build error:

  • Where:
    Script ‘/DELIBERATELY_HIDDEN/node_modules/expo-modules-autolinking/scripts/android/autolinking_implementation.gradle’ line: 377

  • What went wrong:
    A problem occurred evaluating project ‘:expo’.

A problem occurred configuring project ‘:expo-camera’.
Failed to notify project evaluation listener.
> com.android.builder.errors.EvalIssueException: compileSdkVersion is not specified. Please add it to build.gradle
> Could not get unknown property ‘release’ for SoftwareComponent container of type org.gradle.api.internal.component.DefaultSoftwareComponentContainer.

I’ve tried every answer in every related post but it hasn’t helped.

I’ve looked at my android project level, android app level and expo-camera node_modules level build.gradle file’s, but they all specify a compileSdkVersion!

I don’t want to change anything in node_modules as it will be wiped every time I have to reinstall them.

It used to build just fine using expo-camera version 14.1.3, react 18.2.0, react native 0.73.6 & expo 50.0.0 and I haven’t changed those versions.

Incidentally, I also get the following in my problems tab in VS Code, but similar errors have happened with other modules, before, without causing build errors:

Missing Gradle project configuration folder: .settings

Here are my build.gradle file’s:

Project level:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
        minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
        compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
        targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
        kotlinVersion = findProperty('android.kotlinVersion') ?: '1.8.10'

        ndkVersion = "25.1.8937393"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath('com.android.tools.build:gradle')
        classpath('com.facebook.react:react-native-gradle-plugin')
    }
}

apply plugin: "com.facebook.react.rootproject"

allprojects {
    repositories {
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
        }
        maven {
            // Android JSC is installed from npm
            url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist'))
        }

        google()
        mavenCentral()
        maven { url 'https://www.jitpack.io' }
        maven {
            // expo-camera bundles a custom com.google.android:cameraview
            url "$rootDir/../node_modules/expo-camera/android/maven"
        }
    }
}

App level:

apply plugin: 'com.android.application'
apply plugin: "com.facebook.react"

def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()

/**
 * This is the configuration block to customize your React Native Android app.
 * By default you don't need to apply any configuration, just uncomment the lines you need.
 */
react {
    entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
    reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
    hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
    codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()

    // Use Expo CLI to bundle the app, this ensures the Metro config
    // works correctly with Expo projects.
    cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim())
    bundleCommand = "export:embed"

    /* Folders */
    //   The root of your project, i.e. where "package.json" lives. Default is '..'
    // root = file("../")
    //   The folder where the react-native NPM package is. Default is ../node_modules/react-native
    // reactNativeDir = file("../node_modules/react-native")
    //   The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
    // codegenDir = file("../node_modules/@react-native/codegen")

    /* Variants */
    //   The list of variants to that are debuggable. For those we're going to
    /* Bundling */
    //   A list containing the node command and its flags. Default is just 'node'.
    // nodeExecutableAndArgs = ["node"]

    //
    //   The path to the CLI configuration file. Default is empty.
    // bundleConfig = file(../rn-cli.config.js)
    // hermesFlags = ["-O", "-output-source-map"]
}

/**
 * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
 */
def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean()

/**
 * The preferred build flavor of JavaScriptCore (JSC)
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US. Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

apply plugin: "org.jetbrains.kotlin.android"

android {
    ndkVersion rootProject.ext.ndkVersion

    buildToolsVersion rootProject.ext.buildToolsVersion
    compileSdk rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    namespace 'co.uk.tycho.provisioner'
    defaultConfig {
        applicationId 'co.uk.tycho.provisioner'
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 14
        versionName "1.0.0"

        buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString())

        missingDimensionStrategy 'react-native-camera', 'general'
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'provisionerDebugKey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false)
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    packagingOptions {
        jniLibs {
            useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
        }
    }
    // flavorDimensions 'react-native-camera'
    // productFlavors {
    //     general {
    //         dimension 'react-native-camera'
    //     }
    //     mlkit {
    //         dimension 'react-native-camera'
    //     }
    // }
}

// Apply static values from `gradle.properties` to the `android.packagingOptions`
// Accepts values in comma delimited lists, example:
// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini
["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop ->
    // Split option: 'foo,bar' -> ['foo', 'bar']
    def options = (findProperty("android.packagingOptions.$prop") ?: "").split(",");
    // Trim all elements in place.
    for (i in 0..<options.size()) options[i] = options[i].trim();
    // `[] - ""` is essentially `[""].filter(Boolean)` removing all empty strings.
    options -= ""

    if (options.length > 0) {
        println "android.packagingOptions.$prop += $options ($options.length)"
        // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**'
        options.each {
            android.packagingOptions[prop] += it
        }
    }
}

dependencies {
    // The version of react-native is set by the React Native Gradle Plugin
    implementation("com.facebook.react:react-android")

    def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
    def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
    def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";

    if (isGifEnabled) {
        // For animated gif support
        implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
    }

    if (isWebpEnabled) {
        // For webp support
        implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
        if (isWebpAnimatedEnabled) {
            // Animated webp support
            implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
        }
    }

    implementation("com.facebook.react:flipper-integration")

    if (hermesEnabled.toBoolean()) {
        implementation("com.facebook.react:hermes-android")
    } else {
        implementation jscFlavor
    }
}

apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
applyNativeModulesAppBuildGradle(project)

expo-camera node_modules level:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'

group = 'host.exp.exponent'
version = '14.1.3'

def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
if (expoModulesCorePlugin.exists()) {
  apply from: expoModulesCorePlugin
  applyKotlinExpoModulesCorePlugin()
  // Remove this check, but keep the contents after SDK49 support is dropped
  if (safeExtGet("expoProvidesDefaultConfig", false)) {
    useExpoPublishing()
    useCoreDependencies()
  }
}

buildscript {
  // Simple helper that allows the root project to override versions declared by this library.
  ext.safeExtGet = { prop, fallback ->
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
  }

  // Ensures backward compatibility
  ext.getKotlinVersion = {
    if (ext.has("kotlinVersion")) {
      ext.kotlinVersion()
    } else {
      ext.safeExtGet("kotlinVersion", "1.8.10")
    }
  }

  repositories {
    mavenCentral()
  }

  dependencies {
    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
  }
}

// Remove this if and it's contents, when support for SDK49 is dropped
if (!safeExtGet("expoProvidesDefaultConfig", false)) {
  afterEvaluate {
    publishing {
      publications {
        release(MavenPublication) {
          from components.release
        }
      }
      repositories {
        maven {
          url = mavenLocal().url
        }
      }
    }
  }
}

android {
  // Remove this if and it's contents, when support for SDK49 is dropped
  if (!safeExtGet("expoProvidesDefaultConfig", false)) {
    compileSdkVersion safeExtGet("compileSdkVersion", 34)

    defaultConfig {
      minSdkVersion safeExtGet("minSdkVersion", 23)
      targetSdkVersion safeExtGet("targetSdkVersion", 34)
    }

    publishing {
      singleVariant("release") {
        withSourcesJar()
      }
    }

    lintOptions {
      abortOnError false
    }
  }

  def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
  if (agpVersion.tokenize('.')[0].toInteger() < 8) {
    compileOptions {
      sourceCompatibility JavaVersion.VERSION_11
      targetCompatibility JavaVersion.VERSION_11
    }

    kotlinOptions {
      jvmTarget = JavaVersion.VERSION_11.majorVersion
    }
  }

  namespace "expo.modules.camera"
  defaultConfig {
    versionCode 32
    versionName "14.1.3"
  }
}

repositories {
  mavenCentral()
  maven {
    url "$projectDir/maven"
  }
}

dependencies {
  // Remove this if and it's contents, when support for SDK49 is dropped
  if (!safeExtGet("expoProvidesDefaultConfig", false)) {
    implementation project(':expo-modules-core')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
  }
  def camerax_version = "1.4.0-alpha02"

  api "androidx.exifinterface:exifinterface:1.3.6"
  api 'com.google.android:cameraview:1.0.0'

  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  implementation "androidx.camera:camera-video:${camerax_version}"

  implementation "androidx.camera:camera-view:${camerax_version}"
  implementation "androidx.camera:camera-extensions:${camerax_version}"
  implementation "com.google.mlkit:barcode-scanning:17.2.0"
  implementation 'androidx.camera:camera-mlkit-vision:1.4.0-alpha02'

  api 'com.google.android:cameraview:1.0.0'
}

How to Correcting Off-by-One Error in a Loop?

You are given a method that is supposed to print numbers from 1 to N. However, there is an off-by-one error that causes the loop to skip the last number. Identify and correct the error.

public class PrintNumbers {
    public static void printNumbers(int N) {
        for (int i = 1; i < N; i++) { // Incorrect loop condition
            System.out.print(i + " ");
        }
    }

    public static void main(String[] args) {
        printNumbers(5); // Expected Output: 1 2 3 4 5
                         // Actual Output: 1 2 3 4
    }
}
public static void main(String[] args) {
        printNumbers(5); // Expected Output: 1 2 3 4 5
                         // Actual Output: 1 2 3 4
    }
}

TypeError (is not iterable) when adding SVG to FabricJS canvas

I have a fabricjs canvas, and I’m trying to add an SVG to it. But whatever I do, I get problems. It keeps saying:
“Uncaught (in promise) TypeError: t is not iterable”.

let svg = `<svg viewBox="-8 -8 136 136">
<path stroke="#000000" stroke-width="8" d="m0 51.82677l0 0c0 -28.623135 23.203636 -51.82677 51.82677 -51.82677l0 0c13.745312 0 26.927654 5.4603047 36.64706 15.17971c9.719406 9.719404 15.17971 22.901749 15.17971 36.64706l0 0c0 28.623135 -23.203636 51.82677 -51.82677 51.82677l0 0c-28.623135 0 -51.82677 -23.203636 -51.82677 -51.82677zm25.913385 0l0 0c0 14.311565 11.60182 25.913387 25.913385 25.913387c14.311565 0 25.913387 -11.601822 25.913387 -25.913387c0 -14.311565 -11.601822 -25.913385 -25.913387 -25.913385l0 0c-14.311565 0 -25.913385 11.60182 -25.913385 25.913385z" fill="none"></path>
</svg>`;

let canvas = new fabric.Canvas("canvas");
let path = fabric.loadSVGFromString(svg, function(objects, options) {
    let obj = fabric.util.groupSVGElements(objects, options);
    
    obj.set({
        left: canvas.width / 2 - obj.width / 2,
        top: canvas.height / 2 - obj.height / 2
    });
    canvas.add(obj).renderAll();
});

Hopefully someone can help me out

How do I wait for action complete on introjs onbeforechange

In my intro tour, I have a section where I need to expand a div with a slider before I can run intro on the internal elements. I use onbeforechange to expand the div, but it is a jquery animation. The problem is that the top coordinate of the div is off screen when I get to this step of my tour. I want to wait until the animation is complete before drawing the next introjs box. Is there a way to do this? Here is my code…

       }).onbeforechange(function(targetElement) {
            // Check if you want to trigger a click on the current step
            if (this._currentStep === 3 || this._currentStep === 4 ||this._currentStep === 5 ||this._currentStep === 6 ||this._currentStep === 7) {
                if ($('.btn-arrow').text() == 'Click for ↓ Details') {
                    const elementToClick = document.querySelector(".btn-arrow");
                    if (elementToClick) {
                        elementToClick.click();
                    }
                }   
            }

The conditional is a test for whether the div is expanded yet. It is saying “if not, then expand before change.” but introjs does not wait for the expand to complete since it is asynchronous. I guess what I need is a ‘pause’ introjs, then a ‘restart’ that I can trigger on complete of my animation?

Thanks for any hints.

JavaScript Fullscreen: fullscreenEnabled is always false and fullscreenElement is not the element requested on

There is a [Lit] WebComponent that I call requestFullscreen() on (this.requestFullscreen()). It’s a toggle, so when the same action is clicked again I check for if (document.fullscreenElement === this), since this is the element that requested fullscreen.

However, document.fullscreenElement is actually the next highest ancestor WebComponent, not even any of the native HTML ancestors between these two WebComponents. So I decided to use document.fullscreenEnabled, just to see if it was and toggle fullscreen off. Turns out, document.fullscreenEnabled is always false.

For now my workaround, because document.fullscreenElement is either that ancestor or null, I am just checking if (!!document.fullscreenElement). This is kinda kludgy, IMO, but works.

Why is document.fullscreenEnabled always false and document.fullscreenElement not this when I called this.requestFullscreen() to invoke fullscreen?

trace cookie creation in browser devtools

I’m trying to understand a website’s login process

After I login, it creates a cookie but I can’t find out which code is creating this cookie

I used firefox devTools and I can see that after posting data to login page the next request contains that specific cookie but none of the previous request’s responses have any header to create that cookie

I searched for document.cookie in every js file, and set breakpoint on every line but none of them triggered for that cookie creation

I injected this code in console before login, but still no luck

origDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');
Object.defineProperty(document, 'cookie', {
  get() {
    return origDescriptor.get.call(this);
  },
  set(value) {
    debugger;
    return origDescriptor.set.call(this, value);
  },
  enumerable: true,
  configurable: true
});

The website is written with angular I guess (ng-version=”17.0.8″)

Is there any other way to create cookies? I’m a web developer myself and I’ve always thought that it’s only possible to create cookie through js and http response headers

P.S: I was googling around and saw some posts about firebug and the ability to create breakpoint on cookie creation but it seems it’s replaced by firefox dev edition and this one doesn’t have that ability

Unexpected behaviour with JavaScript’s “onanimationend” – follow-up

This is a follow-up to this question along with its accepted answer.

This time there is one more list level and the list style item is also highlighted.

Please have a look at this code snippet:

const highlight = (element) => {
  element.classList.remove('highlight');
  setTimeout(() => {
    element.classList.add('highlight');
  }, 0);
  element.onanimationend = e => {
    e.stopPropagation();
    element.classList.remove('highlight');
  }
}
document.querySelector('body').addEventListener('click', event => {
  if (event.target.hash) {
    const element = document.querySelector(event.target.hash);
    highlight(element);
  }
});
@keyframes highlight {
  from {
    background: red;
  }
  to {
    background: transparent;
  }
}

ol {
  counter-reset: enumeration;
  list-style: none;
}

ol > li {
  position: relative;
}

ol > li::before {
  position: absolute;
  margin-left: -2em;
  width: 1em;
  counter-increment: enumeration;
  content: counter(enumeration) '.';
}

ol > li > ol {
  counter-reset: alphabet;
  list-style: none;
}

ol > li > ol > li {
  position: relative;
}

ol > li > ol > li::before {
  position: absolute;
  margin-left: -2em;
  width: 1em;
  counter-increment: alphabet;
  content: counter(alphabet, lower-alpha) ')';
}

div.highlight,
ol > li.highlight,
ol > li.highlight::before,
ol > li:has(.highlight)::before {
  animation: highlight 5s;
}
<ul>
  <li>
    <a href="#foo">Foo</a>
    <div>
      <ul>
        <li>
          <a href="#foo-1">Foo 1</a>
          <ul>
            <li><a href="#foo-1-1">Foo 1.1</a></li>
            <li><a href="#foo-1-2">Foo 1.2</a></li>
            <li><a href="#foo-1-3">Foo 1.3</a></li>
          </ul>
        </li>
        <li><a href="#foo-2">Foo 2</a></li>
        <li><a href="#foo-3">Foo 3</a></li>
      </ul>
    </div>
  </li>
  <li><a href="#bar">Bar</a></li>
  <li><a href="#baz">Baz</a></li>
</ul>

<hr>

<div id="foo">
  <h2>Foo</h2>
  <ol>
    <li id="foo-1">
      Foo 1
      <ol>
        <li id="foo-1-1">Foo 1.1</li>
        <li id="foo-1-2">Foo 1.2</li>
        <li id="foo-1-3">Foo 1.3</li>
      </ol>
    </li>
    <li id="foo-2"> Foo 2</li>
    <li id="foo-3"> Foo 3</li>
  </ol>
</div>

<div id="bar">
  <h2>Bar</h2>
</div>

<div id="baz">
  <h2>Baz</h2>
</div>

Then please run the code snippet (preferably on full page) and try:

Click on “Foo 1.1” (or “Foo 1.2” or “Foo 1.3”), wait 3 seconds and then click on “Foo”. As you can see, the background color animation of “Foo” ends at the same time as the background color animation of “Foo 1.1” (or “Foo 1.2” or “Foo 1.3”). One could also say that the CSS class “highlight” is removed from “Foo” too early.

Furthermore, if you initially click on “Foo 1.1” (or “Foo 1.2” or “Foo 1.3”), the list style item of “Foo” is highlighted as expected (and intended). But if you click on “Foo 1.1” (or “Foo 1.2” or “Foo 1.3”) again within 5 seconds, the list style item of “Foo” is not highlighted again. Only after waiting 5 seconds at least and then clicking on “Foo 1.1” (or “Foo 1.2” or “Foo 1.3”) again, the list style item of “Foo” is highlighted again.

This strange behaviour may be due to the pseudo-element ::before. So it is about ol > li:has(.highlight)::before. stopPropagation() doesn’t seem to affect pseudo-elements because they are not part of the actual DOM.

Any idea how to fix this?

Can’t figure out how to configure Chakra-UI

I have this to templates main.jsx and app.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import { Provider } from "@chakra-ui/react";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>
);

and app.jsx

import { Button } from "@chakra-ui/react";

function App() {
  return (
    <>
      <Button>Hello!</Button>
    </>
  );
}

export default App;

I’m trying to configure and use Chakra-UI but that button won’t be added there with everything that I tried
I also tried this in main.js

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import ChakraProvider from "@chakra-ui/react";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <ChakraProvider>
      <App />
    </ChakraProvider>
  </React.StrictMode>
);

The error for the first type of main.jsx is

The requested module '/node_modules/.vite/deps/@chakra-ui_react.js?v=88ddfe76' does not provide an export named 'Provider' (at main.jsx:4:10)

And for the second type

 The requested module '/node_modules/.vite/deps/@chakra-ui_react.js?v=88ddfe76' does not provide an export named 'default' (at main.jsx:4:8)

Please help me with some ideas…

Javascript array with data inside but ’empty header’ [duplicate]

I’m new to JS. I created the 1st array with loop and push, from cloud database. Then I manually declared the 2nd array with the same data. But in firefox console, when you console.log() them, it is like this:

enter image description here

As it shows, the 1st one has an ’empty header’ and length is empty too.

The difference I have found so far is that when you run:

console.log(JSON.stringify(array1));
console.log(JSON.stringify(array2));

The output is gonna be:
console outputs

My question is: How to transform (or fix) the 1st array to make it exactly same as the 2nd array?

——————————–
Updated the code to fetch data from Firebase.

        // Function to fetch locations from Firebase
        const loclist = [];
        async function getLocs() {
            const dbRef = await db.ref('chatbot')

            await dbRef.once('value', (snapshot) => {
                snapshot.forEach((childSnapshot) => {
                    const childData = childSnapshot.val();
                    if (childData && childData.user_loc) { // Check if loc exists
                        loclist.push(childData.user_loc); // Add loc to the list
                    }
                });

                // Display in the HTML
                const userlocElement = document.getElementById("loclist_html");
                loclist.forEach(loc => {
                    const li = document.createElement("li");
                    li.textContent = loc; // Set loc as the text content of the list item
                    userlocElement.appendChild(li); // Append list item to the list
                });
            });
        };

        getLocs();