';
39 | echo '
';
40 | // jetpack_breadcrumbs();
41 | }
42 |
43 | function between_thankyou( $order_id ) {
44 | $order = wc_get_order( $order_id );
45 | $show_customer_details = is_user_logged_in() && $order->get_user_id() === get_current_user_id();
46 | if( $show_customer_details ) {
47 | wc_get_template( 'order/order-details-customer.php', array('order' => $order) );
48 | }
49 |
50 | echo '';
51 | echo '
';
52 | }
53 |
54 | function after_thankyou( $order_id ) {
55 | echo '';
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const path = require('path');
4 |
5 | const jsPath = './src/js';
6 | const outputPath = 'dist';
7 | const entryPoints = {
8 | 'hwc-public': `${jsPath}/hwc-public.js`,
9 | 'hwc-admin': `${jsPath}/hwc-admin.js`,
10 | 'hwc-variations': './module-variations-ui/src/hwc-variations.js',
11 | };
12 |
13 | module.exports = {
14 | entry: entryPoints,
15 | output: {
16 | path: path.resolve(__dirname, outputPath),
17 | filename: '[name].js',
18 | },
19 | plugins: [
20 | new MiniCssExtractPlugin({
21 | filename: '[name].css',
22 | }),
23 |
24 | new DependencyExtractionWebpackPlugin({
25 | injectPolyfill: true,
26 | }),
27 | ],
28 | module: {
29 | rules: [
30 | {
31 | test: /\.s?[ac]ss$/i,
32 | use: [
33 | MiniCssExtractPlugin.loader,
34 | 'css-loader',
35 | 'sass-loader',
36 | ],
37 | },
38 | {
39 | test: /\.(jpg|jpeg|png|gif|woff|woff2|eot|ttf|svg)$/i,
40 | use: 'url-loader?limit=1024',
41 | },
42 | {
43 | test: /\.jsx$/i,
44 | use: [
45 | require.resolve('thread-loader'),
46 | {
47 | loader: require.resolve('babel-loader'),
48 | options: {
49 | cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true,
50 | babelrc: false,
51 | configFile: false,
52 | presets: [
53 | require.resolve('@wordpress/babel-preset-default'),
54 | ],
55 | },
56 | },
57 | ],
58 | },
59 | ],
60 | },
61 | };
62 |
--------------------------------------------------------------------------------
/admin/locate-template.php:
--------------------------------------------------------------------------------
1 | template_url;
14 | }
15 |
16 | $plugin_path = HWC_PATH . '/templates/';
17 |
18 | // Look within passed path within the theme - this is priority
19 | $template = locate_template(
20 | array($template_path . $template_name, $template_name)
21 | );
22 |
23 | if(!$template && file_exists( $plugin_path . $template_name ) ) {
24 | $template = $plugin_path . $template_name;
25 | }
26 |
27 | if(!$template ) {
28 | $template = $_template;
29 | }
30 |
31 | return $template;
32 | }
33 |
34 | /**
35 | * Locate the called template in /plugins/your-plugin/templates/$template_name.
36 | * http://jeroensormani.com/how-to-add-template-files-in-your-plugin/
37 | *
38 | * @param string $template_name - Template to load.
39 | * @param string $default_path - Default path to template files.
40 | * @return string - Path to the template file.
41 | */
42 | function hoo_locate_template( $template_name, $default_path = '' ) {
43 | // Set default plugin templates path.
44 | if(!$default_path) {
45 | $default_path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/edje-wc-library/templates/'; // Path to the template folder
46 | }
47 |
48 | $template = $default_path . $template_name;
49 |
50 | return apply_filters( 'hoo_locate_template', $template, $template_name, $default_path );
51 | }
--------------------------------------------------------------------------------
/module-gutenberg/webpack.config.js:
--------------------------------------------------------------------------------
1 | const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | // const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
4 | var path = require('path');
5 |
6 | const outputPath = 'dist';
7 | // const localDomain = 'http://shop.test/';
8 | const entryPoints = {
9 | 'h-shop-editor': './src/shop-editor.js',
10 | 'h-featured-category': './src/featured-category.jsx',
11 | 'h-products': './src/products.jsx',
12 | };
13 |
14 | module.exports = {
15 | entry: entryPoints,
16 | output: {
17 | path: path.resolve(__dirname, outputPath),
18 | filename: '[name].js',
19 | },
20 | plugins: [
21 | new MiniCssExtractPlugin({
22 | filename: '[name].css',
23 | }),
24 |
25 | new DependencyExtractionWebpackPlugin( {
26 | injectPolyfill: true
27 | } ),
28 | ],
29 | module: {
30 | rules: [
31 | {
32 | test: /\.s?[ac]ss$/i,
33 | use: [
34 | MiniCssExtractPlugin.loader,
35 | 'css-loader',
36 | 'sass-loader',
37 | ]
38 | },
39 | {
40 | test: /\.(jpg|jpeg|png|gif|woff|woff2|eot|ttf|svg)$/i,
41 | use: 'url-loader?limit=1024'
42 | },
43 | {
44 | test: /\.jsx$/i,
45 | use: [
46 | require.resolve( 'thread-loader' ),
47 | {
48 | loader: require.resolve( 'babel-loader' ),
49 | options: {
50 | cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true,
51 | babelrc: false,
52 | configFile: false,
53 | presets: [
54 | require.resolve( '@wordpress/babel-preset-default' ),
55 | ],
56 | },
57 | },
58 | ],
59 | }
60 | ]
61 | },
62 |
63 | };
--------------------------------------------------------------------------------
/module-variations-ui/src/_settings.scss:
--------------------------------------------------------------------------------
1 | $version: 0;
2 |
3 | $text: #333;
4 | $text-dim: #5c6c7a;
5 | $text-invert: #ebeef0;
6 |
7 | $border: #eee;
8 | $panel: #fafafa;
9 |
10 | $red : #e35950;
11 | $yellow : #edc200;
12 | $green : #4caf50;
13 | $blue: #47c1bf;
14 |
15 | $purple: #763eaf;
16 | $orange: #ff9517;
17 |
18 | $red-light : #ffc58b;
19 | $yellow-light : #ffea8a;
20 | $green-light : #c8e6c9;
21 | $blue-light: #cae9f7;
22 |
23 | $g-radius: 4px;
24 | $g-transition: all .25s ease-in-out;
25 |
26 | @mixin variation-select($color) {
27 | color: $color;
28 |
29 | &:hover { background-color: rgba($color, .2); }
30 | }
31 |
32 | @mixin wp-button() {
33 | cursor: pointer;
34 | display: inline-block;
35 | background: #f7f7f7;
36 | height: 28px;
37 | width: 28px;
38 | margin: 0;
39 | padding: 0;
40 | border: 1px solid #ccc;
41 |
42 | white-space: nowrap;
43 | text-decoration: none;
44 | font-size: 13px;
45 | line-height: 26px;
46 | color: #555;
47 | border-color: #ccc;
48 | vertical-align: top;
49 |
50 | -webkit-appearance: none;
51 | border-radius: 3px;
52 | box-sizing: border-box;
53 | box-shadow: 0 1px 0 #ccc;
54 |
55 | &:hover {
56 | background: #fafafa;
57 | border-color: #999;
58 | color: #23282d;
59 | }
60 |
61 | &:active {
62 | background: #eee;
63 | background-color: white;
64 | border-color: #999;
65 |
66 | box-shadow: inset 0 2px 5px -3px rgba(0,0,0,.5);
67 | -webkit-transform: translateY(1px);
68 | transform: translateY(1px);
69 | }
70 | }
71 |
72 | @mixin wp-button-error-on-hover() {
73 | &:hover {
74 | background: #e35950;
75 | border-color: #ba281e;
76 | color: #fff;
77 | box-shadow: 0 1px 0 #ba281e;
78 | }
79 |
80 | &:active {
81 | background: #d02c21;
82 | border-color: #ba281e;
83 | box-shadow: inset 0 2px 0 #ba281e;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/module-widgets/acf-json/group_62e8a1ac395ff.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "group_62e8a1ac395ff",
3 | "title": "Edje Widget - My Account Button",
4 | "fields": [
5 | {
6 | "key": "field_62e8a1be39d2e",
7 | "label": "Label Logged Out",
8 | "name": "label_logged_out",
9 | "type": "text",
10 | "instructions": "Leave empty to not have a label",
11 | "required": 0,
12 | "conditional_logic": 0,
13 | "wrapper": {
14 | "width": "",
15 | "class": "",
16 | "id": ""
17 | },
18 | "default_value": "Login",
19 | "placeholder": "",
20 | "prepend": "",
21 | "append": "",
22 | "maxlength": ""
23 | },
24 | {
25 | "key": "field_62e8a1c939d2f",
26 | "label": "Label Logged In",
27 | "name": "label_logged_in",
28 | "type": "text",
29 | "instructions": "",
30 | "required": 0,
31 | "conditional_logic": 0,
32 | "wrapper": {
33 | "width": "",
34 | "class": "",
35 | "id": ""
36 | },
37 | "default_value": "View Profile",
38 | "placeholder": "",
39 | "prepend": "",
40 | "append": "",
41 | "maxlength": ""
42 | }
43 | ],
44 | "location": [
45 | [
46 | {
47 | "param": "widget",
48 | "operator": "==",
49 | "value": "hwc_myaccount"
50 | }
51 | ]
52 | ],
53 | "menu_order": 0,
54 | "position": "normal",
55 | "style": "default",
56 | "label_placement": "top",
57 | "instruction_placement": "label",
58 | "hide_on_screen": "",
59 | "active": true,
60 | "description": "",
61 | "show_in_rest": 0,
62 | "modified": 1662369364
63 | }
--------------------------------------------------------------------------------
/templates/single-product/tabs/tabs.php:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 | $product_tab ) : ?>
27 | -
28 |
29 |
30 |
31 |
32 |
33 |
34 | $product_tab ) : ?>
35 |
39 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/edje-wc-library.php:
--------------------------------------------------------------------------------
1 |
11 |
12 |
40 | __('Create a link to My Account page')
10 | ]);
11 | }
12 |
13 | function widget($args, $instance) {
14 | $widget_id = 'widget_' . $args['widget_id'];
15 |
16 | $label_logged_out = get_field('label_logged_out', $widget_id);
17 | $label_logged_in = get_field('label_logged_in', $widget_id);
18 |
19 | $data = apply_filters('hwc_widget_myaccount_args', [
20 | 'label_logged_out' => $label_logged_out ? $label_logged_out : 'Login',
21 | 'label_logged_in' => $label_logged_in ? $label_logged_in : 'View Profile',
22 | 'icon' => '
',
23 | ]);
24 |
25 | $custom_render = apply_filters('hwc_widget_myaccount', '', $data);
26 |
27 | echo $args['before_widget'];
28 | echo $custom_render ? $custom_render : $this->render_widget($data);
29 | echo $args['after_widget'];
30 | }
31 |
32 | function render_widget($data) {
33 | [
34 | 'label_logged_out' => $label_logged_out,
35 | 'label_logged_in' => $label_logged_in,
36 | 'icon' => $icon,
37 | ] = $data;
38 | ob_start(); ?>
39 |
40 |
44 | = $icon ?>
45 |
46 |
47 |
48 | = $label_logged_in ?>
49 |
50 |
51 |
52 |
53 | = $label_logged_out ?>
54 |
55 |
56 |
57 |
58 |
59 | {
37 | // abort if not our targetted block
38 | let targetBlocks = [ 'woocommerce/handpicked-products' ];
39 | if ( !targetBlocks.includes( props.name ) ) {
40 | return (
41 |
42 | );
43 | }
44 |
45 | let atts = props.attributes;
46 |
47 | return (
48 |
49 |
50 |
51 |
54 |
55 |
56 | );
57 |
58 | //
59 | function updateAlignment( newValue ) {
60 | newValue = newValue || '';
61 | props.setAttributes({ textAlign: newValue });
62 |
63 | // remove existing alignment class
64 | if( atts.className ) {
65 | atts.className = atts.className.replace( /has-text-align-\w+/, '' ).trim();
66 | } else {
67 | atts.className = ''; // initialize
68 | }
69 |
70 | // add Align class
71 | if( newValue ) {
72 | props.setAttributes({ className: `${atts.className} has-text-align-${ newValue }` });
73 | }
74 | }
75 | };
76 | }
--------------------------------------------------------------------------------
/module-widgets/_index.php:
--------------------------------------------------------------------------------
1 | __('Create a Cart dropdown menu')
13 | ]);
14 | }
15 |
16 | /**
17 | *
18 | */
19 | function widget($args, $instance) {
20 | $widget_id = 'widget_' . $args['widget_id'];
21 | $data = [
22 | 'cart_style' => get_field('cart_style', $widget_id),
23 | ];
24 |
25 | $custom_render = apply_filters('hwc_widget_cart', '', $data);
26 |
27 | echo $args['before_widget'];
28 | echo $custom_render ? $custom_render : $this->render_widget($data);
29 | echo $args['after_widget'];
30 | }
31 |
32 | /**
33 | *
34 | */
35 | function render_widget($data) {
36 | [
37 | 'cart_style' => $cart_style,
38 | ] = $data;
39 | ob_start(); ?>
40 |
41 |
42 | = _hwc_cart_button() ?>
43 |
44 |
45 |
46 | cart->get_cart_contents_count();
56 | $count = $count > 0 ? "
{$count}" : '';
57 |
58 | $extra_class = $woocommerce->cart->is_empty() ? 'is-cart-empty' : 'is-cart-filled';
59 |
60 | $args = apply_filters('hwc_cart_button_args', [
61 | 'label' => '
' . __('Cart') . '',
62 | 'icon' => '
',
63 | ]);
64 |
65 | $button = "";
68 | return $button;
69 | }
70 |
71 | /**
72 | * @filter woocommerce_add_to_cart_fragments
73 | */
74 | function _hwc_cart_button_fragment($fragments) {
75 | $fragments['.is-cart-button'] = _hwc_cart_button();
76 | return $fragments;
77 | }
--------------------------------------------------------------------------------
/dist/hwc-public.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function o(n){if(t[n])return t[n].exports;var c=t[n]={i:n,l:!1,exports:{}};return e[n].call(c.exports,c,c.exports,o),c.l=!0,c.exports}o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)o.d(n,c,function(t){return e[t]}.bind(null,c));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t){const o={init(){document.querySelectorAll(".woocommerce-cart .woocommerce, form.cart").forEach(e=>{e.addEventListener("click",this.changeQuantity)})},changeQuantity(e){if(!e.target.classList.contains("quantity__h-spin"))return;e.preventDefault();const t=e.target.closest(".quantity").querySelector('input[type="number"]'),o=e.target.classList.contains("is-plus")?1:-1,n=parseInt(t.value,10)+o;if(n<=0)return;t.value=n;const c=new Event("input",{bubbles:!0});t.dispatchEvent(c)}},n={init(){[...document.querySelectorAll(".h-cart")].forEach(e=>{e.addEventListener("click",this.openPopup)}),document.addEventListener("click",this.closePopup)},openPopup(e){(e.target.classList.contains("is-cart-button")||e.target.closest(".is-cart-button"))&&(e.preventDefault(),e.target.closest(".h-cart").classList.toggle("is-active"))},closePopup(e){if(e.target.closest(".widget_shopping_cart")||e.target.closest(".is-cart-button"))return;const t=document.querySelector(".h-cart.is-active");t&&t.classList.remove("is-active")}},c={init(){if(!document.querySelector("body").classList.contains("woocommerce-checkout"))return;const e=document.querySelectorAll(".showcoupon, .showlogin"),t=document.querySelectorAll(".woocommerce-form-coupon, .woocommerce-form-login"),o=document.querySelector(".woocommerce-form-coupon");[...e].forEach(e=>{e.addEventListener("click",this.openForm)}),[...t].forEach(e=>{e.addEventListener("click",e=>e.stopPropagation())}),document.addEventListener("click",this.closeForm),o&&o.addEventListener("submit",this.closeForm)},openForm(e){e.preventDefault(),e.stopPropagation();const t=e.target.classList.contains("showcoupon")?".woocommerce-form-coupon":".woocommerce-form-login",o=document.querySelector(t);o&&(o.classList.toggle("is-open"),document.querySelector("body").classList.toggle("has-checkout-form-open"))},closeForm(){const e=document.querySelector(".woocommerce-form-coupon.is-open, .woocommerce-form-login.is-open");e&&(document.querySelector("body").classList.remove("has-checkout-form-open"),e.classList.remove("is-open"))}},r={init(){[...document.querySelectorAll(".h-tab-mobile a")].forEach(e=>{e.addEventListener("click",this.onClick)})},onClick(e){e.preventDefault();const t=e.currentTarget.getAttribute("href"),o=document.querySelector(t),n=e.currentTarget.closest(".h-tab-mobile");o&&(n.classList.contains("active")?o.style.display="none":o.style.display="",n.classList.toggle("active"))}};document.addEventListener("DOMContentLoaded",(function(){o.init(),n.init(),c.init(),r.init()})),document.addEventListener("load",(function(){}))}]);
--------------------------------------------------------------------------------
/src/sass/hwc-admin-profile.scss:
--------------------------------------------------------------------------------
1 | @import "setting-admin";
2 | @import "edje-v15";
3 |
4 | ///// USER PROFILE
5 |
6 | #your-profile {
7 |
8 | @include display-flex;
9 | flex-wrap: wrap;
10 |
11 | *,
12 | *::before,
13 | *::after {
14 | box-sizing: border-box;
15 | }
16 |
17 | .form-table {
18 | display: block;
19 | width: 40%;
20 | background-color: white;
21 | padding: 1.25em;
22 | margin-bottom: 1.5em;
23 | border: 1px solid rgba(black, .15);
24 | border-radius: $g-radius;
25 |
26 | @include below( small ) {
27 | width: 80%;
28 | }
29 |
30 | @include below( mini ) {
31 | width: 100%;
32 | }
33 | }
34 |
35 | h2 {
36 | width: 100%;
37 | margin-top: 0.5rem;
38 | margin-bottom: 0.5rem;
39 | line-height: 1.3;
40 |
41 | font-size: 28px;
42 | font-weight: 400;
43 |
44 | @include below( small ) {
45 | width: 20%;
46 | margin-bottom: 0;
47 | }
48 |
49 | @include below( mini ) {
50 | width: 100%;
51 | padding-left: 0;
52 | font-size: 22px;
53 | }
54 | }
55 |
56 | tbody {
57 | @include display-flex;
58 | flex-wrap: wrap;
59 | margin: 0 -0.5em;
60 | }
61 |
62 | tr {
63 | width: 50%;
64 | padding: 0 0.5em;
65 |
66 | @include below( mini ) {
67 | width: 100%;
68 | margin-bottom: 0.5em;
69 | }
70 | }
71 |
72 | th, td {
73 | display: block;
74 | padding: 0;
75 | }
76 |
77 | th {
78 | color: $color-passive;
79 | }
80 |
81 | td {
82 | margin-bottom: 12px;
83 | }
84 |
85 | // field size
86 |
87 | input[type="text"],
88 | input[type="email"],
89 | input[type="url"],
90 | select,
91 | .form-table textarea, {
92 | width: 100%;
93 | padding: 5px 10px;
94 | }
95 |
96 | .select2-container {
97 | width: 100% !important;
98 | }
99 |
100 | .user-description-wrap,
101 | .user-profile-picture {
102 | width: 100%;
103 |
104 | p { display: none; }
105 | img { width: 75px; height: auto; }
106 | td { margin-bottom: 0; }
107 | }
108 |
109 | .user-sessions-wrap {
110 | width: 100%;
111 | }
112 | }
113 |
114 | #your-profile {
115 | ///// field order
116 |
117 | // ADMIN COLOR
118 | table:first-of-type,
119 | h2:first-of-type {
120 | display: none;
121 | }
122 |
123 | // NAME
124 | h2:nth-of-type(2),
125 | table:nth-of-type(2) {
126 | order: 1;
127 | }
128 |
129 | // CONTACT INFO
130 | h2:nth-of-type(3),
131 | table:nth-of-type(3) {
132 | order: 3;
133 | }
134 |
135 | // ABOUT THE USER
136 | h2:nth-of-type(4),
137 | table:nth-of-type(4) {
138 | order: 2;
139 | }
140 |
141 | // ACCOUNT MANAGEMENT
142 | h2:nth-of-type(5),
143 | table:nth-of-type(5) {
144 | order: 4;
145 | }
146 |
147 | // BILLING ADDRESS
148 | h2:nth-of-type(6),
149 | table:nth-of-type(6) {
150 | order: 5;
151 | }
152 |
153 | // BILLING ADDRESS
154 | h2:nth-of-type(7),
155 | table:nth-of-type(7) {
156 | order: 6;
157 | }
158 |
159 | .submit {
160 | order: 7;
161 | width: 100%;
162 | }
163 |
164 |
165 | ///// field design
166 |
167 | table:nth-of-type(4),
168 | table:nth-of-type(5) {
169 | background-color: $panel-bg;
170 | }
171 |
172 | }
173 |
174 | // Shipping and Billing
175 |
176 | #your-profile {
177 | #fieldset-billing,
178 | #fieldset-shipping {
179 | br { display: none; }
180 | }
181 |
182 | #fieldset-billing {
183 | tr:nth-child(1),
184 | tr:nth-child(2),
185 | tr:nth-child(3) {
186 | width: 33.333%;
187 | }
188 | }
189 |
190 | #fieldset-shipping {
191 | tr:nth-child(1) {
192 | width: 100%;
193 | }
194 |
195 | tr:nth-child(2),
196 | tr:nth-child(3),
197 | tr:nth-child(4) {
198 | width: 33.333%;
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/module-gutenberg/src/featured-category.jsx:
--------------------------------------------------------------------------------
1 | // Add Vertical Alignment to woocommerce/featured-category block
2 |
3 | import './featured-category.sass';
4 |
5 | import { assign } from 'lodash';
6 | import { addFilter } from '@wordpress/hooks';
7 | import { select } from '@wordpress/data';
8 | import { Fragment } from '@wordpress/element';
9 | import {
10 | BlockControls,
11 | BlockVerticalAlignmentToolbar,
12 | getColorObjectByColorValue,
13 | InspectorControls,
14 | PanelColorSettings } from '@wordpress/block-editor';
15 |
16 |
17 | addFilter( 'blocks.registerBlockType', 'wc-featured-category/attributes', addAttribute );
18 | addFilter( 'editor.BlockEdit', 'wc-featured-category/edit', addControl );
19 |
20 |
21 | /**
22 | * Add the Vertical Align attribute
23 | */
24 | function addAttribute( settings, name ) {
25 | // abort if not our targetted block
26 | let targetBlocks = [ 'woocommerce/featured-category', 'woocommerce/featured-product' ];
27 | if ( !targetBlocks.includes( name ) ) {
28 | return settings;
29 | }
30 |
31 | settings.attributes = assign( settings.attributes, {
32 | verticalAlignment: { type: 'string', default: 'center' },
33 | textColor: { type: 'string', default: 'white' },
34 | } );
35 |
36 | return settings;
37 | }
38 |
39 |
40 | /**
41 | * Add the Vertical Align option to the toolbar
42 | */
43 | function addControl( BlockEdit ) {
44 | return ( props ) => {
45 | // abort if not our targetted block
46 | let targetBlocks = [ 'woocommerce/featured-category', 'woocommerce/featured-product' ];
47 | if ( !targetBlocks.includes( props.name ) ) {
48 | return (
49 |
50 | );
51 | }
52 |
53 | let atts = props.attributes;
54 |
55 | return (
56 |
57 |
58 |
59 |
63 |
64 |
65 |
75 |
76 |
77 |
78 | );
79 |
80 |
81 | //
82 | function updateAlignment( newValue ) {
83 | newValue = newValue || '';
84 | props.setAttributes( { verticalAlignment: newValue } );
85 |
86 | // remove existing VAlign class
87 | if( atts.className ) {
88 | atts.className = atts.className.replace( /is-vertically-aligned-\w+/, '' );
89 | } else {
90 | atts.className = ''; // initialize
91 | }
92 |
93 | // add VAlign class
94 | if( newValue ) {
95 | props.setAttributes({ className: `${atts.className} is-vertically-aligned-${ newValue }` });
96 | }
97 | }
98 |
99 | /**
100 | *
101 | */
102 | function updateTextColor( newColor ) {
103 | newColor = newColor || 'white';
104 | props.setAttributes({ textColor: newColor });
105 |
106 | // remove existing color class
107 | if( atts.className ) {
108 | atts.className = atts.className.replace( /has-text-color has-[\w-]+-color/, '' ).trim();
109 | } else {
110 | atts.className = ''; // initialize
111 | }
112 |
113 | // if none selected
114 | if( newColor === 'white' ) {
115 | props.setAttributes({ className: atts.className.trim() });
116 | }
117 | else {
118 | const settings = select( 'core/editor' ).getEditorSettings();
119 | const colorObject = getColorObjectByColorValue( settings.colors, newColor );
120 |
121 | props.setAttributes({ className: `${atts.className} has-text-color has-${colorObject.slug}-color` });
122 | }
123 | }
124 | };
125 | }
--------------------------------------------------------------------------------
/frontend/products.php:
--------------------------------------------------------------------------------
1 |
73 |
74 | {$data->image}
75 | {$data->title}
76 |
77 | {$new_badge}
78 | {$data->price}
79 | {$data->rating}
80 | {$data->button}
81 | ";
82 | }
83 |
84 |
85 | /**
86 | * Get a Sale badge saying "% Off"
87 | *
88 | * @param WC_Product $product
89 | * @return string - HTML of the badge
90 | */
91 | function _h_get_sale_badge($product) : string {
92 | $percentage = 100;
93 |
94 | if ($product->is_type('variable')) {
95 | $percentages = [];
96 |
97 | $prices = $product->get_variation_prices();
98 |
99 | foreach ($prices['price'] as $key => $price) {
100 | if ($prices['regular_price'][$key] !== $price) {
101 | $percentages[] = round(
102 | 100 - (
103 | $prices['sale_price'][$key] / $prices['regular_price'][$key] * 100
104 | )
105 | );
106 | }
107 | }
108 |
109 | if (count($percentages) >= 1) {
110 | $percentage = max($percentages);
111 | }
112 | } else {
113 | $regular_price = (float) $product->get_regular_price();
114 | $sale_price = (float) $product->get_sale_price();
115 |
116 | if ($regular_price > 0) {
117 | $percentage = round(100 - ($sale_price / $regular_price * 100));
118 | }
119 | }
120 |
121 | // if has discount
122 | if ($percentage < 100) {
123 | $label = sprintf(__('%s%% Off'), $percentage);
124 | $label = apply_filters('h_product_onsale_label', $label, $percentage);
125 | return "
{$label}";
126 | }
127 |
128 | return '';
129 | }
130 |
131 | /**
132 | * Get an "Out of Stock" badge
133 | */
134 | function _h_get_outofstock_badge($product) : string {
135 | if (!$product->is_in_stock()) {
136 | $label = __('Out of Stock');
137 | return "
{$label}";
138 | }
139 |
140 | return '';
141 | }
--------------------------------------------------------------------------------
/frontend/my-account-register.php:
--------------------------------------------------------------------------------
1 | fields = $this->_set_fields();
15 | }
16 |
17 | /*
18 | @action woocommerce_register_form_start
19 | */
20 | function add_extra_register_fields() {
21 | foreach ($this->fields as $name => $field) {
22 | woocommerce_form_field($name, $field);
23 | }
24 | }
25 |
26 | /*
27 | @action woocommerce_register_post
28 | */
29 | function validate_extra_register_fields( $username, $email, $validation_errors ) {
30 | foreach($this->fields as $name => $field) {
31 |
32 | $required_isset = isset( $field['required'] );
33 | // if required arg doesn't exist OR exist but false
34 | if( !$required_isset || ( $required_isset && !$field['required'] ) ) {
35 | continue;
36 | }
37 |
38 | // if field not empty
39 | if( isset( $_POST[ $name ] ) && empty( $_POST[ $name ] ) ) {
40 | $validation_errors->add(
41 | $name . '_error',
42 | printf( __('%l is required ', 'h'), $field['label'] )
43 | );
44 | }
45 | }
46 |
47 | return $validation_errors;
48 | }
49 |
50 |
51 | /*
52 | @woocommerce_created_customer
53 | */
54 | function save_extra_register_fields( $user_id ) {
55 | foreach( $this->fields as $name => $field ) {
56 | if( !isset( $_POST[ $name ] ) ) { continue; }
57 |
58 | $value = sanitize_text_field( $_POST[ $name ] );
59 | update_user_meta( $user_id, $name, $value );
60 |
61 | switch( $name ) {
62 | case 'billing_first_name':
63 | update_user_meta( $user_id, 'first_name', $value );
64 | break;
65 |
66 | case 'billing_last_name':
67 | update_user_meta( $user_id, 'last_name', $value );
68 | break;
69 | }
70 | }
71 | }
72 |
73 | /////
74 |
75 | function _set_fields() {
76 | global $woocommerce;
77 | $wc_countries = new \WC_Countries();
78 | $countries = $wc_countries->get_shipping_countries();
79 |
80 | // TODO: need to make ajax to change state when country is changed
81 | reset( $countries );
82 | $states = $wc_countries->get_states( key( $countries ) );
83 |
84 | $fields = array(
85 | 'billing_first_name' => [
86 | 'type' => 'text',
87 | 'label' => __('First name'),
88 | 'required' => true,
89 | ],
90 | 'billing_last_name' => [
91 | 'type' => 'text',
92 | 'label' => __('Last name'),
93 | 'required' => true,
94 | ],
95 | //
96 | 'billing_address_1' => [
97 | 'type' => 'text',
98 | 'label' => __('Address'),
99 | 'required' => true,
100 | 'placeholder' => __('Street Address'),
101 | ],
102 | 'billing_address_2' => [
103 | 'type' => 'text',
104 | 'label' => __('Address 2'),
105 | 'placeholder' => __('Apartment, Suite, Unit No.'),
106 | ],
107 | //
108 | 'billing_country' => [
109 | 'type' => 'select',
110 | 'label' => __('Country'),
111 | 'required' => true,
112 | 'options' => $countries,
113 | ],
114 | 'billing_state' => [
115 | 'type' => 'select',
116 | 'label' => __('Province / State'),
117 | 'required' => true,
118 | 'options' => $states
119 | ],
120 | 'billing_postcode' => [
121 | 'type' => 'text',
122 | 'label' => __('Postcode'),
123 | 'required' => true,
124 | ],
125 | //
126 | 'billing_city' => [
127 | 'type' => 'text',
128 | 'label' => __('Town / City'),
129 | 'required' => true,
130 | ],
131 | 'billing_phone' => [
132 | 'type' => 'text',
133 | 'label' => __('Phone'),
134 | ],
135 | );
136 |
137 | // prepopulate fields
138 | foreach( $fields as $name => $f ) {
139 | if( isset( $_POST[ $name ] ) ) {
140 | $fields[ $name ]['default'] = $_POST[ $name ];
141 | }
142 | }
143 |
144 | return $fields;
145 | }
146 |
147 | }
148 |
149 |
150 | new H_WooCommerce_Register();
--------------------------------------------------------------------------------
/src/sass/_settings.scss:
--------------------------------------------------------------------------------
1 | // EDJE Functional Sass
2 | // - Single-file version
3 | // - v3.0.0
4 |
5 | @charset "UTF-8";
6 |
7 | ///// COLORS
8 |
9 | // Palette
10 | $red : #d32f2f;
11 | $red-light: #ffcdd2;
12 | $yellow : #ffee58;
13 | $yellow-light: #fff9c4;
14 | $green : #4caf50;
15 | $green-light: #c8e6c9;
16 | $blue: #1976d2;
17 | $blue-light: #bbdefb;
18 |
19 | // Named colors
20 | $main : #2196f3;
21 | $main-dark : darken($main, 20%);
22 | $main-light : lighten($main, 10%);
23 |
24 | $sub : #607d8b;
25 | $sub-dark: darken($sub, 15%);
26 | $sub-light: lighten($sub, 10%);
27 |
28 | $gray : #b0bcc4;
29 | $gray-light: #f3f6f8;
30 | $gray-dark: #93a3ae;
31 |
32 | $body-background: #fff;
33 |
34 | // Media Query
35 | $size-xs : 480px;
36 | $size-s : 767px;
37 | $size-m : 960px;
38 | $size-l : 1120px;
39 |
40 | $below-xs: "max-width:#{ $size-xs }";
41 | $above-xs: "min-width:#{ $size-xs + 1px }";
42 | $below-s: "max-width:#{ $size-s }";
43 | $above-s: "min-width:#{ $size-s + 1px }";
44 | $below-m: "max-width:#{ $size-m }";
45 | $above-m: "min-width:#{ $size-m + 1px }";
46 | $below-l: "max-width:#{ $size-l }";
47 | $above-l: "min-width:#{ $size-l + 1px }";
48 |
49 | $below-nav: $below-s; // small navigation breakpoint
50 | $above-nav: $above-s;
51 |
52 | $portrait: "orientation: portrait";
53 | $landscape: "orientation: landscape";
54 | $retina: "min-resolution: 192dpi";
55 |
56 | // Typography
57 | $font-family : -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
58 | $font-family-header : "Apple Garamond", "Baskerville", "Times New Roman", "Droid Serif", "Times","Source Serif Pro", serif;
59 | $font-family-monospace: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
60 |
61 | // Put file in /assets/fonts directory
62 | $font-faces: (
63 | // "Open Sans": (
64 | // ( "opensans.woff", 400 ),
65 | // ( "opensans-italic.woff", 400, italic ),
66 | // ( "opensans-bold.woff", 700 )
67 | // )
68 | );
69 |
70 | $font-color : #222;
71 | $font-passive : #888;
72 | $font-weight : 400;
73 | $font-line : 1.65;
74 | $font-size : 16px;
75 |
76 | $color-link : inherit;
77 | $color-link-hover : inherit;
78 |
79 | // Typography - Header
80 | $header-color : $font-color;
81 | $header-weight : 700;
82 | $header-line : 1.25;
83 | $header-spacing : 0;
84 | $header-transform : none;
85 |
86 | $h1: (base: 42px, s: 30px);
87 | $h2: (base: 36px, s: 26px);
88 | $h3: (base: 30px, s: 22px);
89 | $h4: (base: 24px, s: 20px);
90 | $h5: (base: 20px, s: 18px);
91 | $h6: (base: $font-size, s: $font-size);
92 |
93 | // Typography List
94 | $ul-parent : disc;
95 | $ul-child : circle;
96 | $ol-parent : decimal;
97 | $ol-child : lower-alpha;
98 |
99 | // Grid
100 | $grid-columns : 12;
101 | $grid-gap : 20px;
102 | $grid-rim : 16px;
103 | $grid-max-width : $size-l;
104 |
105 | // Tile
106 | $tile-max : 8;
107 | $tile-gap : 20px;
108 |
109 | // Shadow
110 | $shadow-z0: 0 0.5px 2px rgba(black, .18), 0 1.5px 6px rgba(black, .08);
111 | $shadow-z1: 0 1.5px 4px rgba(black, .24), 0 1.5px 6px rgba(black, .12);
112 | $shadow-z2: 0 3px 12px rgba(black, .23), 0 3px 12px rgba(black, .16);
113 | $shadow-z3: 0 6px 12px rgba(black, .23), 0 10px 40px rgba(black, .19);
114 |
115 | // Other
116 | $g-radius : 4px;
117 | $g-transition : all .25s ease-out;
118 |
119 | $image-url: '../images/';
120 | $font-url: '../fonts/';
121 |
122 | // Blog
123 | $blog-width: 650px;
124 | $blog-font-size: 18px;
125 |
126 |
127 | // ----------------
128 | // FUNCTIONAL SASS
129 | // ----------------
130 |
131 | // COLORS for FUNCTIONAL SASS
132 | // - Accessible by these shorthand styles: bg, bc, c
133 | // - You can add transparency by adding underscore and number between 1-99
134 | // - Example: bg-main, c-black_10
135 | $h-colors: (
136 | 'main': $main,
137 | 'main-dark': $main-dark,
138 | 'main-light': $main-light,
139 |
140 | 'sub': $sub,
141 | 'sub-dark': $sub-dark,
142 | 'sub-light': $sub-light,
143 |
144 | 'red': $red,
145 | 'red-light': $red-light,
146 | 'yellow': $yellow,
147 | 'yellow-light': $yellow-light,
148 | 'green': $green,
149 | 'green-light': $green-light,
150 | 'blue': $blue,
151 | 'blue-light': $blue-light,
152 |
153 | 'black': black,
154 | 'white': white,
155 | 'gray': $gray,
156 | 'gray-light': $gray-light,
157 | 'gray-dark': $gray-dark,
158 |
159 | 'text': $font-color,
160 | 'passive': $font-passive,
161 | 'header': $header-color,
162 |
163 | 'body-bg': $body-background
164 | );
165 |
166 |
167 | // If the CSS doesn't fit in any variable, put it here
168 | $h-custom: (
169 | m0-auto: ( margin: 0 auto ),
170 | content-empty: ( content: '' ),
171 | );
172 |
173 |
174 | @import "edje/utility-h";
175 | @import "edje/utility";
176 | @import "edje/functional-vars";
177 | @import "edje/output";
--------------------------------------------------------------------------------
/module-gutenberg/dist/h-shop-editor.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId]) {
10 | /******/ return installedModules[moduleId].exports;
11 | /******/ }
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ i: moduleId,
15 | /******/ l: false,
16 | /******/ exports: {}
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.l = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // define getter function for harmony exports
37 | /******/ __webpack_require__.d = function(exports, name, getter) {
38 | /******/ if(!__webpack_require__.o(exports, name)) {
39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
40 | /******/ }
41 | /******/ };
42 | /******/
43 | /******/ // define __esModule on exports
44 | /******/ __webpack_require__.r = function(exports) {
45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
47 | /******/ }
48 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
49 | /******/ };
50 | /******/
51 | /******/ // create a fake namespace object
52 | /******/ // mode & 1: value is a module id, require it
53 | /******/ // mode & 2: merge all properties of value into the ns
54 | /******/ // mode & 4: return value when already ns object
55 | /******/ // mode & 8|1: behave like require
56 | /******/ __webpack_require__.t = function(value, mode) {
57 | /******/ if(mode & 1) value = __webpack_require__(value);
58 | /******/ if(mode & 8) return value;
59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
60 | /******/ var ns = Object.create(null);
61 | /******/ __webpack_require__.r(ns);
62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
64 | /******/ return ns;
65 | /******/ };
66 | /******/
67 | /******/ // getDefaultExport function for compatibility with non-harmony modules
68 | /******/ __webpack_require__.n = function(module) {
69 | /******/ var getter = module && module.__esModule ?
70 | /******/ function getDefault() { return module['default']; } :
71 | /******/ function getModuleExports() { return module; };
72 | /******/ __webpack_require__.d(getter, 'a', getter);
73 | /******/ return getter;
74 | /******/ };
75 | /******/
76 | /******/ // Object.prototype.hasOwnProperty.call
77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
78 | /******/
79 | /******/ // __webpack_public_path__
80 | /******/ __webpack_require__.p = "";
81 | /******/
82 | /******/
83 | /******/ // Load entry module and return exports
84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/shop-editor.js");
85 | /******/ })
86 | /************************************************************************/
87 | /******/ ({
88 |
89 | /***/ "./src/shop-editor.js":
90 | /*!****************************!*\
91 | !*** ./src/shop-editor.js ***!
92 | \****************************/
93 | /*! no exports provided */
94 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
95 |
96 | "use strict";
97 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _shop_editor_sass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shop-editor.sass */ \"./src/shop-editor.sass\");\n/* harmony import */ var _shop_editor_sass__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shop_editor_sass__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\n\n//# sourceURL=webpack:///./src/shop-editor.js?");
98 |
99 | /***/ }),
100 |
101 | /***/ "./src/shop-editor.sass":
102 | /*!******************************!*\
103 | !*** ./src/shop-editor.sass ***!
104 | \******************************/
105 | /*! no static exports found */
106 | /***/ (function(module, exports, __webpack_require__) {
107 |
108 | eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./src/shop-editor.sass?");
109 |
110 | /***/ })
111 |
112 | /******/ });
--------------------------------------------------------------------------------
/src/js/hwc-public.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Added (+) and (-) button to Quantity box. This is the listener for it.
3 | */
4 | const hQuantity = {
5 | init() {
6 | const $cartForms = document.querySelectorAll('.woocommerce-cart .woocommerce, form.cart');
7 | $cartForms.forEach(($f) => {
8 | $f.addEventListener('click', this.changeQuantity);
9 | });
10 | },
11 |
12 | changeQuantity(e) {
13 | if (!e.target.classList.contains('quantity__h-spin')) { return; }
14 |
15 | e.preventDefault();
16 | const $field = e.target.closest('.quantity').querySelector('input[type="number"]');
17 | const change = e.target.classList.contains('is-plus') ? 1 : -1;
18 | const result = parseInt($field.value, 10) + change;
19 |
20 | if (result <= 0) { return; }
21 |
22 | $field.value = result;
23 |
24 | // trigger change event for future use
25 | // const changeEvent = new Event('change');
26 | // $field.dispatchEvent(changeEvent);
27 |
28 | // trigger input event to enable "Update Cart" button in Cart page
29 | const event = new Event('input', { bubbles: true });
30 | $field.dispatchEvent(event);
31 | },
32 | };
33 |
34 | /**
35 | * Added custom Mini Cart widget. This is the listener to keep it open.
36 | */
37 | const hMiniCart = {
38 | init() {
39 | const $minicarts = document.querySelectorAll('.h-cart');
40 |
41 | [...$minicarts].forEach(($cart) => {
42 | $cart.addEventListener('click', this.openPopup);
43 | });
44 |
45 | document.addEventListener('click', this.closePopup);
46 | },
47 |
48 | openPopup(e) {
49 | if (!e.target.classList.contains('is-cart-button') && !e.target.closest('.is-cart-button')) { return; }
50 |
51 | e.preventDefault();
52 | e.target.closest('.h-cart').classList.toggle('is-active');
53 | },
54 |
55 | closePopup(e) {
56 | if (e.target.closest('.widget_shopping_cart') || e.target.closest('.is-cart-button')) { return; }
57 |
58 | const $openMinicart = document.querySelector('.h-cart.is-active');
59 |
60 | if ($openMinicart) {
61 | $openMinicart.classList.remove('is-active');
62 | }
63 | },
64 | };
65 |
66 | /**
67 | * Changed the coupon and login form in Checkout into Popup
68 | */
69 | const hCheckoutForm = {
70 | init() {
71 | if (!document.querySelector('body').classList.contains('woocommerce-checkout')) { return; }
72 |
73 | const $formLinks = document.querySelectorAll('.showcoupon, .showlogin');
74 | const $forms = document.querySelectorAll('.woocommerce-form-coupon, .woocommerce-form-login');
75 | const $couponForm = document.querySelector('.woocommerce-form-coupon');
76 |
77 | [...$formLinks].forEach(($link) => {
78 | $link.addEventListener('click', this.openForm);
79 | });
80 |
81 | // prevent closing when clicking inside the form
82 | [...$forms].forEach(($form) => {
83 | $form.addEventListener('click', (e) => e.stopPropagation());
84 | });
85 |
86 | // close the form when clicking outside
87 | document.addEventListener('click', this.closeForm);
88 |
89 | if ($couponForm) {
90 | $couponForm.addEventListener('submit', this.closeForm);
91 | }
92 | },
93 |
94 | /**
95 | *
96 | */
97 | openForm(e) {
98 | e.preventDefault();
99 | e.stopPropagation();
100 | const formTarget = e.target.classList.contains('showcoupon')
101 | ? '.woocommerce-form-coupon'
102 | : '.woocommerce-form-login';
103 |
104 | const $form = document.querySelector(formTarget);
105 |
106 | if ($form) {
107 | $form.classList.toggle('is-open');
108 | document.querySelector('body').classList.toggle('has-checkout-form-open');
109 | }
110 | },
111 |
112 | /**
113 | *
114 | */
115 | closeForm() {
116 | const $openedForm = document.querySelector('.woocommerce-form-coupon.is-open, .woocommerce-form-login.is-open');
117 |
118 | if ($openedForm) {
119 | document.querySelector('body').classList.remove('has-checkout-form-open');
120 | $openedForm.classList.remove('is-open');
121 | }
122 | },
123 | };
124 |
125 | /**
126 | * Listener for custom Mobile tab in Single Product page
127 | */
128 | const hMobileTabs = {
129 | init() {
130 | const $tabButtons = document.querySelectorAll('.h-tab-mobile a');
131 |
132 | [...$tabButtons].forEach(($b) => {
133 | $b.addEventListener('click', this.onClick);
134 | });
135 | },
136 |
137 | onClick(e) {
138 | e.preventDefault();
139 | const tabId = e.currentTarget.getAttribute('href');
140 | const $tab = document.querySelector(tabId);
141 | const $button = e.currentTarget.closest('.h-tab-mobile');
142 |
143 | if (!$tab) { return; }
144 |
145 | if ($button.classList.contains('active')) {
146 | $tab.style.display = 'none';
147 | } else {
148 | $tab.style.display = '';
149 | }
150 |
151 | $button.classList.toggle('active');
152 | },
153 | };
154 |
155 | function onReady() {
156 | hQuantity.init();
157 | hMiniCart.init();
158 | hCheckoutForm.init();
159 | hMobileTabs.init();
160 | }
161 |
162 | function onLoad() {
163 |
164 | }
165 |
166 | document.addEventListener('DOMContentLoaded', onReady);
167 | document.addEventListener('load', onLoad);
168 |
--------------------------------------------------------------------------------
/dist/hwc-variations.css:
--------------------------------------------------------------------------------
1 | .metaboxes .wc-metabox{border:none;border-bottom:1px solid #eee}body:not(.is-product-type-variable) .attribute_tab{display:none !important}#product_attributes h3,#variable_product_options h3{display:flex;align-items:center}#product_attributes a.delete,#variable_product_options a.delete{order:4;width:27px;height:27px;margin-top:0 !important;border-radius:4px;visibility:visible;text-align:center;font-size:0;color:#5c6c7a}#product_attributes a.delete::before,#variable_product_options a.delete::before{content:"";font-family:dashicons;font-size:initial;vertical-align:top;-webkit-font-smoothing:antialiased}#product_attributes a.delete:hover,#variable_product_options a.delete:hover{color:#e35950;background-color:rgba(227,89,80,.1)}#product_attributes .sort,#variable_product_options .sort{order:2;margin:0;padding:.5rem;margin-left:auto}#product_attributes div.handlediv,#variable_product_options div.handlediv{order:3}#product_attributes .woocommerce_attribute:nth-child(1){--color: #4caf50}#product_attributes .woocommerce_attribute:nth-child(2){--color: #763eaf}#product_attributes .woocommerce_attribute:nth-child(3){--color: #ff9517}#product_attributes .wc-metaboxes{border-bottom:none}#product_attributes .wc-metabox{border:none;border-bottom:1px solid #eee}#product_attributes .toolbar.toolbar-top{background-color:#fafafa}#product_attributes .toolbar .expand-close{display:none}#product_attributes h3{padding:.75rem 1rem !important;cursor:default}#product_attributes h3>label{display:none}#product_attributes strong.attribute_name,#product_attributes input.attribute_name{display:inline-block;width:75px;margin-right:1rem;color:var(--color, #333)}#product_attributes .wc-metabox:not(.taxonomy) strong.attribute_name{display:none}#product_attributes .select2-container,#product_attributes textarea{min-width:300px}#product_attributes .select2-selection,#product_attributes textarea{border-color:#eee}#product_attributes textarea{max-height:4rem}#product_attributes button.select_all_attributes,#product_attributes button.select_no_attributes{display:none}#product_attributes button.add_new_attribute{padding:0 .5rem;border:1px solid rgba(0,0,0,.1);font-size:12px;line-height:1}#product_attributes div.handlediv{display:none}#product_attributes .wc-metabox-content{display:none !important}#variable_product_options h3 select:nth-of-type(1),#variable_product_options .variations-defaults select:nth-of-type(1){--color: #4caf50}#variable_product_options h3 select:nth-of-type(2),#variable_product_options .variations-defaults select:nth-of-type(2){--color: #763eaf}#variable_product_options h3 select:nth-of-type(3),#variable_product_options .variations-defaults select:nth-of-type(3){--color: #ff9517}#variable_product_options .toolbar-variations-defaults{display:flex;background-color:#fafafa}#variable_product_options .toolbar-variations-defaults .woocommerce-help-tip{display:none}#variable_product_options .toolbar-variations-defaults select[name*=default_attribute]{max-width:100px;border:none;color:var(--color)}#variable_product_options .toolbar-variations-defaults .variation_actions{order:2;margin-left:auto;width:150px;margin-right:.25rem}#variable_product_options .toolbar-variations-defaults .variation_actions optgroup:nth-of-type(4){display:none}#variable_product_options .toolbar-variations-defaults .button.bulk_edit{order:3;display:flex;align-items:center}#variable_product_options .toolbar-top{display:flex}#variable_product_options .toolbar-top .variations-pagenav{display:none !important}#variable_product_options .h-variation-buttons{display:flex;column-gap:.5rem;width:100%}#variable_product_options .h-variation-buttons .button{display:flex;align-items:center;column-gap:.5rem;margin:0}#variable_product_options .h-variation-buttons svg{height:1rem;width:auto}#variable_product_options .h-variation-buttons path{fill:currentColor}#variable_product_options .h-variation-buttons [data-action=set-stock]{margin-right:auto}#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-price],#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-sale-price],#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-stock]{display:none}#variable_product_options h3>strong{display:none}#variable_product_options h3 select{color:var(--color);border:none;padding:0 .5rem;background:none}#variable_product_options h3 div.handlediv{display:flex;align-items:center;justify-content:center;visibility:visible !important;margin-top:0;padding:0 .5rem 0 0;border-radius:4px;width:auto;height:27px}#variable_product_options h3 div.handlediv:hover{background-color:rgba(0,0,0,.1)}#variable_product_options h3 div.handlediv::before{position:static;padding:0}#variable_product_options h3 div.handlediv::after{content:"Edit"}#variable_product_options .form-row.hide_if_variation_virtual.form-row-full,#variable_product_options .form-row[class*=variable_tax_class]{display:none !important}#variable_product_options .woocommerce_variable_attributes .data{background-color:#fafafa}.h-variation-overview{display:flex;column-gap:1rem;row-gap:1rem;margin-left:2rem;color:#5c6c7a}.h-variation-overview svg{height:1rem;width:auto;opacity:.5}.h-variation-overview path{fill:#5c6c7a}.h-variation-overview p{display:flex;align-items:center;column-gap:.5rem;margin:0}.h-variation-overview p.hidden{display:none}.h-variation-overview span{line-height:1}
2 |
--------------------------------------------------------------------------------
/frontend/checkout.php:
--------------------------------------------------------------------------------
1 |
";
36 | }
37 |
38 | function h_before_checkout_add_middle_wrapper() {
39 | echo "
";
40 | }
41 |
42 | /**
43 | * @filter woocommerce_before_checkout_form - 15
44 | */
45 | function h_before_checkout_add_closing_wrapper() {
46 | echo "
";
47 | }
48 |
49 | /**
50 | * @action woocommerce_checkout_before_order_review_heading
51 | */
52 | function h_order_review_add_wrapper() {
53 | echo "";
54 | }
55 |
56 | /**
57 | * @action woocommerce_checkout_after_order_review
58 | */
59 | function h_order_review_add_closing_wrapper() {
60 | echo "
";
61 | }
62 |
63 | /**
64 | * Add thumbnail to CART and ORDER table
65 | * @filter woocommerce_cart_item_name
66 | *
67 | * @param $name
68 | * @param $cart_item - The product data
69 | * @param $cart_item_key
70 | * @return - The HTML tag for item name
71 | */
72 | function h_order_review_add_thumbnail(string $name, $cart_item, $cart_item_key) : string {
73 | if (is_checkout() || is_wc_endpoint_url('view-order')) {
74 | $image = get_the_post_thumbnail($cart_item['product_id'], 'thumbnail');
75 | $image = $image ? $image : sprintf("