Using Google App script library in Google spreadsheet add-on

I have a Google Spread sheet add-on, Formula Tracer Sidebar. I also have App Script library, I want to use some of its functionality within the add-on server code. Library is deployed and shared to anyone with link

enter image description here

addon loads the library with the following self executing function:

const _ftUtils = (function(){
   return FTCommon.getUtils();
})();

where:

FTCommon is the library identifier in the appscript.json as the below partial appscript.json shows.

"dependencies": {
    "libraries": [
      {
        "userSymbol": "FTCommon",
        "libraryId": "1APwfEOzs5n55tSXp2xvrQRqd_YK4pUInssQQH3epxnQWp4DVQ5gmWhlR",
        "version": "5"
      }
    ]
  },

However, when launching the add-on all users but me (library owner), fail with the following library missing error message.

enter image description here

Why is it happening and how to fix?

how to alter reduce function so it produce different result

I have this array:

data: [
  '+section1+',
  'big text 1 here.',
  'big text 2 here followed by list:',
  '-this is list item;',
  '-this is another list item;',
  '+section2+',
  'big text 3 here followed by list:',
  '-this is list item;',
  '-this is another list item;',
  '-this is another list item;',
  '+section3+', 
  'big text 4 here.'
],

I want to transform that array into

"data": [
   {
    section: "section1",
    content: [
    {
      "text": "big text 1 here.",
      "list": []
    },
    }
    {
      "text": "big text 2 here followed by list:",
      "list": [
        "-this is list item;",
        "-this is another list item;"
      ]
    },
    ]
   }
   {
    section: "section2"
    content:[
    {
      "text": "big text 3 here followed by list:",
      "list": [
        "-this is list item;",
        "-this is another list item;",
        "-this is another list item;"
      ]
    },
    ]
   }
   {
   section: "section3",
   content: [
    {
      "text": "big text 4 here.",
      "list": []
    }
    ]
   }
  ]

I have this code that doing about that:

interface DataItem {
    text: string
    list: string[]
}

function isListItem(item: string): boolean {
    return item.startsWith('-') && item.endsWith(';')
}

const transformedData = data.reduce<DataItem[]>((acc, item) => {
    // if item is list item
    if (isListItem(item)) {
        // get last DataItem from acc
        const lastDataItem = acc[acc.length - 1]

        // and use it as list item's parent
        if (lastDataItem) {
            lastDataItem.list.push(item)
        } else {
            console.error(`Parent text not found for list item ${item}`)
        }

        return acc
    }

    // if item is not list item, use it as new parent/DataItem
    const dataItem: DataItem = {
        text: item,
        list: []
    }

    return [...acc, dataItem]
}, [])

What it missing is ignoring the sections. Any ideas how to modify that reduce function so it will produce expected result?

To determine a section I came up with this funciton:

function isSection(item: string): boolean {
    return item.startsWith('+') && item.endsWith('+')
}

Unable to edit input text inside a modal when using introjs

I have a bootstrap modal that includes input text. I’ve added the input text to introJs steps to highlight it and for the user to be able to input their name etc. But once the input text was highlighted, I’m not able to change its values. Maybe because they are the same modal? Its working if the input text is not on a popup modal.

Here are some sample script.

<div class="modal fade" tabindex="-1" role="dialog" id="addModal">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title">Modal Title</h4>
      </div>

      <form role="form" action="#" method="post" id="createForm">
        <div class="modal-body">
          <div class="form-group">
            <label for="brand_name">Name</label>
            <input type="text" class="form-control" data-step='add_name' id="name" placeholder="Enter Name">
          </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
              <button type="submit" class="btn btn-primary">Save changes</button>
            </div>
          </div>
        </div>
      </form>
    </div>
  </div>
</div>





const intro = introJs();

intro.setOptions({
  doneLabel: 'Next',
  exitOnOverlayClick: false,
  steps: [
    {
      intro: 'Enter you name',
      element: '#name',
    }
  ]
})
if (RegExp('multipage', 'gi').test(window.location.search)) {

  intro.start().onchange(function(targetElement) {
    if ($(targetElement).attr("data-step") == 'add_name') {
      $("#addModal").modal('show');
    }
  }));
}

Socket IO: New Connection breaks room connection

