How to rearrange/customize html in woocommerce checkout form fields - php

I want to accomplish 2 things in my woocommerce checkout form:
1. Put some text between some groups of fields, for example (h3):
<h3>my custom heading</h3>
<p class="form-row form-row validate-required">
<input type="email">...
</p>
<h3>my other custom heading</h3>
<p class="form-row form-row validate-required">
<input type="text">...
</p>
<p class="form-row form-row validate-required">
<input type="text">...
</p>
2. Display input tag first and label tag as second in html (woocommerce display label before input by default)
I figured out that checkout form is displayed by this code (for billing):
<?php foreach ( $checkout->checkout_fields['billing'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
How can I customize it in way I described?

I'm not sure on part 1, but for part 2, you can modify the output of woocommerce_form_field() by filtering woocommerce_form_field_$type.
So your part 2 can be solved like so:
function so_39267627_form_field( $field, $key, $args, $value ){
if ( $args['required'] ) {
$args['class'][] = 'validate-required';
$required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce' ) . '">*</abbr>';
} else {
$required = '';
}
$args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
$args['autocomplete'] = ( $args['autocomplete'] ) ? 'autocomplete="' . esc_attr( $args['autocomplete'] ) . '"' : '';
if ( is_string( $args['label_class'] ) ) {
$args['label_class'] = array( $args['label_class'] );
}
if ( is_null( $value ) ) {
$value = $args['default'];
}
// Custom attribute handling
$custom_attributes = array();
// Custom attribute handling
$custom_attributes = array();
if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) ) {
foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
}
}
$field = '';
$label_id = $args['id'];
$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
$field .= '<input type="' . esc_attr( $args['type'] ) . '" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['maxlength'] . ' ' . $args['autocomplete'] . ' value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
if ( ! empty( $field ) ) {
$field_html = '';
$field_html .= $field;
if ( $args['description'] ) {
$field_html .= '<span class="description">' . esc_html( $args['description'] ) . '</span>';
}
if ( $args['label'] && 'checkbox' != $args['type'] ) {
$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) .'">' . $args['label'] . $required . '</label>';
}
$container_class = 'form-row ' . esc_attr( implode( ' ', $args['class'] ) );
$container_id = esc_attr( $args['id'] ) . '_field';
$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
$field = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
}
return $field;
}
add_filter( 'woocommerce_form_field_password', 'so_39267627_form_field', 10, 4 );
add_filter( 'woocommerce_form_field_text', 'so_39267627_form_field', 10, 4 );
add_filter( 'woocommerce_form_field_email', 'so_39267627_form_field', 10, 4 );
add_filter( 'woocommerce_form_field_tel', 'so_39267627_form_field', 10, 4 );
add_filter( 'woocommerce_form_field_number', 'so_39267627_form_field', 10, 4 );
You would need to write a few more functions (mostly I copied and pasted whole swaths of code from WooCommerce and then just swapped the label part around ) for other other field types, but this should serve as an example.

For the first one you can do the following to display single input field
<?php
woocommerce_form_field(
"billing_first_name",
$checkout->checkout_fields['billing']['billing_first_name'],
$checkout->get_value( 'billing_first_name' )
);
?>
where you can replace first_name with any key of the checkout billing fields
So for your example it will be something like this
<h3>my custom heading</h3>
<p class="form-row form-row validate-required">
<?php woocommerce_form_field( "billing_email", $checkout->checkout_fields['billing']['billing_email'], $checkout->get_value( 'billing_email' ) ); ?>
</p>
As for the second I'm not sure how you can achieve that. I needed something similar and i used javascript to reposition the labels.
something like :
jQuery('form.checkout label').each(function(){
jQuery(this).insertAfter(jQuery(this).parent().find('input'));
})

As far as I think, woo commerce does not support html, there's a plugin known as woocommerce checkout field editor, see if it solves your issue.

Related

trying to style woocommerce dropdown with adding a span inside php code

