How to check for text created by CSS? - html

I have the following HTML:
<h4 id="myModalLabel"></h4>
I set the content in CSS:
#myModalLabel::after {
content: "gebeurtenis";
}
jsFiddle
This way, Behat can't seem to find the text when running this for example:
Scenario: Viewing gebeurtenis
Given I am on "hrm/calendar"
Then I should see "gebeurtenis"
The result:
Then I should see "gebeurtenis" # HRMContext::assertPageContainsText()
The text "gebeurtenis" was not found anywhere in the text of the current page. (Behat\Mink\Exception\ResponseTextException)
How can I make it so this test will be successfull?

May I suggest a little trick, css att(), to use a text in a pseudo and at the same time have it accessible in the DOM
h4:after {
content: attr(data-txt);
}
<h4 id="myModalLabel" data-txt="gebeurtenis">Here we go ... </h4>
If you still need to look for a text that might be (or you know) in a css rule, then you can do like this, though to scan all elements looking for "text hidden in pseudo css" might not be that speedy.
var element = document.getElementById('div_1'),
style = window.getComputedStyle(element,':after'),
value = style.getPropertyValue('content').replace(/^\"|\"$/gm,''),
result = document.getElementById('result');
if(value.length > 0) {
result.innerHTML = 'Found in css: ' + value;
}
#div_1 {
color: red;
}
#div_1:after {
content: 'world';
color: blue;
}
#result {
margin-top: 20px;
}
<div id="div_1">hello </div>
<div id="result"></div>

Related

How to display different text and links in html depending on the class that its embedded in

I want to display different text and links depending on the category/class that the code is embedded in.
The following works in that it displays "Read more about Apples" or "Read more about Oranges" depending on the category/class that the code is embedded in. However I also want it to include different hyperlinks. I thought that the last two lines would do the job but the text doesn't appear with hyperlinks in it. Any ideas?
<style>
.category-apples themainbodya::after {
content: " Apples";
}
.category-oranges themainbodyb::after {
content: " Oranges";
}
</style>
<p>Read more about</p>
<themainbodya href=https://testa.test.com/ ></themainbodya>
<themainbodyb href=https://testo.test.com/ ></themainbodyb>
I am a little worried that using pseudo elements that way could make the site a little less accessibility friendly as screen readers may not read out their content.
This snippet uses a slightly different method, the text 'apples', 'oranges' (and any other fruit) is put into the relevant element (as is an image just to show one way of it being done, though you may prefer to use background-image). Those elements are set to display: none initially, and then they display depending on which of the categories is set in the class list of the containing element.
As there are only two elements in the test, the toggle function is used to go between them, but of course for more elements you will want a bit more JS to remove the unwanted classes.
*[class*="themainbody"] {
display: none;
}
.category-apples .themainbodya {
display: block;
}
.category-oranges .themainbodyb {
display: block;
}
.container img {
width: 100px;
height: 100px;
}
<button onclick="const c = document.querySelector('.container'); c.classList.toggle('category-oranges'); c.classList.toggle('category-apples');">Toggle between oranges and apples</button>
<div class="container category-oranges">
<p>Read more about</p>
<a class=themainbodya href=https://testa.test.com/><img src="https://i.stack.imgur.com/W4FFq.jpg" alt="apple">Apples</a>
<a class=themainbodyb href=https://testo.test.com><img src="https://i.stack.imgur.com/wsIvt.png" alt="orange">Oranges</a>
</div>
Thanks to the hint from A Haworth I worked out the answer. HOWEVER I still can't work out how to add a different image depending on whether it's apples or oranges.
<style>
.category-apples .themainbodya::after {
content: " Apples";
}
.category-oranges .themainbodyb::after {
content: " Oranges";
}
</style>
<p>Read more about</p>
<a class=themainbodya href=https://testa.test.com/ ></a>
<a class=themainbodyb href=https://testo.test.com/ ></a>
The answer from A Haworth is excellent. I added to it to get a default too. I expect it can be optimised, so feel free to make further suggestions.
<style>
*[class*="themainbody"] {
display: none;
}
*[class*="samsdefault"] {
display: block;
}
.category-apples .themainbodya {
display: block;
}
.category-apples .samsdefault {
display: none;
}
.category-oranges .themainbodyb {
display: block;
}
.category-oranges .samsdefault {
display: none;
}
.container img {
width: 100px;
}
</style>
<button onclick="const c = document.querySelector('.container'); c.classList.toggle('category-oranges'); c.classList.toggle('category-apples');">Toggle between oranges and apples</button>
<div class="container category-oranges">
<p>Read more about</p>
<a class=themainbodya href=https://testa.test.com/><img src="https://i.stack.imgur.com/W4FFq.jpg" alt="apple">Apples</a>
<a class=themainbodyb href=https://testo.test.com><img src="https://i.stack.imgur.com/wsIvt.png" alt="orange">Oranges</a>
<a class=samsdefault href=https://testd.test.com /><img src="https://i.stack.imgur.com/wsIvt.png" alt="carrot"><br>Carrots</a>
</div>

