window.showOpenFilePicker polyfill - javascript

Is there a polyfill for window.showOpenFilePicker (MDN)?

function showOpenFilePickerPolyfill(options) {
return new Promise((resolve) => {
const input = document.createElement("input");
input.type = "file";
input.multiple = options.multiple;
input.accept = options.types
.map((type) => type.accept)
.flatMap((inst) => Object.keys(inst).flatMap((key) => inst[key]))
.join(",");
input.addEventListener("change", () => {
resolve(
[...input.files].map((file) => {
return {
getFile: async () =>
new Promise((resolve) => {
resolve(file);
}),
};
})
);
});
input.click();
});
}
if (typeof window.showOpenFilePicker !== 'function') {
window.showOpenFilePicker = showOpenFilePickerPolyfill
}

Related

How to turn off the websocket after component unmounts

this is my code snippet bellow,
I am trying to close the websocket connection after component unmounts, I just totally dont know how to do it
I am using this useEffect inside the same component I am also using useref to count the mounted count of the component so that the websocket doesn't creates more that 1 instance at a time
const mountedCount = useRef(0);
useEffect(() => {
const handleWebsocket = () => {
mountedCount.current++;
const socketURL = 'socket url here'
const socket = new WebSocket(socketURL);
socket.onopen = () => {
console.log('socket open')
};
socket.onclose = (closeEvent) => {
if (closeEvent.wasClean) return;
timeout = setTimeout(() => {
handleWebsocket();
}, envVariables.webSocketReconnectionTimeout);
};
socket.onerror = () => {
console.log('error here')
};
socket.onmessage = (messageEvent) => {
console.log('got the message')
};
return socket;
};
if (mountedCount.current === 0) {
handleWebsocket();
}
return () => {
clearTimeout(timeout);
};
}, [
dispatch,
userData.userInformation,
wss.connectionStatus
]);
const mountedCount = useRef(0);
const [currentSocket,setCurrentSocket]=useState(null)
useEffect(() => {
const handleWebsocket = () => {
mountedCount.current++;
const socketURL = 'socket url here'
const socket = new WebSocket(socketURL);
socket.onopen = () => {
console.log('socket open')
};
socket.onclose = (closeEvent) => {
if (closeEvent.wasClean) return;
timeout = setTimeout(() => {
handleWebsocket();
}, envVariables.webSocketReconnectionTimeout);
};
socket.onerror = () => {
console.log('error here')
};
socket.onmessage = (messageEvent) => {
console.log('got the message')
};
return socket;
};
if (mountedCount.current === 0) {
setCurrentSocket(handleWebsocket());
}
return () => {
clearTimeout(timeout);
currentSocket?.close();
};
}, [
dispatch,
userData.userInformation,
wss.connectionStatus
]);
or you can declare socket variable in one upper scope:
const mountedCount = useRef(0);
useEffect(() => {
let socket
const handleWebsocket = () => {
mountedCount.current++;
const socketURL = 'socket url here'
socket = new WebSocket(socketURL);
socket.onopen = () => {
console.log('socket open')
};
socket.onclose = (closeEvent) => {
if (closeEvent.wasClean) return;
timeout = setTimeout(() => {
handleWebsocket();
}, envVariables.webSocketReconnectionTimeout);
};
socket.onerror = () => {
console.log('error here')
};
socket.onmessage = (messageEvent) => {
console.log('got the message')
};
return socket;
};
if (mountedCount.current === 0) {
handleWebsocket();
}
return () => {
clearTimeout(timeout);
socket.close()
};
}, [
dispatch,
userData.userInformation,
wss.connectionStatus
]);

Trying to make button stay disabled when input not valid