I have PHP code like this:
$html .= '<option value="' . esc_attr( $term->slug ) . '" '
. selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>'
. esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . $price_html )
. '</option>';
I want to add <span class="XXX"> before $price_html variable and closing span tag after that, so on I can style the price. I tried the code below but no success:
$html .= '<option value="' . esc_attr( $term->slug ) . '" '
. selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>'
. esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . '<span class="XXX">' . $price_html . '</span>')
. '</option>';
Any help?
Edit: the code block i am trying to edit:
// Utility function to get the price of a variation from it's attribute value
function get_the_variation_price_html( $product, $name, $term_slug ){
foreach ( $product->get_available_variations() as $variation ){
if($variation['attributes'][$name] == $term_slug ){
return strip_tags( $variation['price_html'] );
}
}
}
// Add the price to the dropdown options items.
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'show_price_in_attribute_dropdown', 10, 2);
function show_price_in_attribute_dropdown( $html, $args ) {
// Only if there is a unique variation attribute (one dropdown)
if( sizeof($args['product']->get_variation_attributes()) == 1 ) :
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
$class = $args['class'];
$show_option_none = $args['show_option_none'] ? true : false;
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' );
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
$html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
$terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {
// Get and inserting the price
$price_html = get_the_variation_price_html( $product, $name, $term->slug );
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . $price_html ) . '</option>';
}
}
} else {
foreach ( $options as $option ) {
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
// Get and inserting the price
$price_html = get_the_variation_price_html( $product, $name, $term->slug );
$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) . ' = ' . $price_html ) . '</option>';
}
}
}
$html .= '</select>';
endif;
return $html;
}
The reason why you don't see the desired output is in esc_html() function. Also, <span> tag inside a <option> tag doesn't get any CSS styles. You have to place desired class="XXX" inside the <option> tag.
For now you have something like:
<option value="123">escaped_price_html</option>
Replace lines:
'<option value="' . esc_attr( $term->slug ) . '" '
with
'<option class="XXX" value="' . esc_attr( $term->slug ) . '" '
and
. esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . '<span class="XXX">' . $price_html . '</span>')
with
. esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . $price_html)
which will change the structure on:
<option class="XXX" value="123">escaped_price_html</option>
.x{
color: blue;
font-weight: bold;
}
<select>
<option value="1"><span class="x">TEXT1</span></option>
<option class="x" value="2"><span>TEXT2</span></option>
<option value="3"><span class="x">TEXT3</span></option>
</select>

display by stock quantity woocommorce

I'm preparing a shopping site with woocommerce. As in the sample link, I show the product stock information in the drop down menu. this is the code I use:
$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
$html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {
$stock_status = get_variation_stock_status( $product, $name, $term->slug );
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ).$stock_status ) . '</option>';
}
}
} else {
foreach ( $options as $option ) {
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}
}
$html .= '</select>';
return $html;
}
function get_variation_stock_status( $product, $name, $term_slug ){
foreach ( $product->get_available_variations() as $variation ){
if($variation['attributes'][$name] == $term_slug ){
$variation_obj = wc_get_product( $variation['variation_id'] );
$stock_qty = $variation_obj->get_stock_quantity();
break;
}
}
return $stock_qty == 0 ? ' - ' . __(pll__('Stokta Yok'), 'mytheme') : ' - ' . $stock_qty . ' ' . __(pll__('adet Stokta'), 'mytheme-');
}
If the stock quantity is over 20, I don't want to show this information. how can I do that?
Just add a check to the get_variation_stock_status function:
function get_variation_stock_status( $product, $name, $term_slug ){
foreach ( $product->get_available_variations() as $variation ){
if ( $variation['attributes'][$name] == $term_slug ) {
$variation_obj = wc_get_product( $variation['variation_id'] );
// if the stock of the product is greater than 20 it returns
if ( $variation_obj->get_stock_quantity() > 20 ) {
return '';
}
$stock_qty = $variation_obj->get_stock_quantity();
break;
}
}
return $stock_qty == 0 ? ' - (Out Of Stock)' : ' - ' . $stock_qty . ' In Stock';
}
The entire code (from the link in your comment) has been tested and works. Add it to your active theme's functions.php.

Woocommerce get stock quantity of each item variation