Append symbol to end of input which leads value

I have an input field that accepts a percent, but I'd like to indicate to the user that the value they are entering is a percent.
The problem I'm having is that I'd like the percent to lead the text, so in the input it looks like this: 100% or 10000%, but I don't want the % to be part of the actual input.
Is there a way to achieve? I've tried a couple of options to do this with CSS but fall short when the % value doesn't actually adjust the placement in the input. Instead it's always appended to the very end of the input field instead of catching up with the input.
The component looks like this:
class Input extends Component {
constructor(props) {
super(props);
this.state = {
isActive: false,
}
}
render() {
return (
<div>
<input
value={this.props.value} >
</input>
</div>
)
}
}
CSS:
div {
input:after {
content: '%';
position: absolute;
top: 3.4rem;
z-index: 9999;
color: blue;
font-size: 2rem;
}
}
Example of what I'm trying to achieve, the highlighted text in the example below is what I want the user to be able to edit, and the % to dynamically move depending on the length of the input.
It's easy by using data-attribute on a container (because input cannot handle :before and :after, [More here]) and CSS content:attr()
update = function(el) {
el.parentElement.setAttribute('data-value', el.value)
}
div[data-value] {
position: relative;
}
div[data-value]:after {
content: attr(data-value) "%";
position: absolute;
top: 2px; /* Borders */
left: 2px; /* Borders */
}
div[data-value] input {
color: #FFF; /* Optional bug avoid visual bugs */
}
<div data-value="0.01">
<input value="0.01" oninput="update(this)"/>
</div>
PS: I did it on vanillia but it's easy to update in React
Using jQuery:
$("#input").on("keyup", function(){
$(this).val($(this).val().replace(/[^0-9]/gi, '') + '%')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input"/>
This would make it so there's always a % sign at the end and they cannot remove it or add anything except for numbers!
You can also convert this to regular Javascript if you wanted to

Getting element by ID in coffeescript

I'm trying to create a HTML widget:
HTML:
<div>
<h1 class="title" data-bind="title">Title</h1>
<div>
<h1 id = "dc1" class="dc">DC1</h1>
</div>
<div>
<h1 id = "dc2" class="dc">DC2</h1>
</div>
<p class="updated-at" data-bind="updatedAtMessage"></p>
</div>
And I need to be able to set the background color of the id="dc1" and id="dc2" elements dynamically in CoffeeScript. I plan to do this by adding a class with a background color setting:
SCSS:
&.up {
background-color: green;
}
&.down {
background-color: red;
}
.dc {
background-color: orange;
font-size: 30px;
float: left;
width: 50%;
}
So far I have managed to set the whole widget background but not the child elements mentioned above:
I have been using:
CoffeeScript:
$(#node).removeClass('up down')
$('#dc1').removeClass('up down')
$('#dc2').removeClass('up down')
$(#node).addClass('down')
$('#dc1').addClass('down')
$('#dc2').addClass('up')
Note ultimately I will add the classes depending on some data rather than hard coding them to 'up' or 'down' in the coffeescript.
But nothing happends.. Am I getting selecting the id="dc#" elements correctly?
If it helps with context I'm doing this for Dashing
Your SCSS doesn't make sense so I'd guess that your missing an error from the SCSS-to-CSS conversion. An & in SCSS is a reference to the parent selector:
& will be replaced with the parent selector as it appears in the CSS
so have &.up at the top level makes no sense and should generate an error. If we fix the SCSS so that .up and .down apply only to .dc:
.dc {
/* ... */
&.up {
background-color: green;
}
&.down {
background-color: red;
}
}
then everything seems to work just fine.
Demo: http://jsfiddle.net/ambiguous/9y9uywm9/
You can use Sassmeister (and other similar online tools) to see what SCSS thinks of your original SCSS.

How to override and reset a background-color property from a hover rule?

Is there a way to reset a background-color property of a :hover rule?
I have a list of elements which are highlighted when mouse goes over. I want to apply an additional CSS rule that will disable highlighting. Here is a demo:
http://jsfiddle.net/vqLuU/1/
What should I put in the second appearance of the "style1:hover" rule in order to disable highlighting at all? The result must be the same with case when all "style1:hover" rules are removed.
I do not want to redefine all styles ("green" and "blue") again. My goal is to disable the "style1:hover" rule.
HTML:
<div class="style1 green">AAA</div>
<div class="style1 blue">BBB</div>
CSS:
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.style1:hover {
background-color: red;
}
.style1:hover {
/* How to disable highlighting from here? */
}
Thanks!
Since the first appearance of the .style1:hover rule cannot be changed or removed, the only way to achieve that is by adding the following rules:
.green:hover {
background-color: green;
}
.blue:hover {
background-color: blue;
}
I feel the need to add a disclaimer: this solution is not very elegant, and I don't think of it as the best solution, I think it's the only possible solution given the requirements.
Note: this may not be a viable solution as you have not mentioned whether you can use JavaScript.
You can remove the CSS rule by editing the stylesheets with JavaScript. However it doesn't feel right to me, so I can't fully recommend this =) Maybe other SOers can comment on this method (see jsFiddle).
for (var i = 0; i < document.styleSheets.length; i++ ) {
var done = false;
var sheet = document.styleSheets[i];
# Some browsers use rules (Chrome) others use cssRules (Firefox)
var rules = sheet.rules || sheet.cssRules;
for (var j = 0; j < rules.length; j++) {
var rule = rules[j];
var selectorText = rule.selectorText;
if (selectorText.indexOf(".style1:hover") != -1) {
sheet.deleteRule(j);
done = true;
break;
}
}
if (done) break;
}
.style1:hover {
background-color: red;
}
.style1:hover {
background-color: transparent !important;
}
Easiest way I can think to achieve what I think you want is to add an extra class to the elements. I've chosen 'hoverEnabled'
You can simply add or remove the class hoverEnabled to an element to have a different :hover style attached.
CSS
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.style1.hoverEnabled:hover {
background-color: #FFAAAA;
}
.style2.hoverEnabled:hover {
background-color: #AAAAAA;
}
HTML
<div class="style1 green">AAA</div>
<div class="style1 blue">BBB</div>
<div class="style1 hoverEnabled green">AAA</div>
<div class="style2 hoverEnabled blue">BBB</div>

HTML5 placeholder disappears on focus

Is there a freely available jQuery plugin that changes placeholder behavior to match HTML5 spec?
Before Focus
On Focus Good (Safari)
On Focus Bad (Chrome, Firefox)
You can what your browser does with this simple fiddle.
HTML5 draft spec says:
User agents should present this hint to the user, after having stripped line breaks from it, when the element's value is the empty string and/or the control is not focused (e.g. by displaying it inside a blank unfocused control and hiding it otherwise).
The "/or" is new in current draft so I suppose that's why Chrome and Firefox don't support it yet. See WebKit bug #73629, Chromium bug #103025.
Stefano J. Attardi wrote a nice jQuery plugin that just does that.
It is more stable than Robert's and also fades to a lighter grey when the field gets focused.
See the demo page
Grab it on GitHub
Play with the fiddle
I modified his plugin to read placeholder attribute as opposed to manually creating a span.
This fiddle has complete code:
HTML
<input type="text" placeholder="Hello, world!">
JS
// Original code by Stefano J. Attardi, MIT license
(function($) {
function toggleLabel() {
var input = $(this);
if (!input.parent().hasClass('placeholder')) {
var label = $('<label>').addClass('placeholder');
input.wrap(label);
var span = $('<span>');
span.text(input.attr('placeholder'))
input.removeAttr('placeholder');
span.insertBefore(input);
}
setTimeout(function() {
var def = input.attr('title');
if (!input.val() || (input.val() == def)) {
input.prev('span').css('visibility', '');
if (def) {
var dummy = $('<label></label>').text(def).css('visibility','hidden').appendTo('body');
input.prev('span').css('margin-left', dummy.width() + 3 + 'px');
dummy.remove();
}
} else {
input.prev('span').css('visibility', 'hidden');
}
}, 0);
};
function resetField() {
var def = $(this).attr('title');
if (!$(this).val() || ($(this).val() == def)) {
$(this).val(def);
$(this).prev('span').css('visibility', '');
}
};
var fields = $('input, textarea');
fields.live('mouseup', toggleLabel); // needed for IE reset icon [X]
fields.live('keydown', toggleLabel);
fields.live('paste', toggleLabel);
fields.live('focusin', function() {
$(this).prev('span').css('color', '#ccc');
});
fields.live('focusout', function() {
$(this).prev('span').css('color', '#999');
});
$(function() {
$('input[placeholder], textarea[placeholder]').each(
function() { toggleLabel.call(this); }
);
});
})(jQuery);
CSS
.placeholder {
background: white;
float: left;
clear: both;
}
.placeholder span {
position: absolute;
padding: 5px;
margin-left: 3px;
color: #999;
}
.placeholder input, .placeholder textarea {
position: relative;
margin: 0;
border-width: 1px;
padding: 6px;
background: transparent;
font: inherit;
}
/* Hack to remove Safari's extra padding. Remove if you don't care about pixel-perfection. */
#media screen and (-webkit-min-device-pixel-ratio:0) {
.placeholder input, .placeholder textarea { padding: 4px; }
}
Robert Nyman discusses the problem and documents his approach in his blog.
This fiddle that has all the neccessary HTML, CSS and JS.
Unfortunately, he solves the problem by changing value.
This will not work by definition if placeholder text is itself a valid input.
I found this question by googling out the solution to the same problem. It seems that existing plugins either don't work in elder browsers or hide placeholder on focus.
So I decided to roll on my own solution while trying to combine best parts from existing plugins.
You may check it out here and open an issue if you face any problems.
How about something simple like this? On focus save out the placeholder attribute value and remove the attribute entirely; on blur, put the attribute back:
$('input[type="text"]').focus( function(){
$(this).attr("data-placeholder",$(this).attr('placeholder')).removeAttr("placeholder");
});
$('input[type="text"]').blur( function(){
$(this).attr("placeholder",$(this).attr('data-placeholder'));
});
I wrote my own css3 only solution. See if that fullfills all your needs.
http://codepen.io/fabiandarga/pen/MayNWm
This is my solution:
the input element is set to "required"
an aditional span element for the placeholder is needed. This element is moved on top of the input element (position: absolute;)
with css selectors the input element is tested for validity (required fields are invalid as long as there is no input) and the placeholder is then hidden.
Pitfall: The placeholder is blocking mouseevents to the input! This problem is circumvented by hiding the placeholder element when the mouse is inside the parent (wrapper).
<div class="wrapper">
<input txpe="text" autofocus="autofocus" required/>
<span class="placeholder">Hier text</span>
</div>
.placeholder {
display: none;
position: absolute;
left: 0px;
right: 0;
top: 0px;
color: #A1A1A1;
}
input:invalid + .placeholder {
display: block; /* show the placeholder as long as the "required" field is empty */
}
.wrapper:hover .placeholder {
display: none; /* required to guarantee the input is clickable */
}
.wrapper{
position: relative;
display: inline-block;
}
Maybe you can try with Float Label Pattern :)
See Float labels in CSS