Implementing a gradient background in in the latest chart.js?

This question has an implementation and I’m trying to transfer it to this demo using the latest version of chart.js, however the gradient settings are not taking effect.

Any ideas?

This is the entire implementation:

const canvas = document.getElementById('chart') as HTMLCanvasElement;
const ctx = canvas.getContext('2d');
var gradient = ctx.createLinearGradient(0, 0, 0, 400);
gradient.addColorStop(0, 'rgba(250,174,50,1)');
gradient.addColorStop(1, 'rgba(250,174,50,0)');

const config: ChartConfiguration = {
  type: 'line',
  options: {
    responsive: true,
    datasetStrokeWidth: 10,
    pointDotStrokeWidth: 14,
    tooltipFillColor: 'rgba(0,0,0,0.8)',
    tooltipFontStyle: 'bold',
    tooltipTemplate:
      "<%if (label){%><%=label + ' hod' %>: <%}%><%= value + '°C' %>",
    scaleLabel: "<%= Number(value).toFixed(0).replace('.', ',') + '°C'%>",
    scales: {
      y: {
        beginAtZero: true,
      },
    },
  },
  data: {
    labels: [
      '02:00',
      '04:00',
      '06:00',
      '08:00',
      '10:00',
      '12:00',
      '14:00',
      '16:00',
      '18:00',
      '20:00',
      '22:00',
      '00:00',
    ],
    datasets: [
      {
        lineTension: 0.4,
        strokeColor: '#ff6c23',
        pointColor: '#fff',
        fillColor: gradient, // Put the gradient here as
        pointStrokeColor: '#ff6c23',
        pointHighlightFill: '#fff',
        pointHighlightStroke: '#ff6c23',
        label: '# of Votes',
        data: [
          25.0, 32.4, 22.2, 39.4, 34.2, 22.0, 23.2, 24.1, 20.0, 18.4, 19.1,
          17.4,
        ],
        borderWidth: 1,
      },
    ],
  },
};

new Chart(ctx, config);

promise problems in javascript and msal.js in getting querry information asynchronously [duplicate]

first of all, I apologize if I make a mistake, I am learning to use msal.js and I am in a dilemma regarding the acquisition of information with the querry, I attach my source code.

const Test009 = async function () {
  tok = null;
  arr = ["aa", "bb", "cc"];
  try {
    getTokenPopup(loginRequest)
      .then((response) => {
        tok = response.accessToken;
        t = Function01(response.accessToken).then(function teste(val) {
          console.log("the val 1 is:" + val + " ");
          arr[0] = val;
        });
      })
      .then((response) => {
        t = VerificacionMe(tok, tok).then(function teste(val) {
          console.log("the val 2 is:" + val + " ");
          arr[1] = val;
        });
      })
      .then((response) => {
        t = VerificacionMe(tok, tok).then(function teste(val) {
          console.log("the val 3 is:" + val + " ");
          arr[2] = val;
        });
      })
      .then(function teste3(val) {
        console.log(arr);
        console.log(arr[0]);
        console.log(arr[1]);
        console.log(arr[2]);

        setTimeout(function () {
          console.log(arr);
          console.log(arr[0]);
          console.log(arr[1]);
          console.log(arr[2]);
        }, 100);
      });
  } catch (error) {
    console.error(`Error: ${error}`);
  }
};

async function Function01(token) {
  const res = await fetch("https://graph.microsoft.com/v1.0/me/department", {
    method: "GET",
    headers: {
      Authorization: token,
      "Content-Type": "application/json",
    },
  });
  const data = await res.json();
  return data.value;
}

async function VerificacionMe(array, token) {
  const respuesta = await fetch("https://graph.microsoft.com/v1.0/me/", {
    method: "GET",
    headers: {
      Authorization: token,
      "Content-Type": "application/json",
    },
  });
  const data = await respuesta.json();
  return data;
}

the result I get is:

aa
bb
cc

the val 2 is:[object Object] 
the val 1 is : "Departament"
the val 3 is:[object Object] 

----------------------------
[object object] is 

@odata.context
: 
"https://graph.microsoft.com/v1.0/$metadata#users/$entity"
businessPhones
: 
['+52 (55) 5555-5555']
displayName
: 
"Name LastName"
givenName
: 
"Name"
id
: 
"1111111-2222-3333-4444-555555555555"
jobTitle
: 
"Job"
mail
: 
"[email protected]"
mobilePhone
: 
null
officeLocation
: 
"Hell"
preferredLanguage
: 
null
surname
: 
"LastName"
userPrincipalName
: 
"[email protected]"

