How to force UI draw in ElectronJS prior to intense computation task?

I am building an Electron program to identify molecular ions from precise mass determinations. The calculation can take several seconds or even a few minutes. To let the user know that it is processing, I would like to change the text on the button that starts the calculation to “Processing…” before the intense calculation begins. But Everything I try results in the change being displayed after the calculation completes!

In principle I thought this would work, as a similar code works for reading the atomic mass database before parsing it.

function fnFindSCM(){

  async function showProcessing() {
    document.getElementById("btnFindSCM").innerHTML = "Processing...";   
  }

  async function awaitShowProcessing(){
    await showProcessing();

  }

  awaitShowProcessing();

  reallyFindSCM();

}

The function fnFindSCM() is the button’s click event listener, while reallyFindSCM() is the function that does the heavy calculations.

I am hoping that a solution to this problem will also solve my next problem — displaying “hits” as they are found rather than all at once when the search is complete.

Adjacent Plot with Shared Y-axis in Scichart JS

I’d like to create a live dashboard supporting streaming stock candlesticks for OHLCV data, and to its right a chart with GEX levels plotted as horizontal bars as a function strike price (ladder chart). These two charts should share their Y-axis and the GEX levels should change dynamically for each time point of the OHLCV data as one moves one’s mouse pointer horizontally along the OHLCV data.

As a starting point there’s Multi-Pane Stock Charts using Sync Multi-Chart and I would like the GEX chart to appear beside the first chart here and to it’s right.

However, I am unable to modify the code to get the desired result. enter image description here

Using useEffect takes time to load and not using it leads to render the component twice

I have been working on password generator and I want a feature that generates the initial password when the user opens the site.

This takes time to load lets say 1-2 seconds.

const [password, setPassword] = useState<string>("");
useEffect(() => {
    setPassword(generatePassword(current));
}, []);

This renders the password twice…

const [password, setPassword] = useState<string>(generatePassword());

I am passing it in a input box.

<input type="text" disabled value={password} readOnly />

Why spreading array is required in angular application? [duplicate]

I was trying with an angular application containing reactive form. I have a custom component for displaying data in tabular format.

    <app-custom-table [data]="bankDetailsData" [...some other attributes]  >
    </app-custom-table>

Here, bankDetailsData is array of object declared like following.

bankDetailsData = <any>[];

This array contains data in object form from group of controls. When user click add button I add object into array like following.

if (this.someFormGroup?.valid) {
      this.bankDetailsData.push({
        bankName: this.formGroup?.get("someformControl")?.value,
        bankAccountNumber: this.formGroup?.get("someformControl")?.value,
        nomination: this.formGroup?.get("someformControl")?.value
      }); 

But above data record is not being displayed until I do following.

this.bankDetailsData = [...this.bankDetailsData];

I don’t understand why this is required and how it magically works. Can someone explain me regarding this?

Note: I have used bankDetailsData as an argument of my custom validator initially while creating form. I doubt this (spreading & assigning) causes problem in performing custom validation because now
bankDetailsData is whole together different object than that I have passed initially in my custom validator.

Local file path to File/Blob to be read by SheetJS’s read function

I want to use SheetJS to display an Excel sheet in a small app I am working on. Currently, the Excel workbook is on my local machine, and I want to read the file using SheetJS, then use SheetJS’s sheet_to_html functionality to display the sheet in the browser.

SheetJS provides a readFile function, but this does not work on the browser side. They offer a read file too, which accepts a binary blob of data. I am pretty new to Javascript, and can’t seem to get my local file path as a string into the correct format to be read by SheetJS read.

Here’s what I want:

const file = "my_local_excel_file.xlsx";
const reader = new FileReader();
data = // ... read file into a binary array buffer from reader
wb = XLSX.read(data);
// get sheet, display as HTML

I’ve been through all the documentation and previous StackOverflow questions, but I can’t seem to find an answer to this question. Nearly all other examples have some File type which is already a Blob to be read by XLSX.read, such as from an upload button. However, my file is coming directly as a string.

I do have a Python backend, and I have tried to parse the data using pandas and passing the data as JSON to SheetJS, but while that displays something in the browser, the formatting is all wrong.

Does anyone have any advice?

Retry request until API returns proper value then continue with further requests

I need to retry particular request in Postman to wait until task will be unlocked.
I don’t know how long it will take, it may be from 1 sec up to 1min.
Below script seems to not always be working due to asynchronous behaviour.

What kind of solution would you recommend here?

function checkIfTaskIsLocked(responseJson) {
    if(responseJson.items && responseJson.items(taskId) {
    if (responseJson.items[taskId].isLocked === false {
    return true;
    } else {
        console.log("task is locked");
        return false
    }
} else {
    console.log("task not found")
    return false;
}
}

if(!checkIfTaskIsLocked(responseJson)) {
    console.log("retrying request")
    setTimeout(function() {
        pm.execution.setNextRequest(pm.info.requestName)
    }, 10000)
}

How not to re-render the canvas once state changes?

I have couple of states where I change on different parts of the project:

which are:

    const [sketchDimensions, setSketchDimensions] = useState(SHOE_DIMENSIONS);
    const [selectedSegment, setSelectedSegment] = useState(null);
    const [activeSidebar, setActiveSidebar] = useState(1);
    
    // and so on 

and I’m using @P5-wrapper/react as a p5 wrapper.

I have a canvas component:

const Canvas = memo(({ sketchDimensions, setSketchDimensions, selectedSegment, setSelectedSegment, activeSidebar, selectedView, currentView }) => {
    if (sketchDimensions.length > 0) {
        console.log('initialized canvas');

        return (
            <ReactP5Wrapper
                sketch={shoeSketch}
                sketchDimensions={sketchDimensions}
                setSketchDimensions={setSketchDimensions}
                selectedSegment={selectedSegment}
                setSelectedSegment={setSelectedSegment}
                // and others
            />
        );
    }
});

and problem appears when the state changes and it creates new canvas elements and GPU increases around 0.8-0.9GB every time one of the states change.

task manager

is it possible not to re-render the canvas every time state changes?

What is the alternative API for Safari iOS for ‘webRequest.onBeforeRequest’ since this API is not available on Safari iOS?

I am working on a Safari extension for an AdBlocker. I want to use the JavaScript API ‘webRequest.onBeforeRequest’ for content blocking with ‘updateDynamicRules,’ but it’s not available on Safari iOS. What is the alternative API for this?

Doc Link :- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest

Alternate API or solution for this

Uncaught TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator))

I’m trying to use MUI(Material UI) App bar. This one. Version : v6.1.1
In the sandbox, when I’m testing its working fine.
Though, when I’m using it in my project. It breaks with the following error :
Uncaught TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator))