I have a page like this:
I have manage stocks enabled in variations, and I want to filter out items that are not in stock. For example, if size 9.5 is not available in variations, it should not appear in the front end as well. The questions posted here are all quite old and I could not get any of the suggestions posted in them to work. Here is what I have done so far:
// Get terms if this is a taxonomy - ordered
if ( taxonomy_exists( $attribute_name ) ) {
$is_attr_color = false;
$attribute_color = wc_sanitize_taxonomy_name( 'color' );
if( $attribute_name == wc_attribute_taxonomy_name( $attribute_color ) ){
$is_attr_color = true;
}
$terms = wc_get_product_terms( $post->ID, $attribute_name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
if( $is_attr_color ){
$datas = get_term_meta( $term->term_id, 'ts_product_color_config', true );
if( strlen( $datas ) > 0 ){
$datas = unserialize( $datas );
}else{
$datas = array(
'ts_color_color' => "#ffffff"
,'ts_color_image' => 0
);
}
}
$class = sanitize_title( $selected_value ) == sanitize_title( $term->slug ) ? 'selected' : '';
$class .= ' option';
if( $is_attr_color ){
$class .= ' color';
}
echo '<div data-value="' . esc_attr( $term->slug ) . '" class="' . $class . '">';
if( $is_attr_color ){
if( absint($datas['ts_color_image']) > 0 ){
echo '' . wp_get_attachment_image( absint($datas['ts_color_image']), 'ts_prod_color_thumb', true, array('title'=>$term->name, 'alt'=>$term->name) ) . '';
}
else{
echo '' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '';
}
}
else{
// !!!!!!!!!!MAIN ISSUE HERE!!!!!!!!!!!!
if($term->count > 0){
echo '' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '';
}
}
echo '</div>';
}
} else {
foreach ( $options as $option ) {
$class = sanitize_title( $selected_value ) == sanitize_title( $option ) ? 'selected' : '';
$class .= ' option';
echo '<div data-value="' . esc_attr( $option ) . '" class="' . $class . '">' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</div>';
}
}
Any idea how I could fix this? I have been at it for hours and I cannot find a solution for it. It's really frustrating.

How to change "add to cart" in WooCommerce?

I wanna use <ul> <li> instead of <select> <option>
I enter this code in function.php but doesn't work:
function wc_dropdown_variation_attribute_options( $args = array() ) {
.
.
.
$html = '<div class="tt-wrapper"><div class="tt-title-options">اندازه:</div><ul id="' . esc_attr( $id ) . '" class="tt-options-swatch options-large ' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms(
$product->get_id(),
$attribute,
array(
'fields' => 'all',
)
);
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options, true ) ) {
$html .= '<li><a href="#" value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</a></li>';
}
}
} else {
foreach ( $options as $option ) {
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
$html .= '<li><a href="#" value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</a></li>';
}
}
}
$html .= '</ul></div></div>';
echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args ); // WPCS: XSS ok.
}
How can I change woocommerce HTML codes to my own HTML codes?
this is more detail for post this question
To override the default themes of WooCommerce you better have a "woocommerce" sub-directory on your theme folder.
for example:
/wp-content/themes/mytheme/woocommerce/
There you can specify exactly which of the themes you want to change.
Learn more about it here.
Also, you can hook to actions and filters. In the example you sent, you can hook to this filter: woocommerce_dropdown_variation_attribute_options_html to change it's final output.
Learn more about it here and here.

Custom textbox in wordpress woocommerce

Is it possible to get a normal text instead to use a slug? I need to use this custom code for Wordpress WooCommerce product page. The small problem the output get small letters and line "-" between words.
<?php /*CUSTOM MID*/ else: ?>
<td class="value">
<select id="<?php echo esc_attr( sanitize_title($name) ); ?>"
name="attribute_<?php echo sanitize_title($name); ?>">
<option value="">
<?php echo __('Choose an option', 'woocommerce') ?>…
</option>
<?php
if ( is_array( $options ) ) {
if ( empty( $_POST ) )
$selected_value = ( isset( $selected_attributes[ sanitize_title( $name ) ] ) ) ? $selected_attributes[ sanitize_title( $name ) ] : '';
else
$selected_value = isset( $_POST[ 'attribute_' . sanitize_title( $name ) ] ) ? $_POST[ 'attribute_' . sanitize_title( $name ) ] : '';
// Get terms if this is a taxonomy - ordered
if ( taxonomy_exists( sanitize_title( $name ) ) ) {
$terms = get_terms( sanitize_title($name), array('menu_order' => 'ASC') );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) continue;
echo '<option value="' . $term->slug . '" ' . selected( $selected_value, $term->slug, false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '</option>';
}
} else {
foreach ( $options as $option )
echo '<option value="' . $option . '" ' . selected( $selected_value, $option, false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $option ) . '</option>';
}
}
?>
</select> <?php
if ( sizeof($attributes) == $loop )
echo '<a class="reset_variations" href="#reset">'.__('Clear selection', 'woocommerce').'</a>';
?></td>
remove - you can do it by pure php using str_replace
You have to give us more of your code to understand it.

Categories