How do you pass a bound method as a parameter in javascript?

I’m trying to pass a bound method to a function, but I can’t quite figure out the syntax. It seems like javascript wants to somehow differentiate between an unbound method and a bound method, but where the calling context changes that. (Most programming languages simply define a method as a bound class function).

What’s the syntax for passing a bound method to a function, and then calling that bound method in the new scope?

Here’s the relevant snippets

const mongoose = require('mongoose');
const caching = require('../lib/caching')

const Blog = mongoose.model('Blog');

// This is where I'm trying to pass a method to another function. I'm unclear of the syntax here
Blog.find = caching.makeCachable(Blog.find.bind(Blog), Blog)

module.exports = app => {
  app.get('/api/blogs', requireLogin, async (req, res) => {
    let blogs = await Blog.find({_user: req.user.id});
    return res.send(blogs);
  });

  // ... other routes
}

caching.js

const util = require('util');
const redis = require('redis');

const client = redis.createClient('redis://localhost:6379');
const asyncGet = util.promisify(client.get).bind(client);

const DEFAULT_CACHING = [
    'EX', 60 * 60 * 1,//caching expires after 4 hours
]

// This is where I take the method and pass it on to another function. I hope this just passes through
function makeCachable(method, thisObject) {
    console.log(method, thisObject, `${method.className}.${method.name}`);
    return cachedQuery.bind(method, `${thisObject.className}.${method.name}`);
}

async function cachedQuery(queryFunction, queryKey, queryParams=null, cacheConfig=DEFAULT_CACHING) {
    //check redis before executing queryFunction
    const redisKey = JSON.stringify([queryKey, queryParams]);
    const cacheValue = await asyncGet(redisKey);

    if(cacheValue) {
        return JSON.parse(cacheValue);
    }
    
    // This is where I try to call the bound method
    const blogs = await queryFunction.call(queryParams);
    
    if(blogs) {
        client.set(redisKey, JSON.stringify(blogs), ...cacheConfig);
    }

    return blogs;
}

exports.makeCachable = makeCachable;

Combine data from different cells in a table

I’m trying to read data stored in a csv file and present it in a table, using JavaScript. The csv data (comma delimited) is (I reduced it to be much smaller than the actual one):

Number, PDF1, PDF2, PDF3
0,,,
1,1.pdf,,
2,2a.pdf,2b.pdf,
3,3a.pdf,3b.pdf,3c.pdf

The correspondence between cells in the csv and online is 1 to 1, except 3 last columns (PDF1/2/3). I need them to appear online in the same cell (for each row) as links, separated by space. That is, instead of 3 columns PDF1/2/3 there will be just one, called PDF, containing links to pdfs 1, 2 and 3, if present. The desired output is:

| Number | PDF                                      |
| 0      |                                          |
| 1      | [link>1.pdf]                             |
| 2      | [link>2a.pdf] [link>2b.pdf]              |
| 3      | [link>3a.pdf] [link>3b.pdf] [link>3c.pdf]|

What I have so far:

html:

<span id="output"></span>

JS:

async function fetchCSV(url) {
    try {
        const response = await fetch(url);
        const data = await response.text();
        document.getElementById('output').innerText = data;
        processData(data);
    } catch (error) {
        console.error('Error fetching CSV:', error);
    }
}

//Link to csv file
fetchCSV('https://blabla/myfile.csv');

//read csv and save contents to variable "lines"
function processData(csv){
    var allTextLines = csv.split(/rn|n/);
    var lines = [];
    var keys = allTextLines.shift().split(','); //first line (headers) of csv
    while (allTextLines.length) {
        var arr = allTextLines.shift().split(',');
        var obj = {};
        for(var i = 0; i < keys.length; i++){
            obj[keys[i]] = arr[i];
    }
        lines.push(obj);
    }
    console.log(lines);
    drawOutput(lines);
}

//draw table function drawOutput(lines){
    //clear previous data
    document.getElementById("output").innerHTML = "";
    var table = document.createElement("table");