Code :

export default function NavBar() {
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); // error points to this line
  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState<null | HTMLElement>(null);

  const isMenuOpen = Boolean(anchorEl);
  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

Check the complete code here

Detailed error message :

navBar.jsx:59 Uncaught TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator))
at NavBar (navBar.jsx:59:1)
at renderWithHooks (react-dom.development.js:15486:1)
at mountIndeterminateComponent (react-dom.development.js:20103:1)
at beginWork (react-dom.development.js:21626:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27490:1)
at performUnitOfWork (react-dom.development.js:26596:1)
at workLoopSync (react-dom.development.js:26505:1)

To know more about the error from MDN, refer.

Could anyone from the community assist me for this.

Inconsistent window.scrollTo(0, 0) Behavior

I’m using Barba.js for page transitions on my website, and I want the scroll position to always reset to the top of the page during transitions. I’ve added window.scrollTo(0, 0) in the afterEnter hook, but it doesn’t consistently work. For example, when transitioning from the homepage to the corporate page, it only works about 2 out of 10 times.

Here’s a simplified version of my code:

history.scrollRestoration = "manual"

barba.hooks.afterEnter(() => {
  console.log("window scrollTo 0, 0");
  window.scrollTo(0, 0);
});

barba.init({
  transitions: [{
    name: 'default',
    async afterEnter() {
      console.log("window scrollTo 0, 0");
      window.scrollTo(0, 0);
    },
  }]
});

Despite seeing the log message every time, indicating that the code is executed, the scroll position doesn’t always reset as expected.

What could be causing this inconsistent behavior? Thank you

How to clip curvedText in fabricjs version 5?

I am using the following code to create curvedText object:

fabric.CurvedText=fabric.util.createClass(fabric.Text, fabric.Collection, /** @lends fabric.CurvedText.prototype */ {
    /**
     * Type of an object
     * @type String
     * @default
     */
    type: 'curvedText',
    /**
     * The radius of the curved Text
     * @type Number
     * @default 50
     */
    radius: 50,
    /**
     * Special Effects, Thanks to fahadnabbasi
     * https://github.com/EffEPi/fabric.curvedText/issues/9
     */
    range: 5,
    smallFont: 10,
    largeFont: 30,
    effect: 'curved',
    /**
     * Spacing between the letters
     * @type fabricNumber
     * @default 20
     */
    spacing: 20,
//      letters: null,

    /**
     * Reversing the radius (position of the original point)
     * @type Boolean
     * @default false
     */
    reverse: false,
    /**
     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
     * as well as for history (undo/redo) purposes
     * @type Array
     */
    stateProperties: stateProperties,
    /**
     * Properties that are delegated to group objects when reading/writing
     * @param {Object} delegatedProperties
     */
    // delegatedProperties: delegatedProperties,
    /**
     * Properties which when set cause object to change dimensions
     * @type Object
     * @private
     */
    _dimensionAffectingProps: _dimensionAffectingProps,
    /**
     *
     * Rendering, is we are rendering and another rendering call is passed, then stop rendering the old and
     * rendering the new (trying to speed things up)
     */
    _isRendering: 0,
    /**
     * Added complexity
     */
    complexity: function (){
      this.callSuper('complexity');
    },
    initialize: function (text, options){
      options||(options={});
      this.__skipDimension=true;
      delete options.text;
      this.setOptions(options);
      this.__skipDimension=false;

      if(parseFloat(fabric.version) >= 2) {
        this.callSuper('initialize', text, options);
      }

      this.letters=new fabric.Group([], {
        selectable: false,
        padding: 0
      });
      this.setText(text);
      // this.render(this.ctx,true);
    },
    setText: function (text){
      if(this.letters){
        while(this.letters.size()){
          this.letters.remove(this.letters.item(0));
        }
        for(var i=0; i<text.length; i++){
          //I need to pass the options from the main options
          if(this.letters.item(i)===undefined){
            this.letters.add(new fabric.Text(text[i]));
          }else{
            this.letters.item(i).text = text[i];
          }
        }
      }
      this.text = text;

      var i = this.letters.size();
      while(i--){
        var letter = this.letters.item(i);
        letter.set({
          objectCaching: false,
          fill: this.fill,
          stroke: this.stroke,
          strokeWidth: this.strokeWidth,
          fontFamily: this.fontFamily,
          fontSize: this.fontSize,
          fontStyle: this.fontStyle,
          fontWeight: this.fontWeight,
          underline: this.underline,
          overline:  this.overline,
          linethrough: this.linethrough,
          lineHeight: this.lineHeight
        });
      }

      this._updateLetters();

      this.canvas && this.canvas.renderAll();
    },
    _initDimensions: function (ctx){
      // from fabric.Text.prototype._initDimensions
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      if(this.__skipDimension){
        return;
      }
      if(!ctx){
        ctx=fabric.util.createCanvasElement().getContext('2d');
        this._setTextStyles(ctx);
      }
      this._textLines=this.text.split(this._reNewline);
      this._clearCache();
      var currentTextAlign=this.textAlign;
      this.textAlign='left';
      this.width=this.get('width');
      this.textAlign=currentTextAlign;
      this.height=this.get('height');
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      this._updateLetters();
    },
    _updateLetters: function (){
      var renderingCode=fabric.util.getRandomInt(100, 999);
      this._isRendering=renderingCode;
      if(this.letters && this.text){
        var curAngle=0,
          curAngleRotation=0,
          angleRadians=0,
          align=0,
          textWidth=0,
          space=parseInt(this.spacing),
          fixedLetterAngle=0;

        //get text width
        if(this.effect==='curved'){
          for(var i=0, len=this.text.length; i<len; i++){
            textWidth+=this.letters.item(i).width+space;
          }
          textWidth-=space;
        }else if(this.effect==='arc'){
          fixedLetterAngle=((this.letters.item(0).fontSize+space)/this.radius)/(Math.PI/180);
          textWidth=((this.text.length+1)*(this.letters.item(0).fontSize+space));
        }
        // Text align
        if(this.get('textAlign')==='right'){
          curAngle=90-(((textWidth/2)/this.radius)/(Math.PI/180));
        }else if(this.get('textAlign')==='left'){
          curAngle=-90-(((textWidth/2)/this.radius)/(Math.PI/180));
        }else{
          curAngle=-(((textWidth/2)/this.radius)/(Math.PI/180));
        }
        if(this.reverse)
          curAngle=-curAngle;

        var width=0,
          multiplier=this.reverse?-1:1,
          thisLetterAngle=0,
          lastLetterAngle=0;

        for(var i=0, len=this.text.length; i<len; i++){
          if(renderingCode!==this._isRendering)
            return;

          for(var key in letterProperties){
            this.letters.item(i).set(key, this.get(key));
          }

          this.letters.item(i).set('left', (width));
          this.letters.item(i).set('top', (0));
          this.letters.item(i).set('angle',0);
          this.letters.item(i).set('padding', 0);

          if(this.effect==='curved'){
            thisLetterAngle=((this.letters.item(i).width+space)/this.radius)/(Math.PI/180);
            curAngle=multiplier*((multiplier*curAngle)+lastLetterAngle);
            angleRadians=curAngle*(Math.PI/180);
            lastLetterAngle=thisLetterAngle;

            this.letters.item(i).set('angle',curAngle);
            this.letters.item(i).set('top', multiplier*-1*(Math.cos(angleRadians)*this.radius));
            this.letters.item(i).set('left', multiplier*(Math.sin(angleRadians)*this.radius));
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);

          }else if(this.effect==='arc'){//arc
            curAngle=multiplier*((multiplier*curAngle)+fixedLetterAngle);
            angleRadians=curAngle*(Math.PI/180);

            this.letters.item(i).set('top', multiplier*-1*(Math.cos(angleRadians)*this.radius));
            this.letters.item(i).set('left', multiplier*(Math.sin(angleRadians)*this.radius));
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);
          }else if(this.effect==='STRAIGHT'){//STRAIGHT
            //var newfont=(i*5)+15;
            //this.letters.item(i).set('fontSize',(newfont));
            this.letters.item(i).set('left', (width));
            this.letters.item(i).set('top', (0));
            this.letters.item(i).set('angle',0);
            width+=this.letters.item(i).get('width');
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set({
              borderColor: 'red',
              cornerColor: 'green',
              cornerSize: 6,
              transparentCorners: false
            });
            this.letters.item(i).set('selectable', false);
          }else if(this.effect==='smallToLarge'){//smallToLarge
            var small=parseInt(this.smallFont);
            var large=parseInt(this.largeFont);
            //var small = 20;
            //var large = 75;
            var difference=large-small;
            var center=Math.ceil(this.text.length/2);
            var step=difference/(this.text.length);
            var newfont=small+(i*step);

            //var newfont=(i*this.smallFont)+15;

            this.letters.item(i).set('fontSize', (newfont));

            this.letters.item(i).set('left', (width));
            width+=this.letters.item(i).get('width');
            //this.letters.item(i).set('padding', 0);
            /*this.letters.item(i).set({
                         borderColor: 'red',
                         cornerColor: 'green',
                         cornerSize: 6,
                         transparentCorners: false
                         });*/
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);
            this.letters.item(i).set('top', -1*this.letters.item(i).get('fontSize')+i);
            //this.letters.width=width;
            //this.letters.height=this.letters.item(i).get('height');

          }else if(this.effect==='largeToSmallTop'){//largeToSmallTop
            var small=parseInt(this.largeFont);
            var large=parseInt(this.smallFont);
            //var small = 20;
            //var large = 75;
            var difference=large-small;
            var center=Math.ceil(this.text.length/2);
            var step=difference/(this.text.length);
            var newfont=small+(i*step);
            //var newfont=((this.text.length-i)*this.smallFont)+12;
            this.letters.item(i).set('fontSize', (newfont));
            this.letters.item(i).set('left', (width));
            width+=this.letters.item(i).get('width');
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set({
              borderColor: 'red',
              cornerColor: 'green',
              cornerSize: 6,
              transparentCorners: false
            });
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);
            this.letters.item(i).top=-1*this.letters.item(i).get('fontSize')+(i/this.text.length);

          }else if(this.effect==='largeToSmallBottom'){
            var small=parseInt(this.largeFont);
            var large=parseInt(this.smallFont);
            //var small = 20;
            //var large = 75;
            var difference=large-small;
            var center=Math.ceil(this.text.length/2);
            var step=difference/(this.text.length);
            var newfont=small+(i*step);
            //var newfont=((this.text.length-i)*this.smallFont)+12;
            this.letters.item(i).set('fontSize', (newfont));
            this.letters.item(i).set('left', (width));
            width+=this.letters.item(i).get('width');
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set({
              borderColor: 'red',
              cornerColor: 'green',
              cornerSize: 6,
              transparentCorners: false
            });
            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);
            //this.letters.item(i).top =-1* this.letters.item(i).get('fontSize')+newfont-((this.text.length-i))-((this.text.length-i));
            this.letters.item(i).top=-1*this.letters.item(i).get('fontSize')-i;

          }else if(this.effect==='bulge'){//bulge
            var small=parseInt(this.smallFont);
            var large=parseInt(this.largeFont);
            //var small = 20;
            //var large = 75;
            var difference=large-small;
            var center=Math.ceil(this.text.length/2);
            var step=difference/(this.text.length-center);
            if(i<center)
              var newfont=small+(i*step);
            else
              var newfont=large-((i-center+1)*step);
            this.letters.item(i).set('fontSize', (newfont));

            this.letters.item(i).set('left', (width));
            width+=this.letters.item(i).get('width');

            this.letters.item(i).set('padding', 0);
            this.letters.item(i).set('selectable', false);

            this.letters.item(i).set('top', -1*this.letters.item(i).get('height')/2);
          }
        }

        var scaleX=this.letters.get('scaleX');
        var scaleY=this.letters.get('scaleY');
        var angle=this.letters.get('angle');

        this.letters.set('scaleX', 1);
        this.letters.set('scaleY', 1);
        this.letters.set('angle', 0);

        // Update group coords
        this.letters._calcBounds();
        this.letters._updateObjectsCoords();
        //this.letters.saveCoords();
        // this.letters.render(ctx);

        this.letters.set('scaleX', scaleX);
        this.letters.set('scaleY', scaleY);
        this.letters.set('angle', angle);

        this.width=this.letters.width;
        this.height=this.letters.height;
        this.letters.left= -(this.letters.width/2);
        this.letters.top= -(this.letters.height/2);
      }
    },
    render: function (ctx){
      // do not render if object is not visible
      if(!this.visible)
        return;
      if(!this.letters)
        return;


      ctx.save();

      // if(noTransform){
      this.transform(ctx);
      // }

      var groupScaleFactor=Math.max(this.scaleX, this.scaleY);

      this.clipTo&&fabric.util.clipContext(this, ctx);

      //The array is now sorted in order of highest first, so start from end.
      for(var i=0, len=this.letters.size(); i<len; i++){
        var object=this.letters.item(i),
          originalScaleFactor=object.borderScaleFactor,
          originalHasRotatingPoint=object.hasRotatingPoint;

        // do not render if object is not visible
        if(!object.visible)
          continue;

//              object.borderScaleFactor=groupScaleFactor;
//              object.hasRotatingPoint=false;

        object.render(ctx);
//              object.borderScaleFactor=originalScaleFactor;
//              object.hasRotatingPoint=originalHasRotatingPoint;
      }
      this.clipTo&&ctx.restore();

      //Those lines causes double borders.. not sure why
//          if(!noTransform&&this.active){
//              this.drawBorders(ctx);
//              this.drawControls(ctx);
//          }
      ctx.restore();
      this.setCoords();
    },
    /**
     * @private
     */
    _set: function (key, value){
      if(key === "text"){
        this.setText(value);

        return;
      }
      this.callSuper('_set', key, value);
      if(this.text && this.letters){
        if(["angle","left","top","scaleX","scaleY","width","height"].indexOf(key) === -1){
          var i = this.letters.size();
          while(i--){
            this.letters.item(i).set(key, value);
          }
        }
        //Properties are delegated with the object is rendered
//              if (key in this.delegatedProperties) {
//                  var i = this.letters.size();
//                  while (i--) {
//                      this.letters.item(i).set(key, value);
//                  }
//              }
        if(this._dimensionAffectingProps.indexOf(key) !== -1){
          this._updateLetters();
          //this._initDimensions();
          this.setCoords();
        }
      }
    },
    initDimensions: function() {

    },
    toObject: function (propertiesToInclude){
      var object = extend(this.callSuper('toObject', propertiesToInclude), {
        radius: this.radius,
        spacing: this.spacing,
        reverse: this.reverse,
        effect: this.effect,
        range: this.range,
        smallFont: this.smallFont,
        largeFont: this.largeFont
        //letters: this.letters //No need to pass this, the letters are recreated on the fly every time when initiated
      });

      if(!this.includeDefaultValues){
        this._removeDefaultValues(object);
      }
      return object;
    },
    /**
     * Returns string represenation of a group
     * @return {String}
     */
    toString: function (){
      return '#<fabric.CurvedText ('+this.complexity()+'): { "text": "'+this.text+'", "fontFamily": "'+this.fontFamily+'", "radius": "'+this.radius+'", "spacing": "'+this.spacing+'", "reverse": "'+this.reverse+'" }>';
    },
    /* _TO_SVG_START_ */
    /**
     * Returns svg representation of an instance
     * @param {Function} [reviver] Method for further parsing of svg representation.
     * @return {String} svg representation of an instance
     */
    toSVG: function (reviver){
      var markup=[
        '<g ',
        'transform="', this.getSvgTransform(),
        '">'
      ];
      if(this.letters){
        for(var i=0, len=this.letters.size(); i<len; i++){
          markup.push(this.letters.item(i).toSVG(reviver));
        }
      }
      markup.push('</g>');
      return reviver?reviver(markup.join('')):markup.join('');
    }
    /* _TO_SVG_END_ */
  });