As you can see, they are nested “then”, with double console.log -the first block is executed immediately, with the default values- and the second block is executed after 100 milliseconds -with the values that I really need-.

The idea is to: execute function by function – in the example “Function01”, “VerificacionMe” and “VerificacionMe” in order, save the results in an array and at the end print the information of this array, which I still can’t get and that’s why I ask for help for this case.

What does Webpack “output.asyncChunks” option do?

According to Webpack there’s a property on the output object in their configuration settings.
https://webpack.js.org/configuration/output/#outputasyncchunks

I am struggling to understand what exactly this will do and when/why it should be set to a certain value (true/false).

I can’t seem to find any explanations online either, other than another SO post linking to another article which is about a different property (see: What is an async chunk in webpack?).

So is there anyone that can help me out and explain to me in simple terms when and why to use asyncChunks and what it will do?

Keyframe animations with Intersection Observer run unexpectedly when clicking on child elements with onClick

I want css keyframe animations to run 1 time when the bridge element is in the viewport. Intersect observer does this well, but the issue is the animations fire randomly when clicking on other parts of the element that have onClicks to show new text paragraphs.

The point was to call attention to the user that hey! you can click on these parts of the bridge element by showing a delayed box shadow when main element is in view. Maybe there is a better way to show users that an area is clickable, maybe there is a JS rule I am overlooking? Any suggestions appreciated – Thank you!

Example:
https://codepen.io/robyngraha/pen/LYaZMVg

HTML

<div class="scroll-container">
<!-- For Spacing -->
   <h1>Scroll down....<br />Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus architecto voluptatem numquam, nihil ullam suscipit, odit placeat labore natus maxime laborum aliquam voluptates animi, dicta facere debitis earum beatae nemo. Lorem ipsum dolor sit amet consectetur adipisicing elit. Rem totam aut fugiat nostrum animi, sed illum ad minima sint sequi nemo, labore, suscipit et reiciendis fuga corrupti! Provident, tempore ab. Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis enim ad quos incidunt culpa necessitatibus eveniet aut earum quia, est iste debitis eos quidem facilis facere? Velit temporibus esse adipisci?</h1>

    <div class="bridge-container bridge">
      <div id="first-brother" class="bridge-green" onclick="firstBro()" ></div>
      <div id="second-brother"  onclick="secondBro()"></div>
      <div id="third-brother" onclick="thirdBro()"></div>
      <div id="rmg">HELLO</div>
    </div>
    
    <div id="first-bro-text">
      <p style="color:#225BBE;font-weight:900;">First Brother</p>
      <p>So, the oldest brother, who was a combative man, asked for a wand more powerful than any in existence.
        A wand that must always win battles for its owner. A wand worthy of a wizard who had conquered Death.
        So, Death had crossed to an Elder Tree on the banks of the river, fashioned a wand from a branch that had hung there, and gave it to the oldest brother</p>
      </div>     
      <div id="second-bro-text">
      <p style="color:#225BBE;font-weight:900;">Second Brother</p>
      <p>Then the second brother, who was an arrogant man, decided that he wanted to humiliate Death still further, and asked for the power to recall others from Death. So, Death picked up a stone from the riverbank and gave it to the second brother, and told him that the stone would have the power to bring back the dead.</p>
      </div>
      <div id="third-bro-text">
      <p style="color:#225BBE;font-weight:900;">Third Brother</p>
      <p>Finally, Death turned to the third brother. A humble man, he asked for something that would enable him to go forth from that place without being followed by Death. And so it was that Death reluctantly handed over his own Cloak of Invisibility. </p>
      </div>
  
  <div id="click-me">Click Me</div>
   <!-- For Spacing -->
    <h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus architecto voluptatem numquam, nihil ullam suscipit, odit placeat labore natus maxime laborum aliquam voluptates animi, dicta facere debitis earum beatae nemo. Lorem ipsum dolor sit amet consectetur adipisicing elit. Rem totam aut fugiat nostrum animi, sed illum ad minima sint sequi nemo, labore, suscipit et reiciendis fuga corrupti! Provident, tempore ab. Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis enim ad quos incidunt culpa necessitatibus eveniet aut earum quia, est iste debitis eos quidem facilis facere? Velit temporibus esse adipisci?</h1>