//first row (cols names) with "th"
var tableHeader = table.insertRow(-1);
Object.keys(lines[0]).forEach(function(key){
    if (key == "PDF1") {} //don't show "PDF1" column
    else if (key == "PDF2") {} //don't show "PDF2" column
    else {
        var el = document.createElement("TH");
        if (key == "PDF3") {el.innerHTML = "PDF";} //show "PDF3" column as "PDF"
        else {el.innerHTML = key;}
        tableHeader.appendChild(el);
    }
});

//the data (rest of the table)
for (var i = 0; i < lines.length-1; i++) {
    var row = table.insertRow(-1);
    Object.keys(lines[0]).forEach(function(key){
      if (key == "PDF1") {var pdflink1 = lines[i][key];}
      else if (key == "PDF2") {var pdflink2 = lines[i][key];}
      else if (key == "PDF3") {var pdflink3 = lines[i][key];
          var data = row.insertCell(-1);
          if (pdflink1 != []) {
              var a1 = document.createElement('a');
              a1.innerHTML = 'pdf1 ';
              a1.href = "dir/" + pdflink1;
              data.appendChild(a1);
          }
          if (pdflink2 != []) {
              var a2 = document.createElement('a');
              a2.innerHTML = 'pdf2 ';
              a2.href = "dir/" + pdflink2;
              data.appendChild(a2);
          }
          if (pdflink3 != []) {
              var a3 = document.createElement('a');
              a3.innerHTML = 'pdf3';
              a3.href = "dir/" + pdflink3;
              data.appendChild(a3);}
          }
      else {
    var data = row.insertCell(-1);
    data.appendChild(document.createTextNode(lines[i][key]));
  }});
}
document.getElementById("output").appendChild(table);
}

Everything seems to work OK, but I’m struggling to “keep” the pdf names in pdflink1 and pdflink2 to put them together with pdflink3 when key == “PDF3” is true. Out of three, only the latter is presented as desired in the output:

| Number | PDF                                         |
| 0      |                                             |
| 1      | [dir/undefined]                             |
| 2      | [dir/undefined] [dir/undefined]             |
| 3      | [dir/undefined] [dir/undefined] [dir/3c.pdf]|

I appreciate any assistance. Thank you.

JS, Is there a way web client access file cached date of image url?

I have a react component for thumbnails in client,

export default function Thumbnail({
  url,
  updatedDate, // updatedDate is from server api
}) {
  const cachedDate = new Date(.....);
  const queryStr = cachedDate < updatedDate ? '?force=' + Math.random() : '';

  return (
    <img
      src={url + queryStr}
      alt={'THUMB'}
    />

)}

How can I get cachedDate? Is it possible?

mouse drag function in javascript

I am not familiar with javascript coding to deal with the problem of the source code on my own.
I downloaded a nice Linkage Simulator code written in Javascript from this website https://edu-mat.sakuraweb.com/linksim/index_en.html. Please go down to Download and click on icon download system. You will get linksys_1.01.zip file. Unzip it to get javascript code on your computer.
The problem is dragging the parts on the screen. When I run Linksys from their website, the dragging of the mechanical parts on the screen with you mouse icon works fine.
When I run javascript code from my PC, the code runs fine except when I try drag mechanical parts with my mouse. The parts are stuck. Obviously, the mouse function for dragging the parts is disabled. How do I enable it?
Thank you for your time.

Problems with some glowing style on safari

Im having trouble with safari, that makes me that square effect, I don’t remember how to fix it!

const getGlowingStyles = (theme: Theme) => {
  const glowing = keyframes`
    0% { background-position: 0 0; }
     50% { background-position: 400% 0; }
    100% { background-position: 0 0; }
  `

  const glowingStyles = {
    position: 'absolute',
    right: '0px',
    bottom: '0px',
    background: `linear-gradient(45deg, ${theme.palette.accent.light}, ${theme.palette.accent.main}, ${theme.palette.accent.main}, ${theme.palette.accent.main}, ${theme.palette.accent.light}, ${theme.palette.accent.main}, ${theme.palette.accent.light}, ${theme.palette.accent.main})`,
    backgroundSize: '800%',
    borderRadius: '50%',
    filter: 'blur(8px)',
    animation: `${glowing} 15s linear infinite`,
    zIndex: -1,
    overflow: 'hidden'
  }
  return glowingStyles
}