Under the render function, this code is used to clip the curvedText object – this.clipTo&&fabric.util.clipContext(this, ctx);. This is not working with fabricJs version 5 as clipTo & fabric.util.clipContext are deprecated. I tried adding clipPath to the curvedText but that doesn’t clip the object, although it is working as expected with text & image objects.

How to make clipping work with curvedText objects?

How to exit process.stdin.on without exiting the entire program?

I’m using readline.emiteKeypressEvents(process.stdin) to read user input letter by letter. This is part of a terminal tool I’m creating and this part of code is stored in a script called liveinput.js.

I’d like to exit the script to move to an another one and using process.exit() unfortunately closes the entire program. Forcing an another function inside of the script bricks the terminal completely that even CTRL+C cannot fix.

Is there a way to say: ‘I’d like to close this current input stream, but not the entire program!’

I’ve tried process.exit(), making it an interface, removing listeners and so much more.

I’ll try to crop the code that the “irrelevant” parts are cropped out.

import * as readline from "node:readline";
import fs from "fs";

const stopListen = () => process.stdin.removeAllListeners('keypress');

export function liveInput(socket, terminalStart){

    readline.emitKeypressEvents(process.stdin);
    if (process.stdin.isTTY){
        process.stdin.setRawMode(true);
    }

    let text = fs.readFileSync("./txt/current_text.txt", "utf8");

    console.clear();
    console.log("Liveinput:n" + text + "<");

    readInput();
    function readInput() {
        // Exit with ESC or Ctrl+C
        process.stdin.on("keypress", (str, key) => {
            if (key.seq === "escape") {
                // Close this loop, but no the whole program!!!
            } else if (key.name === 'backspace') {
                text = text.slice(0, -1);
            } else if (key.name === 'space') {
                text += ' ';
            } else if (str && str.length === 1 && !key.ctrl && !key.meta) {
                text += str; 
            }

            console.clear();
            console.log("Liveinput:n" + text + "<");
        });
    } 
}