</div>

CSS

.scroll-container {
  max-width: 480px;
}
/* Bridge CSS */
.bridge-container {
    height:65px;
    color:white;
    border-radius: 8px;
    display: flex;
    gap: 2px;
    justify-content: space-between;
    font-size: 1.3rem;
    background: black;
    cursor: pointer;
    background: linear-gradient(180deg, #28411F 20.31%, #000 100%);
}
/* center div */
#second-brother {
  font-size: 1.8rem;
  width: 80%;
  margin: 0 auto;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: black solid 2px;
  border-right: black solid 2px;
}

.animation {
  animation-name: highlight;
  animation-duration: 1s;
  animation-iteration-count: 1;
}

@keyframes highlight {
  0% {box-shadow: none;}
  50% {  box-shadow: 0 0px 10px 10px orange;}
  100% {box-shadow: none;}
}
/* center changing text  */
#second-brother::after {
  content: "2nd";
  position: relative;
}

/* outer left div */
#first-brother {
    border-radius:  8px 0px 0px 8px;
    width: 20%;
    height: 65px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 20px;
    font-size: 1.5rem;
}
/* outer left div text */
#first-brother::after {
  content: "1st";
  position: relative;
}
/* outer right div */
#third-brother {
    border-radius: 0px 8px 8px 0px;
    width: 20%;
    height: 65px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 20px;
    font-size: 1.5rem;
}

.animation2 {
  animation-name: highlight2;
  animation-delay: .5s;
  animation-duration: 1s;
  animation-iteration-count: 1;
}
@keyframes highlight2 {
  0% {box-shadow: none;}
  50% {  box-shadow: 0 0px 10px 10px orange;}
  100% {box-shadow: none;}
}
/* outer right div text */
#third-brother::after {
  content: "3rd";
  position: relative;
}

@media (max-width: 625px) {
    #first-brother-left::after {
        margin-left: 12px;
}
}

@media (max-width: 480px) {
    #countdown-right, #countdown-left, #center-battery {
    font-size: 1rem;
}
}

/* Brothers text */
@keyframes fadeIn {
  0% { opacity: 0; }
  100% { opacity: 1; }
}
#first-bro-text {
    display: block;
    animation: fadeIn .5s;
}
#second-bro-text {
    display: none;
    animation: fadeIn .5s;
}
#third-bro-text {
    display: none;
    animation: fadeIn .5s;
}

.bridge-green {
background: linear-gradient(180deg, #4A7938 20.31%, #000 100%);
animation: fadeIn 1s;
}
#click-me {
  box-shadow: red;
}

JS


function firstBro() {
  document.getElementById("first-bro-text").style.display = "block";
    document.getElementById("second-bro-text").style.display="none";
    document.getElementById("third-bro-text").style.display = "none";
    document.getElementById("first-brother").classList.add("bridge-green");
    document.getElementById("second-brother").classList.remove("bridge-green");
    document.getElementById("third-brother").classList.remove("bridge-green");
  }

  function secondBro() {
    document.getElementById("first-bro-text").style.display = "none";
    document.getElementById("second-bro-text").style.display="block";
    document.getElementById("third-bro-text").style.display = "none";
    document.getElementById("first-brother").classList.remove("bridge-green");
    document.getElementById("second-brother").classList.add("bridge-green");
    document.getElementById("third-brother").classList.remove("bridge-green");
  }

  function thirdBro() {
    document.getElementById("first-bro-text").style.display = "none";
    document.getElementById("second-bro-text").style.display="none";
    document.getElementById("third-bro-text").style.display = "block";
    document.getElementById("first-brother").classList.remove("bridge-green");
    document.getElementById("second-brother").classList.remove("bridge-green");
    document.getElementById("third-brother").classList.add("bridge-green");
  }

//battery animatiom
const bridge = document.querySelector('.bridge');
const secondBroEl = document.querySelector('#second-brother');
const thirdBroEl = document.querySelector('#third-brother');
const observer = new IntersectionObserver(entries => {
  secondBroEl.classList.toggle('animation', entries[0].isIntersecting);
  thirdBroEl.classList.toggle('animation2', entries[0].isIntersecting);
  console.log(entries)
});

observer.observe(bridge);

  

I tried setting the animation-iteration-count to 1 in CSS but the animation starts over whenever clicking on 1st, 2nd or 3rd elements that have onClick functions.