<Box
  sx={{
    width: 115,
    height: 115,
    top: '25px',
    left: '25px',
    ...getGlowingStyles(theme)
  }}
/>

Safari’s view:

enter image description here

Chrome’s view:

enter image description here

Run Cypress 13 on a machine without Internet connection

We would like to run Cypress tests on a machine that has no connection to the Internet. The machine runs an Ubuntu 22.04.5LTS operating system.

Steps to reproduce:

On an Ubuntu machine with Internet access:

  • Run “npm install cypress –save-dev” to install cypress (current version 13.17.0) on the machine.

  • Run “npx cypress open”: Cypress app can be opened

  • Copy the parent folder where npm install was executed and the Cypress cache under “~/.cache/Cypress/13.17.0” to a similar Ubuntu machine without internet access. It was placed under the same folder structure on the target machine.

On the Ubuntu machine without Internet access:

  • Run “npx cypress open”: Cypress app starts up but is stuck on the first loading screen (see image: Cypress loading screen)

Is there any way to open/run Cypress (13.17.0) without any connection to the Internet? Are we missing any files required to open Cypress?

getComputedStyle wrong for placeholder on some mobile devices

This seems like a browser bug to me but I couldn’t find anyone else seeing the same problem. It seems like getComputedStyle isn’t getting the right font-size for an input placeholder for some mobile browsers.

In my example below the placeholder font-size is set to 11px. In some mobile browsers, getComputedStyle thinks the placeholder’s font size is 16px.

I’ve tested this on:

  • iPhone 16 in Safari and Chrome: 16px

  • Samsung Galaxy S22 in Chrome: 16px

  • Samsung Galaxy S22 in Firefox: 11px

  • Chrome and Firefox on Win11: 11px

See this jsfiddle, or snippet below:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css">
<style>
.form-control::placeholder {
  font-size: 11px;
}
</style>

<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<script>
function updatePlaceholderLength(el) {
    var styles = window.getComputedStyle(el);
    var placeholderFontSize = window.getComputedStyle(el, '::placeholder').fontSize;
    
   document.querySelector('.debug-info-js').textContent = 'placeholder font size: ' + placeholderFontSize;
}

updatePlaceholderLength(document.getElementById('whatever'));
</script>

<div class="container">
  <label class="control-label" for="whatever">Check it out</label>
  <input class="form-control" id="whatever" type="text" placeholder="Here is my placeholder.">
  <hr>
  <pre class="debug-info-js"></pre>
</div>

Just wondering if anyone has any info on this… is it a known bug/limitation? Is this by design? Is there any workaround to get the right font-size?

Tried adding !important to the font-size declaration which of course didn’t work… I have no idea what else I can do.

Arabic “Majed” voice randomly not showing in SpeechSynthesis (TTS) API

Browsers with the SpeechSynthesis provide Arabic through one voice “Majed” as ar-001 or ar-SA and it usually works on all browsers except ones that use WebKit I noticed.
On Webkit based browsers, especially iPhones & iPads, that specific voice doesn’t appear randomly sometimes! I am trying to figure out how can I make sure that an Arabic language can always be used?

Here’s a codepen where you can try it yourself. For the SAME device, when I go to that page the first time, Majed appears, but it didn’t appear a few times later. You can also just open a developer console on any page and put in window.speechSynthesis.getVoices() and the first element in the list should be arabic (majed)

This is what it looks like on a Mac using Safari sometimes, where Arabic does appear above Daria as it does appear correctly with other browsers and operating systems
Screenshot showing Arabic
This is what it looks like on an iPhone/iPad sometimes, where the Arabic doesn’t appear at all when it should appear above “Daria”:
Screenshot from iPhone not showing Arabic

Show / hide div using checkbox and addEventListener click event

The following javascript works but not in my application as a product filter. In my case, clicking the checkbox displays the div but unchecking does not hide the div. Applying, onclick event to the checkbox is also not doable. Is it possible to have two addEventlistener ‘click’ events, one for opening and one for closing?