I have an application with an object that can be moved on an X-Y-Z axis. A user can use a button to retrieve the socket ID and send it to a friend. When you start the application and set the room parameter, you are added to the user’s group.

My problem now is:
As soon as a new user opens the application (with and without parameter in url), then the connection does not work in the group anymore..
When I log all groups to the console, then I can see that these 2 socket.id’s are still in the same group, but its not working anymore.

Client.js

// client
var socket = io();
// object which holds position data
var obj = app.scene.getObjectByName('persp1');
// on connection receive socket.id
socket.on("connect", () => {
  $('#inviteURL').html(socket.id);
});

// detect if client joined a session, cannot detect if host
if (!hasQueryParams(window.location.href)) {
  document.getElementById("buttonInvite").style.display = "block";
} else {
  document.getElementById("buttonLeave").style.display = "block";
}

function hasQueryParams(url) {
  return url.includes('?');
}
// when receiving data from server update objects position
socket.on('newPos', function (pos) {
  obj.position.x = pos.x;
  obj.position.y = pos.y;
  obj.position.z = pos.z;
});
// current position of object
var x = obj.position.x;
var y = obj.position.y;
var z = obj.position.z;
var oldPos;
// check if position has changed, if yes then send event to server with new position in 60fps
setInterval(function () {
  if (typeof oldPos !== "undefined" && (x !== obj.position.x || y !== obj.position.y || z !== obj.position.z)) {
    socket.emit('movement', {
      x: obj.position.x,
      y: obj.position.y,
      z: obj.position.z
    });
  }
  oldPos = obj.position.x;
  x = obj.position.x;
  y = obj.position.y;
  z = obj.position.z;
}, 1000 / 60);

Server.js

//server
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);

const {Server} = require("socket.io");
const io = new Server(server);
const url = require('url');
// use public folder
app.use(express.static(__dirname + '/public'));
//variable which will hold get-url-parameter with roomID
var room;
// send users to index.html
app.get('/', (req, res) => {
  //get url parameter room
  room = req.query.room;
  res.sendFile(__dirname + '/roman_websockets.html');
});
// on connection
io.on('connection', (socket) => {
  // if theres a get-url parameter then join the room
  if (typeof room !== "undefined") {
    socket.join(room);
  }
  // show rooms all 5 seconds
  setInterval(function () {
    console.log('rooms');
    console.log(io.sockets.adapter.rooms);
  }, 5000);

  // when receiving new client-data from event movement, send client-data to all clients in group including sender
  socket.on('movement', function (movementData) {
    io.in(room).emit('newPos', movementData);
  });
  // on disconnect
  socket.on('disconnect', () => {
    socket.disconnect();
    socket.removeAllListeners();
    console.log('user disconnected');
  });
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

Request intermittently not including ‘access-control-allow-origin’ header in response

I am running a HTTP lambda through serverless – I have set up cors using serverless.

For the majority of users – there’s no issue.

For a very small percentage of users – the request following the OPTIONS call is not returning access-control-allow-origin.

It has a successful preflight, that returns access-control-allow-origin – but the POST request following doesn’t return access-control-allow-origin – causing a CORS error.

For the users it doesn’t work for – no matter if they change computer or network – it still happens – and it’s always the same users.

What can affect returning an access-control-allow-origin? I’ve looked through the HAR files and for the 98% of users it works for and the 2% it doesn’t – the requests and responses look the same apart from access-control-allow-origin missing in the preceding POST

iteriate(move) the elements in the array to left

lets say arrayA=[ 1,2,3,4,5]
after moving to the left it should be arrayA = [5,4,3,2,1] and then after another iteration [3,4,5,1,2]

fucntion move left(array1,the amount of itteriations{
}
i tried for(int i = myarr.length-1;i<=0;i--) if(myarray[i] < *the amount of itteriations*) return i; }return -1;

JavaScript for loop string to array

It just all of a suddenly crossed my mind we all know using regular for loop and push() method to convert string characters into an array

let myStr = "Perseverance";
let emptyArr = [];

for (let i = 0; i < myStr.length; i++) {
    emptyArr.push(myStr[i]);
}
console.log(emptyArr); 

then I decided to convert a whole string into a single element of an array just using push()…worked

let myStr = "Perseverance powers";
let emptyArr = [];

for (let i = 0; i < myStr.split().length; i++) {
  emptyArr.push(myStr);
}
console.log(emptyArr);

Now here when I want to separate each word into a single element of an array just using push() I can’t…
I wanted to accomplish it using only push()

P.S. A lot ways exist yet it was just a thought came to my mind ‘what if’
Thanks

Displaying mark up/malicious code strings as literal strings

I have a page containing a table to which values can be added via a textbox in a modal popup and the values will appear in the table on the page.
It is being tested by adding the string ); to the textbox and it fails because this string will initiate a popup. So I need to allow this code to be added and appear innocuously in its original format on the page without initiating a popup etc.
I’ve tried HTMLDecode(‘user added string’) but this just cleanses the string and returns );
Is there a way to do this?