I added an onClick function outside of the intersect observation element and the animations do not run, so it must be related to the element with the intersection observer.

I added an element with in the intersection observer without an onclick (Hello text) and the animations do not fire so the issue must be related to elements with an onclick.

Convert Windows HICON to raw data for display in html frontend: tauri, rust, js

I am making a window-switcher in tauri using rust and solidjs.
I am new to rust and I’d like to learn it since it seems so useful

I am using winapi to interact with Windows.

For now i have:

  1. HashMap of <window_title (string), HWND >
  2. I send the window titles to the frontend
  3. When clicked, it correctly switches the windows.

I want to display the app icon beside its title, so it can be more recognizable.

This is my method:

unsafe extern "system" fn enum_windows_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
    let title_length = GetWindowTextLengthW(hwnd);
    if title_length > 0 {
        let mut buffer: Vec<u16> = vec![0; (title_length + 1) as usize]; // +1 for null terminator
        GetWindowTextW(hwnd, buffer.as_mut_ptr(), buffer.len() as i32);

        if IsWindowVisible(hwnd) != 0 {
            let window_title = OsString::from_wide(&buffer).to_string_lossy().to_string();
            let title_map = &mut *(lparam as *mut HashMap<String, (HWND, HICON)>);
            let app_icon = get_app_icon(hwnd);

            if app_icon.is_some() {
                title_map.insert(window_title, (hwnd, app_icon.unwrap()));
            }
        }
    }

    1
}

fn get_app_icon(hwnd: HWND) -> Option<HICON> {
    let icon_handle: usize = unsafe { GetClassLongPtrW(hwnd, GCLP_HICON as i32) };
    if icon_handle == 0 {
        None
    } else {
        Some(icon_handle as HICON)
    }
}

I modified it to have the icon beside the window handle

How can i do? I really don’t have any clue. Any help is very much appreciated.
Is my method for retrieving the HICON correct? How can I log it? I tried to print the icon_handle but it shows nothing. But when I try to log any string in its place it logs correctly.

React Router v6.4+ Data API: Retry loader without displaying error

Using react-router 6.21.1 and the new data api, I have routes setup like:

