I am using the onclick function with window.open popup, the popup comes to front with the same button, but after closing it is not opening again
<Button hideLabel aria-label={zxxxx "}
className = {styles.button}
icon = "plus"
color = "danger"
size = "lg"
circle
onClick = {
() => {
if (!this.state.isOpened) {
this.setState({
isOpened: true
})
var mywin = window.open("https://app.mural.co", "MsgWindow", "width=1366,height=768")
mywin.addEventListener("beforeunload", function(e) {
this.setState({
isOpened: true
})
}, false)
this.setState({
windows: mywin
}
this.setState(mywin)
}
else {
const window = this.state.windows;
if (window) {
window.focus();
}
}
}
}/>
There is something wrong in your code. Please refer to the commented line.
if (!this.state.isOpened) {
this.setState({
isOpened: true
})
var mywin = window.open("https://app.mural.co", "MsgWindow", "width=1366,height=768")
mywin.addEventListener("beforeunload", function(e) {
this.setState({
isOpened: true
})
}, false)
this.setState({ // there is no closing parenthesis for this
windows: mywin
}
this.setState(mywin)
}
else {
const window = this.state.windows;
if (window) {
window.focus();
}
}
}
Moreover aria-label={zxxxx "} also is missing something. I would highly recommend a code editor that points out these errors for you.
Related
I've a state named modal in my React App. The initial value is an object that says {show: false, photo: null}.
I've two buttons in the page. One is calling the close function and another is calling the open function. open is setting the state to {show: true, photo: true} and close is just logging modal
I also wrote some code to call the close function when the Esc button is clicked.
Here's my code:
function App() {
const [modal, setModal] = useState({ show: false, photo: null });
// open func
function open() {
setModal({ show: true, photo: true });
}
// close func
function close() {
console.log(modal);
}
// function for esc key press
function escFunc(event) {
if (event.key === `Escape`) {
close();
}
}
useEffect(() => {
document.addEventListener(`keydown`, escFunc, true);
return () => {
document.removeEventListener(`keydown`, escFunc, true);
};
}, []);
return (
<>
<button onClick={open}>open</button>
<br />
<button onClick={close}>close</button>
</>
);
}
so now when I click the open button and then click the close button, it's logging {show: true, photo: true} (as expected). but the problem comes in if I press Esc now. It should log {show: true, photo: true} (as the state is already updated by the open function), but it's logging {show: false, photo: null} as if the state hasn't changed yet
Why is it happening?
Whenever a component rerenders, the entire function is reran.
In your useEffect, which is only called on the first render, you call document.addEventListener with the callback function escFunc. This escFunc has a closure that stores the value of modal, which is a reference to the original object state { show: false, photo: null }.
In your open function, you set the state to { show: true, photo: true } using the object literal syntax, which creates a whole new object with a new reference location.
The event listener is still tracking the original object.
To be able to get the new state reference, you need to remove the old event listener and then add a new event listener.
There are multiple ways to do this.
useEffect(() => {
document.addEventListener(`keydown`, escFunc, true);
return () => {
document.removeEventListener(`keydown`, escFunc, true);
};
}, [modal]); // add modal to dep array
useEffect(() => {
document.addEventListener(`keydown`, escFunc, true);
return () => {
document.removeEventListener(`keydown`, escFunc, true);
};
}, [escFunc]); // add escFunc to dep array, but this would run every render
Stylistically, this is the best option because it properly shows dependencies and doesn't have extra rerenders, but the calls to useCallback might make it slower
const close = useCallback(function() {
console.log(modal);
}, [modal]); // depends on modal
const escFunc = useCallback(function(event) {
if (event.key === `Escape`) {
close();
}
}, [close]); // depends on close
useEffect(() => {
document.addEventListener(`keydown`, escFunc, true);
return () => {
document.removeEventListener(`keydown`, escFunc, true);
};
}, [escFunc]); // add escFunc to dep array
In fact, you don't even need to have escFunc outside of useEffect if you don't use it elsewhere
const close = useCallback(function() {
console.log(modal);
}, [modal]); // depends on modal
const escFunc = useCallback(function(event) {
if (event.key === `Escape`) {
close();
}
}, [close]); // depends on close
useEffect(() => {
function escFunc(event) {
if (event.key === `Escape`) {
close();
}
}
document.addEventListener(`keydown`, escFunc, true);
return () => {
document.removeEventListener(`keydown`, escFunc, true);
};
}, [close]); // add escFunc to dep array
I have an app created with vuetify and i want to hide the main scrollbar when my dialog is open. For example, there is two scrollbar when the dialog is open: https://i.stack.imgur.com/a4xt7.png
I just want to hide the main scrollbar only when the dialog is open. This is what I have tried :
document.body.style.overflow = "hidden";
but it doesn't work.
Here is where the code being implemented :
async mounted() {
this.$store.commit("SET_LOADING", true);
try {
await this.loadData();
if (!this.item) {
this.$showDialog({
title: "Something Wrong",
body: `Member not found!`,
});
this.closePage();
} else {
// here
document.body.style.overflow = "hidden";
await this.$store.dispatch("area/get");
this.role = this.item?.roles[0];
if (
this.item?.user &&
this.$store.state.user?.roles?.find(
(x) => x == this.$roles.Admin
)
)
this.email = this.item?.user.email;
}
} catch (error) {
Promise.reject(error);
} finally {
this.$store.commit("SET_LOADING", false);
}
},
you can set false value scrollable prop for your dialog
I have a problem, I can't remove the event listener in the condition inside the callback function.
I have the impression that the syntax is correct. But the event is still active.
Does anyone know how to remove the event touchstart?
mutation.target.removeEventListener("touchstart",(e) => { handleClickButton(e) }, true);
const headerSearchBox = document.querySelector(".search-box");
function handleClickButton(event) {
event.preventDefault();
alert("You Clicked on the button")
}
const mutationCallback = function (mutationList) {
mutationList.forEach((mutation) => {
let isSearchOpen = mutation.target.classList.contains("search-container");
// If Search Bar is Open : Do This...
if (mutation.type === "attributes" && isSearchOpen && mutation.oldValue.includes("open")) {
console.log("Search Bar is Open");
mutation.target.addEventListener("touchstart",(e) => { handleClickButton(e) }, true);
} else {
console.log("Search Bar is Close");
mutation.target.removeEventListener("touchstart",(e) => { handleClickButton(e) }, true);
}
});
};
const observer = new MutationObserver(mutationCallback);
observer.observe(headerSearchBox, {
attributes: true,
attributeOldValue: true,
attributeFilter: ["class"],
});
Thanks for your support
So in a chrome extension.
when the user clicks a button
send a message to background
open a new popup window
in the new window, click on the specific element
I can get most of the way but fail to be able to focus in on the necessary document for the js to get the element ID on.
content.js
user_clicked_btn.addEventListener('click', () => {
chrome.storage.sync.get(['xyz'], (result) => {
if (result.xyz['u'].includes('123') && result.xyz['da'] !== 'cool') {
chrome.runtime.sendMessage(
{
s: 'quick',
}
);
}
});
background.js
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick') {
chrome.windows.create({
url: './options.html', type: "popup", focused: true
},
() => {
let queryOptions = { active: true, currentWindow: true };
chrome.tabs.query(queryOptions, function (tabs) {
tabs[0].document.getElementById("element_of_interest").click()
});
}
);
}
});
the issue could be summarized as, how do I get the "document" of a different tab? (assuming I own the 'different tab')
The solution for my problem was to add message passing the whole way to the element of interest and have it click itself.
The result looks like this and behaves as desired.
content.js
user_clicked_btn.addEventListener('click', () => {
chrome.storage.sync.get(['xyz'], (result) => {
if (result.xyz['u'].includes('123') && result.xyz['da'] !== 'cool') {
chrome.runtime.sendMessage(
{
s: 'quick',
}
);
}
});
background.js
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick') {
chrome.windows.create({
url: './options.html', type: "popup", focused: true
}, () => {
setTimeout(() => {
console.log("send message to options page")
chrome.runtime.sendMessage(
{
s: 'quick_click',
}
);
}, 1000);
});
}
});
in the options.html file, the desired element is a react element, so I was able to add a listener in the componentDidMount function
options/index.js
componentDidMount() {
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick_click') {
this.handleClick()
}
});
}
I want to this : If user clicked favorite button I show dialog box
"Report added to favorites"
and user clicked favorite button second time I created dialog box
"Report removed from favorites "
again but dialog boxs has same id.
My code s the following :
$scope.toogleReportToFavorites = function (item) {
if (!item.isInFavorites) {
item.isInFavorites = true;
RepService.AddToDefaultFavourites(item.ReportId, function (reportCat) {
if ($scope.showRemovedDialog) {
$("#denemePicker").dialog("close"); //its works only first time
$scope.showAddedDialog = false;
}
else {
$scope.showAddedDialog = true;
}
WarningDialogs("Report added to favorites");
}, function (ex) {
GlobalErrorHandler(ex);
});
} else {
item.isInFavorites = false;
RepService.RemoveFromFavourites(item.ReportId, function () {
if ($scope.showAddedDialog) {
$("#denemePicker").dialog("close");
$scope.showRemovedDialog = false;
}
else {
$scope.showRemovedDialog = true;
}
WarningDialogs("Report removed from favorites");
}, function (ex) {
GlobalErrorHandler(ex);
});
}
};
and this is my WarningDialogs function code :
function WarningDialogs(text, messageType, dialogWidth, callback, textAlign) {
if (textAlign == null || textAlign.length < 1) {
textAlign = 'center';
}
$('<div>', { title: "deneme", id: 'denemePicker' }).html(text).css('text-align', textAlign).dialog(
{
resizable: true, modal: true, closeOnEscape: true, width: dialogWidth,
create: function () {
isWarningDialogsShown = true;
$(this).css('maxHeight', '300px');
},
close: function (event, ui) {
isWarningDialogsShown = false;
if (callback) {
callback();
}
},
buttons: {
Close: function () {
$(this).dialog("close");
}
}
}).css('overflow', 'auto');
return;
}
I want to always work for this : $("#denemePicker").dialog("close"); but its only work first time. I guess reason same id ?
How can ix this please ?
This code may help You
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<button type="button" class="btn btn-info" style="width:90%;" id="textChanger" status="1" onclick="counter;">D Box</button>
<script>
$(document).on('click','#textChanger',function(){
var status = $(this).attr('status');
if(status ==1){
$(this).attr('status',0);
alert('Report added to favorites');
}else{
$(this).attr('status',1);
alert('Report removed from favorites');
}
})
</script>