I am trying to make button stay disabled when input not valid...
I am using just simple Javascript validation. I can't make it work. Help please?
const hasInvalidInput = (inputList) => {
return inputList.some((inputElement) => {
return !inputElement.validity.valid;
});
};
const toggleButtonState = (inputList, buttonElement, inactiveButtonClass) => {
if (hasInvalidInput(inputList)) {
buttonElement.classList.add(inactiveButtonClass);
buttonElement.setAttribute("disabled", "");
} else {
buttonElement.classList.remove(inactiveButtonClass);
buttonElement.removeAttribute("disabled", "");
}
};
const checkInputValidity = (formElement, inputElement, inputErrorClass, errorClass) => {
if (!inputElement.validity.valid) {
showInputError(formElement, inputElement, inputElement.validationMessage, inputErrorClass, errorClass);
} else {
hideInputError(formElement, inputElement, inputErrorClass, errorClass);
}
};
const showInputError = (formElement, inputElement, errorMessage) => {
const errorElement = formElement.querySelector(.${inputElement.id}-error);
inputElement.classList.add("popup__error");
errorElement.textContent = errorMessage;
errorElement.classList.add("popup__error_visible");
};
const hideInputError = (formElement, inputElement, inputErrorClass, errorClass) => {
const errorElement = formElement.querySelector(`.${inputElement.id}-error`);
inputElement.classList.remove(inputErrorClass);
errorElement.classList.remove(errorClass);
errorElement.textContent = "";
};
const setEventListeners = (formElement, inputSelector, submitButtonSelector, inactiveButtonClass, inputErrorClass, errorClass) => {
const inputList = Array.from(formElement.querySelectorAll(inputSelector));
const buttonElement = formElement.querySelector(submitButtonSelector);
inputList.forEach((inputElement) => {
inputElement.addEventListener("input", () => {
checkInputValidity(formElement, inputElement, inputErrorClass, errorClass);
toggleButtonState(inputList, buttonElement, inactiveButtonClass);
});
});
};
const enableValidation = ({
formSelector,
inputSelector,
submitButtonSelector,
inactiveButtonClass,
inputErrorClass,
errorClass,
}) => {
const formList = Array.from(document.querySelectorAll(formSelector));
formList.forEach((formElement) => {
formElement.addEventListener("submit", function (evt) {
evt.preventDefault();
});
setEventListeners(
formElement,
inputSelector,
submitButtonSelector,
inactiveButtonClass,
inputErrorClass,
errorClass
);
});
};
enableValidation({
formSelector: ".popup__form",
inputSelector: ".popup__input",
submitButtonSelector: ".popup__button",
inactiveButtonClass: "popup__button_disabled",
inputErrorClass: "popup__error",
errorClass: "popup__error_visible"
});

Cancelling my axios call on ReactJS but not working

I'm working on a project with graphs and I need to be able to cancel my requests if the user selects a different tab.
Here's my API call
export const getDifferentialData = (
sourceId: string,
sourceLine: string,
source: any
) => {
const graph1Request = getData(
sourceId,
sourceLine,
source
)
const graph2Request = getData(
sourceId,
sourceLine,
source
)
return Promise.all([graph1Request, graph2Request]).then(results => {
const [graphA, graphB] = results
return {
graphA: parsedData(graphA),
graphB: parsedData(graphB),
}
})
}
export const getData = (
sourceId: string,
sourceLine: string,
source?: any
) => {
if (sourceId && sourceLine) {
return api.get(`apiGoesHere`, { cancelToken: source.token }).then(response => {
const { data } = response
return parsedData(data)
})
} else {
return api.get(`apiGoesHere`, { cancelToken: source.token }).then(response => {
const { data } = response
return parsedData(data)
})
}
}
And the component where I'm doing the call. userDidChangeTab is called when pressing on a tab and it calls fetchGraph
const Graph: FC<Props> = () => {
const source = axios.CancelToken.source();
// we ensure that the query filters are up to date with the tab selected
const userDidChangeTab = (tabIndex: number) => {
const isDifferentialTabSelected = isDifferentialTab(tabIndex)
let newFilters = queryFilters
if (isDifferentialTabSelected) {
newFilters = {
// props go here
}
} else {
newFilters = {
// props go here
}
}
source.cancel()
fetchGraph(isDifferentialTabSelected)
setActiveTab(tabIndex)
}
// Function to fetch two differential graphs.
const fetchGraph = (isDifferential: boolean) => {
setFetching(true)
if (isDifferential) {
getDifferentialData(
sourceId,
sourceLine,
source
)
.then(({ graphA, graphB }: any) => {
setGraphData(graphA)
setMatchData(new diffMatch(graphA, graphB, 1.0))
})
.catch(reason => {
const errorMessage = errorMessageFromReason(reason)
addMessageToContainer(errorMessage, true)
})
.finally(() => {
setFetching(false)
})
} else {
getGraph(
sourceId,
sourceLine,
source
)
.then((graphData: any) => {
setGraphData(graphData)
setMatchData(null)
})
.catch(reason => {
const errorMessage = errorMessageFromReason(reason)
addMessageToContainer(errorMessage, true)
})
.finally(() => {
setFetching(false)
})
}
}
}

