Add button feature
This commit is contained in:
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
12
.idea/add-to-basket.iml
generated
Normal file
12
.idea/add-to-basket.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Max Scheme" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/add-to-basket.iml" filepath="$PROJECT_DIR$/.idea/add-to-basket.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
18
README.md
Normal file
18
README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Add To Basket Button #
|
||||||
|
|
||||||
|
Use the function to generate the markup. Then just insert the button somewhere in your item element.
|
||||||
|
|
||||||
|
### How to use ###
|
||||||
|
|
||||||
|
1. Copy the code, and use **idmAddToBasket** function to generate the markup
|
||||||
|
2. Don't forget to put it somewhere after
|
||||||
|
|
||||||
|
```
|
||||||
|
const afterWhatPaste = document.getElementById('item-container');
|
||||||
|
const idmAddToBasketElement = idmAddToBasket(product, size);
|
||||||
|
afterWhatPaste.insertAdjacentHTML('afterend', idmAddToBasketElement);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Created by • **[IdoMods](https://idomods.pl/)** • 2025
|
||||||
92
main.js
Normal file
92
main.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* @product {object} product information
|
||||||
|
* @size product size, get form product.sizes.[0]
|
||||||
|
* @return html markup
|
||||||
|
**/
|
||||||
|
function idmAddToBasket(product, size) {
|
||||||
|
const can = product?.type === 'product' && product?.sizes?.length === 1 && size;
|
||||||
|
if (!can) return '';
|
||||||
|
|
||||||
|
const sellBy = size?.unitSellby || 1;
|
||||||
|
const precision = size?.unitPrecision || 0;
|
||||||
|
const max = (typeof size?.amount === 'number' && size.amount > 0) ? size.amount : '';
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class='idm-products-banner__add-to-basket'>
|
||||||
|
<form class='idm-products-banner__add-to-basket-form' action='/basketchange.php' method='post'>
|
||||||
|
<input type='hidden' name='mode' value='1'>
|
||||||
|
<input type='hidden' name='product' value='${escapeHtml(product.id)}'>
|
||||||
|
<input type='hidden' name='size' value='${escapeHtml(size.id)}'>
|
||||||
|
|
||||||
|
<div class='idm-products-banner__qty'
|
||||||
|
data-sell-by='${escapeHtml(String(sellBy))}'
|
||||||
|
data-precision='${escapeHtml(String(precision))}'
|
||||||
|
data-max='${escapeHtml(String(max))}'>
|
||||||
|
<button type='button' class='idm-products-banner__qty-decrease'>−</button>
|
||||||
|
|
||||||
|
<input type='number'
|
||||||
|
name='number'
|
||||||
|
class='idm-products-banner__qty-input'
|
||||||
|
value='${escapeHtml(String(sellBy))}'
|
||||||
|
step='${escapeHtml(String(sellBy))}'
|
||||||
|
min='${escapeHtml(String(sellBy))}'
|
||||||
|
max='${escapeHtml(String(max))}'>
|
||||||
|
|
||||||
|
<button type='button' class='idm-products-banner__qty-increase'>+</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type='submit' class='btn --solid --medium idm-products-banner__add-to-basket-button'>
|
||||||
|
<span>${<iai:variable vid='Do koszyka' />}</span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// +/- i walidacja inputów ilości
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
const wrapper = e.target.closest('.idm-products-banner__qty');
|
||||||
|
if (!wrapper) return;
|
||||||
|
|
||||||
|
const input = wrapper.querySelector('.idm-products-banner__qty-input');
|
||||||
|
const step = parseFloat(wrapper.dataset.sellBy || '1');
|
||||||
|
const precision = parseInt(wrapper.dataset.precision || '0');
|
||||||
|
const max = parseFloat(wrapper.dataset.max || '999999');
|
||||||
|
let current = parseFloat(input.value) || 0;
|
||||||
|
|
||||||
|
if (e.target.classList.contains('idm-products-banner__qty-increase')) {
|
||||||
|
current += step;
|
||||||
|
if (current > max) current = max;
|
||||||
|
} else if (e.target.classList.contains('idm-products-banner__qty-decrease')) {
|
||||||
|
current -= step;
|
||||||
|
if (current < step) current = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.value = current.toFixed(precision);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('blur', (e) => {
|
||||||
|
if (!e.target.classList.contains('idm-products-banner__qty-input')) return;
|
||||||
|
|
||||||
|
const input = e.target;
|
||||||
|
const wrapper = input.closest('.idm-products-banner__qty');
|
||||||
|
const step = parseFloat(wrapper.dataset.sellBy || '1');
|
||||||
|
const precision = parseInt(wrapper.dataset.precision || '0');
|
||||||
|
const max = parseFloat(wrapper.dataset.max || '999999');
|
||||||
|
|
||||||
|
let val = parseFloat(input.value);
|
||||||
|
if (isNaN(val) || val < step) {
|
||||||
|
val = step;
|
||||||
|
} else if (val > max) {
|
||||||
|
val = max;
|
||||||
|
} else {
|
||||||
|
val = Math.round(val / step) * step;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.value = val.toFixed(precision);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// helper
|
||||||
|
const escapeHtml = (v = '') => String(v)
|
||||||
|
.replace(/&/g, '&').replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>').replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
53
style.less
Normal file
53
style.less
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
.idm-products-banner__qty {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.idm-products-banner__qty-input {
|
||||||
|
height: 4rem;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
width: 60%;
|
||||||
|
max-width: unset;
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.idm-products-banner__qty button {
|
||||||
|
background: #000;
|
||||||
|
height: 4rem;
|
||||||
|
width: 4rem;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
min-width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.idm-products-banner__add-to-basket {
|
||||||
|
display: flex;
|
||||||
|
align-items: end;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.--solid.--medium.idm-products-banner__add-to-basket-button {
|
||||||
|
height: 4rem;
|
||||||
|
background: #000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.--solid.--medium.idm-products-banner__add-to-basket-link {
|
||||||
|
width: 100%;
|
||||||
|
height: 4rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #000;
|
||||||
|
border: 1px solid #000;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user