Creating a schema with minified version of a type

How can I create a Prisma schema for mongoDb that contains sort of a minified version of another object?

To explain better the data I am working with could look something like this:

const basicUser = {
  id: "62091d9ae17cad32fbe0eda5",
  displayName: "John Smith",
};
const post = {
  title: "My Title",
  content: "My content",
  author: basicUser,
};

const user = {
    id: "62091d9ae17cad32fbe0eda5",
    firstName: "John",
    lastName: "Smith",
    displayName: "John Smith",
    emailAddress:"[email protected]"
}

I am not interested in creating relations as I just want to include this basic data and then to be able to look up the full user if I need to.

Decompress JSON data in Javascript

The R rgl package exports an HTML widget with the rglwidget() function, built using the htmlwidgets package. Often the data for this widget is quite large, and Pandoc and webshot2 choke on it.

I would like to try compressing the data when the HTML page is created, and uncompressing it in Javascript before display. I can see that there’s a Javascript package pako that appears to do what I want, and it can be “browserified”, but I can’t see how to make it available to rglwidget(). Can anyone describe what’s necessary?

Jest fail : The above error occurred in the component: can anyone help me out?

console.error
The above error occurred in the component:

      at ScrollViewMock (/Users/arqum/Desktop/support/faveo-support-app/node_modules/react-native/jest/mockScrollView.js:21:52)
      at _class (/Users/arqum/Desktop/support/faveo-support-app/node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js:199:47)
      at View
      at Component (/Users/arqum/Desktop/support/faveo-support-app/node_modules/react-native/jest/mockComponent.js:28:18)
      at ChangePasswordScreen (/Users/arqum/Desktop/support/faveo-support-app/src/components/functionality/LoginUser/ChangePassword/ChangePassword.js:17:24)
  
  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

  at logCapturedError (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10989:23)
  at update.callback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11022:5)
  at callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3662:12)
  at commitUpdateQueue (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3683:9)
  at commitLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11855:11)
  at commitLayoutEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14443:7)
  at Object.invokeGuardedCallbackProd (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11308:10)
  at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11499:31)

● Language Screen Components and Unit Testing › Get Update Language Component

TypeError: Cannot read properties of undefined (reading 'major')

  at Object.extractNativeRef (node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js:135:93)
  at _this._handleRef (node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js:508:52)
  at commitAttachRef (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11992:7)
  at commitLayoutEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14448:9)
  at Object.invokeGuardedCallbackProd (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11308:10)
  at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11499:31)
  at commitRootImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14172:9)
  at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:468:12)
  at runWithPriority (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2486:10)
  at commitRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14011:3)

Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 1.379 s, estimated 2 s
Ran all test suites.

Uncaught TypeError: Cannot read property of undefined (reading ‘green’)

const mainebutton = document.querySelector("button");
const body = document.body;

function randomcolorgenerator() {
  const red = Math.floor(Math.random() * 256);
  const green = Math.floor(Math.random() * 256);
  const blue = Math.floor(Math.random() * 256);
  console.log(red, green, blue);
  const randomcolor = "rgb ${red},${green},${blue}";
  return randomcolor;
}
mainebutton.addEventListener("click", () => {
  const randomcolor = randomcolorgenerator();
  console.log(randomcolor);
});

Uncaught TypeError: Cannot read property of undefined (reading ‘green’)

Transform complex object into key value

I have an array

const arr = [
  {
    "id": 1,
    "name": "Bitcoin",
    "symbol": "BTC",
    "slug": "bitcoin",
    "rank": 1,
    "is_active": 1,
    "first_historical_data": "2013-04-28T18:47:21.000Z",
    "last_historical_data": "2022-02-18T11:39:00.000Z",
    "platform": null
  },
  {
    "id": 2,
    "name": "Litecoin",
    "symbol": "LTC",
    "slug": "litecoin",
    "rank": 20,
    "is_active": 1,
    "first_historical_data": "2013-04-28T18:47:22.000Z",
    "last_historical_data": "2022-02-18T11:39:00.000Z",
    "platform": null
  }
]

And I want to transform the array to this

[{"BTC": "Bitcoin"}, {"LTC": "litecoin"}]

I tried this but no luck