Stop function on mouseout | JS

I've built the following function, which changes the content of a span on mouseover. Everything works fine. The only problem is that I'm not sure how to stop the function on mouseout (initial and mouseout state should be the same).
Here is my current solution.
var squWrd = document.getElementById("squWrd");
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
squWrd.onmouseover = function () {
squWrd.innerHTML = "Design.";
sleep(250).then(() => { squWrd.innerHTML = "UX."; });
sleep(500).then(() => { squWrd.innerHTML = "Marketing."; });
sleep(750).then(() => { squWrd.innerHTML = "Social Media."; });
sleep(1000).then(() => { squWrd.innerHTML = "Education."; });
sleep(1250).then(() => { squWrd.innerHTML = "Branding."; });
sleep(1500).then(() => { squWrd.innerHTML = "Packaging."; });
sleep(1750).then(() => { squWrd.innerHTML = "Design."; });
sleep(2000).then(() => { squWrd.innerHTML = "Processes."; });
sleep(2250).then(() => { squWrd.innerHTML = "E-Commerce."; });
sleep(2500).then(() => { squWrd.innerHTML = "Advertising."; });
sleep(2750).then(() => { squWrd.innerHTML = "Photos."; });
sleep(3000).then(() => { squWrd.innerHTML = "Products."; });
sleep(3250).then(() => { squWrd.innerHTML = "Logos."; });
sleep(3500).then(() => { squWrd.innerHTML = "Emotions."; });
sleep(3750).then(() => { squWrd.innerHTML = "Solutions."; });
}
squWrd.onmouseout = function () {
squWrd.innerHTML = "Solutions.";
}
Do you guys have any suggestions? Thanks in advance!
Timeouts are still running, you need to call clearTimeout. I recommend you to add a second argument to the sleep function, a callback function that pass the timeout reference, this way you can clear only the timeouts related to the texts and not all the timers.
Also instead of call sleep for every text, you can store this texts inside an array an iterate over it:
var squWrd = document.getElementById("squWrd");
function sleep(ms, cb=()=> {}) {
return new Promise(resolve => {
const time = setTimeout(() => {
resolve();
}, ms);
cb(time);
});
}
const texts = ["Design", "UX.", "Marketing.", "Social Media.", "Education.", "Branding.", "Packaging.", "Design.", "Processes.", "E-Commerce.", "Advertising.", "Photos.", "Products.", "Logos.", "Emotions.", "Solutions."];
const textTimeouts = [];
squWrd.onmouseover = function() {
texts.forEach((text, i) => {
sleep(250 * i, (time) => textTimeouts.push(time)).then(res => {
squWrd.innerHTML = text;
});
});
};
squWrd.onmouseout = function() {
squWrd.innerHTML = "Solutions.";
textTimeouts.forEach(time => clearTimeout(time));
};
<h1 id="squWrd">Solutions</h1>
The problem is that even when onmouseout gets triggered, there are still sleep promises pending. You need to save the reference for each setTimeout call and clear it at onmouseout event. See here.
var squWrd = document.getElementById('squWrd');
var timeoutRefs = [];
function sleep(ms) {
return new Promise(resolve => timeoutRefs.push(setTimeout(resolve, ms)));
}
squWrd.onmouseover = function () {
squWrd.innerHTML = "Design.";
sleep(250).then(() => { squWrd.innerHTML = "UX."; });
sleep(500).then(() => { squWrd.innerHTML = "Marketing."; });
sleep(750).then(() => { squWrd.innerHTML = "Social Media."; });
sleep(1000).then(() => { squWrd.innerHTML = "Education."; });
sleep(1250).then(() => { squWrd.innerHTML = "Branding."; });
sleep(1500).then(() => { squWrd.innerHTML = "Packaging."; });
sleep(1750).then(() => { squWrd.innerHTML = "Design."; });
sleep(2000).then(() => { squWrd.innerHTML = "Processes."; });
sleep(2250).then(() => { squWrd.innerHTML = "E-Commerce."; });
sleep(2500).then(() => { squWrd.innerHTML = "Advertising."; });
sleep(2750).then(() => { squWrd.innerHTML = "Photos."; });
sleep(3000).then(() => { squWrd.innerHTML = "Products."; });
sleep(3250).then(() => { squWrd.innerHTML = "Logos."; });
sleep(3500).then(() => { squWrd.innerHTML = "Emotions."; });
sleep(3750).then(() => { squWrd.innerHTML = "Solutions."; });
};
squWrd.onmouseout = function () {
timeoutRefs.forEach(function (timeoutRef) {
clearTimeout(timeoutRef)
});
timeoutRefs = [];
squWrd.innerHTML = 'Solutions.';
};
<div id="squWrd">INITIAL VALUE</div>

