How to Add Bootstrap glyphicons to Woocommerce Checkout Input Fields? - wordpress

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.

Related

Change link text using CSS

To customize some pages/plugins of a Wordpress page I have to use CSS because the dashboard doesn't allow these changes.
I'm having problems with a specific case. I want to change the text of an item in a list. In this case I want to change the text "Certificates" by "Certificados". The HTML code is this:
<ul>
...
<li class="certificates">
<a href="https://url/to/user_1/certificates" data-slug:"https://url/to/user_1/certificates">
<i class="fas fa-certificate">
::before
</i>
Certificates
::after
</a>
</li>
...
</ul>
In other cases I used something like this to change texts in CSS with success:
.class-to-change {
visibility: hidden;
}
.class-to-change:after {
visibility: visible;
content: "new text";
}
But my list item seems very complex to apply this solution. Could I change the text using CSS in that case?
There is an option that we can override our custom css with plugin css. These are the steps which fixed your issue.
Then add a dequeue function to the functions.php file, and invoke it on the wp_enqueue_scripts with a priority higher than the priority level set on the plugin's original enqueue function. e.g.
function custom_style() {
wp_dequeue_style( 'plugin_css' );
wp_dequeue_style( plugin_css_2' );
wp_enqueue_style( 'custom-style', get_bloginfo('stylesheet_url') );
}
add_action('wp_enqueue_scripts', 'custom_style', 99 );
In your custom_style you can write whatever css code you have written and override the property of class.
You may embed "Certificates" in html tag. In this way you will have p element nested into li tag. After that you could set its display property to "none" (display: none;) and then might use this code:
i::after { content: "new text"; }

Advanced Custom Fields (ACF) css

I have been trying to find out how to add PHP from ACF to style some text in CSS. Using: https://www.advancedcustomfields.com/resources/color-picker/
.special-color {
background-color: <?php the_field('color'); ?>;
}
To echo php into workable CSS, you'll have to include the CSS in the php sections of the site (or something more advanced, probably using functions.php). This will work if you simply add:
<style>
.special-color {
background-color: <?php the_field('color'); ?>;
}
</style>
..to (say) your single.php file within the loop.
As an aside, I don't think this would be a viable way to alter site colours (if that's what you are trying to do?), but more as a way of (say) specifying a particular color for a title of one post.
Then you might think of including the style INLINE (pseudo code):
<h1 style="color: <?php the_field('color'); ?>">Post title</h1>
Simply I get the "advanced custom field" value (which is custom_color for an element) of the current post, and then change the element's color using JQuery.
So I created a new js file (custom_css.js) in the child theme with the following code:
jQuery(document).ready(function($) {
console.log(css.custom_color);
// add dynamic css to the elements
});
Then here is the code in functions.php file:
add_action('wp_enqueue_scripts', 'custom_css');
/* Get position details */
function custom_css() {
wp_enqueue_script('custom_css', get_stylesheet_directory_uri() . '/js/custom_css.js', array('jquery'));
wp_localize_script('custom_css', 'css', array(
'admin_url' => admin_url(),
'custom_color' => get_field('custom_color', get_queried_object_id() )
));
}

jquery Tag-it plugin's input field styling

html
<p> Tags:<input name="tags" id="tags" /></p>
jquery
$('#tags').tagit( {tagLimit:3});
I want to control the size of input field,how can i do that ?
If you look at the dynamic HTML that is generated by the tag-it plugin, ul.tagit is the class assigned to the UL that is generated. So to set the width to 200px in your CSS set:
ul.tagit {
width: 200px;
}
(function( $ ) {
$.fn.extend({
tagit: function (params) {
return this.each(function () {
console.log(params);
console.log(params['tagLimit'] );
$(this).attr('maxLength', params.tagLimit );
$(this).parent().css('maxwidth', params.tagLimit );
$(this).parent().css('width', params.tagLimit );
});
}
} )
}( jQuery ));
But you can do it directly by jQuery too, like below:
var _width = 3;
$("p input").each( function() {
$(this).css('width', _width);
$(this).css('maxWidth', _width);
})
Since I had tag-it being used in multiple places, I decided to do it in Javascript. The size needs to be big enough that it doesn't do to a double line when you add tags to it. The basic code is:
// adjust tag it size
$("ul.tagit").attr("style", "width:450px;")
Offcourse, you can decide to choose something other than 450px.
However, I also wanted to line it up with other jquery-ui buttons, which I styled with ul, instead of li, so they would have a fairly snug fit with the search box. The bottom margin needs to be adjusted to have it line up more precisely with the buttons. Here is the code for that.
// adjust tag it size and line it up with buttons
$("ul.tagit").attr("style", "width:450px; display:inline-block; margin-bottom:-10px")