const result = arr.reduce((r, c) => {Object.keys(c).map(x => {
     r.push({ [x.symbol]: x.name })})})

console.log(result)

React function expression ‘this’ undefined

Can someone briefly explain why this keyword is undefined in a function expression, but defined in an arrow function. I’m simply trying to follow the tutorial on the React website and they gloss over a seemingly important concept regarding confusing behavior of this but the link refers to a very in-depth article which is not at all friendly to beginners. After completing the tutorial I wanted to play around and try to understand what works and what doesn’t and I tried replacing an arrow function with a function expression, and suddenly the onClick event failed to work.

This is the code as written in the tutorial:

class Board extends React.Component {
    renderSquare(i) {
        return (
            <Square
                value={this.props.squares[i]}
                onClick={() => {
                    this.props.onClick(i);
                }} />
        );
    }
//other stuff
}

And I wanted to change the arrow function to a traditional function expression, but had some problems

class Board extends React.Component {
    renderSquare(i) {
        return (
            <Square
                value={this.props.squares[i]}
                onClick={function() {
                    console.log(this);          //undefined
                    console.log(this.props);    //throws exception
                    this.props.onClick(i);      //throws exception
                }} />
        );
    }
}

Why is this undefined in the function expression? When I read the documentation for arrow function and function expressions on MDN it seems that the opposite should be true. What’s going on here?

Here the codepen
Here’s the full project:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function Square(props) {
    return (
        <button className="square" onClick={props.onClick}>
            {props.value}
        </button>
    );
}

class Board extends React.Component {
    renderSquare(i) {
        return (
            <Square
                value={this.props.squares[i]}
                onClick={() => this.props.onClick(i) } />
        );
    }

    render() {
        return (
            <div>
                <div className="board-row">
                    {this.renderSquare(0)}
                    {this.renderSquare(1)}
                    {this.renderSquare(2)}
                </div>
                <div className="board-row">
                    {this.renderSquare(3)}
                    {this.renderSquare(4)}
                    {this.renderSquare(5)}
                </div>
                <div className="board-row">
                    {this.renderSquare(6)}
                    {this.renderSquare(7)}
                    {this.renderSquare(8)}
                </div>
            </div>
        );
    }
}

class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isX: true,
            history: [{
                squares: Array(9).fill(null)
            }],
            stepNumber: 0
        }
    }

    handleClick(i) {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = this.state.history[history.length - 1];
        const squares = current.squares.slice();
        if (squares[i] == null) {
            squares[i] = this.state.isX ? 'X' : 'O';
        } else {
            console.log("Square [" + i + "] is already marked!");
            return;
        }
        this.setState({
            history: history.concat([{squares: squares}]),
            isX: !this.state.isX,
            stepNumber: history.length
        });
    }

    jumpTo(step) {
        this.setState({
            stepNumber: step,
            xIsNext: (step % 2) === 0,
        });
    }

    render() {
        const history = this.state.history;
        const current = this.state.history[this.state.stepNumber];
        const winner = calculateWinner(current.squares);

        const moves = history.map((step, move) => {
            const desc = move ?
                'Go to move #' + move :
                'Go to game start';
            return (
                <li key={move}>
                    <button onClick={() => this.jumpTo(move)}>{desc}</button>
                </li>
            );
        });

        let status;
        if (winner) {
            status = 'Winner: ' + winner;
        } else {
            status = 'Next player: ' + (this.state.isX ? 'X' : 'O');
        }
        return (
            <div className="game">
                <div className="game-board">
                    <Board
                        squares={current.squares}
                        onClick={(i) => this.handleClick(i)}/>
                </div>
                <div className="game-info">
                    <div>{status}</div>
                    <ol>{moves}</ol>
                </div>
            </div>
        );
    }
}

function calculateWinner(squares) {
    const lines = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
            return squares[a];
        }
    }
    return null;
}

// ========================================

ReactDOM.render(
    <Game />,
    document.getElementById('root')
);

Firebase 9.6.6 JS from CDN errors out

I am trying to hook CDN based firebase libs for one of my project and as per the doc its doable
https://firebase.google.com/docs/web/alt-setup

But when i put below html/js code