const routes = [
    {
        element: <RootWrapper/>,
        errorElement: <ErrorWrapper/>,
        children: [
            {path: "/login?", element: <LoginWrapper/>},
            {path: "/logout", element: <Logout/>},
            {
                id: "AuthenticatedRoot",
                element: <AuthenticatedRoot/>,
                children: [
                    // ...
                    {path: "/dashboard", element: <Dashboard/>, loader: fetchDashboard},
                ]
            }
        ]
]

My dashboard view is on display 24/7 and revalidates every 5 minutes. It needs to stay up through up to 5 errors to give at least 30 minutes for releases or other unknown downtimes. It was simple to do when doing manual useEffects for data fetching because I could just handle the error that returned from the fetch request:

await axios.get('dashboard')
    .then(
        response => {setData(response.data)},
        error => {
            setRetries(origRetries => {
                if (origRetries >= 6) {
                    setError(true)
                    setErrorMessage(error.message)
                    return 0
                } else {
                    return origRetries + 1
                }
            })
        }
    )

Is there anyway to do something like this with the new loaders?

jquery dialog won’t open on one page but works on others?

I have a web page for downloading data. A jquery dialog is supposed to open when the ‘download full dataset’ button is clicked. It works on some pages and not on others and I can’t figure out why!

this page is working (click Download Options -> Download Full Dataset, and the dialog opens) : https://www.uvm.edu/femc/data/archive/project/ambient-air-monitoring-for-ozone/dataset/ny-ozone/data

This page is not working: https://www.uvm.edu/femc/data/archive/project/indicators_dashboard/dataset/tblindicators/data

It’s the same code, so I can’t figure out why it isn’t working on the second page! I don’t see anything in the console or network tab causing an issue. Any help is appreciated!

html:

<div id="explorer-download-options" style="display:none;">
    <small><button type="button" id='explorer-download-all' class="btn btn-primary data-download-button downloadButton data-archive-button">Download Full Dataset</button></small>
    <small><button type="button" id='explorer-download-preview' class="btn btn-primary data-download-button downloadButton data-archive-button">Download Data Subset</button></small>
    <div id="explorer-current-filter"><h4>Current Filters</h4><small>Here's were some plain-english filter text would go</small></div>
    <div class="cf"></div>
</div>

javascript

$('.downloadButton').click(function(){
   ($(this).hasClass('downloadVersionButton')) ? $('#downloadForm').attr('downloadVersion', true) : $('#downloadForm').attr('downloadVersion', false);
    $('#downloadForm').dialog("open");
    if ($(this).attr('id')=='explorer-download-preview'){
       $('#filtered').val(1)//Set flag indicating filtered query
         }
    else{
       $('#filtered').val(0)//Set flag indicating not a filtered query
         }
});

We are on very old versions of jquery and jquery-ui but are in the middle of upgrading on our development servers. However, both pages are using the same versions and one works, so I don’t think that’s the problem…

Let me know if you have any other questions that would help troubleshoot. Thanks!

Sorting Messages loaded locally and using Ajax

I’m running into a problem sorting what I refer to as “messages”; some of which are in the HTML doc and some others using Ajax. It doesn’t always sort the messages (by date) and if refreshing the page, it doesn’t sort at all and displays in the order they were loaded. Any assistance is greatly appreciated. I’m by no means very experienced with Javascript. I’ll happily provide more information if required.

HTML and Javascript:

 <section id="all messages">
    <!-- Local messages go here -->
    <div id="local-messages">
        <!-- Example of a local message with a date data attribute -->      
        <div class="message" data-date="2023-11-17">
            <div class="panel panel-success mrgn-bttm-xl">
                <header class="panel-heading">
                    <h5 class="panel-title">Local Post #1<span class="pull-right">Posted: 2023-11-17</span></h5>
                </header>
                <div class="panel-body mrgn-lft-md mrgn-rght-md">                                                                    
                    <p>Local Message Content 1.</p>
                </div>                   
            </div>                                                 
        </div>

        <div class="message" data-date="2023-11-10">
            <div class="panel panel-success mrgn-bttm-xl">
                <header class="panel-heading">
                    <h5 class="panel-title">Local Post #2<span class="pull-right">Posted: 2023-11-10</span></h5>
                </header>
                <div class="panel-body mrgn-lft-md mrgn-rght-md">                                                                    
                    <p>Local Message Content 2</p>
                </div>                   
           </div>
       </div>

       <div class="message" data-date="2023-11-01">
           <div class="panel panel-success mrgn-bttm-xl">
               <header class="panel-heading">
                   <h5 class="panel-title">Local Post #3<span class="pull-right">Posted: 2023-11-01</span></h5>
               </header>
               <div class="panel-body mrgn-lft-md mrgn-rght-md">                                                                    
                   <p>Local Message Content 3</p>
                </div>                   
           </div>
       </div>
    </div>

    <!-- Container for regional messages; will be filled via AJAX -->
    <div id="regional-messages" class="wb-ajax" data-ajax-replace="data/path.html"></div>
    </section>

    <script src="../js/jquery/2.2.4/jquery.min.js"></script>
    <script src="../js/wet-boew.min.js"></script>
    <script src="../js/i18n/en.min.js"></script>
    <script src="/js/wet-retrigger.js"></script>
    <span id="wb-rsz" class="wb-init">&nbsp;</span>

    <script>
        $(document).on("wb-ready.wb", function() {
        var $messagesContainer = $('#all-messages');

        // Function to sort messages from newest to oldest
        function sortMessages() {
            var $messages = $messagesContainer.find('.message').toArray();
            $messages.sort(function(a, b) {
                var dateA = new Date($(a).data('date')), dateB = new Date($(b).data('date'));
                return dateB - dateA;
            });

            $.each($messages, function(index, message) {
                $messagesContainer.append(message);
            });
        }

        // Listen for the wb-contentupdated event on the regional messages container
        $('#regional-messages').on("wb-contentupdated", function(event) {
            // Wait a brief moment to ensure content is fully rendered
            setTimeout(function() {
                sortMessages();
            }, 100); // Adjust this delay as needed
        });

        // Apply the sorting logic on initial page load as well
        sortMessages();
    });
    </script>

I tried the code above and as mentioned, it would sort when first loaded, but if refreshed, would just load in the order the “messages” came in and not by date.

How to insert data into a li, inputted by the user? JS

I am very new to JavaScript and am trying to create a to do list. I am trying to create a function that takes the data entered by the user and display it in a list below.

I can’t seem to figure out how to get the value that has been inputted and display it below in a li.

HTML:

     <div>
        <input type="text" id="task" placeholder="What do you need to do?" />
        <button class="btn" onclick="createToDo()">Submit</button>
      </div>
      <div>
        <ul id="list">
          <li id="taskInput"></li>
        </ul>
      </div>

JS:

function createToDo() {
  var input = document.getElementById("task").value;
  var ul = document.getElementById("list");
  var li = document.createElement("li");
  li.appendChild((element.attribute = input));
  ul.appendChild(li);
}

I have figured out how to manually insert text by using:

  li.appendChild((document.createTextNode("Input"));

but of course this returns the text.

I’m not sure if I have approached the function totally wrong or it is a minor solution but any help or guidance would be greatly appreciated.

ASP.NET core razor pages: tag not performing whats written in it’s @onclick

So I have this line of code (pageName: Closet):

<a href="javascript:void(0);" class="btn" id="addText" onclick="AddPart()">Add Part</a>

and this is the addPart() function:

async Task AddPart()
{
    data_.Parts.Add(new CloPart());
    DataService.DB.Add(data_.Parts[data_.Parts.Count - 1]);

    await JSRuntime.InvokeVoidAsync("handleAddPartButtonClick", DataService.DB[DataService.DB.Count - 1].PartName);
}

As I understand the AddPart() func will call a javascript function, this is that function:

function handleAddPartButtonClick(PartName) {
    // addText.innerHTML += "<p>n${PartName}</p>"
    DotNet.invokeMethodAsync('ClosetUI164', 'AddPart()');
    console.log("linked correctly");
}

and i did include the tag correctly with the correct path.

but still the javascript is not connected to the Closet page. Why do you think that is?

I tries way too many things and almost 6+ hours with chat gpt, but im new to razor web apps and its my first project on the topic without learning anything about it previously so im short on information here.

How to catch Javascript exceptions of type? [duplicate]

I wonder how can I implement Javascript exception of type. Let’s suppose that I have a Javascript class, for example MyCustomException and I would like to have a try-catch where the catch would specify that I want to catch any exception thrown that is an instance of MyCustomException or a subclass.

This is a sample Javascript try-catch:

try {
  nonExistentFunction();
} catch (error) {
  console.error(error);
  // Expected output: ReferenceError: nonExistentFunction is not defined
  // (Note: the exact output may be browser-dependent)
}

This is a sample PHP try-catch (PHP is just an illustration, this question is not about PHP):

<?php

class MyException extends Exception { }

class MyOtherException extends Exception { }

class Test {
    public function testing() {
        try {
            throw new MyException();
        } catch (MyException | MyOtherException $e) {
            var_dump(get_class($e));
        }
    }
}

$foo = new Test;
$foo->testing();

In this latter example I can tell PHP to catch any MyException or MyOtherException, even if the exception is a subclass of any of them. Is this possible in Javascript?

JavaScript – How do I shuffle the characters in a string skipping certain character(S)

I’m a javascript beginner and I got stuck having a problem. I have a javascript’s function to shuffle the characters in a string in that way that words length and spaces are kept like in original sentence.

`function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

String.prototype.shuffle = function () {
  // pass to shuffleArray an array of all non-whitespace characters:
  const randomChars = shuffleArray([...this.replace(/s+/g, '')]);
  let index = 0;
  // `S` matches any non-whitespace character:
  return this.replace(/S/g, () => randomChars[index++]);
}

console.log(
  `The keys are under the mat`
  .shuffle()
);`

What I want to add is adding to the function a variable with defined letters which should be skipping in shuffle process. Now we have, i.e:

  • original string:
    The keys are under the mat

  • now shuffled string looks like:
    atd meey eke nTshr hau ert

  • and what I want:
    I want to define characters e.g: [hr] and those letters should stay “frozen” in their positions and not be processed by shuffle function:

original string: T**h**e keys a**r**e unde**r** t**h**e mat

`final result:
a**h**d meey e**r**e nTsh**r** a**h**u ert`

How to get product data from online stores for chrome extension?

Trying to develop a chrome extension. Extension will compare the prices of a product in other stores and show the cheapest one. For example, I can select a product on Amazon and get its data using DOM. I couldn’t figure out how to get the data of the same product from other stores in the background and I need help on this issue. I use CSS, HTML and JavaScript for extension development.

Since it was my first extension development, I couldn’t think of anything. I added a button to the product using DOM on Amazon and I can get its data. I want to access the data of the same product on other sites in the background without going to other sites.