const check = document.getElementById("checkbox-id");
if (check) {
    check.addEventListener('click', event => {
    this.event = event;
if (check.checked) { document.getElementById("showDiv").style.display = "block"; } 
else { document.getElementById("showDiv").style.display = "none"; }
});
}
#showDiv{display:none;width:100%;background-color:#252525;color:#ffffff;}
<form>
<input class="input" type="checkbox" id="checkbox-id">
</form>
<div id="showDiv">Show / hide</div>

I have tried the following (and others) but I have not been able to hide the box after being revealed. Just know, the click event is the only way that has produced a result. Happy to provide any other info if needed. TY

const general = document.getElementById("checkbox-id");
  const checkOpen = () => {document.getElementById("showDiv").style.display = "block";}
  const checkClosed = () => {document.getElementById("showDiv").style.display = "none";}
if (element) {
    element.addEventListener('click', event => {
    this.event = event;
checkOpen();
checkClosed();
});
}

Chart.js barplot keeps getting bigger without stopping

Just like the title says. I have a chart that when I open the page it keeps getting bigger and bigger and bigger. I genuinely don’t understand why because I have another plot pretty similar with the same html/css.
Here’s the chart:

new Chart(
        document.getElementById("weeklyWatched_id"),
        {
            type: 'bar',
            data: {
                labels: filteredData.map(row => row.week_number),
                datasets: [
                    {
                        data: filteredData.map(row => row.weekly_quantity),
                        backgroundColor: 'rgb(255, 0, 0)',
                        borderWidth: 0
                    }
                ]
            },
            options: {
                title: {
                    display: true,
                    text: 'Data Semanal',
                    fontColor: '#131313', // Change title color
                    fontFamily: 'Arial' // Change title font to Arial
                },
                legend: { display: false },
                responsive: true,
                maintainAspectRatio: false,
                scales: {
                    yAxes: [{
                        ticks: { display: false, beginAtZero: true }, // Remove y-axis text
                        gridLines: { display: false } // Remove y-axis grid lines
                    }],
                    xAxes: [{
                        ticks: { display: false }, // Remove x-axis text
                        gridLines: { display: false } // Remove x-axis grid lines
                    }]
                },
                tooltips: {
                    callbacks: {
                        label: function(tooltipItem, data) {
                            const value = tooltipItem.value;
                            const weekNumber = data.labels[tooltipItem.index];
                            const weekRange = filteredData[tooltipItem.index].week_range;
                            const peliText = value <= 1 ? ' Peli' : ' Pelis';
                            return `${value}${peliText}n${weekNumber} Sem.n${weekRange}`;
                        }
                    },
                    displayColors: false
                },
                layout: { padding: 20 }
            }
        }
    );

Custom VueJS ESLint rule for parsing section does not work

I have the following config, custom rule, and template:

export default [
  {
    files: ['**/*.{js,vue}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      parser: vueEslintParser,
    },
    plugins: { example: exampleRules },

    rules: {
      'example/warn-something': 'warn',
    }
  }
]

export default {
  meta: {
    type: 'suggestion',  // Can be 'problem', 'suggestion', or 'layout'
    docs: {
      description: 'find a node with attribute class',
      category: 'Best Practices',
      recommended: false,
    },
    fixable: null, // This rule doesn't have an auto-fix.
    schema: [], // No options for this rule.
  },
  create (context) {
    // return context.parserServices.defineTemplateBodyVisitor(context, {
    return {
      'VAttribute[name="class"]' (node) {
        console.log('found VAttribute with class attribute. node:', node)

          context.report({
            node,
            message: 'found VAttribute with class attribute',
          })
      }
    }
  }
}

<template>
  <div :class="['style-dark']"></div>
</template>

The parser does not parse the <template> section. I’d like to find out why 'VAttribute[name="class"]' (node) is not called.

a) Is there a way to set breakpoints and debug rules? I haven’t found anything online about it.

b) Is the parser configured correctly? The docs say to use a string parser: 'vue-eslint-parser', but it errors. Other sources say to use an import parser: vueEslintParser.

c) How to get access to parserServices? I saw this used a few ways but it ends up undefined here.

Any help appreciated.