how to make the text in the items to float above the image in SwipeJS?

I’m trying to duplicate this effect from the SwipeJS demo page, where the text floats on the bottom part, but not outside of, the image in each slide.

I’ve tried using slide-content like I see in the devtools and I also tried using title and subtitle classes like it says in the docs (in the parallax part). but they all fails, as in showing the texts below the image, instead of over the image. what am I doing wrong? any help is appreciated.

this is my code:

      var swiper = new Swiper(".mySwiper", {
        effect: "coverflow",
        grabCursor: true,
        centeredSlides: true,
        slidesPerView: "auto",
        coverflowEffect: {
          rotate: 50,
          stretch: 0,
          depth: 100,
          modifier: 1,
          slideShadows: true,
        },
        pagination: {
          el: ".swiper-pagination",
        },
      });
      html,
      body {
        position: relative;
        height: 100%;
      }

      body {
        background: #eee;
        font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
        font-size: 14px;
        color: #000;
        margin: 0;
        padding: 0;
      }

      .swiper {
        width: 100%;
        padding-top: 50px;
        padding-bottom: 50px;
      }

      .swiper-slide {
        background-position: center;
        background-size: cover;
        width: 300px;
        height: 300px;
      }

      .swiper-slide img {
        display: block;
        width: 100%;
      }

      .swiper-slide .card-img-text {
        translatey: (-50%);
        mix-blend-mode: exclusion;
      }

      .swiper-slide .card-img-text * {
      }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Swiper demo</title>
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
    />
    <!-- Link Swiper's CSS -->
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"
    />
  </head>

  <body>
    <!-- Swiper -->
    <div class="swiper mySwiper">
      <div class="swiper-wrapper">
        <div class="swiper-slide">
          <img
            src="https://picsum.photos/800"
            class="card-img-top"
            alt="example image 1"
          />
          <div class="slide-content">
            <h5>Slide 1 Title</h5>
            <p>Slide 1 Description</p>
          </div>
          <!-- <img src="https://swiperjs.com/demos/images/nature-1.jpg" /> -->
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-2.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-3.jpg" />
        </div>
      </div>
      <div class="swiper-pagination"></div>
    </div>

    <!-- Swiper JS -->
    <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
  </body>
</html>

Next Page is not loading and setting values in Suitelet Page

I am not able to go to the nextpage using the pageIndex field .When I click on the that it reloads into as new page with blank filter and sublist
Suitelet Script

/**
 * @NApiVersion 2.1
 * @NScriptType Suitelet
 */
