I have a CSS declaration as follows:
span.boshbashbosh:nth-child(1):active:after {
content: 'FC';
}
I am trying to access the content (FC) it by using:
var content = window.getComputedStyle(document.getElementsByClassName("boshbashbosh:nth")[0], '::active').getPropertyValue('content');
alert(content);
However, all the alert does is show normal or none
Any advice on how to do this in plain JS? If I had 1000 of these, I wouldn't want to click/hover each one, is there a way I could dump some code into the developer console to do this?
There are a few issues here, the main one being that the CSS selector will only return an active element during a click interaction by the user, seeing that a click interaction causes the target element to become :active.
With that in mind, you could wrap your login in a mousedown element as shown below to extract the expected content value while the corresponding span element is :active as shown:
document.addEventListener("mousedown", () => {
/* When mouse down occours, look for the element that we want to read
pseudo content from */
var element = document.querySelector(".boshbashbosh:nth-child(1):active");
if (element) {
/* If the target element is active, read the content of the ::after
pseudo element */
var content = window.getComputedStyle(element, ":after")
.getPropertyValue("content");
alert(content);
}
})
span.boshbashbosh:nth-child(1):active:after {
content: 'FC';
}
/* Added for clarity/usability of snippet */
span {
background: pink;
margin: 1rem 0;
padding: 1rem;
display: block;
height: 1rem;
}
span.boshbashbosh:active {
background: yellow;
}
<p>Clicking first box alerts the ::after content</p>
<div>
<span class="boshbashbosh"></span>
<span class="boshbashbosh"></span>
<span class="boshbashbosh"></span>
</div>
I've also replaced the getElementsByClassName() call with querySelector() to simplify the code. Hope that helps!
Update
To access the content of multiple pseduo elements, you could adapt the snippet above as follows:
document.querySelectorAll(".boshbashbosh").forEach((element) => {
var content = window.getComputedStyle(element, ":after")
.getPropertyValue("content");
console.log(content);
});
span.boshbashbosh:nth-child(1):after {
content: 'FC';
}
span.boshbashbosh:nth-child(2):after {
content: 'EB';
}
span.boshbashbosh:nth-child(3):after {
content: 'DA';
}
<div>
<span class="boshbashbosh"></span>
<span class="boshbashbosh"></span>
<span class="boshbashbosh"></span>
</div>
Related
Hi,
I have this markup:
<div data-users="room2">
<span data-room="room1,room2,room3">john</span>
<span data-room="room1">george</span>
<span data-room="room2">jane</span>
</div>
I want only users that have the same room data as the div parent so I wrote this css:
span { display: none; }
[data-users="room2"] [data-room*="room2"] { display: block; }
fiddle: https://jsfiddle.net/ehpt9f5z/2/
However, since the data in the div parent can change to any room number I need a variable there so the CSS selector will always match the room data from the child with its parent, something like this:
[data-users=$1] [data-room*=$1] { display: block; }
Is it even possible with pure css?
Thank you.
This is not accomplishable with CSS alone, since there is no CSS parent selector.
A JavaScript solution would be to loop through each div which has the data-users attribute, then loop through each child of the div and show the ones whose data-room attribute contains the data-users attribute value.
const divs = document.querySelectorAll('div[data-users]')
divs.forEach(e => [...e.children].forEach(f => {
if(f.dataset.room.split(',').includes(e.dataset.users)){
f.style.display = "block"
}
}))
span { display: none; }
<div data-users="room2">
<span data-room="room1,room2,room3">john</span>
<span data-room="room1">george</span>
<span data-room="room2">jane</span>
</div>
I'm running into an issue where the getElementById() function is unable to get a particular element on the page that has the display: none property applied to it, even though it's visible in the DOM (I can see that the div and its id exists on the final rendered page).
Is there a way around this?
Here's the code:
togglePanel() {
const panelId = this.accordionItem.querySelector("#collapsible-panel");
this.shouldShowAccordion = !this.shouldShowAccordion;
if (this.shouldShowAccordion) {
panelId.classList.remove("collapsed");
}
else {
panelId.classList.add("collapsed");
}
}
"collapsible-panel" is the ID of the div which has display: none applied to it.
setTimeout(() => {
document.querySelector("div[id='collapsiblepanel']").style.display = 'block';
}, 2000)
#collapsiblepanel {
width: 200px;
height: 100px;
background-color: red;
display: none;
}
Following is ana example where I am selecting a div which has the value of display as none. After 2 seconds I am setting up it's display to block.
<div id="collapsiblepanel">
</div>
Currently, I have a button class which lets me place a clickable button inside a sentence, and a div class which lets me add content to the button which I placed at the end of the paragraph containing the sentence.
This is an example of how I use them
Try to click <button class="col">THIS</button> and see what happens.
<div class="con">nice!</div>
Did you try?
When this text is displayed on the page, the two sentences are placed inside two different paragraphs, so the div object is placed between them.
Here is a snippet with the css classes and the javascript.
( function() {
coll = document.getElementsByClassName("col");
conn = document.getElementsByClassName("con");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].setAttribute('data-id', 'con' + i);
conn[i].setAttribute('id', 'con' + i);
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = document.getElementById(this.getAttribute('data-id'));
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
} )();
.col {
cursor: help;
border-radius: 0;
border: none;
outline: none;
background: none;
padding: 0;
font-size: 1em;
color: red;
}
.con {
padding: 0 1em;
max-height: 0;
overflow: hidden;
transition: .3s ease;
background-color: yellow;
}
Try to click <button class="col">THIS</button> and see what happens.
<div class="con">nice!</div>
Did you try?
I wonder if it is possible to implement a shortcut to place the two objects with one command, that is to obtain the previous example by using something like this
Try to click [[THIS|nice!]] and see what happens.
Did you try?
What I mean is that the command [[THIS|nice!]] should place the object <button class="col">THIS</button> in the same position and the object <div class="con">nice!</div> at the end of the paragraph containing the command.
Is it possible to implement such a command (or a similar one)?
EDIT
I forgot to say that the content of the button, ie what is written inside the div, should also be possible to be a wordpress shortcode, which is a shortcut/macro for a longer piece of code or text.
Using jQuery, closest() find the nearest <p> element and add <div class="con">nice!</div> after <p> element. To toggle you can use class active and add or remove .con element.
$('.col').click(function(){
let traget = $(this).closest('p');
if(traget.hasClass('active')) {
traget.removeClass('active');
traget.next('.con').remove();
} else {
traget.addClass('active');
traget.after(`<div class="con">${$(this).data('message')}</div>`);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Try to click <button class="col" data-message="Hello">THIS</button> and see what happens.</p>
<p>Did you try?</p>
You usually dont use div to type text. you use it to define areas or group items. you could obtain what youre asking for in a 1 sentence like this:
html
<h1> some random text <a class="btnID">button</> some more text<h1>
css
.btnID {
color: red;
}
I appended a few divs with inside img tags. Every tag has own unique id = "theImg"+i where "i" is number. I want to mouseover on specific img and show the content of span (which also have specific id with number). Here is my code so far but not working.
var j;
document.onmouseover = function(r) {
console.log(r.target.id);
j = r.target.id;
}
$(document).on({
mouseover: function(e){
$("span").show();
},
mouseleave: function(e){
$("span").hide();
}
}, "img#"+j);
If you have a span after every img, maybe it's a good idea to not use JavaScript at all? ;-)
You could use :hover pseudoclass in CSS, making your thing always work reliably.
Consider the following example:
img + span {
display: none;
}
img:hover + span {
display: block;
}
/*/ Optional styles /*/
div {
position: relative;
float: left;
}
div img + span {
position: absolute;
color: #fff;
background: #27ae60;
border: solid 1px #2ecc71;
border-radius: 50px;
z-index: 1;
bottom: 1em;
width: 80%;
left: 50%;
margin-left: -43%;
padding: 2% 3%;
text-align: center;
}
<div>
<img src="https://placehold.it/400x200">
<span>This is an image of a gray rectangle!</span>
</div>
<div>
<img src="https://placehold.it/200x200">
<span>This is an image of a gray square!</span>
</div>
<div>
<img src="https://placekitten.com/g/400/200">
<span>This is an image of a cute kitten inside a rectangle!</span>
</div>
<div>
<img src="https://placekitten.com/g/200/200">
<span>This is an image of even cuter kitten inside a square!</span>
</div>
So the issue is that you are trying to set your handler on a dynamic selector ("img#"+j) but this will not work. For one thing, that equation will be evaluated only once, on page load, when j is undefined.
So you want to do this instead:
target only img tags for your mouse over... Better yet, give your special images all the same css class so you can attach the event handlers only to those. That will be more efficient.
When an image is moused over or out of, grab it's id attribute, extract the number from it, then use that to build a selector for the appropriate span to show.
var get_span_from_image = function(image) {
var image_id = image.attr("id");
var matches = image_id.match(/theImg(\d+)/);
if(matches) return $("theSpan" + matches[1]);
return $(); // nothing found, return an empty jQuery selection
};
$("img").hover(
function() { // mouse over
get_span_from_image($(this)).show();
},
function() { // mouse out
get_span_from_image($(this)).hide();
}
);
Note: There are better ways to "link" two nodes together, but this is just to answer your question with the current structure you have.
UPDATE: Some ideas to link two nodes together
So instead of trying to extract a number from an id attribute, a better way would be to tell either one of the image or span about it's sibling. You could output your html like this, for instance:
<img id="theImg1" data-target="theSpan1" class="hoverable" src="..."/>
....
<span id="theSpan1">...</span>
Of course now your ideas could be anything - you don't have to use numbered values or anything.
Then your hover code becomes quite simply:
var get_span_from_image = function(image) {
var span_id = image.data("target");
return $("#" + span_id);
};
$("img").hover(
function() { // mouse over
get_span_from_image($(this)).show();
},
function() { // mouse out
get_span_from_image($(this)).hide();
}
);
Hope this helps!
I have the following case: (styling is done in SASS and unnecessary stylings are omitted.)
.header {
...
&::before {
...
position: absolute;
height: 0.5rem;
...
}
}
This creates a bar on top of the application's menu bar. In certain cases this bar has to be removed. I have read questions like these, but with no success. What would be the best way to remove this bar added by the ::before selector?
Only CSS can remove pseudo element, so you need to have an other class that display:none; the before. First declare that class in the CSS :
.header {
...
&::before {
...
position: absolute;
height: 0.5rem;
...
}
&.no-before::before{
display:none;
}
}
Then, when you want to remove it :
$('.header').addClass('no-before'); //Remove before
$('.header').removeClass('no-before'); //Re-add before
The usual way is to create a more specific rule that applies to the element(s) in question (or a later rule with the same specificity), and specify display: none to hide the pseudo in that case.
For example: Here, I want to have an X in front of <span class="foo">, but not if they're in .header:
span.foo::before {
content: 'X ';
}
.header span.foo::before {
display: none;
}
<div>
These have the X:
<span class="foo">span.foo 1</span>
<span class="foo">span.foo 2</span>
<span class="foo">span.foo 3</span>
</div>
<div class="header">
These don't:
<span class="foo">span.foo 4</span>
<span class="foo">span.foo 5</span>
<span class="foo">span.foo 6</span>
</div>
If you are manipulating the DOM by using JavaScript, you can add a class name - for instance .remove-bar - to the element having .header in order to remove the pseudo-element (generated content):
.remove-bar {
&::before { content: none; }
}
Also make sure that it is placed after the previous styles, or use a more specific selector if needed.
For remove special element use this method.
<button onclick="myFunction()">Remove</button>
<div id="myList">
<div> Coffee </div>
<div id="child2" > Tea </div>
<div> Milk </div>
</div>
your JavaScript :
<script>
function myFunction() {
const list = document.getElementById("myList");
if (list.hasChildNodes()) {
list.removeChild(list.children[0]);
}
}
</script>
you can combine above function with this code:
const parent = document.getElementById('myList');
const children = parent.children;
let index = -1;
for (let i = 0; i < children.length; i++) {
if (children[i].id === 'child3') {
index = i;
break;
}
}
alert(index); // 👉️ 2