Binding scalar data to HTML element – JavaScript Proxies

I may be guilty of a bit of an XY question here, but I’m doing this out of theoretical interest rather than any immediate need.

My goal is, ultimately, to build a lightweight framework that allows me to bind scalar data to a property of an HTML element such that the property updates “automagically” whenever the value changes.

I’m trying to come up with the most syntactically elegant way to do this, that puts IDE code-completion and developer convenience at the forefront.

I’m aware of Proxies, and I’ll get to that in a moment. My challenge is really in the syntactic sugar I’m trying to create, so come along for the ride – I can always fall back to many tried-and-true approaches but I’m hoping for something more magical.

Let’s assume I already have a nice little framework that wraps DOM Nodes with additional functionality, and can Proxy the DOM Node if needed.

The ultimate data-binding implementation from a syntax/API perspective would be:

let someVar = "foo"
let someElement = MyFramework.getById("some-div"); // returns a proxied HTMLElement with additional methods added
someElement.bind("innerText", someVar);

// later...
someVar = "bar"; // someElement.innerText automatically updates

Now, before you freak out, I’m aware that this will simply not work, as there’s no way to proxy a Primitive, so I’m happy to wrap this in a state object that CAN be proxied.

let state = MyFramework.createState(); // returns a proxy of the State object
state.someVar = "foo";
let someElement = MyFramework.getById("some-div");
someElement.bind("innerText", state.someVar);

This is where it gets tricky, because I actually need to access the object key “someVar” within my .bind() function, but I’m just getting the value of state.someVar.

I CAN set a proxy within my createState() function which can trap the getter and instead of returning the value, returns the property name like this:

MyFramework.createState = function(initialProps = {}){
  let proxy = new Proxy(initialProps, {
     get(target, prop, receiver){
        return prop;
     }
   }

   return proxy;
}

…but then I can’t really make use of the variable, because I don’t know how to make my “get” trap conditional – ie, only return the prop when being accessed from within the bind() function, otherwise just return Reflect(...arguments).

What I’m hoping to avoid is the following:

someElement.bind("innerText", state, "someVar");

Similarly,

someElement.bind("innerText", state, state.someVar)

just seems redundant and prone to user error.

Alternatively I’d be open to:

state.someVar.bind(someElement, "innerText");

but that won’t work (that I can think of) because someVar is still a scalar (primitive) and therefore can’t get any custom properties (like .bind() attached).

I was thinking I could intercept the first accessor (state.someVar), Proxy THAT and trap its get to handle the non-existent “bind” function, but again, without being able to do that contextually, the user would then never be able to use state.someVar in a simple scalar context, and we’d have to resort to something ugly like state.someVar.set("new val") and state.someVar.get(), and that defeats the purpose of my inquiry.

I think I’ve about exhausted my level of JS internals knowledge and wondering if there’s something obvious I’m missing.

And I should point out that if you are tempted to say “well, you’re asking about Y but really you should approach X differently” I appreciate that, but only if there really is NO way to achieve the syntactic elegance I’m looking for. Like I said, there are plenty of documented ways to achieve this – I’m trying to see if I can do it fancier.

Template parsing of ESLint rule for VueJS does not work

The following questions are related to a single issue of the parser not seemingly parsing. Why this is, is unknown, and I’m looking for ways to debug it or get it to work.

What is the correct way to configure eslint.config.js? The documentation shows parser: 'vue-eslint-parser', but in my case got the following error

TypeError: Key “languageOptions”: Key “parser”: Expected object with parse() or parseForESLint() method.

There are other recommendations to use an import instead. What is the proper way?

import exampleRules from './example/eslint-plugin-rules.js'
import vueEslintParser from 'vue-eslint-parser'

export default [
  {
    files: ['**/*.{js,vue}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      parser: vueEslintParser,
    },
    plugins: { example: exampleRules },

    rules: {
      'example/warn-something': 'warn',
    }
  }
]

Below is a simplified custom rule and template.

Is there a way to step through, and debug rules in say VSCode? I’d like to see console.log statements or stop at a breakpoint but have not seen anything documented about it.

export default {
  meta: {
    type: 'suggestion',  // Can be 'problem', 'suggestion', or 'layout'
    docs: {
      description: 'find a node with attribute class',
      category: 'Best Practices',
      recommended: false,
    },
    fixable: null, // This rule doesn't have an auto-fix.
    schema: [], // No options for this rule.
  },
  create (context) {
    // return context.getSourceCode().parserServices.defineTemplateBodyVisitor(context, {
    return {
      'VAttribute[name="class"]' (node) {
        console.log('found VAttribute with class attribute. node:', node)
      },
    }
  }
}

<template>
  <div :class="['style-dark']"></div>
</template>

Why does create(context) sometimes return an object of methods, and other times return the result from defineTemplateBodyVisitor(context, {}) for template parsing?

Appreciate any answers or advice.

How to configure, develop and debug ESLint rule for VueJS

I’d like to create a custom ESLint rule for Vue, which runs inside a <template> tag.

The following questions are related to a single issue of the parser not seemingly parsing. Why this is, is unknown, and I’m looking for ways to debug it or get it to work.

a) What is the correct way to configure eslint.config.js? I saw the documentation and many examples with parser: 'vue-eslint-parser', but in my case got the following error

