How to listen for iframe creation before running javascript

I’m trying to wait for an iframe to be created before running some javascript, and i’ve tried a few methods but none seem to actually wait for the iframe – the error i’m getting in the console is Uncaught (in promise) TypeError: Cannot read properties of null (reading 'src').

The current code, below, tries to include the waitForElm function from this SO post, but ‘m still getting the same error.

I need a value from within the iframe, so I want to wait for the iframe to load and then get the src of the iframe and use fetch() to call, parse with DOMParser and then get the item barcode.

It’s for implementation of the Google Books Viewer API.

I also don’t have access to the main html for the page, or directly to the iframe – which is why, for example, the creation of a script tag for the google books api is via a function.

I’m quite new to javascript so apologies if there’s some basic errors going on here.

// creates a script tag to load google books api
(function(){
const gb = document.createElement('script');
gb.type = 'text/javascript';
gb.src = 'https://www.google.com/books/jsapi.js';
gb.addEventListener('load', () => google.books.load());
document.head.appendChild(gb);
})();

//function to wait for iframe to load
function waitForElm(selector) {
return new Promise(resolve => {
  if (document.querySelector(selector)) {
      return resolve(document.querySelector(selector));
  }
  const observer = new MutationObserver(mutations => {
      if (document.querySelector(selector)) {
          resolve(document.querySelector(selector));
      }
  });
  observer.observe(document.body, {
      childList: true,
      subtree: true
  });
});
}



app.controller('prmAlmaMashupAfterController', [function() {
this.$onInit = async function() {
  const frame = document.querySelector("#iFrameResizer0");
  fetch(frame.src)
    .then(res => res.text())
    .then(text => new DOMParser().parseFromString(text, 'text/html'))
    .then(document => {
      const bCode = document.getElementsByClassName('itemBarcode')[0].innerText || '';
      if (bCode) {
        const canvas = document.getElementById('viewerCanvas');
        const viewer = new google.books.DefaultViewer(canvas);
        viewer.load('NLS:' + bCode);
    console.log(bCode);
      } else {
        console.log('No barcode');
      }
    })
    .catch( e => {
      console.log('ERROR', e);
    });
}
}]);

//creates a div called viewerCanvas to hold the viewer
app.component('prmAlmaMashupAfter', {
bindings: { parentCtrl: '<' },
controller: 'prmAlmaMashupAfterController',
//  template: '<div id="viewerCanvas" style="height: 500px; width: 600px; border: 1px solid blue"></div>'
template: '<div id="viewerCanvas" style="height: 500px; width: 100%; margin: 1% auto !important;"></div>'
});

Filter if value inside array exists has key in object

