How can I use querySelectorAll with htmx

I am working with htmx which is a fantastic library, I have a little problem that’s not very clear on how to solve. htmx uses queryselector to locate elements to swap/update example with hx-swap="...", hx-target="..." how do I do a querySelectorAll. example I have a class bookmark, when a user bookmarks a post, I want to update all the classes with .bookmark

How to make a simple count down timer from milliseconds with Javascript/REACT

I’m wondering the best way to make a simple minute/second countdown timer to next refresh. This component’s prop get updated every 5 minutes and counts down until the next refresh per second. This seems to get out of sync pretty quickly. Any thoughts?

I’m not sure if timeRemaining < 0 makes sense — if we subtract 1000 from 1100 we would have 100 (how do I account for that?) I’m hoping there’s a better way. Should I convert this back to seconds?

Thanks for any feedback.

...

const CountdownToNextRefresh = ({milliToNextRounded5Min}) => {
  const [, setCount] = useState(0);
  const [timeRemaining, setTimeRemaining] = useState(milliToNextRounded5Min);

  useEffect(() => {
    const oneSecond = 1000;
    const interval = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
      setTimeRemaining(timeRemaining < 0 ? milliToNextRounded5Min : timeRemaining - oneSecond);
    }, oneSecond);
    return () => clearInterval(interval);
  }, [timeRemaining, milliToNextRounded5Min]);

  function msToTime(milliseconds) {
    // Get hours from milliseconds.
    const hoursFromMilli = milliseconds / (1000*60*60);
    const absoluteHours = Math.floor(hoursFromMilli);
    const h = absoluteHours > 9 ? absoluteHours : `0${absoluteHours}`;

    // Get remainder from hours and convert to minutes.
    const minutesfromHours = (hoursFromMilli - absoluteHours) * 60;
    const absoluteMinutes = Math.floor(minutesfromHours);
    const m = absoluteMinutes > 9 ? absoluteMinutes : `0${absoluteMinutes}`;

    // Get remainder from minutes and convert to seconds.
    const seconds = (minutesfromHours - absoluteMinutes) * 60;
    const absoluteSeconds = Math.floor(seconds);
    const s = absoluteSeconds > 9 ? absoluteSeconds : `0${absoluteSeconds}`;

    return h === "00" ? `${m}:${s}` : `${h}:${m}:${s}`;
  }

return (<div>{msToTime(timeRemaining)}</div>)
}

How does YouTube’s dynamic loading on the homepage work?

I’m making an extension that will put a button under each video on the home page but I found out very quickly that this wouldn’t be possible by just using a selectAll statement. The only thing that a selectAll statement does is it retrieves the first 3 rows of videos on the homepage. I think what’s happening is there are videos being loaded after the page has loaded thus the elements don’t exist at “document_end”(this being when my chrome extension is injecting the js/css onto the page). I would be looking for something like an event listener but an explanation as to why this is happening would be appreciated as well.

People.People.searchDirectoryPeople() query with multiple email addresses

In a Google Apps Script I need to query the Google user profile picture URL of many coworkers.

Here is a working example for a single user:

searchDirectoryPeople('[email protected]');

function searchDirectoryPeople(query) {
  const options = {
    query: query,
    readMask: 'photos,emailAddresses',
    sources: ['DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE']
  }
  const people = People.People.searchDirectoryPeople(options);
  if(people && people.people) {
    Logger.log('size: '+people.people.length);
    people.people.forEach(person => {
      let url = '';
      let email = '';
      if(person) {
        if(person.photos && person.photos[0]) {
          url = person.photos[0].url;
        }
        if(person.emailAddresses && person.emailAddresses.length) {
          person.emailAddresses.forEach(item => {
            if(item.metadata && item.metadata.sourcePrimary) {
              email = item.value;
            }
          });
        }
      }
      Logger.log('email: '+email+': '+url);
      //Logger.log('person: %s', JSON.stringify(person, null, 2));
    });
  } else {
    Logger.log('no people.people');
  }
}

I found out that I can query all jimmy people:

searchDirectoryPeople('jimmy');

I have the email address of all employees. I could loop through a big list of 1000+ employees one by one, but this is not practical. I am looking for a way to query multiple email addresses. The docs at https://developers.google.com/people/api/rest/v1/people/searchDirectoryPeople are cryptic for the query. I tried many things like these but nothing works:

I am looking for a query by list of email addresses as input, such as:

[ '[email protected]', '[email protected]', '[email protected]' ]

Possible?

What would be the easiest way to do a list of skills on a page that open in a popup?

I’m trying to list a bunch of skills on my website and have each of them open in a pop-up on click to give a little more info.
Basically, I want it to look like this, not as a button.
Image for reference

I’ve tried some codes from the internet but they either don’t work or break my WordPress theme.

The closest I’ve gotten was with this piece of code:

“Example code

How to throw unwanted data from form?

I am making a site to add product to a database.
The site has a type switcher for multiple types of the product.
by changing the type the input fields are changed by using display attribute CSS.
so there is a problem where the invisible inputs are still in the form and they are also submitted with the form. Also i wanted to validate the data but it have the same problem how do i validate the data shown to the user?.
i tried to change the whole by js document.create methods so i can create the inputs and labels i want but it was really complex . is there anyway i can fix this problem?