<html>
<body>
  <script type="module">
    import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.6.6/firebase-app.js'
    // Add Firebase products that you want to use
    import { auth } from 'https://www.gstatic.com/firebasejs/9.6.6/firebase-auth.js'
    const firebaseConfig = {
        apiKey: "<>",
        authDomain: "<>.firebaseapp.com",
        projectId: "<>",
        storageBucket: "<>.appspot.com",
        messagingSenderId: "<>",
        appId: "<>",
        measurementId: "<>"
   };
    // Initialize Firebase
    const app = initializeApp(firebaseConfig);
  </script>
</body>
</html>

Its error out with below log (seen on console)

Uncaught SyntaxError: import not found: auth

I do not want to fallback to older version of firebase, so is there any solution someone can suggest?

JS define const with computed name inside loop

I am trying to create a couple of consts inside a loop, but stuck at concat the name string+key

for (const [key, value] of Object.entries(myObj)) {
  console.log("hello: ", `${key}: ${value}`); // works 

  const [`IMG-${key}`] = "hello"; // Parsing error: Unexpected token 
}

expected output: const [IMG0, IMG0Status] = useImage("0000.jpg");

thank you!

How to split an array into three arrays in a way they are divided as fairly as possible JavaScript

Here is my array:

const sorted = [
  { pwr: 10 },
  { pwr: 9 },
  { pwr: 9 },
  { pwr: 8 },
  { pwr: 6 },
  { pwr: 6 },
  { pwr: 2 },
  { pwr: 2 },
  { pwr: 1 },
];

What I want to do is dividing it to three separate arrays in a way the total value of pwr in each array be the closest value to the others arrays.

For example this is not fair division at all:

arr1: [ { pwr: 10 },
      { pwr: 9 },
      { pwr: 9 }]

arr2: [ { pwr: 8 },
      { pwr: 6 },
      { pwr: 6 }]

arr3: [ { pwr: 2 },
      { pwr: 2 },
      { pwr: 1 }]

Since the total value of arr1 is 10+9+9 = 28, while the arr2 is 20 and arr3 is just 5 !

The splitted array should be something like this:

arr1: [ { pwr: 10 },
      { pwr: 6 },
      { pwr: 1 }]

arr2: [ { pwr: 9 },
      { pwr: 6 },
      { pwr: 1 }]

arr3: [ { pwr: 9 },
      { pwr: 8 },
      { pwr: 2 }]



arr1 =17
arr2=16
arr3=19
which is somehow fair.

My suggestion is that picking from the first array (which is sorted by default) like this:

In the first stage, arr1 gets first element (index0) and arr2 gets second elemtns (index1), and arr3 gets 2 element (index 2 and index3):

arr1[{pwr: 10}]
arr2[{pwr: 9}]
arr3[{pwr:8},{pwr:6}]

Then, from now on each array gets just one element until the sorted element finishes. I mean we get back to arr1 and give it the next item (index4) then arr2 gets (index5) arr3 (index6) again arr1 (index7) and…

Do you guys have any idea to achieve the most fair arrays?
Could you guys provide me with snippets?

Property ‘this’ does not exist on type ‘{ type: string | null; location: string | null; }’. while Destructuring assignment

In my angular app, i have a function that basically returns an object.

private getTypeAndLocation() {
    const type = sessionStorage.getItem('type');
    const location = sessionStorage.getItem('location');
    return {type, location};
  }

Now I am calling this function from ngOnint like this:

({this.MyObjectVariable.type, this.MyObjectVariable.location} = this.getWorkClearanceTypeAndLocation());

But unfortunately its not working. I am getting this error:
Property 'this' does not exist on type '{ type: string | null; location: string | null; }'.

It could be possible that getTypeAndLocation will return undefined if the type and location are not set.

In that case, how can i do the object Destructuring?

Group data by multiply keys, sum and count for different keys in RamdaJS

I have an array of data that looks something like this