TypeError: Key “languageOptions”: Key “parser”: Expected object with parse() or parseForESLint() method.

However, also saw recommendations to use an import instead, for those where using a string caused an error. Here’s the config below. Should this be done differently?

import exampleRules from './example/eslint-plugin-rules.js'
import vueEslintParser from 'vue-eslint-parser'

export default [
  {
    files: ['**/*.{js,vue}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      parser: vueEslintParser,
    },
    plugins: { example: exampleRules },

    rules: {
      'example/warn-something': 'warn',
    }
  }
]

b) How are custom rules usually developed? I did the tutorial which worked fine. I also saw RuleTester, which is good for testing a rule. But is there a way to develop, step through, and debug in say VSCode? Is there a way to see console.log statements or stop at a breakpoint?

Below is a simplified custom rule with a minimal method for handling an element with a class attribute. The context in create(context) does not seem to have parserServices, which are used by a lot of the rules in eslint-plugin-vue. I’ve seen this create method developed a couple ways: one returns an object of methods, another returns the result from defineTemplateBodyVisitor(context, {}). What is the difference?

export default {
  meta: {
    type: 'suggestion',  // Can be 'problem', 'suggestion', or 'layout'
    docs: {
      description: 'find a node with attribute class',
      category: 'Best Practices',
      recommended: false,
    },
    fixable: null, // This rule doesn't have an auto-fix.
    schema: [], // No options for this rule.
  },
  create (context) {
    // return context.getSourceCode().parserServices.defineTemplateBodyVisitor(context, {
    return {
      'VAttribute[name="class"]' (node) {
        console.log('found VAttribute with class attribute. node:', node)
      },
    }
  }
}

c) Below is a simplified Vue <template>. I believe the method 'VAttribute[name="class"]'(node) above should be invoked when traversing the AST. Does that look correct?

<template>
  <div :class="['style-dark']"></div>
</template>

I tried a slightly more complicated custom rule and template but it doesn’t seem to work, and developing/debugging does not seem straightforward. Appreciate any answers or advice.

Failed to fetch –

I have read How do I upload a file with the JS fetch API?

and

Getting “TypeError: Failed to fetch” when the request hasn’t actually failed

I have some javascript that sends a javascript object to WebApi backend, and it works!

I am now trying to use the same code to upload a file.

This is what I’m trying to upload to (my C# WebApi 2)

public async Task UploadImage([FromBody] object o)
{
    //do something
}

and the javascript

const file = inputTypeFile.files[0];

async function withData(url = '', data = {}, verb, success) {

const response = await fetch(url, {
     method: verb, 
     mode: 'cors', 
     cache: 'no-cache',
     credentials: 'same-origin', 
     headers: getHeader(),
     referrerPolicy: 'no-referrer', 
     body: file
 }).catch(function (e) {
     errorHandler(e);
 });

I always get a failure

Failed to fetch at withData

If I change the value of file to a valid json object, like {some:123} then it works fine.