define(['N/email', 'N/record', 'N/search', 'N/ui/serverWidget','N/file','N/redirect'],
    /**
 * @param{email} email
 * @param{record} record
 * @param{search} search
 * @param{serverWidget} serverWidget
 * @param{file} file
 *  @param{redirect} redirect
 */
    (email, record, search, serverWidget, file,redirect) => {
        /**
         * Defines the Suitelet script trigger point.
         * @param {Object} scriptContext
         * @param {ServerRequest} scriptContext.request - Incoming request
         * @param {ServerResponse} scriptContext.response - Suitelet response
         * @since 2015.2
         */
        function EmployeeSearch(){
            try {
               let searchObj = search.create({
                   type: search.Type.EMPLOYEE,
                   filters:  ["isinactive","any","F"],
                   columns: ['entityid','internalid']
               })
               let results = searchObj.run().getRange({
                start: 0,
                end: 1000
            });
            //    log.debug("results",results)
                return results;
               
               
            } catch (e) {
               log.error("error",e.message)
            }
           }
        function createCsvFile(request,lineCount){
            let docNo ;
            let vendor;let memo;
            let total;
            //let fileId;
            let csvContent = 'DocumentNo,Vendor,Memo,Amountn';
            for(let i=0;i<lineCount;i++){
                let select = request.getSublistValue({
                    group: "custpage_jj_porder",
                    line:i,
                    name: "custpage_jj_sub_porder_select"
                });
                log.debug("select",select);
                if(select ==='T'){
                docNo = request.getSublistValue({
                    group: "custpage_jj_porder",
                    line:i,
                    name: "custpage_jj_sub_porder_docno"
                });
                vendor  = request.getSublistValue({
                    group: "custpage_jj_porder",
                    line:i,
                    name:"custpage_jj_sub_porder_vendor"
                });
               
                memo  = request.getSublistValue({
                    group: "custpage_jj_porder",
                    line:i,
                    name: "custpage_jj_sub_porder_memo"
                });
              
               total  = request.getSublistValue({
                    group: "custpage_jj_porder",
                    line:i,
                    name: "custpage_jj_sub_porder_total"
                });
                csvContent +=docNo+','+vendor+','+memo+','+total+"n";
              
                } 
           

              
              
            }
           
            return csvContent;
        }
        function sendEmailToSupervisor(supervisor,csvFileId,supervisorName){
            email.send({
                author:-5 ,
                body: "Dear SuperVisor ,Here are the orders that are pending this month",
                recipients:supervisor,
                subject:"Pending Billed Purchase Orders",
                attachments:[file.load({
                    id: csvFileId
                })]
            })
            
            let body = "Email Sent to "+supervisorName;
            return body;
        }
        function fetchSearchResult(pagedData,pageIndex) {

        try {
            let searchPage = pagedData.fetch({
                index : pageIndex
            });
            // log.debug("")
        let results = new Array();

        searchPage.data.forEach(function (result) {
           
            results.push({
                "docno":result.getValue({name: "tranid", label: "Document Number"}),
                "vendor": result.getValue({ name: "entityid",
                    join: "vendor",
                    label: "Name"}),
                "memo":result.getValue({ name: "memo", label: "Memo"}),
                "total":result.getValue({ name: "amount", label: "Amount"})
            });
            return true;
        });
        return results;
        } catch (e) {
            log.error("Error on Fetch Search Results",e.message)
        }
        }
        const onRequest = (scriptContext) => {
        try{
               
            if(scriptContext.request.method === "GET"){
                let form = serverWidget.createForm({
                    title: "Email Report",
                });
                form.addFieldGroup({
                    id: "custpage_jj_filter",
                    label: "FIlter"
                })
                form.addFieldGroup({
                    id: "custpage_jj_page_group",
                    label: "Page Group"
                })
                form.clientScriptFileId = 3253;
                let employee = form.addField({
                    id: "custpage_jj_employee",
                    label: "Select a Employee",
                    type: serverWidget.FieldType.SELECT,
                    container: "custpage_jj_filter"
                });
                let results = EmployeeSearch();
                employee.addSelectOption({
                    value: "",
                    text: "",
                });
                for(let i =0;i<results.length;i++){
                    employee.addSelectOption({
                        value: results[i].getValue({
                            name: "internalid"
                        }),
                        text:  results[i].getValue({
                            name: "entityid"
                        })
                    })
                }
              
                form.addButton({
                    id: "custpage_jj_get_values_button",
                    label: "Get Values",
                    functionName: 'setValues'
                });
                form.addSubmitButton({
                    label: "Send Email"
                })
                let subList = form.addSublist({
                    id: "custpage_jj_porder",
                    label: "Purchase Order",
                    type: serverWidget.SublistType.LIST
                });
                subList.addField({
                    id: "custpage_jj_sub_porder_docno",
                    label: "Document No",
                    type: serverWidget.FieldType.INTEGER,
                })
                subList.addField({
                    id: "custpage_jj_sub_porder_vendor",
                    label: "Vendor",
                    type: serverWidget.FieldType.TEXT,
                  
                })
                let memo = subList.addField({
                    id: "custpage_jj_sub_porder_memo",
                    label: "Memo",
                    type: serverWidget.FieldType.TEXT,
                  
                })
                subList.addField({
                    id: "custpage_jj_sub_porder_total",
                    label: "Total Amount",
                    type: serverWidget.FieldType.CURRENCY,
                })
                subList.addField({
                    id: "custpage_jj_sub_porder_select",
                    label: "Select",
                    type: serverWidget.FieldType.CHECKBOX,
                    
                })
                let selectOptions = form.addField({
                    id : 'custpage_jj_pageid',
                    label : 'Page Index',
                    type : serverWidget.FieldType.SELECT,
                    container:"custpage_jj_page_group"
                });
                let employeeId = scriptContext.request.parameters.empId||null;
              
                employee.defaultValue = employeeId;
                // const pageSize  = 10;
                log.debug("empid",employeeId);
                if(employeeId){
                    let purchaseorderSearchObj = search.create({
                        type: "purchaseorder",
                        settings:[{"name":"consolidationtype","value":"ACCTTYPE"}],
                        filters:
                        [
                           ["type","anyof","PurchOrd"], 
                           "AND", 
                           ["mainline","is","T"], 
                           "AND", 
                           ["datecreated","within","thismonth"], 
                           "AND", 
                           ["status","anyof","PurchOrd:F"], 
                           "AND", 
                           ["createdby","anyof",employeeId]
                        ],
                        columns:
                        [
                           search.createColumn({name: "tranid", label: "Document Number"}),
                           search.createColumn({
                              name: "entityid",
                              join: "vendor",
                              label: "Name"
                           }),
                           search.createColumn({name: "memo", label: "Memo"}),
                           search.createColumn({name: "amount", label: "Amount"}),
                           search.createColumn({name: "datecreated", label: "Date Created"}),
                           search.createColumn({name: "createdby", label: "Created By"})
                        ]
                     });
                     let searchResults  = purchaseorderSearchObj.run();
                    
                     let results = purchaseorderSearchObj.run().getRange({
                        start:0,
                        end:1000
                     });
                     log.debug("resultsearch",searchResults);
                     let pageSize = 10;
                     let pagedData = purchaseorderSearchObj.runPaged({ pageSize: pageSize });
                     let searchResultCount = pagedData.count;
                    log.debug("purchaseorderSearchObj result count",searchResultCount);
                   
                    let pageId = parseInt(scriptContext.request.parameters.pageid)||0;   
                     let pageCount = Math.ceil(searchResultCount / pageSize);
                     log.debug("pageCount",pageCount);
                   
                     if (pageCount === 0) {
                        alert("No Results Found")
                      } else {
                        
                        if (pageId < 0 || pageId >= pageCount) {
                          pageId = 0;
                        }
                        else if (pageId >= pageCount)
                            pageId = pageCount - 1;

                        if (pageId != 0) {
                            form.addButton({
                                id : 'custpage_previous',
                                label : 'Previous',
                                functionName : 'getSuiteletPage(' + (pageId - 1) +')',
                                container:'custpage_jj_page_group'
                            });
                        }
            
                        if (pageId != pageCount - 1) {
                            form.addButton({
                                id : 'custpage_next',
                                label : 'Next',
                                functionName : 'getSuiteletPage(' +(pageId + 1) + ')',
                                container:'custpage_jj_page_group'
                            });
                        }
                        
                        let addResults = fetchSearchResult(pagedData, pageId);
                        log.debug("array result",addResults);
                        var j = 0;
                        addResults.forEach(function (result) {
                           subList.setSublistValue({
                               id: "custpage_jj_sub_porder_docno",
                               line: j,
                               value: result.docno
                           });
                           subList.setSublistValue({
                               id: "custpage_jj_sub_porder_vendor",
                               line: j,
                               value: result.vendor
                           });
                           subList.setSublistValue({
                               id: "custpage_jj_sub_porder_memo",
                               line: j,
                               value: result.memo
                           });
                           memo.updateDisplayType({
                               displayType : serverWidget.FieldDisplayType.ENTRY
                           });
                           subList.setSublistValue({
                               id: "custpage_jj_sub_porder_total",
                               line: j,
                               value: result.total
                           });
                           j++;
                       })
                }
                   
                     for (let i = 0; i < pageCount; i++) {
                    if (i == pageId) {
                        selectOptions.addSelectOption({
                            value : 'pageid_' + i,
                            text : ((i * pageSize) + 1) + ' - ' + ((i + 1) * pageSize),
                            isSelected:true
                        });
                        // redirect.toSuitelet({
                        //     scriptId: "customscript_jj_sl_email_sup_otp7939",
                        //     deploymentId: "customdeploy_jj_sl_email_sup_otp7939",
                        //     parameters:{
                        //         pageid : pageId
                        //     }
                        // })
                    } else {
                        selectOptions.addSelectOption({
                            value : 'pageid_' + i,
                            text : ((i * pageSize) + 1) + ' - ' + ((i + 1) * pageSize)
                        });
                    }
                    log.debug("'pageid_' "+ i)
                    }
                

             }
             scriptContext.response.writePage(form);     
    }else{
        let request = scriptContext.request;
      
        let lineCount = request.getLineCount({
            group: "custpage_jj_porder"
        });
        let csvFile;
        let body;
        let employeeId = scriptContext.request.parameters.custpage_jj_employee;
        let lookupSearchObj  = search.lookupFields({
            type: search.Type.EMPLOYEE,
            id: employeeId,
            columns: ['supervisor']
            });
            let supervisor = lookupSearchObj.supervisor[0].value;
            let supervisorName = lookupSearchObj.supervisor[0].text;
            log.debug("supervisor",supervisor);
            log.debug("supervisor",supervisorName);
            let csvFileId;
        if(lineCount>0){
            csvFile = createCsvFile(request,lineCount);
            log.debug("csv",csvFile);
            let csvDocument = file.create({
                name: "Pending Billed Purchase Orders"+employeeId,
                fileType: file.Type.CSV,
                contents: csvFile,
                folder: -15,
                isOnline: true
            })
             csvFileId = csvDocument.save();
           //body    = sendEmailToSupervisor(supervisor,csvFileId,supervisorName)
        } 
        //let finalText = "CsvContent"+csvFile+"n"+body;
        scriptContext.response.write(csvFileId);     
    }


        }catch(e){
         log.error("error",e.message+e.stack);
        }

}


        return {onRequest}

    });