How can I turn the data that is a image came from API to url to use in img tag in react Js

I have uploaded an image. Now, I have a download API that gives me this image as a data. The response looks like this:

enter image description here
enter image description here

the header of the response is like this:

enter image description here

Now the problem is that I want to show this image on the web page using img tag or anything else possible in react js. Passing the content to src attr shows nothing.
Does anyone have any ideas? Is there any possible way?

Onload event fulfills the promise, but image not completely loaded when required

This issue concerns my preloader of sprite sheets, which are split in a separate images then rotated to create required assets for the game I am writing.
This function parses an array of sheets, then for each sheet, after is loaded, splits sequence to sprite instances, then perform required rotations:

function loadRotatedSheetSequences(arrPath = LoadRotatedSheetSequences) {
    console.log(`%c ...loading ${arrPath.length} rotated sheet sequences`, ENGINE.CSS);
    var toLoad = [];
    arrPath.forEach(function (el) {
      ASSET[el.name] = new LiveSPRITE("1D", []);
      toLoad.push({ srcName: el.srcName, name: el.name, count: el.count, rotate: el.rotate });
    });
    ENGINE.LOAD.HMRotSeq = toLoad.length;
    if (ENGINE.LOAD.HMRotSeq) appendCanvas("RotSeq");
    const temp = Promise.all(
      toLoad.map((img) => loadImage(img, "RotSeq"))
    ).then(function (obj) {
      obj.forEach(function (el) {
        ENGINE.seqToSprite(el);
        ENGINE.rotateAsset(el.name, el.rotate.first, el.rotate.last, el.rotate.step);
      });
    });
    return temp;
  }

The function works perfectly fine if rotations are not required or if the source is a single sprite. Function loadImage is defined as (some irrelevant parts are excluded for simplification):

function loadImage(srcData, counter, dir = ENGINE.SOURCE) {
    //setting properties
    return new Promise((resolve, reject) => {
      const img = new Image();
      var obj = {
        img: img,
        name: name,
        count: count,
        tag: tag,
        parent: parent,
        rotate: rotate,
        asset: asset
      };
      img.onload = function () {
        console.log("loaded img", img);
        ENGINE.LOAD[counter]++;
        ENGINE.drawLoadingGraph(counter);
        resolve(obj);
      };
      img.onerror = (err) => reject(err);
      img.crossOrigin = "Anonymous";
      img.src = src;
    });
  }

And finally, the method responsible for rotation:

    rotateAsset(assetName, startAngle, endAngle, step = 1) {
    let sprites = ASSET[assetName].linear;
    for (let i = 0; i < sprites.length; i++) {
      console.log(".sprite", sprites[i].complete);
      for (let angle = startAngle; angle <= endAngle; angle += step) {
        let name = `${assetName}_${i.toString().padStart(2, "0")}_${angle}`;
        ENGINE.rotateImage(sprites[i], angle, name);
      }
    }
  },

Console states that sprites[i].complete is false at execution time, but it is complete after checking with debugger. So the root cause IMO is that the image is not completely loaded when onload triggers, and this does not prevent cutting sequence to sprites, but stops rotation, since within the rotation I ‘trim away’ blank pixels, but since image loading is not complete, they are all blank.
I tried to substitute img.onload with img.onloadend, but the latter is never triggered.
Currently, if I encounter that function wants to trim an empty image, I perform location.reload(), then in the next attempt the image is in the cache and everything works fine. Of course, this is only a provisional solution.

Is there an elegant way to assure that an image is completely loaded before fulfilling the promise, or using some other event handler?