Here is the code im using:

            function TypeListener() {
              var x = document.getElementById("productType").value;
                document.getElementById("Hidden_Div1").style.display = x == 1 ? 'block' : 'none';
                document.getElementById("Hidden_Div2").style.display = x == 2 ? 'block' : 'none';
                document.getElementById("Hidden_Div3").style.display = x == 3 ? 'block' : 'none';
            }
.Type {
display: none;
}
<form id="product_form" action="<?=$_SERVER['PHP_SELF'] ?>" method="post">
<label for="Type Switcher">Type Switcher</label><select name="typeSwitcher" id="productType" onchange="TypeListener()">
                                                    <option value="" disabled selected>Type Switcher</option>
                                                    <option value="1" id="DVD">DVD</option>
                                                    <option value="2" id="Furniture">Furniture</option>
                                                    <option value="3" id="Book">Book</option>
                                                </select><br><br>
        <div id="Hidden_Div1" class="Type">
            <label for="Size">Size (MB)</label><input type="number" name="size" id="size" min="0"><br>
            <h5>Please, provide size in MB.</h5><br>
        </div>
        <div id="Hidden_Div2" class="Type">
            <label for="Height">Height (CM)</label><input type="number" name="height" id="height" min="0"><br>
            <label for="Width">Width (CM)</label><input type="number" name="width" id="width" min="0"><br>
            <label for="Length">Length (CM)</label><input type="number" name="length" id="length" min="0"><br>
            <h5>Please, provide dimensions in CM.</h5><br>
        </div>
        <div id="Hidden_Div3" class="Type"> 
            <label for="Weight">Weight (KG)</label><input type="number" name="weight" id="weight" min="0"><br>
            <h5>Please, provide weight in KG.</h5><br>
        </div>
</form>

FilePond | onprocessfiles callback is not working if I uploaded files both the file type is supported and is not supported

I tried to duplicate this issue but I couldn’t since it needs to set some server side codes and couldn’t do it on codesandbox.

But you can at least see working code on code sandbox.

And this is a record gif for my problem.

So, when I upload multiple files and if one of the file types is not supported, user won’t be able to click the save button, but if user removes the file that is not supported and has only files that are supported, user should be able to click the save button.

But the issue I have is user can’t click the save button even though he has only files that are supported.

I disabled and abled the save button based with imagesUploading value that changes value depending on the file uploading status like start uploading, uploading right now or uploaded successfully.

function App() {
  const [files, setFiles] = useState([]);
  const [imagesUploading, setImagesUploading] = useState(false);

  return (
    <div className="App">
      <FilePond
        files={files.map((file) => file.file)}
        maxFiles={50}
        maxFileSize="10MB"
        acceptedFileTypes={["image/jpg", "image/jpeg", "image/png"]}
        allowMultiple={true}
        onupdatefiles={(fileItems) => {
          setFiles(fileItems);
        }}
        onaddfilestart={() => {
          console.log("onaddfilestart");
          setImagesUploading(true); // make the save button disabled
        }}
        onprocessfilestart={() => {
          console.log(`onprocessfilestart`);
          setImagesUploading(true); // make the save button disabled
        }}
        onprocessfiles={() => {
          console.log(`onprocessfiles`);
          setImagesUploading(false); // make the save button abled
        }}
        imageResizeTargetWidth={1920}
        allowImageTransform={true}
        imageTransformOutputQuality={70}
      />
      <button disabled={imagesUploading || files.length < 1}>Save</button>
    </div>
  );
}

On the console, I see onaddfilestart and imagesUploading: true twice since there are two files are about to start uploading process.

Also, I see just onprocessfilestart letter and no value for imagesUploading and I assume because one of the file types is not supported, so process failed and the rest of callbacks(onprocessfiles) never got called where set imagesUploading value false to abled the button.

Does anybody have the same issue?

React/Jest: Testing React Context methods (Result: TypeError: setScore is not a function)

I’m using React Context API to create a game.

In one of my components (GameStatus) I pull in some methods from the provider:

const context = React.useContext(MyContext);
const { setGameStart, setGameEnd, setScore } = context;

And in the component I invoke these three methods onClick of the start game button, which in turn sets the state back in the provider.

GameStatus Component

import React from 'react';
import { MyContext } from './Provider';

const GameStatus = ({ gameStart, gameEnd, score, total, getPlayers }: { gameStart: boolean, gameEnd: boolean, getPlayers: () => void, score: number, total: number }) => {
    const context = React.useContext(MyContext);
    const { setGameStart, setGameEnd, setScore } = context;
    return (
        <>
            {!gameStart && (
                <button onClick={() => {
                    getPlayers();
                    setScore(0);
                    setGameStart(true);
                    setGameEnd(false);
                }}>
                    Start game
                </button>
            )}
            {gameEnd && (
                <p>Game end - You scored {score} out {total}</p>
            )}
        </>
    )
}

export default GameStatus;