How do I conditionally apply CSS styles in AngularJS?

Q1. Suppose I want to alter the look of each "item" that a user marks for deletion before the main "delete" button is pressed. (This immediate visual feedback should eliminate the need for the proverbial "are you sure?" dialog box.) The user will check checkboxes to indicate which items should be deleted. If a checkbox is unchecked, that item should revert back to its normal look.
What's the best way to apply or remove the CSS styling?
Q2. Suppose I want to allow each user to personalize how my site is presented. E.g., select from a fixed set of font sizes, allow user-definable foreground and background colors, etc.
What's the best way to apply the CSS styling the user selects/inputs?
Angular provides a number of built-in directives for manipulating CSS styling conditionally/dynamically:
ng-class - use when the set of CSS styles is static/known ahead of time
ng-style - use when you can't define a CSS class because the style values may change dynamically. Think programmable control of the style values.
ng-show and ng-hide - use if you only need to show or hide something (modifies CSS)
ng-if - new in version 1.1.5, use instead of the more verbose ng-switch if you only need to check for a single condition (modifies DOM)
ng-switch - use instead of using several mutually exclusive ng-shows (modifies DOM)
ng-disabled and ng-readonly - use to restrict form element behavior
ng-animate - new in version 1.1.4, use to add CSS3 transitions/animations
The normal "Angular way" involves tying a model/scope property to a UI element that will accept user input/manipulation (i.e., use ng-model), and then associating that model property to one of the built-in directives mentioned above.
When the user changes the UI, Angular will automatically update the associated elements on the page.
Q1 sounds like a good case for ng-class -- the CSS styling can be captured in a class.
ng-class accepts an "expression" that must evaluate to one of the following:
a string of space-delimited class names
an array of class names
a map/object of class names to boolean values
Assuming your items are displayed using ng-repeat over some array model, and that when the checkbox for an item is checked you want to apply the pending-delete class:
<div ng-repeat="item in items" ng-class="{'pending-delete': item.checked}">
... HTML to display the item ...
<input type="checkbox" ng-model="item.checked">
</div>
Above, we used ng-class expression type #3 - a map/object of class names to boolean values.
Q2 sounds like a good case for ng-style -- the CSS styling is dynamic, so we can't define a class for this.
ng-style accepts an "expression" that must evaluate to:
an map/object of CSS style names to CSS values
For a contrived example, suppose the user can type in a color name into a texbox for the background color (a jQuery color picker would be much nicer):
<div class="main-body" ng-style="{color: myColor}">
...
<input type="text" ng-model="myColor" placeholder="enter a color name">
Fiddle for both of the above.
The fiddle also contains an example of ng-show and ng-hide. If a checkbox is checked, in addition to the background-color turning pink, some text is shown. If 'red' is entered in the textbox, a div becomes hidden.
I have found problems when applying classes inside table elements when I had one class already applied to the whole table (for example, a color applied to the odd rows <myClass tbody tr:nth-child(even) td>). It seems that when you inspect the element with Developer Tools, the element.style has no style assigned. So instead of using ng-class, I have tried using ng-style, and in this case, the new CSS attribute does appear inside element.style. This code works great for me:
<tr ng-repeat="element in collection">
[...amazing code...]
<td ng-style="myvar === 0 && {'background-color': 'red'} ||
myvar === 1 && {'background-color': 'green'} ||
myvar === 2 && {'background-color': 'yellow'}">{{ myvar }}</td>
[...more amazing code...]
</tr>
Myvar is what I am evaluating, and in each case I apply a style to each <td> depending on myvar value, that overwrites the current style applied by the CSS class for the whole table.
UPDATE
If you want to apply a class to the table for example, when visiting a page or in other cases, you can use this structure:
<li ng-class="{ active: isActive('/route_a') || isActive('/route_b')}">
Basically, what we need to activate a ng-class is the class to apply and a true or false statement. True applies the class and false doesn't. So here we have two checks of the route of the page and an OR between them, so if we are in /route_a OR we are in route_b, the active class will be applied.
This works just having a logic function on the right that returns true or false.
So in the first example, ng-style is conditioned by three statements. If all of them are false, no style is applied, but following our logic, at least one is going to be applied, so, the logic expression will check which variable comparison is true and because a non empty array is always true, that will left an array as return and with only one true, considering we are using OR for the whole response, the style remaining will be applied.
By the way, I forgot to give you the function isActive():
$rootScope.isActive = function(viewLocation) {
return viewLocation === $location.path();
};
NEW UPDATE
Here you have something I find really useful. When you need to apply a class depending on the value of a variable, for example, an icon depending on the contents of the div, you can use the following code (very useful in ng-repeat):
<i class="fa" ng-class="{ 'fa-github' : type === 0,
'fa-linkedin' : type === 1,
'fa-skype' : type === 2,
'fa-google' : type === 3 }"></i>
Icons from Font Awesome
This works well when ng-class can't be used (for example when styling SVG):
ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"
(I think you need to be on latest unstable Angular to use ng-attr-, I'm currently on 1.1.4)
I have published an article on working with AngularJS+SVG. It talks about this issue and numerous others. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS
span class="circle circle-{{selectcss(document.Extension)}}">
and code
$scope.selectcss = function (data) {
if (data == '.pdf')
return 'circle circle-pdf';
else
return 'circle circle-small';
};
css
.circle-pdf {
width: 24px;
height: 24px;
font-size: 16px;
font-weight: 700;
padding-top: 3px;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
background-image: url(images/pdf_icon32.png);
}
This solution did the trick for me
<a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>
You can use ternary expression. There are two ways to do this:
<div ng-style="myVariable > 100 ? {'color': 'red'} : {'color': 'blue'}"></div>
or...
<div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>
Another option when you need a simple css style of one or two properties:
View:
<tr ng-repeat="element in collection">
[...amazing code...]
<td ng-style="{'background-color': getTrColor(element.myvar)}">
{{ element.myvar }}
</td>
[...more amazing code...]
</tr>
Controller:
$scope.getTrColor = function (colorIndex) {
switch(colorIndex){
case 0: return 'red';
case 1: return 'green';
default: return 'yellow';
}
};
See the following example
<!DOCTYPE html>
<html ng-app>
<head>
<title>Demo Changing CSS Classes Conditionally with Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="res/js/controllers.js"></script>
<style>
.checkboxList {
border:1px solid #000;
background-color:#fff;
color:#000;
width:300px;
height: 100px;
overflow-y: scroll;
}
.uncheckedClass {
background-color:#eeeeee;
color:black;
}
.checkedClass {
background-color:#3ab44a;
color:white;
}
</style>
</head>
<body ng-controller="TeamListCtrl">
<b>Teams</b>
<div id="teamCheckboxList" class="checkboxList">
<div class="uncheckedClass" ng-repeat="team in teams" ng-class="{'checkedClass': team.isChecked, 'uncheckedClass': !team.isChecked}">
<label>
<input type="checkbox" ng-model="team.isChecked" />
<span>{{team.name}}</span>
</label>
</div>
</div>
</body>
</html>
As of AngularJS v1.2.0rc, ng-class and even ng-attr-class fail with SVG elements (They did work earlier, even with normal binding inside the class attribute)
Specifically, none of these work now:
ng-class="current==this_element?'active':' ' "
ng-attr-class="{{current==this_element?'active':' '}}"
class="class1 class2 .... {{current==this_element?'active':''}}"
As a workaround, I've to use
ng-attr-otherAttr="{{current==this_element?'active':''}}"
and then style using
[otherAttr='active'] {
... styles ...
}
One more (in the future) way to conditionally apply style is by conditionally creating scoped style
<style scoped type="text/css" ng-if="...">
</style>
But nowadays only FireFox supports scoped styles.
There is one more option that I recently discovered that some people may find useful because it allows you to change a CSS rule within a style element - thus avoiding the need for repeated use of an angular directive such as ng-style, ng-class, ng-show, ng-hide, ng-animate, and others.
This option makes use of a service with service variables which are set by a controller and watched by an attribute-directive I call "custom-style". This strategy could be used in many different ways, and I attempted to provide some general guidance with this fiddle.
var app = angular.module('myApp', ['ui.bootstrap']);
app.service('MainService', function(){
var vm = this;
});
app.controller('MainCtrl', function(MainService){
var vm = this;
vm.ms = MainService;
});
app.directive('customStyle', function(MainService){
return {
restrict : 'A',
link : function(scope, element, attr){
var style = angular.element('<style></style>');
element.append(style);
scope.$watch(function(){ return MainService.theme; },
function(){
var css = '';
angular.forEach(MainService.theme, function(selector, key){
angular.forEach(MainService.theme[key], function(val, k){
css += key + ' { '+k+' : '+val+'} ';
});
});
style.html(css);
}, true);
}
};
});
well i would suggest you to check condition in your controller with a function returning true or false .
<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>
and in your controller check the condition
$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
One thing to watch is - if the CSS style has dashes - you must remove them. So if you want to set background-color, the correct way is:
ng-style="{backgroundColor:myColor}"
Here's how i conditionally applied gray text style on a disabled button
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
styleUrls: [ './app.component.css' ],
template: `
<button
(click)='buttonClick1()'
[disabled] = "btnDisabled"
[ngStyle]="{'color': (btnDisabled)? 'gray': 'black'}">
{{btnText}}
</button>`
})
export class AppComponent {
name = 'Angular';
btnText = 'Click me';
btnDisabled = false;
buttonClick1() {
this.btnDisabled = true;
this.btnText = 'you clicked me';
setTimeout(() => {
this.btnText = 'click me again';
this.btnDisabled = false
}, 5000);
}
}
Here's a working example:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

