Eg.
<div style="display:none">
<span id=test style="display:none"></span>
</div>
I know in jquery you can do :visible
I tried something like :not([display=none]) > span but this will also select nested invisible elements. Eg:
document.querySelectorAll(':not([display=none]) > span').forEach(elem =>
console.log(elem.id)
);
<div id=d style="display:none">
<div id=dd>
<span id=dds></span>
</div>
<span id=ds></span>
</div>
Is there anyone to make a selector that would only accept visible elements?
If there were an AND selector I could do something like the following:
:and(
:not([display=none]) > span,
:not([display=none]) > * > span,
:not([display=none]) > * > * > span,
etc.
)
These are my best workarounds:
function* allVisibleElems(parent = document)
{
for (let elem of parent.children)
{
if (elem.style.display === 'none') continue;
yield elem;
yield* allVisibleElems(elem);
}
}
This function would have equivalent functionality to document.querySelectorAll(':visible').
function isVisible (elem)
{
while (elem !== document)
{
if (elem.style.display === 'none') return false;
elem = elem.parentNode;
}
return true;
}
This function would have equivalent functionality to elem.matches(':visible').
Note: these solutions only work when setting the style.display property to none but that is all I need for my application.
I think you are looking for something like that ?
document.querySelectorAll('span').forEach( sp =>
{
let
pDiv = sp.closest('div')
, pDivOK = true
;
while(pDivOK && pDiv)
{
pDivOK &&= (getComputedStyle(pDiv).display != 'none')
pDiv = pDiv.parentNode.closest('div')
}
if ( pDivOK )
console.log( sp.id, "<-- parents '<div' are all visible")
});
.noDisplay {
display: none;
}
<div id="d" style="display:none">
<div id="dd">
<span id="dds"></span>
</div>
<span id="ds"></span>
</div>
<div id="1d" class="noDisplay">
<div id="1dd">
<span id="1dds"></span>
</div>
<span id="1ds"></span>
</div>
<div id="2d">
<span id="2ds"></span>
</div>
Related
I'm trying to add a Collapsible in my project. The functionality works simply. But there is a CSS issue in collapsible. When I click on a header the collapsible panel opens on after all the header. I want to open the collapsible panel next to each header. I'm using react-collapsible package.
Here is my code,
return (
assignTasklist && assignTasklist.map((assign) =>
<div className="dashboard-tasklists-group_header">
<div id={assign.TaskType} className={ "dashboard-tasklists-group_header-left"} onClick={()=> {
// e.preventDefault();
// e.stopPropagation();
this.onToggleAccordion(assign.TaskType)}}>
{assign.Description}
</div>
<div className="dashboard-tasklists-group_header-right">
<button className="dashboard-tasklists-group_header-caret-button" onClick={()=> {
// e.preventDefault();
// e.stopPropagation();
this.onToggleAccordion(assign.TaskType)}}>
<CaretIcon />
</button>
</div>
</div>
)
);
}
render() {
const { assignDetails } = this.props;
return <div className="dashboard-tasklists-group">
<Collapsible trigger={this.groupWorkingHeader()} /* handleTriggerClick={() => {
}}open={this.state.testflag} */ >
{assignDetails && assignDetails.length>0 && <div className="dashboard-index_announcements-wrapperWP" style={{cursor:'pointer'}}>
<div /* className="dashboard-index_announcements" */ style={{maxHeight: '240px',overflowY: "scroll"}}>
{assignDetails.map(patient =>
<div onClick={()=> { browserHistory.push(`/patientsTask/${patient.PatientID}`); }} className="showingdet"><span style={{fontWeight:700}}>{patient.PatientID}</span>-{patient.Name}</div>
)}
</div>
</div>}
</Collapsible>
</div>;
}
Please help me to solve
Problem: I have some html that uses *ngFor to generate a bunch of divs, all with the same class. I want to be able to add an active class to single elements. I keep running into the issue though of having that class applied to all of my elements instead of just one.
HTML:
<div class="feed" infiniteScroll [infiniteScrollDistance]="2" [infiniteScrollThrottle]="50" (scrolled)="onScroll()" >
<div class="mentions" *ngFor = 'let item of feed; let i = index;'>
<div class="content-wrapper">
<img src={{item.image}}>
<div class="content-text">
<div>{{item.name}}</div><br>
<div>{{item.text}}</div><br>
<div>{{item.followers}}</div><br>
</div>
</div>
<div class="votebtn">
<button mat-button matSuffix mat-icon-button aria-label="UpVote" id = u-{{item.source}} class="UpVote" (click)="vote(i, item, 'keep')">
<mat-icon>thumb_up</mat-icon>
</button>
<button mat-button matSuffix mat-icon-button aria-label="DownVote" id=d-{{item.source}} class=DownVote (click)="vote(i, item, 'ignore')">
<mat-icon>thumb_down</mat-icon>
</button>
</div>
</div>
</div>
Goal: Ultimately, I'd love to be able to do something as simple as adding box-shadow: 1px -1px 12px 0px #c9c9c9 to the a single mentions element on mouseover and then remove it on mouseout. This is my most recent attempt.
<div *ngFor = 'let item of feed; let i = index;' [ngClass] = 'state' (mouseover) = "state = 'mentions hover'" (mouseout) = "state = 'mentions'">
Again, it would add to all elements.
Late reply. I let the object array do most of the work as this pattern is cleaner for me:
CSS
li.selected {
border-bottom: thick solid purple;
}
li.hover {
border-bottom: thick dotted gray;
}
Object
NavigtionMenu = [
{
name: 'Home',
link: 'path/to/link',
hover: false,
selected: false,
},
{
name: 'About Us',
link: 'path/to/link',
hover: false,
selected: false,
}
]
Template
<li
*ngFor="let item of items; let i = index"
(mouseover)="item.hover = true"
(mouseout)="item.hover = false"
(click)="item.selected = true"
[routerLink]="item.link"
[ngClass]="{
'selected' : link.selected === true && link.hover === false,
'hover' : link.hover === true
}"
>
{{ item.name }}
</li>
You could archive this visual effect by defining a small attribute directive:
#Directive({
selector: '[ngHoverClass]'
})
export class NgHoverClassDirective {
#Input(`ngHoverClass`)
set classesToAply(v: string | string[]){
this.classes = Array.isArray(v) ? v: v.split(' ');
}
private classes: string[] = [];
constructor(private renderer: Renderer2, private element: ElementRef){}
#HostListener('mouseover')
onHover(){
this.classes.forEach(c=> this.renderer.addClass(this.element.nativeElement, c));
}
#HostListener('mouseleave')
onLeave(){
this.classes.forEach(c=> this.renderer.removeClass(this.element.nativeElement, c));
}
}
After making it available for consume, you could use it in a component as follows:
<div *ngFor = 'let item of feed; let i = index;' ngHoverClass='hover' class="mentions">
<div *ngFor="let item of feed; let i = index;" [ngClass]="{'hovered': item.isHovered'}" (mouseover)="item.isHovered=true" (mouseout)="item.isHovered=false">
I'm developing a react application and I recently start to use semantic ui react module.
Unfortunately I'm not able to make the Tab object responsive...
A really simple script to show this is:
import React from 'react'
import { withRouter } from 'react-router-dom'
import {Tab} from 'semantic-ui-react';
// import NavSection from './NavSection'
var sections = ["SectionA","SectionB","SectionC","SectionD","SectionE","SectionF"]
const NavigatorHeader = () => (
<div>
<h1>Navigator</h1>
<div>
<Tab menu={{ pointing: true }} panes={getPanes(sections)} />
</div>
</div>
)
export default withRouter(NavigatorHeader)
function getPanes(sections){
return sections.map( function(section){
return {
menuItem: section,
render: () =>
<Tab.Pane attacched="false">
<div>
<p>
Some Text that we can change tab from tab. E.g. with the title: <b>{section}</b>
</p>
</div>
</Tab.Pane>
}
})
}
The tabs look great, inline, but if I reduce the screen they just overflow, while I was expecting they would have moved to a second line.
Look like that this is coming from the Selenium-ui css I'm using (https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css). Current version is 2.3.1 but if I go back to use a version before 2.0.0, it was responsive.. is there a way to obtain the same behavior with the new version?
Thanks,
Michele.
Thanks,
Michele.
Based on the previous answer I found an easier way to achieve this.
I defined a CSS with the values suggested:
.wrapped{
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
and then just passed that additional class to the menu
<Tab menu={{ pointing: true, className: "wrapped" }} panes={getPanes(sections)} />
That solved the problem without any additional javascript.
Here is a solution that I created some time ago in regular Semantic. It behaves like Bootstrap and does not require a second set of menu items. It requires just a tiny bit of JS and CSS.
The JS:
$(function() {
// Set up to handle wrapping of tab menu (tab actuator) items
$(window).resize(function() {
checkIfWrapped();
});
checkIfWrapped(); // Make sure the function is fired upon document ready
});
// Detect whether a Semantic UI tabular menu is wrapped
function checkIfWrapped() {
var pos_top_1st = $('.tabular.menu .item').first().position().top;
$('.tabular.menu .item:not(first-child)').each(function() {
var pos_top = $(this).position().top;
if (pos_top > pos_top_1st) {
$(this).parent().addClass('wrapped');
return;
} else if (pos_top == pos_top_1st) {
$(this).parent().removeClass('wrapped');
}
});
The HTML structure. (Note that placing the .tabular.menu .item-s inside a div within the overall .tabular.menu allows the use of a separate .right.menu within the .tabular.menu if desired) :
<div id="tabs-menu" class="ui top attached tabular menu">
<div id="qj-tabs">
<div class="tab item"></div>
<div class="tab item"></div>
<div class="tab item"></div>
</div>
<div class="right menu">
<a class="tab item"><i class="add icon"></i> Add Job</a>
<a class="tab item"><i class="copy icon"></i> Copy Item</a>
</div>
</div>
<div class="botttom attached tab segment"></div>
<div class="botttom attached tab segment"></div>
</div>
The CSS:
#qj-tabs {
display: flex !important; /* Will not work unless defined as display: flex */
flex-direction: row !important;
flex-wrap: wrap !important;
}
#tabs-menu .wrapped .item {
border-radius: 5px !important;
border: 1px lightgray solid !important; /* Just styling for the default theme here */
margin: 0 2px 2px 0 !important;
}
#tabs-menu .wrapped .active.item {
background-color: lightgray;
}
This is what i did some weeks ago in regular Semanitic-ui.
! function($) {
var WinReszier = (function() {
var registered = [];
var inited = false;
var timer;
var resize = function(ev) {
clearTimeout(timer);
timer = setTimeout(notify, 100);
};
var notify = function() {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
registered[i].apply();
}
};
return {
register: function(fn) {
registered.push(fn);
if (inited === false) {
$(window).bind('resize', resize);
inited = true;
}
},
unregister: function(fn) {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
if (registered[i] == fn) {
delete registered[i];
break;
}
}
}
};
}());
var TabDrop = function(element, options) {
this.element = $(element);
var $this = this;
this.dropdown = $('<div class="ui item right dropdown" data-popup data-content="' + options.text + '" data-position="bottom center">' +
options.icon +
'<div class="menu"></div>' +
'</div>').appendTo($this.element);
this.click = function() {
$this.element.removeClass("pointing");
$this.element.find("a.item").not(this).removeClass("active");
};
this.reverseclick = function(el) {
$this.element.find(".item.right.dropdown .menu a.item").removeClass("active selected");
$this.element.addClass("pointing");
};
WinReszier.register($.proxy(this.layout, this));
this.layout();
$(".ui.dropdown").dropdown();
$("[data-popup]").popup();
};
TabDrop.prototype = {
constructor: TabDrop,
layout: function() {
var $main = this;
var $this = this.element;
var $drpdwn = this.dropdown;
var $fullwidth = $this.width() - 25;
this.element
.append($drpdwn.find('.ui.item.right'))
.find('a.item')
.not('.item.right.dropdown')
.each(function() {
var $blockLenght = parseInt($(this).width());
var $space = $fullwidth - $blockLenght;
if ($space > $blockLenght) {
$(this).click($main.reverseclick)
if ($drpdwn.find('.menu a').length > 0) {
var $reverse = $drpdwn.find('.menu a:first-child');
$reverse.click($main.reverseclick).removeClass("selected")
$reverse.insertBefore($drpdwn);
}
} else {
var $dropItem = $(this)
$dropItem.click($main.click)
$drpdwn.find('.menu').append($dropItem);
}
$fullwidth = $space;
});
}
};
$.fn.tabdrop = function(option) {
return this.each(function() {
var $this = $(this),
data = $this.data('tabdrop'),
options = typeof option === 'object' && option;
if (!data) {
$this.data('tabdrop', (data = new TabDrop(this, $.extend({},
$.fn.tabdrop.defaults, options))));
}
if (typeof option == 'string') {
data[option]();
}
});
};
$.fn.tabdrop.defaults = {
text: 'More',
icon: '<i class="icon align justify m-0"></i>'
};
$.fn.tabdrop.Constructor = TabDrop;
}(window.jQuery);
var Tabs = {
tabDrop: function() {
setTimeout(function() {
$('.tabdrop').tabdrop({
text: 'More Configuration'
});
}, 1000)
}
};
$(document).on("ready", function() {
$('.menu .item').tab();
Tabs.tabDrop();
$(window).resize(function() {
Tabs.tabDrop();
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.js"></script>
<div class="ui top attached pointing menu tabdrop">
<a class="item" data-tab="tab1">Tab Item 1</a>
<a class="item" data-tab="tab2">Tab Item 2</a>
<a class="item" data-tab="tab3">Tab Item 3</a>
<a class="item" data-tab="tab4">Tab Item 4</a>
<a class="item" data-tab="tab5">Tab Item (A very long tab title)</a>
</div>
I need to set the background color of a div based on a prop passed into my react component. Inline styling of React components I am pretty clear on, but I don't know how to correctly apply the inline style to change depending on a prop. I only want to assign the value of the prop rightSideColor in the inline styling of right-toggle if the prop selected is equal true.
export default function UiToggle(props) {
const { leftLabel, rightLabel, selected, rightSideColor, leftSideColor } = props;
return (
<div className="lr-toggle-select" style={{ width: `${width}px` }} >
<div className="lr-gray-background" />
<div>
{leftLabel}
</div>
<div className={'lr-toggle right-toggle' style={{ selected ? (backgroundColor: rightSideColor) : null }}>
{rightLabel}
</div>
</div>
);
}
Fixed a typo - { before className
and you can return an empty object if selected is false else the expected value
Example:
export default function UiToggle(props) {
const { leftLabel, rightLabel, selected, rightSideColor, leftSideColor } = props;
return (
<div className="lr-toggle-select" style={{ width: `${width}px` }} >
<div className="lr-gray-background" />
<div>
{leftLabel}
</div>
<div className='lr-toggle right-toggle' style={ selected ? {backgroundColor: rightSideColor} : {} }}>
{rightLabel}
</div>
</div>
);
}
I would suggest placing all styling and also the conditional operator in a separate const.
export default function UiToggle(props) {
const { leftLabel, rightLabel, selected, rightSideColor, leftSideColor } = props;
const rightToggleStyle = {
backgroundColor: selected ? rightSideColor : null
};
return (
<div className="lr-toggle-select" style={{ width: `${width}px` }} >
<div className="lr-gray-background" />
<div>
{leftLabel}
</div>
<div className="lr-toggle right-toggle" style={rightToggleStyle}>
{rightLabel}
</div>
</div>
);
}
I would try to do the same with the styling of the width. Good luck!
You can conditionally set the value of attributes like style, override them using rules of precedence, and determine whether to include them at all.
export default function UiToggle(props) {
const { leftLabel, rightLabel, selected, rightSideColor, leftSideColor } = props;
//specify style and id (and any other attributes) or don't.
const attrs = selected ? { style: { backgroundColor: "rightSideColor" },id:"hi123" }:{}
//Conditionally override the class names if we want:
if (props.className) attrs.className = props.className
return (
<div className="lr-toggle-select" style={{ width: `${width}px` }} >
<div className="lr-gray-background" />
<div>
{leftLabel}
</div>
{/*Use the spread operator to apply your attributes from attr*/}
{/*Note that the 'id' set below can't be overridden by attrs whereas*/}
{/*className will be. That's because precedence goes from right to left.*/}
{/*Rearrange them to get what you want.*/}
{/*Funky comment format is to make valid JSX and also make SO formatter happy*/}
<div className='lr-toggle right-toggle' {...attrs} id="attrs_cant_override_this_because_its_on_the_right">
{rightLabel}
</div>
</div>
);
}
Try something like this:
<div className='lr-toggle right-toggle' style={ selected ? {backgroundColor: rightSideColor} : '' }}>
{rightLabel}
</div>
Actually, I need to activate the background color of a div based on the specific value given by the user. So I have done something like this. And don't know how to go further.
<template>
<div>
<div class="row" style="padding-left:6vw; padding-right:6vw;">
<button #click="r_id = 1"><q-icon name="thumb_up" class="reaction col-auto" style="font-size: 3rem;" /></button>
<button #click="r_id = 2"><q-icon name="ion-happy" class="reaction col-auto" style="font-size: 3rem;" /> </button>
<button #click="r_id = 3"><q-icon name="ion-ios-heart" class="reaction col-auto" style="font-size: 3rem;" /> </button>
<button #click="r_id = 4"><q-icon name="ion-sad" class="reaction col-auto" style="font-size: 3rem;" /></button>
<button #click="r_id = 5"><q-icon name="thumb_down" class="reaction col-auto" style="font-size: 3rem;" /></button>
</div>
<div class="button-group">
<q-btn class="button" push color="amber-7" style="width: 75px" #click="Reset()">Reset</q-btn>
<q-btn class="button" push color="positive" style="width: 75px" #click="Submit()">Submit</q-btn>
</div>
</div>
<div v-bind:class="[{active1: r_id === 1},{active2: r_id === 2},{active3: r_id === 3},{active4: r_id === 4},{active5: r_id === 5}]" >
Mycard
</div>
<template>
And my script part is:
export default {
components: {
QBtn,
QIcon
},
data () {
return {
r_id: '',
name: '',
toName: ''
}
},
computed: {
className () {
return 'active' + this.r_id
}
},
methods: {
Submit: function () {
this.hardcode = {
'r_id': this.r_id,
'user_name': 'Shine',
'fb_title': this.fbTitle,
'fb_id': this.id,
'fb_descrption': this.fbDescription,
'created_time': '10 hours ago',
'user_id': '1'
}
this.fbList.push(this.hardcode)
this.Reset()
this.id++
}
}
and my css part is:
active1{background:red;}
active2{background:black;}
active3{background:green;}
active4{background:yellow;}
active5{background:white;}
So how should I go on using Vuejs?
Seems like r_id already have the correct number so just use a simple computed property:
<div :class="className" >
Mycard
</div>
computed: {
className () {
return 'active' + this.r_id
}
}