Then in my test file below I want to test that when the start game button is clicked the game is started (check the DOM has removed the button and is now showing the game).

But I’m not sure how to pull in the methods in to the test file as I get:

Result: TypeError: setScore is not a function

I tried just copying:

const context = React.useContext(MyContext);
const { setGameStart, setGameEnd, setScore } = context;

But then I get an invalid hook call as I can’t use React hooks inside the test.

Any ideas? Or a better approach to testing this? Thanks

GameStatus Test

import React from 'react';
import { shallow } from 'enzyme';
import { MyContext } from '../components/Provider';
import GameStatus from '../components/GameStatus';

test('should start the game', () => {
    const getPlayers = jest.fn();

    const uut = shallow(
        <MyContext.Provider>
            <GameStatus
                getPlayers={getPlayers}
            />
        </MyContext.Provider>
    ).dive().find('button');

    uut.simulate('click');

    console.log(uut.debug());
});

Next Js + Amplify @sls-next/-component error on deployment

I’ve deployed my app on amplify, the backend deployment is all good to go.

I’ve connected the frontend to my gitlab repo, and after debugging it is finally compiled successfully. Immediately after the compiling, I get this error.

Starting SSR Build...
[ERROR]: Error: Command failed: npm install @sls-next/[email protected] --prefix /root/./

I have tried to override the env with the following commands (I’ve tried previous versions of both next and node, however it doesnt pass the compiling phase unless I use the following)

Amplify CLI - latest
Next.js version - latest
Node.js version - 17

This is my amplify.yml

version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: .next
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

My node_module versions on the project are

 "next": "^12.1.7-canary.16",
 "react": "^18.0.0",
 "react-dom": "^18.0.0",
 "aws-amplify": "^4.3.23"

my node version is 17.0.9 and my local amplify cli is 8.2.0

I should note my build passes locally

What am I missing? I dont have serverless installed anywhere on my project, it appears to be something amplify is trying to install. Perhaps I should be exporting after the build? But this is an ssr app, not static. I have a feeling this is a problem with conflicting versions.

,

Send upload file and a few parameters from javascript AJAX to MVC method

struggling my head trying to pass a file and parameters from javascript using AJAX to mvc method.
I already successfully send and catch the file, but I dont know have to send and receive the strings parameters.

Javascript:

$('#importButton').on("change", function () {
            var fileUpload = $("#importButton").get(0);
            var files = fileUpload.files;
            
            var systemName = "param1";
            var clientName = "param2";
            
            // Create FormData object  
            var fileData = new FormData();

            // Looping over all files and add it to FormData object  
            for (var i = 0; i < files.length; i++) {
                fileData.append(files[i].name, files[i]);
            }
            
            $.ajax({
            url: ImportClick,
            type: 'POST',
            //here is the thing, how send the parameters and the file
            data: fileData,
            cache: false,
            processData: false,
            contentType: false,
            success: function (response) {
                alert(response);
            },
            error: function (err) {
                alert(err.statusText);
            }
        });

MVC:

[HttpPost]
    public ActionResult ImportClick()
    {
        
        //how take the two parameters??
        
        //Here take the file
        HttpFileCollectionBase files = Request.Files;
        
        byte[] fileData = null;
        
        using (var binaryReader = new BinaryReader(files[0].InputStream))
        {
            fileData = binaryReader.ReadBytes(files[0].ContentLength);
        }
        
        service.ImportAllClientConfigurationData(param1, param2, fileData);
        
    }

AG-Grid Side Bar click functionality

So I have a side bar built using ag-grid and was wondering if it was possible to click on a side bar option without having the tool panel open and have a pop up component instead?

const gridOptions = {
    sideBar: {
        toolPanels: [
            {
                id: 'columns',
                labelDefault: 'Columns',
                labelKey: 'columns',
                iconKey: 'columns',
                toolPanel: 'agColumnsToolPanel',
                minWidth: 225,
                maxWidth: 225,
                width: 225
            },
            {
                id: 'filters',
                labelDefault: 'Filters',
                labelKey: 'filters',
                iconKey: 'filter',
                toolPanel: 'agFiltersToolPanel',
                minWidth: 180,
                maxWidth: 400,
                width: 250
            },
            {
                id: 'myComponent',
                labelDefault: 'MyComponent',
                labelKey: 'myComponent',
                iconKey: 'myComponent',
                toolPanel: () => {<MyComponent/>},
                minWidth: 180,
                maxWidth: 400,
                width: 250
            }
        ]
    },
}

For example, in the above code, I pass a component (e.g. <MyComponent/>) in place of the tool panel, but it doesn’t actually open that component when I click on it since it renders on the sideBar loading up.

Can I pass some onClick function into that particular sideBar option to allow me to click on it and open the component?

Add style according to the value of x-text/html value

I want to center my td element when the text is equals to “-“. If the text is equals to something else, I want it align at the left.

How can I do that?

<td x-bind:style="$el.textContent == '-' ? { 'text-align': 'left' } : { 'text-align': 'center' }" x-text="format(variable)"></td>

Yes, I could simple replace the $el.textContent by format(variable), but I would like to not call format(variable) twice.