{
   "data":[
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q2",
         "sub3":"",
         "sub4":"",
         "cost":8531.94,
         "sms_count":3102,
         "payout":29750.0,
         "net_margin":21218.06
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"data_check",
         "sub4":"",
         "cost":5499.16,
         "sms_count":1999,
         "payout":12885.0,
         "net_margin":7385.84
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q1",
         "sub3":"vitrina",
         "sub4":"",
         "cost":8994.3,
         "sms_count":3270,
         "payout":12748.0,
         "net_margin":3753.7
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"webbdata_check",
         "sub4":"",
         "cost":4529.32,
         "sms_count":1647,
         "payout":14280.0,
         "net_margin":9750.68
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q3",
         "sub3":"",
         "sub4":"",
         "cost":8537.82,
         "sms_count":3104,
         "payout":7140.0,
         "net_margin":-1397.82
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q2",
         "sub3":"bounce",
         "sub4":"",
         "cost":2559.94,
         "sms_count":930,
         "payout":4707.0,
         "net_margin":2147.06
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"random",
         "sub4":"",
         "cost":8476.62,
         "sms_count":3082,
         "payout":50616.0,
         "net_margin":42139.38
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"mondata_check",
         "sub4":"",
         "cost":3745.6,
         "sms_count":1362,
         "payout":28000.0,
         "net_margin":24254.4
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q1",
         "sub3":"mondata_check",
         "sub4":"",
         "cost":3894.98,
         "sms_count":1416,
         "payout":4000.0,
         "net_margin":105.02
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"kadata_check",
         "sub4":"",
         "cost":3025.92,
         "sms_count":1100,
         "payout":0,
         "net_margin":-3025.92
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"ppp",
         "sub2":"",
         "sub3":"",
         "sub4":"",
         "cost":0,
         "sms_count":0,
         "payout":49400.0,
         "net_margin":49400.0
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"bot",
         "sub2":"offers_list",
         "sub3":"",
         "sub4":"",
         "cost":0,
         "sms_count":0,
         "payout":4000.0,
         "net_margin":4000.0
      },
      {
         "date":"2022-02-10",
         "date_ts":1644440400,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"bot",
         "sub3":"vitrina",
         "sub4":"",
         "cost":0,
         "sms_count":0,
         "payout":225.0,
         "net_margin":225.0
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"random",
         "sub4":"",
         "cost":7817.72,
         "sms_count":2842,
         "payout":37237.0,
         "net_margin":29419.28
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q1",
         "sub3":"mondata_check",
         "sub4":"",
         "cost":3735.98,
         "sms_count":1358,
         "payout":0,
         "net_margin":-3735.98
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q1",
         "sub3":"vitrina",
         "sub4":"",
         "cost":8381.16,
         "sms_count":3047,
         "payout":9120.0,
         "net_margin":738.84
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"webbdata_check",
         "sub4":"",
         "cost":4255.14,
         "sms_count":1547,
         "payout":14280.0,
         "net_margin":10024.86
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q2",
         "sub3":"",
         "sub4":"",
         "cost":7744.36,
         "sms_count":2816,
         "payout":19125.0,
         "net_margin":11380.64
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"mondata_check",
         "sub4":"",
         "cost":3349.56,
         "sms_count":1218,
         "payout":36000.0,
         "net_margin":32650.44
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"data_check",
         "sub4":"",
         "cost":5051.06,
         "sms_count":1836,
         "payout":15895.0,
         "net_margin":10843.94
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q3",
         "sub3":"",
         "sub4":"",
         "cost":7701.2,
         "sms_count":2800,
         "payout":7140.0,
         "net_margin":-561.2
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d0q1",
         "sub3":"kadata_check",
         "sub4":"",
         "cost":2885.4,
         "sms_count":1049,
         "payout":0,
         "net_margin":-2885.4
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"d1q2",
         "sub3":"bounce",
         "sub4":"",
         "cost":2123.72,
         "sms_count":772,
         "payout":8268.0,
         "net_margin":6144.28
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"ppp",
         "sub2":"",
         "sub3":"",
         "sub4":"",
         "cost":0,
         "sms_count":0,
         "payout":45600.0,
         "net_margin":45600.0
      },
      {
         "date":"2022-02-11",
         "date_ts":1644526800,
         "month":2,
         "week":6,
         "sub1":"sm",
         "sub2":"bot",
         "sub3":"vitrina",
         "sub4":"",
         "cost":0,
         "sms_count":0,
         "payout":3055.0,
         "net_margin":3055.0
      }
   ]
}