How to test promises chain using jest?

I have module executer that will be executed on every api request now i am trying to write cases to unit test that executer. I have promise that returns chain that is being executed based on response. I see issue executing promise in test case , any help here to proper test this use case will be apprecaited.
main.ts
export class Executor {
private passedParam: ILogParams = {} as ILogParams;
constructor(public identity: Identity) {
this._ajv = new Ajv();
}
public execute(moduleName: string): (param1, param2) => any {
const self = this;
// getting rid of the tslint issue with Function
return function(params: any, responseCallback: (param: any , param2: any) => any) {
let _mod;
let _httpRequest;
let _params;
Promise.resolve(getApiModule(self.identity, moduleName))
.then((mod: ModuleBase<any, any>) => {
_mod = mod;
mod.ExecStage = ExecStage.Init;
return mod.init(getHttpModule(self.identity), params);
})
.then((httpRequest: HttpRequestBase) => {
_httpRequest = httpRequest;
if (_mod.Response().Summary.Header) {
throw _mod.Response().Summary;
}
return httpRequest;
})
.then(() => {
// empty the error stack
_mod.objErrorHandler.RemoveAllError();
_mod.ExecStage = ExecStage.Before;
return _mod.before(params);
})
.then((params1: any) => {
const _validators = _mod.getValidators();
let _failed: boolean = false;
return params1;
})
.then((params2: any) => {
_params = params2;
_mod.ExecStage = ExecStage.Core;
return _mod.core(_params, _httpRequest);
})
.catch((data: any) => {
const error: IHeader = {} as IHeader;
})
.then((data: any) => {
responseCallback(data, moduleName.substr(moduleName.indexOf('/') + 1));
});
};
}
}
main.spec.ts
import * as sinon from "sinon";
import {ModuleExecutor} from "./main.ts";
import {ExecStage, Identity} from "../../src/ts/common/Enums";
import ValidateRequestSchema from "../../src/ts/validation/requestSchema.js";
describe("ModuleExecuter", () => {
const sandbox = sinon.createSandbox();
afterEach(function afterTests() {
sandbox.restore();
});
let executer;
let executerSpy;
let results;
let stubbedExecutor;
let apiModule;
let _this;
const stubbedExecutorReturnFuction = sandbox.spy(function(args) {
executer = new ModuleExecutor(Identity.node);
executerSpy = executer.execute();
_this = this;
return new Promise(function(resolve) {
// moduleExecutor.execute(params, callback function)
executerSpy(args, function(data) {
resolve(data.Details);
});
});
});
const stubbedExecutorReturn = sandbox.spy(function(args, innerFunc) {
return innerFunc({Details: successResponse});
});
beforeEach(function() {
stubbedExecutor = sandbox.stub(ModuleExecutor.prototype, "execute").callsFake(function() {
return stubbedExecutorReturn;
});
apiModule = new GetAccountBalance();
const execute = sandbox.spy(stubbedExecutorReturnFuction);
results = execute("Payments/accountBalance/GetAccountBalance", {test:"test"});
});
describe("ModuleExecutor", function() {
it('should call ModuleExecutor.execute', function () {
sinon.assert.calledOnce(stubbedExecutor);
});
it('should return a promise', function() {
results.then(function(data) {
expect(data).toBe(successResponse);
});
});
it('should check validate AJV schema', function() {
let _mod;
results.then((mod: ModuleBase<any, any>) => {
_mod = mod;
mod.ExecStage = ExecStage.Before;
const requestSchema = "I" + _mod.__proto__.constructor.name + "Param";
const classSchema = ValidateRequestSchema[requestSchema];
const valid = _this._ajv.validate(classSchema, {test:"test"});
console.log("BOOLEAN>>>>>>>", valid);
expect(valid).toBeTruthy();
});
});
});
});

Categories