I'm using AG Grid on a website. When the user clicks a cell, it is focused and gets a blue outline.
I need to remove this focus when the user clicks certain other elements on the site, but I don't know how to do it. Is there a method or property to set for that?
Add the following snippet to your css
.ag-cell-focus, .ag-cell {
border: none !important;
}
Example - https://next.plnkr.co/edit/xO5N5u84U8n4HgK5
Angular2+ DEMO
ngAfterViewInit(){
let body = document.body;
body.addEventListener("mouseup", (e) => {
let container = this.agGrid._nativeElement;
if (!container.contains(e.target))
{
this.gridApi.clearFocusedCell();
}
})
}
JavaScript DEMO
var body = document.body;
body.addEventListener("mouseup", (e) => {
let gridDiv = document.querySelector('#myGrid')
if (!gridDiv.contains(e.target))
{
gridOptions.api.clearFocusedCell();
}
})
Apple below code to the global style.css file
.ag-cell-focus {
--ag-range-selection-border-color: transparent !important;
}
Related
Using a Bootstrap5 toggle switch (which is basically just a checkbox) to toggle on and off lines in a grid. I have it set up so if the toggle is true then add the class which adds lines for the grid and if it's false then remove class and the lines. When I toggle off the class that holds the style for the line gets removed correctly but when I toggle on then the class doesn't come back and toggle the lines on. I am also using a forEach() to loop through all the divs.
I have console.log within and they fire for each toggle so I am not sure what I am missing. Here is the code
JS
let gridToggleSwitch = document.querySelector("#gridToggle")
gridToggleSwitch.addEventListener('change', () => {
let boxList = document.querySelectorAll('.box')
let toggleChoice = gridToggleSwitch.checked
if(toggleChoice == true) {
console.log("LINES")
boxList.forEach((e) => {
console.log(e)
e.classList.add('box')
})
} else if (toggleChoice == false) {
console.log('NO LINES')
boxList.forEach((e) => {
console.log(e)
e.classList.remove('box')
})
} else {
console.log('woops')
}
})
CSS:
.box {
border: 1px solid black;
}
SOLVED:
since the grid can change dynamically I needed to also dynamically add an ID to the divs for the grid and instead of using the forEach() for the classes I looped through the ID and added/removed the border style
I'd like to detect a click inside or outside a div area. The tricky part is that the div will contain other elements and if one of the elements inside the div is clicked, it should be considered a click inside, the same way if an element from outside the div is clicked, it should be considered an outside click.
I've been researching a lot but all I could find were examples in jquery and I need pure javascript.
Any suggestion will be appreciated.
It depends on the individual use case but it sounds like in this example there are likely to be other nested elements inside the main div e.g. more divs, lists etc. Using Node.contains would be a useful way to check whether the target element is within the div that is being checked.
window.addEventListener('click', function(e){
if (document.getElementById('clickbox').contains(e.target)){
// Clicked in box
} else{
// Clicked outside the box
}
});
An example that has a nested list inside is here.
You can check if the clicked Element is the div you want to check or not:
document.getElementById('outer-container').onclick = function(e) {
if(e.target != document.getElementById('content-area')) {
console.log('You clicked outside');
} else {
console.log('You clicked inside');
}
}
Referring to Here.
you can apply if check for that inside your click event
if(event.target.parentElement.id == 'yourID')
In Angular 6 and IONIC 3, I do same as here:
import {Component} from 'angular/core';
#Component({
selector: 'my-app',
template: `
<ion-content padding (click)="onClick($event)">
<div id="warning-container">
</div>
</ion-content>
`
})
export class AppComponent {
onClick(event) {
var target = event.target || event.srcElement || event.currentTarget;
if (document.getElementById('warning-container').contains(target)){
// Clicked in box
} else{
// Clicked outside the box
}
}
}
This working fine on web/android/ios.
It might be helpful for someone, Thanks.
Try this solution it uses pure javascript and it solves your problem. I added css just for better overview... but it is not needed.
document.getElementById('outer-div').addEventListener('click', function(){
alert('clicked outer div...');
});
document.getElementById('inner-div').addEventListener('click', function(e){
e.stopPropagation()
alert('clicked inner div...');
});
#outer-div{
width: 200px;
height: 200px;
position: relative;
background: black;
}
#inner-div{
top: 50px;
left: 50px;
width: 100px;
height: 100px;
position: absolute;
background: red;
}
<div id="outer-div">
<div id="inner-div">
</div>
</div>
I came up with a hack for this that's working well for me and that might help others.
When I pop up my dialog DIV, I simultaneously display another transparent DIV just behind it, covering the whole screen.
This invisible background DIV closes the dialog DIV onClick.
This is pretty straightforward, so I'm not going to bother with the code here. LMK in the comments if you want to see it and I'll add it in.
HTH!
closePopover () {
var windowBody = window
var popover = document.getElementById('popover-wrapper') as HTMLDivElement;
windowBody?.addEventListener('click', function(event){
if(popover === event.target) {
console.log("clicked on the div")
}
if(popover !== event.target) {
console.log("clicked outside the div")
}
})
}
}
I recently needed a simple vanilla JS solution which solves for:
Ignoring specific selectors including whether a parent contains one of these selectors
Ignoring specific DOM nodes
This solution has worked quite well in my app.
const isClickedOutsideElement = ({ clickEvent, elToCheckOutside, ignoreElems = [], ignoreSelectors = [] }) => {
const clickedEl = clickEvent.srcElement;
const didClickOnIgnoredEl = ignoreElems.filter(el => el).some(element => element.contains(clickedEl) || element.isEqualNode(clickedEl));
const didClickOnIgnoredSelector = ignoreSelectors.length ? ignoreSelectors.map(selector => clickedEl.closest(selector)).reduce((curr, accumulator) => curr && accumulator, true) : false;
if (
isDOMElement(elToCheckOutside) &&
!elToCheckOutside.contains(clickedEl) &&
!didClickOnIgnoredEl &&
!didClickOnIgnoredSelector
){
return true;
}
return false;
}
const isDOMElement = (element) => {
return element instanceof Element || element instanceof HTMLDocument;
}
In React you can use useClickOutside hook from react-cool-onclickoutside.
Demo from Github:
import { useClickOutside } from 'use-events';
const Example = () => {
const ref1 = React.useRef(null);
const ref2 = React.useRef(null);
const [isActive] = useClickOutside([ref1, ref2], event => console.log(event));
return (
<div>
<div ref={ref1} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
<br />
<div ref={ref2} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
</div>
);
};
Live demo
I want to make the cell of the antd table behave as a link so that it can show all the features that a context menu of a link shows like Open in a new tab and all. I made the cell clickable by implementing onClick method under onCell props. But it doesn't give the feature of Open in a new tab and all. So how can I achieve this?
This is how onCell props look like currently:
onCell: record => ({
onClick: (event) => {
if(event.ctrlKey) {
this.linkViewerNewTab(record.id);
} else {
this.linkViewer(record.id);
}
},
}),
I would suggest you to render the cells with a Link and it will take care of the rest itself
<Link to={url} >Cell Data</Link>
Edit - This would add make just the content clickable, if you want whole cell to be clickable, you can tweak the css a bit
.ant-table-tbody>tr>td {
padding: 0;
}
.ant-table-tbody>tr>td>a {
display: inline-block;
width: 100%;
padding: 16px;
}
But if you want to do it the way you're doing, you can do like this
onCell: record => ({
onClick: (event) => {
const url = '';
if(event.ctrlKey) {
const win = window.open(url, '_blank');
win.focus();
} else {
this.props.history.push(url); // Assuming you're using react router
}
},
}),
I would like to create a popup menu when i click on a table row in svelte. I used the document.querySelectorAll method to add an onclick-event to every table row inside onMount. In the onMount function, I also re-render the shown table. How could I apply the onclick value to the re-rendered elements?
onMount(() => {
console.log(document.querySelectorAll(".results .table table tbody tr"));
/* -> returns array with only 1 element -> not correct */
/* ... re-render logic here */
}
but when I add an timeout:
onMount(() => {
setTimeout(() => {
console.log(document.querySelectorAll(".results .table table tbody tr"));
}, 5000);
/* -> returns array with all elements */
/* ... re-render logic here again */
}
A REPL with the full source-code can be found here
I was writing some thoughts, but it got too long for a comment.
You're doing a decent amount of extra work in that REPL that Svelte can do for you. I agree with #voscausa that you should be delegating events to the table. You should almost never have to use document.querySelector in Svelte. You're looping through all your rows twice. All your event listener attachings should be attributes in the markup, not attached in the JS, nor attached in an initializer function (thus the event delegation to the table). You are constantly monitoring mouse position, but you only use it in the onclick, which is a MouseEvent and has access to X and Y data.
Switch the click listener to the container:
<div class="results" on:click={handleClick}> ... </div>
<script>
function handleClick(e) {
const tr = e.target.closest('tr');
const td = e.target.closest('td');
if (td) {
/* code */
} else {
/* code */
}
}
</script>
If you need it to be on the whole document you can use <svelte:window> instead of .results.
To update the css of the .option div, do something like the following:
<div class="options" style=`left:${optionsStyle.left}px;top:${optionsStyle.top}px`> ... </div>
<script>
let optionsStyle = {left: 0, top: 0};
function handleClick(e) {
/* code */
let left = 0, right = 0;
/* calculate left and right here */
optionsStyle = {left: e.clientX, top: e.clientY};
/* code */
}
</script>
For toggling classes, see the class directive. You can have multiple class directives on one element. (I haven't done all of the logic here, obviously.)
<div class="options" class:expand={optionsExpand}> ... </div>
<script>
let optionsExpand = false;
function handleClick(e) {
const tr = e.target.closest('tr');
const td = e.target.closest('td');
if (td) {
/* code */
optionsExpand = true;
} else {
/* code */
optionsExpand = false;
}
}
</script>
I personally would turn the Options popup into its own component and pass the optionsExpand boolean as a prop.
Doing things more like I've described here will get you thinking in a Svelte mindset, it will simplify your code, you won't need the timeouts, and you won't need the afterUpdates function.
I'm currently working on a project with p5.js and have come against a problem in javascript. I built buttons in javascript to help make certain functions work and I'm looking for a way to style the buttons. For the rest of the project I was using bootstrap so I'm trying to find a way to style it as similar as I can to the rest of the rest off the CSS if possible. The buttons code in javascript follows this.
button1 = createButton('start');
button2 = createButton('stop');
button3 = createButton('play');
button4 = createButton('save');
button1.mousePressed(start_);
button2.mousePressed(stop_);
button3.mousePressed(play_);
button4.mousePressed(save_);
createButton returns a p5.Element object which has a .class() method to set the class property on it. Classes can then be used for styling, either with bootstrap or custom CSS. For example:
let btn;
function setup() {
noCanvas();
const cls = "maroon-bg white-text";
btn = createButton("hello world");
btn.class(cls);
btn.mouseClicked(() => {
btn.class(btn.class() ? "" : cls);
});
}
.maroon-bg {
background-color: maroon;
}
.white-text {
color: white;
}
button {
padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
I prefer separating CSS and JS because it promotes reuse and keeps your JS clean, but if you want to inline your styles, you can use .style():
let btn;
function setup() {
noCanvas();
btn = createButton("hello world");
btn.style("background-color", "maroon");
btn.style("color", "white");
btn.style("padding", "1em");
btn.mouseClicked(() => {
if (btn.style("color") === "rgb(0, 0, 0)") {
btn.style("color", "white");
btn.style("background-color", "maroon");
}
else {
btn.style("background-color", "");
btn.style("color", "");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
This is clearly awkward for this use case, but it can come in handy in other situations and is shown for completeness.