Client Script

/**
 * @NApiVersion 2.1
 * @NScriptType ClientScript
 * @NModuleScope SameAccount
 */
define(['N/currentRecord', 'N/url'],
    /**
     * @param{currentRecord} currentRecord
     * @param{url} url
     */
    function(currentRecord, url) {
        
        /**
         * Function to be executed after page is initialized.
         *
         * @param {Object} scriptContext
         * @param {Record} scriptContext.currentRecord - Current form record
         * @param {string} scriptContext.mode - The mode in which the record is being accessed (create, copy, or edit)
         *
         * @since 2015.2
         */
        function pageInit(scriptContext) {
            window.onbeforeunload =null;
        }
    
        /**
         * Function to be executed when field is changed.
         *
         * @param {Object} scriptContext
         * @param {Record} scriptContext.currentRecord - Current form record
         * @param {string} scriptContext.sublistId - Sublist name
         * @param {string} scriptContext.fieldId - Field name
         * @param {number} scriptContext.lineNum - Line number. Will be undefined if not a sublist or matrix field
         * @param {number} scriptContext.columnNum - Line number. Will be undefined if not a matrix field
         *
         * @since 2015.2
         */
      
        function fieldChanged(scriptContext) {
            console.log("triggering");
        if(scriptContext.fieldId == 'custpage_jj_pageid') {    
        let pageId = scriptContext.currentRecord.getValue({
            fieldId: "custpage_jj_pageid"
        });
        let pageStr  = parseInt(pageId.split('_')[1]);
        console.log("pageId",pageStr);
        // let result = pageStr.split('- ')[1];
        // let integer = parseInt(result);
        //pageId = parseInt(pageId.split('-')[1]);//NaN
        // console.log("pagestr",result);
        if(pageId){
        document.location = url.resolveScript({
            deploymentId:  getParameterFromURL('deploy'),
            scriptId: getParameterFromURL('script'),
            params: {
                pageid : pageStr
            }
        })
    }
    
        }
    }
        function setValues(){
         try {
            
            let currRecord = currentRecord.get();
            let employeeId = currRecord.getValue({
                fieldId: "custpage_jj_employee"
            });
            console.log("employee",employeeId);
            document.location = url.resolveScript({
                deploymentId: "customdeploy_jj_sl_suite_otp7939",
                scriptId: "customscript_jj_sl_suite_otp7939",
                params: {
                    empId : employeeId
                }
            })

          
        
         } catch (e) {
            console.log("error",e.message+e.stack)
         }
    }
        // function returnPageId(){
         
        // }
        function getSuiteletPage(pageId) {
           
            document.location = url.resolveScript({
                    scriptId : "customdeploy_jj_sl_suite_otp7939",
                    deploymentId : "customscript_jj_sl_suite_otp7939",
                    params : {
                        pageid : pageId,
                    }
                });
        }
        function getParameterFromURL(param) {
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            for (var i = 0; i < vars.length; i++) {
                var pair = vars[i].split("=");
                if (pair[0] == param) {
                    return decodeURIComponent(pair[1]);
                }
            }
            return (false);
        }
     
      
        return {
            pageInit: pageInit,
            setValues:setValues,
            fieldChanged:fieldChanged,
           getSuiteletPage: getSuiteletPage
        };
        
    });
 

