CSS Style Parent Element - css

I've got a piece of PHP code that iterates through a database lookup and each iteration adds a option to a parent select element.
I'm able to add column values from the table to the name the class of each option, which i can then refer to by using option[class*="columnvalue"]
I want to set the background color of the select element that the option belongs to.
So in short i'd like:
Parent::option[class*="xyz"]
I've seen something about the < operator but this didnt work.
echo '<select class="dropdown" name="'.$time.'-'.$group.'-'.$iteration.'-'.$new_date.'" >';
$code="";
while ($row = $result->fetch_assoc()) {
unset($firstname, $lastname);
$firstname = $row['firstname'];
$lastname = $row['lastname'];
$memberid = $row['memberid'];
$code = $row['code'];
echo '<option class="drop" value="'.$memberid.'">'.$firstname . ' ' . $lastname .'</option><option value="cancel-'.$memberid.'">Cancel</option>';
}
The following will apply to the option, but the red background only shows when the drop down menu is expanded, not when selected
option[class*="drop"]{background-color:red;}
Also tried this (which i dont believe actually is a valid operator
select < option[class*="drop"]{background-color:red;}

The proposed syntax is
select:has(option[class*="drop"]) { background-color:red; }
to select all select tags that contain option[class*="drop"] elements.
But it isn't supported by any browser yet.

Related

How to Add Bootstrap glyphicons to Woocommerce Checkout Input Fields?

I have narrowed down the code to this filter so far (found this in another SO answer):
//Checkout page editor bootstrap
add_filter('woocommerce_checkout_fields', 'addBootstrapGlyphs' );
function addBootstrapGlyphs($fields) {
foreach ($fields as &$fieldset) {
foreach ($fieldset as &$field) {
// if you want to add the form-group class around the label and the input
$field['class'][] = 'input-group';
// add form-control to the actual input
$field['input_class'][] = 'form-control';
}
}
return $fields;
}
That sets my form and input elements. Now to add glyphicons, I tried reading from $fields but I just can't seem to get a good handle to something that will let me add a span element before the input. Glyphicon needs this:
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
jQuery let's me do it this way:
<script type='text/javascript'>
jQuery(document).ready(function(){
jQuery('#billing_last_name_field').prepend('<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>');
});
</script>
but there has to be a better, more performant way to build the page with this in place already. I want to do this in php, so the checkout pageload remains fast. Please help. I come from a world of Java.
tl;dr: How to add a glyphicon to woocommerce checkout input boxes from https://github.com/woocommerce/woocommerce/blob/master/includes/wc-template-functions.php#L1920
Part 2
making progress w.r.t the above question using something like this:
// define the woocommerce_form_field_<type> callback
function filter_woocommerce_form_field_type( $field, $key, $args, $value ) {
$field = str_replace('<input','<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span><input',$field);
return $field;
};
// add the filter
add_filter( "woocommerce_form_field_email", 'filter_woocommerce_form_field_type', 10, 4 );
I know, that is not the right glyph. However, the next hurdle is to edit the html. Like Mithc mentioned in a comment below, I will now try to do this more elegantly with some type of DOM handling code.
So my follow-up question is, how do I add a DOM element the proper way with php? This time, I am looking for something like,
Convert string to DOM for processing
read some attributes from the <p> or <input>
Determine the type of glyph i should use
Add my span
Convert DOM back to string for return
Any elegant ways to do this, or is str_replace() good enough?
Apparently, there's no filter/action that allows you to modify the forms in that way. You can follow the clue of how the forms are built by checking the /templates/checkout/form-checkout.php and /includes/wc-template-functions.php.
Solution #1: Pure CSS
You could use CSS pseudo elements to add icons to the fields but due to the layout of the form, playing around with ::before and ::after could make the responsiveness a nightmare. But here's an example:
.form-row#billing_company_field {
position: relative;
padding-left: 2.8em;
}
.form-row#billing_company_field::before {
content: '';
width: 2.8em;
height: 2.8em;
background-color: #2d2e34;
position: absolute;
left: 0;
bottom: 0;
}
.form-row#billing_company_field::after {
content: "\e139";
position: absolute;
left: 0;
color: white;
font-family: 'Glyphicons Halflings';
/* Excluding position styling */
}
But as I mentioned before, the responsiveness could be a little bit like... A headache. But totally possible.
Solution #2: Template Override
WooCommerce allows you to override templates via themes. The only thing you have to do is to create a template folder in your theme's root folder.
For instance, if your theme's folder is my-store, you should have my-store/woocommerce. To override the template parts that contain the checkout form, you should have:
my-store/woocommerce/checkout/form-checkout.php
and
my-store/woocommerce/checkout/form-billing.php
Then you can modify any markup there. Just keep in mind that sometimes they update the templates, so keep an eye on them for big changes to keep them up to date too.
Solution #3: DOMDocument() [Update]
If you have the markup of each field on the filter, you can modify the output HTML with the DOMDocument() methods. Here's an example:
// Let's say this is the HTML coming from the filter.
$field = '<p class="form-row validate-required">';
$field .= '<input type="text">...';
$field .= '</p>';
// Create a DOM Object of $field. LIBXML_HTML_NOIMPLIED and LIBXML_HTML_NODEFDTD will help to prevent doctype, html and body tags being inserted at the end.
$field_object = new DOMDocument();
$field_object->loadHTML( $field, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
// Select the wrapper of the input (`<p>`) and the input (`<input />`) to know where to insert the glyph (between them).
$wrapper = $field_object->getElementsByTagName( 'p' )->item( 0 );
$input = $field_object->getElementsByTagName( 'input' )->item( 0 );
// Create the glyphicon HTML.
$glyph = $field_object->createDocumentFragment();
$glyph->appendXML( '<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>' );
// Insert the glyphicon HTML.
$wrapper->insertBefore( $glyph, $input );
The example above will get you:
<p class="form-row validate-required">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span><input type="text">...
</p>
To load attributes you can use getAttribute( $attribute_name )
on the DOMElement (like the $wrapper and $input objects). And, to determine the glyphicon you have to use, you could get the class of the $wrapper and determine the class of the glyphicon based on it. For instance, if the $wrapper contains the class user, then glyphicon's class should be glyphicon glyphicon-user which you can easily insert when you create the glyphicon HTML.

RegExp search and replace path to image in css

It is necessary to perform a search and replace strings in css file. And found only the title picture with.
While the search is done so with the exception of
/:(\s*)url\(((.(?!.*https:|.*http:|.*base64|.*data:image))*)\)/ig
and replace
:$1url(\'../dist/img/vendor/$2\')
In this case, I replace the path in a similar way. And I get this result
background-image: url('../dist/img/vendor/"../images/preloader.gif"');
A need of a string
background-image: url("../images/preloader.gif");
get
background-image: url('../dist/img/vendor/preloader.gif');
Find
/(url\(\s*[\"\'])(?:[^\"\']+\/)?([^\/\"\']+[\"\']\s*\))/ig
Replace
$1../dist/img/vendor/$2
Demo https://regex101.com/r/kU7cC9/3
Using a css parser is a better way if you want among other things to avoid quotes problems (single quotes, double quotes, no quotes).
As an aside, the background-image CSS property isn't the only one that can contain a path to an image file, since the background property can compile all the data from other background- properties.
An example with sabberworm PHP CSS Parser that automatically encloses paths between double quotes:
require __DIR__ . '/vendor/autoload.php';
define('NEW_PATH', '../dist/img/vendor/');
$oCssParser = new Sabberworm\CSS\Parser($css);
$oCssDocument = $oCssParser->parse();
$properties = ['background-image', 'background'];
foreach($oCssDocument->getAllRuleSets() as $oRuleSet) {
foreach($properties as $property) {
$oCssRules = $oRuleSet->getRules($property);
foreach ($oCssRules as $oCssRule) {
$value = $oCssRule->getValue()->__toString();
if (!preg_match('~https?:|base64|data:image~S', $value)) {
$value = preg_replace('~url\("\K(?:[^"/]*/)*~', NEW_PATH, $value);
$oCssRule->setValue($value);
}
}
}
}
echo $oCssDocument->render(Sabberworm\CSS\OutputFormat::createPretty());

Bootstrap continual thumbnail list into grid

I want to make a long list of elements, images for example that will be added into the grid which width is span12 and every elements width should be span3, that makes 4 elements in 1 row.
The problem is, when I list all the elements or I make a php function that lists them Boostrap thinks I want to put it in one row, but I don't. I want to make a new row every 4 elements or so... I want to be able to add as many <li> as I want and not worry about where another row should be.. What should I do ?
This is what happened to me, the 5th image has wrong margin on the left side. I want to make it in the same position as images in the first row.
Screenshot here
I use this php logic to echo out pictures
$dir = "../img";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if (preg_match("/.jpg/", $file)) {
echo "<li class='span3'>
<a href='$dir/$file' class='thumbnail'>
<img src='$dir/$file'>
</a>
</li>
";
}
}
closedir($dh);
}
}
And I have no idea on how to post a new row each 4th picture or so.
Row is marked as <div class='row-fluid'>
That's a common problem, and I think there's no elegant solution. Consider one of these approachings.
Solution 1 Review your iteration logic
If refactoring your PHP logic is an option, try to render a row each 4 elements (I can't suggest an specific code without viewing your current logic).
EDIT
The code for a while loop could be as follows:
<?php
$count = 1;
echo '<div class="row">';
while (your_condition) {
echo '<div class="span3">your_content</div>';
if ($count % 4 == 0) {
echo '</div>';
echo '<div class="row">';
}
$count++;
}
echo '</div>';
Solution 2 Hack the fifth element's margin
Correct the margin-left of the affected elements, so you don't need to respect the native Bootstrap markup.
.thumbnails .span4:nth-child(4n+1) {
margin-left: 0;
}
Unfortunately, that code is not compatible with Internet Explorer, so maybe you'll have to find a JavaScript or jQuery solution.

Set int color based on value being positive or negative using CSS

Quick question. I want to change the color of an int based on the value being positive or negative, using CSS if possible.
Any ideas?
In PHP you could do this:
<span style="color: <?php echo ($var < 0 ? '#FF0000' : '#00FF00'); ?>">Some text</span>
This evaluates the variable $var, if less than zero, applies red to the style (FF0000) otherwise green (00FF00).
It depends on the language you are using. In just about any language you can set the class of the tags around the value using the dynamic part of the language. If the value doesn't have its own tags you can use <span></span> around the value to give it a class. then you just use the dynamic code to set the class.
If you are using a language like Ruby there are some CSS Selectors Gems you can use but I don't know much about them or if they will help.
I use wordpress and the table with newly posted posts and custom posts are on index.php, the code I am inserting between td tags
<td style="font-weight: <?php echo ($var <= 0 ? 'normal' : 'bold'); ?>"><?php echo get_portf_posts_count_from_last_24h(); ?></td>
I tried also this code and neither this works:
<?php
if ($output <= 0) {
$output = 'normal';
print $output;
}
else // +
{
$output = 'bold';
print $output;
}
?>

Automatic CSS Preview Generator - Have css file, want to automatically generate html to preview styles

I have a fairly large CSS file developed by my web designer.
There are, of course, plenty of IDs, classes and tag properties assigned therein. Are there any tools to automatically generate HTML based on a CSS source file?
For example:
#basicInfoHead{
background:url(../images/leftHeaders.jpg) no-repeat;
margin-left: 0px;
width:185px;
height:28px;
}
#basicInfoHead span{
float: left;
}
Would generate
<div id=basicInfoHead><span>#basicInfoHead span</span></div>
Etc etc.
From there, I could preview the generated code in my browser, and see what each of the individual (primarily text) styles would look like.
Thanks in advance!
This doesn't sound really applicable to a real world stylesheet. Your example is straightforward enough (even though it would have to be a div#basicInfoHead for any generator to know what to generate) but what if it becomes more complicated? What about elements that get defined in different was for multiple pages? What about elements that need to be on top of element x, or that need an element y directly following to look well? What about "incomplete" classes e.g. for a <table><tr><th> series that doesn't define anything for the tr? What about specific rules for combined classes .class1.class2.class3?
In the list of style sheets I've been working on, there is not one that could be turned into sensible HTML code by a generator like the one you are looking for. Not sure whether a tool like this exists.
Your designer should be delivering HTML for you to test the CSS. That's the usual way and as far as I can see, the only way that really makes sense.
Here we go. I'm making several assumptions that will only hold because my designer uses a certain style:
Everything is a div
I only want to see text styles, so I'll ignore anything that doesn't seem text-related
Not my best stuff, but it works for the majority of my styles. Had to manually edit a few tags, such as ul, ol, li, and remove 'body'.
#!/usr/bin/perl
use warnings;
use strict;
my $css;
open(FILE, '<', 'styles.css') or die();
while (<FILE>) { $css .= $_; }
close(FILE);
my (#css) = $css =~ m/^([a-zA-Z.#][^\n\r]+{.+?})/gmxs;
my #text_css = grep { /\s(h[1-5]|span|font|color|p|a|ol|ul)\b/ } #css;
foreach my $css(#text_css) {
my ($selector_text) = $css =~ /^([^{]*){/;
my (#selector) = split(/[\s{]/,(split(/[\n\r]+/,$selector_text))[0]);
#selector = grep { !/{/ } #selector;
my $start_html = '';
my $middle_html = join(" ",#selector);
my $end_html = '';
my $result = '';
for (my $i=0; $i< scalar(#selector); $i++) {
$selector[$i] =~ s/:[-\w]+//g;
if (substr($selector[$i],0,1) eq '#') {
$selector[$i] =~ s/^#//g;
$start_html .= qq(<div id="$selector[$i]">);
$end_html = "</div>" . $end_html;
}
elsif (substr($selector[$i],0,1) eq '.') {
$selector[$i] =~ s/^\.//g;
$start_html .= qq(<div class="$selector[$i]">);
$end_html = "</div>" . $end_html;
}
else {
# we have a tag, possibly with an id/class
my($tag,$extra,$type);
if ($selector[$i] =~ m/\./) {
($tag,$extra) = split('.', $selector[$i]);
$extra =~ s/^\.//g;
$type = 'class';
}
elsif ($selector[$i] =~ m/#/) {
($tag,$extra) = split('#', $selector[$i]);
$extra =~ s/^#//g;
$type = 'id';
}
else {
$tag = $selector[$i];
}
if ($extra and $type) {
$start_html .= qq(<$tag $type="$extra">);
}
else {
$start_html .= qq(<$tag>);
}
$end_html = "</$tag>" . $end_html;
}
# is this the last one?
if ($i == scalar(#selector) - 1) {
$result = $start_html . $middle_html . $end_html;
}
print "<div>$result</div>\n" if ($result);
}
}
A python-based CSS preview generator: https://github.com/glowinthedark/css_stylesheet_preview_generator
Depends on cssutils (install with pip3 install cssutils).
Usage:
python3 css_preview_generator.py mystyle.css > preview.html

Resources