jQuery UI styled text input box

jQuery UI makes buttons look nice with $('button').button();.
Is there an equivalent for text input boxes?
There's nothing to stop you from doing $("input").button()... I like this:
$('input:text, input:password')
.button()
.css({
'font' : 'inherit',
'color' : 'inherit',
'text-align' : 'left',
'outline' : 'none',
'cursor' : 'text'
});
A fuller example.
Add the class ui-corner-all to your input and post-style the input with CSS.
$('input').addClass("ui-corner-all");
http://jsfiddle.net/TTShr/
I know this is old. But, if anyone is just looking to style their inputs to look more UIish, just add the following classes: $('input').addClass("ui-widget ui-widget-content ui-corner-all");
You could just hard code the classes too.
To sum things up I would like to add my implementation:
$('input:text, input:password, input[type=email]').button()
.addClass('ui-textfield')
.off('mouseenter').off('mousedown').off('keydown');
The CSS would be:
.ui-textfield {
font: inherit;
color: inherit;
background: none;
text-align: inherit;
outline: none;
cursor: text;
}
See it here: http://jsfiddle.net/UXdLQ/1544/
I had the same problem, I came up with the following solution. Use these classes on your input field:
ui-widget ui-state-default ui-corner-all
You may modify the padding - f.e. if you select elements on your site - to be unified.
jQuery UI v1.11.4
also add a .off('keydown') to Corin's answer to prevent the box from turning white when enter or space is pressed.
The example in your question cites jQuery UI's Button widget. The idea of this widget is to have a range of options including ease of theme-ing. There is a widget for input boxes too. Some of them that I'm aware of are as below:
Auto-Complete Widget
Default Text Plugin for input-box
Text Limit Plugin for input-box / text-area
There are many such plugins if not for widgets. You can always browse/search through at the search box available in the page http://plugins.jquery.com/
I liked the idea of simply adding the classes so much I wrote it as a jQuery plugin. Benifit here is if at some poitn in the future jQueryUI do a version it will most likely use the same format, so converting will be easy.
(function($)
{
$.fn.input = function ()
{
return this.each(function ()
{
$(this).addClass("ui-widget ui-widget-content ui-corner-all ui-button");
});
}
})(jQuery);
Call it like:
$('input, password').input();
If you wanted to add hover effects etc, just add the logic into
return this.each(function ()
{
// display logic
});
EDIT:
Added in additional class "ui-button" to make them the same height / padding etc as .button()
EDIT 2:
This turned out to be such a good idea I've carried on, adding a version for labels, and allowing custom CSS to be passed in.
// some styling for inputs
(function($)
{
$.fn.input = function (css)
{
if (!css)
css = {};
return this.each(function ()
{
$(this).addClass("ui-widget ui-widget-content ui-corner-all ui-button");
$(this).css(css);
});
}
})(jQuery);
// and labels
(function ($)
{
$.fn.label = function (css)
{
if (!css)
css = {};
return this.each(function ()
{
$(this).addClass("ui-widget ui-button");
$(this).css(css);
});
}
})(jQuery);
Then too style your inputs / labels. The class / styles of these don't actually need to exist anywhere.
$(".client-input").input();
$(".client-label").label({ "min-width": "125px", "text-align": "right" });
Outputs UI like this - with inputs and labels matching the style of the button. (Select's need work)
To have the same corners/font/padding/spacing as button, but without the button interactions (hover, active etc.)
HTML:
input type="text" class="ui-button ui-widget ui-corner-all"
if you want to align text add another custom class
CSS:
.textfield { text-align:left; }
HTML:
input type="text" class="ui-button ui-widget ui-corner-all textfield"

Resources