I want to group data by 2 (or more) parameters (in this case by sub1 and sub2) and calculate the sum for the fields payout and cost and get count for the field sms_count and output only these values within groups. For example…

{
   "sm":{
      "d0q3":[
         {
            "date":"2022-02-03",
            "cost":8230.84,
            "sms_count":2993,
            "payout":11900
         },
         {
            "date":"2022-02-03",
            "cost":8230.84,
            "sms_count":2993,
            "payout":11900
         }
      ],
      "d1q1":[
         {
            "date":"2022-02-03",
            "cost":4043.29,
            "sms_count":1470,
            "payout":0
         }
      ]
   }
}

I tried the following code, but it outputs all values and does not do counts

const groupAndSumMultipleParams = R.pipe(
        R.groupBy(R.prop('sub1')),
        R.map(R.groupBy(R.prop('sub2'))),
        R.values,
        R.map(R.reduce(
            R.mergeWith(R.ifElse(R.is(Number), R.add, R.identity)),
            {}
        ))
    )

Vue dispaly audio file fetched from Express backend: audio/mp3

express endpoint:

app.get('/test', (request, response) =>  {
    response.sendFile("/absolute/path/to/file/myfile.mp3");
});

Test.vue:

<template>
  <div>
    <p>test {{text}}</p>
    <audio controls="controls" src="./myfile.mp3">

    </audio>
  </div>

</template>

<script>

import axios from "axios";

export default {
  name: 'Test',

  data: function ()  {
    return  {
      text: 'hello',
      audio: ""
    }
  },

  created() {
    this.$watch(
        () => this.$route.params,
        () => {
          alert("fetching")
          this.fetchData()
        },
        
        { immediate: true }
    )
  },

  methods:  {
    fetchData()  {
      axios.get('http://localhost:3000/test',
          {
            params: {

            }
          })
          .then((response) => {
             alert("done")
             alert(JSON.stringify(response));

             const url = URL.createObjectURL(response);


             alert(url);
          });
    }
  }
}
</script>

When I load the Test.vue I get:

first alert:

enter image description here

second alert:

enter image description here

third alert:

enter image description here

and then the page appears:

enter image description here

I know I need to connect the received response from express to the <audio> element, but I’m not sure how. And I noticed that alert(url) is never displayed (no alert window appears).

Express is at localhost:3000 and Vue is at localhost:8080. When I go to http://localhost:3000/test, I get the page with the playable audio file:

enter image description here

CKEditor 5-insert html and move the caret outside it

i have a button outside ckeditor, when clicked i want to insert a span element at caret position, this is what i have so far:

var el = document.querySelector('#editor');

ClassicEditor.create(el, {
    licenseKey: ''
}).then( editor => {
    appConfigs.editor = editor; //storing the editor for later usage
}).catch( error => {
    //...
});

when the button is clicked i do:

function clickHandler(){
    var editor = appConfigs.editor;

    editor.model.change( writer => {
        var html = '<span class="special-class-name" data-name="something">special word or button</span>';
        var viewFragment = editor.data.processor.toView(html);
        var modelFragment = editor.data.toModel(viewFragment);

        var insertPosition = editor.model.document.selection.getFirstPosition();

        editor.model.insertContent(modelFragment, insertPosition);
    });
}

the code have the following issues:

1)the inserted span get stripped off all its attributes(class, data-name) which i want to preserve.

2)the editing caret doesn’t go back automatically to the editor when the button clicked.

3)when i click the editor to restore caret and start typing, i noticed it edits the text inside inserted span, i want inserted span to be untouched and any further typing goes after it.

i will be so grateful if anyone could help me with those issues.

Why 2 parameters in sort

More specifically, why the 2 parameters in the .sort() function and why does subtracting them
sort them?

const speciesArray = 
[ {speciesName:'shark', numTeeth:50}, 
{speciesName:'dog', numTeeth:42}, 
{speciesName:'alligator', numTeeth:80}, 
{speciesName:'human', numTeeth:32}];


const sortSpeciesByTeeth = arr => arr.sort(
 (a, b) => {return a.numTeeth - b.numTeeth}
)