array = ['data', 'category', 'hour'];

    object = {
        "status": {
            "type": "INFO",
            "messages": []
        },
        "data": {
            "id": 1,
            "tenant": "675832",
            "process": "6911d872-35f8-11ea-8697-001dd8b71c20",
            "category": "resquests"
"time": {
hour: "12",
minute: "30"
        }
    }

I need to check if object has keys with same value contained in array.

I tried split array by dot, and then filter both array and object but it fails.

const array = inputValue.split('.').map((item) => item);

How can I change the colors on this moving gradient canvas?

I was following Kevin Powells new video on recreating the stripe text effect. I was wondering if there was any way I can specifically change the colors of the gradient. I tried to play around with the numbers on the RGB Variables which sort of worked but I wanted to be more specific. Ideally I would like to blend two colors. e.g Blue + Orange. Is there any way I can do this? Here is the pen: Color Embraced

The code:

var c = document.getElementById('canv');
var $ = c.getContext('2d');


var col = function(x, y, r, g, b) {
  $.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
  $.fillRect(x, y, 1, 1);
}
var R = function(x, y, t) {
  return (Math.floor(192 + 64 * Math.cos((x * x - y * y) / 300 + t)));
}

var G = function(x, y, t) {
  return (Math.floor(192 + 64 * Math.sin((x * x * Math.cos(t / 4) + y * y * Math.sin(t / 3)) / 300)));
}

var B = function(x, y, t) {
  return (Math.floor(192 + 64 * Math.sin(5 * Math.sin(t / 9) + ((x - 100) * (x - 100) + (y - 100) * (y - 100)) / 1100)));
}

var t = 0;
var x;
var y;

var run = function() {
  for (x = 0; x <= 35; x++) {
    for (y = 0; y <= 35; y++) {
      col(x, y, R(x, y, t), G(x, y, t), B(x, y, t));
    }
  }
  t = t + 0.015;
  window.requestAnimationFrame(run);
}

run();
canvas {
  width: 100%;
  height: 100%;
}
<div class="canvas-container">
  <canvas id="canv" width="32" height="32">
</div>

Storing multiple select option values in localStorage using select id as key

Context

First off, I am not a developer but I have tried to explain the desired outcome…
I want to use Vanilla JS for this solution.

The problem

I have multiple select dropdowns on the page and ideally want to be able to store the value onchange of each of the dropdowns.

<select name="Value1A" id="Value1A" onchange="storeValue()">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>

<select name="Value1B" id="Value1B" onchange="storeValue()">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>

Essentially I want the code to look something like this…
Not actual working code but hopefully explains what I am trying to do

function storeValue(){
 localStorage.setItem(select.id, select.value);
}

i.e. I want to use the select id as the localStorage key – and onchange store the value of the option of that select field (onchange).

Any help would be really appreciated. Any questions or need to me to explain better, let me know.

How to change the active anchor when scrolling through a section

I have a 4 block right and left sidebar which is implemented with position: sticky with 4 anchors. When you click on the anchor – the page scrolls to this block. When you click on an anchor, it becomes active and a class is added to it. I need to keep track of the height of each block and change the active anchor when scrolling so that the class changes itself when I scroll through the section. How can i do this? An example of how this should work – http://netgain.outcrowd.io/successful-lease-accounting-transition/

<div class="items">
  <div class="anchors">
    <ul class="anchors-items">
      <li class="anchors-item  active-anchor ">
        <a href="#bloc-0">Bloc 1</a>
      </li>
      <li class="anchors-item ">
        <a href="#bloc-1">Bloc 2</a>
      </li>
      <li class="anchors-item ">
        <a href="#bloc-2">Bloc 3</a>
      </li>
      <li class="anchors-item ">
        <a href="#bloc-3">Bloc 4</a>
      </li>
    </ul>
  </div>
  <div class="blocs">
    <div class="first-bloc content-bloc">
      <div class="anchor" id="bloc-0"></div>
    </div>
    <div class="second-bloc content-bloc">
      <div class="anchor" id="bloc-1"></div>
    </div>
    <div class="third-bloc content-bloc">
      <div class="anchor" id="bloc-2"></div>
    </div>
    <div class="fourth-bloc  content-bloc">
      <div class="anchor" id="bloc-3"></div>
    </div>
  </div>

Sending custom header when fetching metadata for request of type ‘document’

The issue

I need to do an authenticated download using javascript and fetch api. However, there is an automatic call to the backend of type document (which is request to fetch metadata), which does not get the necessary access token from the custom header (XCompanyAccessToken) to actually create the file to be downloaded.


The code

I am currently using the following code I found online:

function download(fileUrl) {
  let fileName;
  fetch(fileUrl, , {
        method: 'GET',
        headers: {
          'XCompanyAccesstoken' = '<access-token>',
          /* more headers, obsolete here */
        },
        mode: 'cors',
    })
  // the whole then blocks here only handle gziped files, but I left it here for completeness
  .then(response => {
            const contentEncodingHeader = response.headers?.get('Content-Encoding');
            if (contentEncodingHeader === 'gzip') {
                // kudos: https://stackoverflow.com/questions/40939380/how-to-get-file-name-from-content-disposition
                // there is no "build-in" way of parsing this, unfortunately.
                const contenDispositionHeader = response.headers?.get('Content-Disposition');
                const fileNameSplit = contenDispositionHeader?.split('filename=')?.[1];
                // removes double quotes at the beginning and end
                fileName = JSON.parse(fileNameSplit ?? '""');
                return response.blob();
            }
            return null;
        })
        .then(blobby => {
            if (blobby) {
                const objectUrl = window.URL.createObjectURL(blobby);

                anchor.href = objectUrl;
                anchor.download = fileName;
                anchor.click();

                window.URL.revokeObjectURL(objectUrl);
            }
        })
}

And those headers are correctly set in the call to the backend of type fetch, but missing in the call to the backend of type document.

In order to make the download work, the response header has the following headers exposed:

access-control-expose-headers: Content-Disposition, Content-Encoding

and the values are set correctly:

content-disposition: attachment; filename="2022-10-12_13-12_download.csv"
content-type: text/csv; charset=UTF-8

(note: the content-encoding header is not set)

However, as stated earlier, there are three calls to the backend done.

  1. the preflight (which runs fine)
  2. the metadata call (which needs the token, but does not get it)
  3. the fetch (which has the token):


I tried

to google a dozen different ways, all asking how can i add a custom header to the fetching of metadata for downloads?, but could not find anything on that matter.

Other than that, I noticed, that cookies are send to the backend when fetching the metadata:

So I tried to add the access token to the cookies programmatically, but the cookie is ignored because the cookie header does not include the programmatically set cookie.


Finally, the question

Is there any way, that I can make this work?

Is there any way, that I can send the custom XCompanyAccessToken header to the backend when the browser decides to initiate a call of type document to retrieve metadata?

Are any changes on the backend side needed for this?

Can’t resize ChartJs when printing or in PDF

I have some troubles to have a correct size for my charts when I want to print them.
The charts are responsive in the page as it is supposed to be,
Responsive chart

but when I want to print or convert in PDF my charts the chart is out of the container depending on the size of the screen that was displaying the page.
Chart out of his container

I’m really stuck on this and I really don’t know how to fix this.

Here is how my chart is made:

function graph_config(data_gr, hours_gr, minval, maxval){
Chart.defaults.color = "black";

let data = {
    labels: hours_gr,
    datasets: [{
        backgroundColor: "black",
        borderColor: "black",
        borderWidth: 1,
        pointHoverBackgroundColor: "red",
        pointHoverBorderColor: "red",
        data: data_gr,
    }]
};

let horizontalLine = {
    id: 'horizontalLine',

    beforeDraw(chart, args, options) {
        const {ctx, chartArea: {top, right, bottom, left, width, height},scales:
            {x, y}} = chart;
        ctx.save();

        ctx.strokeStyle = 'green';
        ctx.setLineDash([5, 10]);
        ctx.strokeRect(left, y.getPixelForValue(minval), width, 0.3);
        ctx.textAlign = 'center';
        ctx.font = '12px Arial';
        ctx.fillStyle = 'green';
        ctx.textAlign = 'left';
        ctx.fillText('Min', x.right - 25, y.getPixelForValue(minval) - 5);
        ctx.strokeStyle = 'red';
        ctx.strokeRect(left, y.getPixelForValue(maxval), width, 0.3);
        ctx.textAlign = 'center';
        ctx.font = '12px Arial';
        ctx.fillStyle = 'red';
        ctx.textAlign = 'left';
        ctx.fillText('Max', x.right - 25, y.getPixelForValue(maxval) - 5);
        ctx.restore();
    }
};

let options_interval = getInterval();

let config = {
    borderWidth: 10,
    type: 'line',
    data: data,
    options: {
        scales: {
            x: {
                type: 'time',
                time: options_interval
            }
        },
        interaction:{
            intersect : false,
            mode:'index',
        },
        plugins: {
            legend: {
                display: false
            },
            horizontalLine: {
            },
        },
        elements: {
            point:{
                radius: 0
            }
        },
        responsive:true,
        maintainAspectRatio: false,
    },
    plugins: [horizontalLine]
};

return config

"<div class="card text-black card-container"> " +
                    "<span id='Title" + j +"' style="padding-bottom: 1em; font-weight: 800;"><i class="fas fa-spinner fa-spin"></i> Loading...</span>" +
                        "<div class='card-body'> " +
                            "<div id='canvas-wrap' style='height: 18rem'> " +
                            "<canvas id='myChart" + j +"'></canvas> " +
                        "</div> " +
                    "</div> " +
                "</div> " +

If you have some ideas about this please help me.
Thank you.

Angular Dynamic templates with different CSS, JS and JS files and jQuery versions

I am building an Angular application whereby users have the ability to select HTML(CSS, jQuery, JS) templates for their site. All templates are totally different from one another. For example, template one can have Bootstrap version 3 and jQuery verison 3. Template 2 can have Bootstrap version 5 and jQuery 2.

So far, I have this working by using lazy loaded routes and dynamically adding scripts to the files.
The issue with this is sometimes, the scripts do not load.
Is there something I’m doing wrong or is there a better way to handle such a problem?

applying map.fitbounds()

I’m making a map using openstreetmap I want to show the location of UK when the map loads at very first I’m giving a lat and lng to show the location right now but I want to use map.fitbounds() function to exactly fit the Uk location on map;

const myMap = L.map('map').setView([52.3555, 1.1743], 6);
//getting map tile from open source free openstreetmap tile provider
const tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
//setting attribution at bottom
const attribution =
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> ';
        //adding attribution layer to map
const tileLayer = L.tileLayer(tileUrl, { attribution });
tileLayer.addTo(myMap);

Please right a code to fit Uk location in map using fitbounds

How to calibrate length units for different display devices?

I need to be able to work with real length units for any display device and have to be able to rely on them. So I made myself a little ruler. On my laptop screen it comes out way too small. On my cellphone even smaller.

How can one calibrate this? I imagine the display device should have its physical dimension and then the resolution determines the distance of pixels. How can I do this?

        div {
          margin: 0 0 0 0;
          padding: 0 0 0 0;
        }
        div.ruler {
          counter-reset: major -1;
          width: 10cm;
            white-space: nowrap;
            font-size: 0;
        }
        div.number::after {
            content: counter(major);
          counter-increment: major;
          font-size: 3mm;
        }
        div.major {
          width: calc(1cm - 1px);
          height: 5mm;
          text-align: left;
          border-left: 1px solid black;
            display: inline-block;
            font-size: 0;
        }
        div.minor {
          width: calc(1mm - 1px);
          height: 1mm;
          border-right: 1px solid black;
            display: inline-block;
        }
        div.half {
          height: 2mm;
        }
<html>
    <head>
        <title>Screen Geometry and Gestures</title>
    </head>
    <body>
        <main>
            <h1>Screen Geometry and Gestures</h1>
            <section>
                <h2>Length Units</h2>
                <p>Let's make a ruler!</p>
                <div class="ruler">
                    <div class="major">
                        <div class="number"></div>
                        <div class="minor"></div>
                        <div class="minor"></div>
                        <div class="minor"></div>
                        <div class="minor"></div>               
                        <div class="minor half"></div>
                        <div class="minor"></div>
                        <div class="minor"></div>
                        <div class="minor"></div>               
                        <div class="minor"></div>               
                    </div>
                    <script type="text/javascript">
                        const self = document.currentScript;
                        const div = self.previousElementSibling;
                        for(let i = 0; i < 20; i++) {
                          const newdiv = div.cloneNode(true);
                          self.parentElement.insertBefore(newdiv, self);
                        }
                    </script>
                    <div class="major"></div>
                </div>
            </section>          
        </main>
    </body>
</html>

Query Params get removed from react route when click on button

I am facing an issue in react js, there is route to page e.g https://localhost:3000/profile?abc=123, the url is browsed successfully but the issue is when I click on button (I call api on click of this button using axios) in my website then the query params in the url gets removed automatically like this,
https://localhost:3000/profile. I have debugged, the params are removed when axios call is initiated. Any help would be highly appreciated.

How to send server sent events on database update

I want to send SSE event only when there is a DB update API called.
How do I achieve this? What is the standard market practise to achieve this?

my SSE endpoint looks like this

app.get('/send-events', (req, res) => {
    const headers = {
        Connection: "keep-alive",
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
    };
    res.writeHead(200, headers);

    const data = `data: ${new Date()}nn`;

    res.write(data);
});

i want to trigger the above api when another api is being called. Eg below

app.post('/update-db', (req, res) => {
    res.send('db-updated');

    //perform db update
    //send the latest data thru sse endpoint
});