I was trying to do pagination in my suitelet page with the help of https://suiteanswers.custhelp.com/app/answers/detail/a_id/63272/loc/en_US
Suppose I have 14 results in my search i need to display 10 on one page and 4 on other page
I got the first 10 results but when i clicked on the next page it is not going to the next page instead it is resetting the page

Display of image sequences in Webbrowser using VueJs

I am developing a web frontend using VueJs for the ui part and a python flask server to provide data.
Communication between the two works with axios.

One main task of the frontend is to display images (one at a time, but with high frequency).
The images are provided via zmq. The VueJs makes a request to the flask server every sencond (required are 300ms) to get the newest image. The timer is set in the onMounted of App.vue.
When I restart everything, the frontend displays the images for a few seconds, then just stops. There is no load event from the image control anymore.

Is this a problem with VueJS? Or with the browser? The browser I am using is Google Chrome. Is there a better way to load large image sequences with high display frequency?

This is the python code:

@app.route('/img.jpg')
def image():

    while not socket.poll(10000, zmq.POLLIN):
        continue

    thumbnail = socket.recv(zmq.NOBLOCK)
    
    arr = np.frombuffer(thumbnail, dtype=np.uint8)
    img = np.reshape(arr, ( 2048, 1536,4))
    
    from PIL import Image as im
    data = im.fromarray(img)
    th = io.BytesIO()
    data.save(th, "JPEG")

    th.seek(0)

    return flask.Response(th, mimetype='image/jpeg')

and in my frontend code

the image store

const imageRoute = "img.jpg";
export const useImageStore = defineStore(
'image',
() => {
    const imgUrl = ref("");
    const imageBaseUrl = axios.defaults.baseURL + imageRoute;

    function updateImageData() {
        axios.get(imageRoute)
            .then(() => {                    
                imgUrl.value = imageBaseUrl + "?" + new Date().getTime();
            })
            .catch((err) => {
                console.error(err);
                imgUrl.value = "";
            });
    }

    return {
        updateImageData,
        imgUrl
    }
})

and the vue file:

<script setup>
import {useImageStore} from "../stores/image";

const imageStore = useImageStore();

function triggerRefresh() {
  console.log("refresh triggered by load event!")
}  

</script>

<template>
<main>
  <div class="container">
  <div class="row">
    <div class="col-md-5 px-1">
      <img alt="Grapes" class="rounded w-100  img-thumbnail" :src="imageStore.imgUrl" @load="triggerRefresh"/>
    </div>
  <div>
  <div>
 </main>
 </template>