Outlook Addin – Office.context.mailbox undefined

i am working on an outlook addin that has been deployed to Prod.
I works fine but there it malfunction for very few users.
after trying to debug on one of them i noticed that Office.conext.mailbox was undefined while trying to get the info of the logged user as you can see below.

Office.onReady(function (info) {
  blockUI();
  if (info.host === Office.HostType.Outlook) {
    $('#sideload-msg').hide();
    const username = Office.context.mailbox.userProfile.displayName;
    initializeUser(username);
  }
});

I tried to switch the function callback Office.onready sync and async but changed nothing

Change a certain part of a url in a href [duplicate]

I have a url like this:

https://example.org/it/accept.html?event=77ffafe4-15d6-4512-8213-8270f515e736&token=9a0685b7-5f0d-4a5e-875b-05bb52602e5a&cache=c3078cf0-6a43-490b-9b2d-09b983bbf726

and a language menu:

<a href="" class="changeLang">IT</a>
<a href="" class="changeLang">EN</a>
<a href="" class="changeLang">FR</a>`

I need to change only the language when U click on related menu for ex:

IT

https://example.org/it/accept.html?event=77ffafe4-15d6-4512-8213-8270f515e736&token=9a0685b7-5f0d-4a5e-875b-05bb52602e5a&cache=c3078cf0-6a43-490b-9b2d-09b983bbf726

EN

https://example.org/en/accept.html?event=77ffafe4-15d6-4512-8213-8270f515e736&token=9a0685b7-5f0d-4a5e-875b-05bb52602e5a&cache=c3078cf0-6a43-490b-9b2d-09b983bbf726

How can I change only a specific part of the page url?

I don’t know if a js could help

DateRangePicker not opening on click

I am trying to use the following package: daterangepicker

The following code I try to use to open the calendar on click, but nothing happens (inside a script.js file).

jQuery(function($) {

    $('#b_checkin').on('click', function() {

        // $(this).trigger('show.daterangepicker'); // have tried this also not working
        $(this).daterangepicker();

    });

});

Do I miss anything.

How can I implement a self-adjusting priority queue in JavaScript to manage dynamic task prioritization?

I’m developing a task scheduling application in JavaScript where tasks have varying priorities that can change over time based on specific conditions. I need a data structure that allows:

  • Efficient insertion of tasks.
  • Dynamic adjustment of task priorities.
  • Retrieval of the highest-priority task.

I’ve considered using a simple array and sorting it upon each insertion, but this seems inefficient for a large number of tasks. I also looked into using a binary heap; however, I’m unsure how to efficiently update the priority of an existing task within a heap structure.

I attempted to implement a binary heap to manage the tasks. Insertion and retrieval of the highest-priority task are efficient with this approach. However, updating the priority of an existing task proved challenging. I found that locating the task within the heap and then reheapifying to maintain the heap property could become inefficient, especially as the number of tasks grows.

I expected to find a way to efficiently update task priorities within the heap without compromising performance, but my current implementation doesn’t meet the desired efficiency. I’m seeking guidance on how to design or utilize a data structure in JavaScript that supports efficient priority updates and retrievals.

document.getElementsByName() finds nothing [closed]

I have several divs in my html page. When I use getElementsByName() it finds nothing. When I use getElementsByTagName(), it finds all the divs and the routine works.

id = 130;
//const DIVs = document.getElementsByName("point_"+id);
const DIVs = document.getElementsByTagName("div");
for (let div of DIVs) {
    if (div.name == "point_"+id) {
        console.log("found: "+div.name);
    }
}

Can anyone spot why getElementsByName() doesn’t find anything?

Method called with old props when component size changes via ResizeObserver

I have a problem with the following component.

The method onUpdateScale should be called when props.zoomValue changes, but the value is not the most recent and instead is the one from the first render.
ex. the component is created with zoomValue 1.0 then the value changes to 1.5 but inside onUpdateScale is still 1.5.

I’ve debugged this with console and I get that the function is called with the new value but then another call happens after with the old value. How that’s possible?

The observer is constructed and deconstructed correctly, if on disconnection the call happen here it still doesn’t make sense because when the next observer is created the function gets a call.

I got a little frustrated because I’ve found this bug by accident and I haven’t figured out any way to fix it. To me the update function is created correctly, what’s missing?

In this snippet I’m using the Preact and bootstrap framework.

import { useLayoutEffect, useRef, useState } from "preact/hooks";
import type { JSX } from "preact/jsx-runtime";

export interface WidgetFormContainerProps
{
    vWidth: string | number,
    zoomValue: number,
    children?: any,
}

export const WidgetFormContainer = (props: WidgetFormContainerProps): JSX.Element =>
{
    const [width, setWidth] = useState<number>(0);
    const [height, setHeight] = useState<number>(0);
    const [scale, setScale] = useState<number>(1.0);

    const root = useRef<HTMLDivElement>(null);
    const container = useRef<HTMLDivElement>(null);


    const onUpdateScale = (): void =>
    {
        if (!root.current || !container.current)
        {
            // won't update with no elements.
            return;
        }

        const newScale = (root.current.clientWidth / container.current.clientWidth) * props.zoomValue;

        const newWidth = Math.max(container.current.clientWidth * newScale, root.current.clientWidth);
        const newHeight = container.current.clientHeight * newScale;

        setScale(newScale);
        setWidth(newWidth);
        setHeight(newHeight);
    }

    useLayoutEffect(() =>
    {
        if (!root.current)
        {
            // required root element to create observer, destroy previous observer if any.
            return;
        }

        const observer = new ResizeObserver(onUpdateScale);

        observer.observe(root.current);
        onUpdateScale();

        return () => observer.disconnect();
    }, [root.current]);

    useLayoutEffect(onUpdateScale, [props.zoomValue]);


    return (
    <div class="w-100 h-100 overflow-y-scroll overflow-x-auto" ref={root} >

        <div class="position-relative"
            style={{ width: `${width.toFixed(0)}px`, height: `${height.toFixed(0)}px` }} >

            <div class="position-absolute top-0 end-50" ref={container}
                style={{ width: props.vWidth, padding: '48px',
                    transformOrigin: 'top center',
                    transform: `translateX(50%) scale(${scale.toFixed(3)})` }}
                children={props.children} />
        </div>
    </div>);
}

Issue with LINE Chatbot Rich Menu

I developed a LINE chatbot using Google Apps Script and encountered an issue while working with the rich menu. After generating three menus, I attempted to switch between them using richMenuSwitch. I am certain that the richMenuId was successfully created, but the aliasId fails to link to the existing rich menu, resulting in a “richmenu not found” error. Here is the error message:

Exception: Request failed for https://api.line.me returned code 400. Truncated server response: {"message":"richmenu not found","details":[]} (use muteHttpExceptions option to examine full response)  
createRichMenuAlias @ setupRichMenu.gs:140  
setupRichMenu @ setupRichMenu.gs:12  

Below is the code I used to connect the aliasId to the rich menu:

function createRichMenuAlias(richMenuId, aliasId) {
  let url = "https://api.line.me/v2/bot/richmenu/alias";
  let aliasData = {
    richMenuAliasId: aliasId,
    richMenuId: richMenuId
  };
  let options = {
    "method": "post",
    "headers": { "Authorization": `Bearer ${CHANNEL_ACCESS_TOKEN}`, "Content-Type": "application/json" },
    "payload": JSON.stringify(aliasData)
  };
  let response = UrlFetchApp.fetch(url, options);
  console.log(`Alias ${aliasId} created for Rich Menu ID: ${richMenuId}`);
  console.log(response.getContentText()); // 輸出目前所有的 Alias
}

I would really appreciate any insights on what might be causing this issue and how I can fix it. Thank you in advance!

Issue with Integrating Redis Cache in Next.js Custom Cache Handler (TypeScript & next.config.js Issues)

Problem Statement:

I’m implementing a Redis cache system as a custom cache handler in my Next.js project, but I’m running into multiple issues.


What I Did:

  1. Created a Redis client in lib/redis.js and used it inside a custom cache handler.
  2. Configured the cache handler in next.config.js.
  3. Using TypeScript in my project (tsconfig.json provided below).
  4. Initially created lib/cache-handler.ts, but it was not recognized, so I moved it to a .js file.

Issues I’m Facing:

  1. TypeScript does not recognize cache-handler.ts.
  2. Errors related to next.config.js (invalid options).
  3. Possible misconfiguration in tsconfig.json affecting the build.

Code Snippets:

lib/redis.js (Redis Client)

import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL);

export default redis;

TypeScript does not recognize cache-handler.ts.
Errors related to next.config.js (invalid options).
Issues with tsconfig.json settings.

**Relevant images:**

tsconfig.json

  

    {
      "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "bundler",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "incremental": true,
        "types": ["io-ts"],
        "plugins": [
          {
            "name": "next"
          }
        ],
        "paths": {
          "@/*": ["./*"]
        },
        "noFallthroughCasesInSwitch": true,
        "allowSyntheticDefaultImports": true,
        "forceConsistentCasingInFileNames": true
      },
      "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", ".next/types/**/*.ts", "lib/cache-handler.js", "lib/redis.js"],
      "exclude": ["node_modules"],
      "noUnusedLocals": true,
      "noUnusedParameters": true
    }

this is my custom handler in lib/cache-hander.js
lib/cache-handler.js
(Moved from .ts to .js due to recognition issues)

    const getRedisInstance = require('./redis');
    
    class CacheHandler {
      constructor(options = { ttl: 3600 }) {
        if (!CacheHandler.instance) {  // Ensure only one instance is created
          this.options = options;
          console.log("CacheHandler initialized!");
          this.redis = getRedisInstance(); // Use the Redis instance
          CacheHandler.instance = this;
        }
        return CacheHandler.instance;
      }
    
      async get(key) {
        const cachedData = await this.redis.get(key);
        return cachedData ? JSON.parse(cachedData) : null;
      }
    
      async set(key, data, ctx = {}) {
        const cacheEntry = {
          value: data,
          lastModified: Date.now(),
          tags: ctx.tags || [],
        };
    
        await this.redis.set(key, JSON.stringify(cacheEntry), 'EX', this.options.ttl);
    
        if (ctx.tags) {
          for (const tag of ctx.tags) {
            await this.redis.sadd(`tag:${tag}`, key);
          }
        }
      }
    
      async revalidateTag(tags) {
        tags = Array.isArray(tags) ? tags : [tags];
    
        for (const tag of tags) {
          const keys = await this.redis.smembers(`tag:${tag}`);
          if (keys.length) {
            await this.redis.del(...keys);
            await this.redis.del(`tag:${tag}`);
          }
        }
      }
    
      resetRequestCache() {}
    }

// ✅ Export a single instance
const cacheInstance = new CacheHandler();
module.exports = cacheInstance;

this is my next.config file

    /**
     * @format
     * @type {import('next').NextConfig}
     */
    const path = require("path");
    const nextConfig = {
      logging: {
        logging: 'verbose',
        fetches: {
          fullUrl: true,
        },
      },
      eslint: {
        dirs: ['src'],
      },
      cacheHandler: path.resolve(__dirname, "lib/cache-handler.js"),
      cacheMaxMemorySize: 0, // disable default in-memory caching

when I run the project I'm getting several error

[TypeError: CurCacheHandler is not a constructor]
[TypeError: CurCacheHandler is not a constructor]
[TypeError: CurCacheHandler is not a constructor]
[TypeError: CurCacheHandler is not a constructor]
[TypeError: CurCacheHandler is not a constructor]
[TypeError: CurCacheHandler is not a constructor]

How to make react-material-ui-carousel vertical with three cards

I am using react-material-ui-carousel and showing listing vertically like enter image description here.

Following is the code:

const chunk = (arr, size) =>
  Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
    arr.slice(i * size, i * size + size)
  );
const dummyData = [
    {
      displayName: 'Trupti',
      isMuted: true,
      isSpeaking: false,
      userId: 1
    },
    {
      displayName: 'AAA',
      isMuted: true,
      isSpeaking: false,
      userId: 2
    },
    {
      displayName: 'BBB',
      isMuted: true,
      isSpeaking: false,
      userId: 3
    },
    {
      displayName: 'CCC',
      isMuted: true,
      isSpeaking: false,
      userId: 4
    },
    {
      displayName: 'DDD',
      isMuted: true,
      isSpeaking: false,
      userId: 5
    },
    {
      displayName: 'EEE',
      isMuted: true,
      isSpeaking: false,
      userId: 6
    },
    {
      displayName: 'FFF',
      isMuted: true,
      isSpeaking: false,
      userId: 7
    },
    {
      displayName: 'GGG',
      isMuted: true,
      isSpeaking: false,
      userId: 8
    },
    {
      displayName: 'HHH',
      isMuted: true,
      isSpeaking: false,
      userId: 9
    },
    {
      displayName: 'JJJ',
      isMuted: true,
      isSpeaking: false,
      userId: 10
    },
    {
      displayName: 'KKK',
      isMuted: true,
      isSpeaking: false,
      userId: 77
    },
    {
      displayName: 'LLL',
      isMuted: true,
      isSpeaking: false,
      userId: 12
    },
    {
      displayName: 'MMM',
      isMuted: true,
      isSpeaking: false,
      userId: 13
    },
    {
      displayName: 'NNN',
      isMuted: true,
      isSpeaking: false,
      userId: 14
    }
  ]
  const groupArray = chunk(dummyData, displayCard);

<Carousel
              autoPlay={false}
              navButtonsAlwaysVisible={true}
              navButtonsAlwaysInvisible={isMobile}
              cycleNavigation={false}
              indicators={false}
              className="participants"
              NextIcon
              navButtonsWrapperProps={{ className: 'next-prev-btn' }}
              NavButton={({ onClick, style, next, prev }) => {
                return (
                  <span onClick={(e) => onClick(e)} style={style}>
                    <span>{next && <NavigateNextIcon />}</span>
                    <span>{prev && <NavigateBeforeIcon />}</span>
                  </span>
                )
              }}
            >
              {
                groupArray.length > 0 && groupArray.map((e, index) => {
                  return <div className='participant' key={index} >{e.map((e) => {
                    return <ParticipantCardComponent key={e.displayName} name={e.displayName} isMuted={e.isMuted} isSpeaking={e.isSpeaking} acsUserId={e.userId} setError={setError} />
                  })}</div>
                })
              }
            </Carousel>

On touch screen, it is moving from top to bottom but not able to scroll from down to up. I tried to solve this using CSS as well like moving prev and next at the top and bottom, but it is not working. Please help me here to find what I am doing wrong.

My menu in JS closes when it isn’t supposed to

I was trying to create a menu that would close when you click somewhere else,but when i try clicking anything on the menu, it also closes the menu too which I don’t want. Below i’ll provide my html and JS and CSS. The main problem is not the circle which does not cause the menu to disappear, but rather it is the tags that once clicked on makes the menu go away.

const button = document.getElementById('circleButton');
const circle = document.getElementById('circle');
const mainContent = document.getElementById('mainContent');


button.addEventListener('click', () => {
  if (circle.classList.contains('hidden')) {

    circle.classList.remove('hidden');
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        circle.classList.add('show');
        mainContent.classList.add('blur');
      });
    });
  } else {

    circle.classList.remove('show');
    mainContent.classList.remove('blur');
    setTimeout(() => {
      circle.classList.add('hidden');
    }, 300);
  }
});


document.addEventListener('click', (e) => {
  if (
    e.target !== button &&
    !circle.contains(e.target) &&
    !circle.classList.contains('hidden')
  ) {

    circle.classList.remove('show');
    mainContent.classList.remove('blur');
    setTimeout(() => {
      circle.classList.add('hidden');
    }, 300);
  }
});
body { background-color: gray; }

#circleButton {
  position: fixed;
  top: 20px;
  right: 20px;
  padding: 10px 20px;
  background-color: transparent;
  color: peachpuff;
  border: 1px solid peachpuff;
  cursor: pointer;
  z-index: 10;
  font-family: "Newsreader", serif;
  font-style: italic;
}

.menu {
  z-index: 50;
}

.circle {
  position: fixed;
  top: 50%;
  right: -5%;
  transform: translate(-50%, -50%) scale(0);
  width: 60vmin;
  height: 60vmin;
  background-color: beige;
  border-radius: 50%;
  opacity: 0;
  transition: all 0.3s ease-out;
  pointer-events: none;
  display: flex;
  z-index: 51;
  justify-content: center;
  align-items: center;
}

.circle-inner {
  position: absolute;
  width: 100%;
  height: 100%;
  transition: all 0.3s ease;
  pointer-events: none;
}

.circle-inner h1,
.circle-inner h2,
.circle-inner h3,
.circle-inner h4 {
  font-size: 4.25em;
  transform-origin: center;
  z-index: 52;
  font-family: "Newsreader", serif;
  font-weight: 500;
  position: absolute;
  left: -150%;
  transform: perspective(300px) rotate(5deg) rotateY(2deg) translateY(-50%);
  transition: all 0.3s ease;
  color: white;
}

.circle-inner a {
  text-decoration: none;
  color: inherit;
}

.circle-inner h1:hover,
.circle-inner h2:hover,
.circle-inner h3:hover,
.circle-inner h4:hover {
  text-decoration: underline;
}

.circle-inner h1 {
  top: -10%;
  transform: perspective(300px) rotate(6deg) rotateY(20deg) rotateZ(10deg) translateY(-50%);
}

.circle-inner h2 {
  top: 25%;
  transform: perspective(300px) rotate(2.5deg) rotateY(15deg) rotateZ(5deg) translateY(-50%);
}

.circle-inner h3 {
  top: 55%;
  transform: perspective(300px) rotate(-2.5deg) rotateY(15deg) rotateZ(-5deg) translateY(-50%);
}

.circle-inner h4 {
  top: 75%;
  transform: perspective(300px) rotate(-3deg) rotateY(22deg) rotateZ(-10deg) translateY(-50%);
}

.hidden {
  display: none;
}

.show {
  display: block;
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  pointer-events: auto;
}

#mainContent {
  transition: filter 0.3s ease-out;
  margin: 0;
  padding: 0;
}

#mainContent.blur {
  filter: blur(6px);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Inconsolata:[email protected]&family=Newsreader:ital,opsz,wght@0,6..72,200..800;1,6..72,200..800&display=swap" rel="stylesheet">
  <meta charset="UTF-8">
  <link rel="stylesheet" href="style.css">
  <title>Title</title>
</head>

<body>
  <div id="menu">
    <button id="circleButton">Menu</button>
    <div id="circle" class="circle hidden">
      <div class="circle-inner">
        <nav class="circle-menu">
          <a href="#"><h1>Home</h1></a>
          <a href="#"> <h2>About us</h2></a>
          <a href="#" ><h3>Volumes</h3></a>
          <a href="#" ><h4>Submissions</h4></a>
        </nav>
      </div>
    </div>
  </div>
  <div id="mainContent">

    <div class="container">
      <div class="banner">
        <div class="typewriter-bg">
          <div class="typewriter-container"></div>
        </div>

        <div class="covercontainer">
          <div class="cover"></div>
          <div class="text1">VOLUME 1</div>

        </div>

        <div class="toolbar">
          <h1>Logo</h1>
        </div>
        <div class="description">
          <p class="hiddenp animate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse laoreet tincidunt metus, vitae accumsan odio ultrices et. Nunc sed purus enim.</p>
        </div>
        <p id="typewriter"></p>


        <!--<div class="title">
                 <p>1023</p>
                 <h1>Street</h1>
             </div> -->
      </div>
    </div>
    <div class="container2">

    </div>
  </div>
  <script src="animations.js"></script>
</body>

</html>

Quill.js Resets Text to Normal on Enter Instead of Keeping Selected Size

I’m using Quill.js and need to:

  1. Make “small” the default text size when the editor loads.
  2. Ensure the text size persists when the user types.
  3. Keep the selected size after pressing Enter (right now, it resets to “normal” instead of keeping the selected size).

Problem:

  • The editor starts with “small” ✅.
  • If the user selects another size, it works while typing ✅.
  • When the user presses Enter, the new line always switches to “normal” ❌ instead of keeping the selected size.
  • The toolbar still shows the previously selected size, but newly typed text is actually “normal.”

Code:

html:

<div class="col-12">
    <div class="form-group">
        <label for="editor-container-ar">Content Arabic
           <span class="required" style="color: red">*</span></label>
<div id="editor-container-ar" style="height: 300px;"
    class="ql-container flex-snow"></div> </div></div>

javascript:

<script type="text/javascript">
    $(document)
            .ready(
                    function() {
                        var contentInput = document.getElementById('contentAr');

                        // Initialize Quill editor
                        var quillAr = new Quill('#editor-container-ar', {
                            theme : 'snow',
                            modules : {
                                toolbar : [
                                    [ {
                                        'font' : []
                                    } ],
                                    [ {
                                        'size' : [ 'small', 'normal', 'large',
                                            'huge' ]
                                    } ],
                                    [ 'bold', 'italic', 'underline',
                                        'strike' ], [ {
                                        'color' : []
                                    }, {
                                        'background' : []
                                    } ], [ {
                                        'script' : 'sub'
                                    }, {
                                        'script' : 'super'
                                    } ], [ {
                                        'header' : 1
                                    }, {
                                        'header' : 2
                                    } ], [ 'blockquote', 'code-block' ],
                                    [ {
                                        'list' : 'ordered'
                                    }, {
                                        'list' : 'bullet'
                                    } ], [ {
                                        'indent' : '-1'
                                    }, {
                                        'indent' : '+1'
                                    } ], [ {
                                        'direction' : 'rtl'
                                    } ], [ {
                                        'align' : []
                                    } ], [ 'link', 'image', 'video' ],
                                    [ 'clean' ] ]
                            }
                        });


                        console.log(quillAr);

                    let userSelectedSize = 'small'; // Track the user’s selected size

                    // ✅ Force "Small" as the default size on load
                    setTimeout(function () {
                        let editorContent = quillAr.root.innerHTML.trim();
                        console.log('Editor content:', editorContent);
                        if (editorContent === "<p><br></p>") {
                            quillAr.root.innerHTML = '<p><span class="ql-size-small"><br></span></p>'; // Ensure small visually
                        }
                        quillAr.format('size', 'small'); // Make sure new text starts as "small"
                    }, 100);

                    // ✅ Detect when the user selects a size
                    quillAr.on('selection-change', function (range) {
                        console.log('Selection changed:', range);
                        if (range) {
                            let format = quillAr.getFormat(range);
                            console.log('Format:', format);
                            userSelectedSize = format.size !== undefined ? format.size : 'normal'; // Store user-selected size
                        }
                    });

                    // ✅ Ensure newly typed text follows the selected size
                    quillAr.on('text-change', function (delta, oldDelta, source) {
                        console.log('Text changed:', delta, 'Source:', source);
                        if (source === 'user') {
                            let format = quillAr.getFormat();
                            console.log('Current format:', format, 'User selected size:', userSelectedSize);
                            if (!format.size || format.size !== userSelectedSize) {
                                quillAr.format('size', userSelectedSize); // Apply user-selected size
                            }
                        }
                    });

                    // ✅ Keep the selected size when pressing Enter
                    quillAr.keyboard.addBinding({ key: 'Enter' }, function (range) {
                        setTimeout(() => {
                            let newSize = userSelectedSize || 'small'; // Ensure we have a size

                            // Move cursor to the new line and apply formatting
                            quillAr.formatText(range.index, 1, 'size', newSize);

                            console.log('New line formatted to:', newSize);
                        }, 0);
                    });



                    // ✅ Force "Small" to always use <span>
                    quillAr.clipboard.addMatcher(Node.ELEMENT_NODE, function (node, delta) {
                        console.log('Pasted content:', node, delta);
                        delta.ops.forEach(op => {
                            if (op.attributes && !op.attributes.size) {
                                console.log('Applying small size to:', op);
                                op.attributes.size = 'small'; // Ensure "small" gets a <span>
                            }
                        });
                        return delta;
                    });
....
</script>

Issue:

  • Even with this code, pressing Enter resets the text to “normal” instead of keeping the selected size.
  • The toolbar still shows the correct size, but the actual text formatting is reset.

Limit range input based on another range input with javascript

I have two range inputs. The first should never be higher than the second, and the second should never be lower the the first.

The problem with my script is that the sliders jump around or snap to the min or max. It works perfectly if I change the limit to a fixed number, just not with the input value…

Here is an example of what I have tried:

function minRange(input) {
    let limit = document.getElementById('max').value;           
    if(input.value >= limit) {
        input.value = limit;
    };
};

function maxRange(input) {
    let limit = document.getElementById('min').value;   
    if(input.value <= limit) {
        input.value = limit;
    };
};
<div><input id="min" type="range" min="0" max="100" value="0" step="1" onInput="minRange(this)" /></div>
<div><input id="max" type="range" min="0" max="100" value="100" step="1" onInput="maxRange(this)" /></div>

Can I add words in front of my canvas HTML?

I am trying to create a site where the user can search for words on the screen by drawing onto a white background. The words will be in white and invisible until the cursor draws over them in black revealing the white outline of the word.

The words are always in the background and just get drawn over instead of revealed.
Is there any way I can fix this problem?

Thanks

const canvas = document.getElementById('drawing-board');
const ctx = canvas.getContext('2d');

const canvasOffsetX = canvas.offsetLeft;
const canvasOffsetY = canvas.offsetTop;
canvas.width = window.innerWidth - canvasOffsetX;
canvas.height = window.innerHeight - canvasOffsetY;

let isPainting = true;
let lineWidth = 100;
let startX;
let startY;
const colour = "black";

ctx.strokeStyle = "black"
ctx.fillStyle= "transparent";
ctx.font = "italic bold 15pt Tahoma";
ctx.strokeText("StackOverFlow",100,240);
ctx.strokeStyle = colour;

const draw = (e) => {
    if(!isPainting) {
        return;
    }
    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round';

    ctx.lineTo(e.clientX - canvasOffsetX, e.clientY);
    ctx.stroke();
}
canvas.addEventListener('mousedown', (e) => {
    isPainting = false;
    startX = e.clientX;
    startY = e.clientY;
});

canvas.addEventListener('mouseup', e => {
    isPainting = true;
    ctx.stroke();
    ctx.beginPath();
});
canvas.addEventListener('mousemove', draw);
<body>
<section class="container">
    <div class="drawing-board">
        <canvas id="drawing-board"></canvas>
    </div>
</section>
<script src="./index.js"></script>
</body>

Changing width and position of my div element using JavaScript and a transition style becomes very laggy

monthlyButton.addEventListener('click', () => {
    if (planTerm === 1) {
      basicPrice = prices.monthly.basic;
      essentialsPrice = prices.monthly.essentials;
      premiumPrice = prices.monthly.premium;
      elitePrice = prices.monthly.elite;
      planTerm = 12;

      renderPlanContainers();

      document.querySelectorAll('.plan-subtitle-bill').forEach((element) => {
        element.classList.add('subtitle-bill-hidden');
      });

      selectorBackground.style.transform = 'translateX(0%)';
      selectorBackground.style.width = '7rem';
    }
  });

  yearlyButton.addEventListener('click', () => {
    if (planTerm === 12) {
      basicPrice = prices.yearly.basic;
      essentialsPrice = prices.yearly.essentials;
      premiumPrice = prices.yearly.premium;
      elitePrice = prices.yearly.elite;
      planTerm = 1;

      renderPlanContainers();

      document.querySelectorAll('.plan-subtitle-bill').forEach((element) => {
        element.classList.remove('subtitle-bill-hidden');
      });

      selectorBackground.style.transform = 'translateX(46%)';
      selectorBackground.style.width = '15rem';
    }
  });

I have event listeners that when a button is clicked, it changes some HTML, renders it, and changes the width and position of a selectorBackground to show which button is “selected”. It works as intended for a while, but after 10+ clicks back and forth the animation starts lagging and it becomes more glitchy.

I tried shortening the transition time, removing the transform style and the width style changes individually to see if one of them was causing the lag (both caused lag after some time). I think it has something to do with changing the width and/or translating, because even if I remove the transition time style, it still causes lag after some time. Help is much appreciated!