-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #4 from eduardovillao/feature/release-v2.0
chore: change php minimum version
Showing
12 changed files
with
505 additions
and
425 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,150 @@ | ||
# Form Masks for Elementor | ||
|
||
Form Masks for Elementor create a custom control in field advanced tab for your customize your fields with masks. This plugin require the Elementor Pro (Form Widget). | ||
The Form Masks for Elementor plugin adds a custom control in the Advanced Tab of form fields, allowing you to easily apply input masks. This plugin requires Elementor Pro (Form Widget). | ||
|
||
The masks work with filed types 'text'. | ||
Masks help users input structured data like phone numbers, dates, and more. | ||
|
||
📽️ **Watch how it works:** | ||
https://www.youtube.com/watch?v=NYoykAUl4QE | ||
|
||
#### Masks Available #### | ||
## Features (FREE VERSION) | ||
|
||
* Phone - '0000-0000' or '(000) 000-0000' or '(00) 0000-0000' | ||
Ready-to-Use Masks | ||
- **Phone**: | ||
- 0000-0000 | ||
- (000) 000-0000 | ||
- (00) 0000-0000 | ||
- (00) 0.0000-0000 | ||
- **CPF (Brazilian ID)**: 000.000.000-00 | ||
- **CNPJ (Brazilian Company ID)**: 00.000.000/0000-00 | ||
- **Date**: 00/00/0000 | ||
- **Time**: 00:00:00 | ||
- **Date and Time**: 00/00/0000 00:00:00 | ||
- **Money**: 000.000.000.000.000,00 | ||
- **Postal Code (CEP)**: 00000-000 | ||
- **Credit Card**: 0000-0000-0000-0000 | ||
- **Credit Card Expiry Date**: 00/00 | ||
|
||
* CPF - '000.000.000-00' | ||
## Exclusive PRO Features | ||
- **Custom Masks**: Create your own masks for maximum flexibility. Tailor your forms to any requirement. | ||
|
||
* CNPJ - '00.000.000/0000-00' | ||
🚀 **Coming Soon to the PRO Version** | ||
- **Minimum character limits** to prevent incomplete submissions. | ||
- **Prefix and suffix** options for masks. | ||
- Built-in **validation for CPF, CNPJ**, and other formats. | ||
- And much more… | ||
|
||
* Date - '00/00/0000' | ||
**PRO VERSION** | ||
[Check the PRO version here](https://codecanyon.net/item/form-masks-for-elementor/25872641) | ||
|
||
* Time - '00:00:00' | ||
📽️ **Watch how it works:** | ||
https://www.youtube.com/watch?v=XAuL43HFh8I | ||
|
||
* Date and Time - '00/00/0000 00:00:00' | ||
## Why Choose Form Masks for Elementor? | ||
- Simple to set up and use. | ||
- Increases form usability and data accuracy. | ||
- Seamless integration with Elementor Pro. | ||
- Regular updates with new features and improvements. | ||
|
||
* Money - '000.000.000.000.000,00' | ||
## More Plugins by Us | ||
|
||
* CEP - '00000-000' | ||
Discover other plugins to enhance your WordPress experience:: [WordPress Plugins](https://eduardovillao.me/wordpress-plugins/) | ||
|
||
#### Masks Available #### | ||
## Learn WordPress Tips | ||
|
||
Check the [Pro version](https://codecanyon.net/item/form-masks-for-elementor/25872641) | ||
Visit our blog for expert WordPress insights: [WordPress Tips](https://eduardovillao.me/blog/) | ||
|
||
#### CREDITS #### | ||
## Plugins Suggestions? | ||
|
||
This plugin use the jQuery Mask library plugin. [jQuery Mask Plugin](https://github.com/igorescobar/jQuery-Mask-Plugin) | ||
We’d love to hear from you! [[email protected]](mailto:[email protected]) | ||
|
||
## Installation | ||
|
||
1. Upload the plugin files to the WordPress | ||
2. Activate the plugin in WordPress | ||
3. Go to Widget Elementor Pro in your page | ||
4. Select the custom mask for field in advanced field tab **(works only on text field)** | ||
5. Go to the page for see the results (outside the Elementor editor) | ||
|
||
## Frequently Asked Questions | ||
|
||
1. Does the plugin work without Elementor Pro? | ||
|
||
No, the Form Masks for Elementor plugin requires Elementor Pro, as it relies on the Form Widget, which is only available in Elementor Pro. The plugin is not compatible with alternatives like Pro Elements or similar Elementor-like versions. | ||
|
||
2. Does the mask work on all field types? | ||
|
||
The plugin supports masks only for fields of type text. This means that masks will not work on fields like textarea, number, or other custom field types. | ||
|
||
3. Can I create my own masks? | ||
|
||
Yes, but this feature is available only in the PRO version. With the PRO version, you can define custom masks tailored to your specific needs. | ||
|
||
## Changelog | ||
``` | ||
= 2.0 = | ||
* New: add inputmode to open keybord with input context. Ex.: input with tel mask will open numeric keybord. | ||
* New: remove jQuery mask library to use our own custom library. | ||
* New: support to masks on popup improved. | ||
* Changed: minimum PHP version changed to 7.4. | ||
* Changed: improve build proccess to assets. | ||
= 1.6.5 = | ||
* Changed: compatibility with WordPress 6.7. | ||
* Changed: code improvements. | ||
= 1.6.4 = | ||
* Changed: compatibility with WordPress 6.5. | ||
* Changed: code improvements. | ||
= 1.6.3 = | ||
* Changed: compatibility with WordPress 6.2. | ||
= 1.6.2 = | ||
* Changed: compatibility with WordPress 6.1. | ||
= 1.6.1 = | ||
* Changed: compatibility with WordPress 6.0. | ||
= 1.6 = | ||
* Changed: support to string translations. | ||
* Changed: code improvements. | ||
* Changed: plugin header requirements improved. | ||
= 1.5.3 = | ||
* Tweak: conflict with jQuery old versions. | ||
= 1.5.2 = | ||
* Tweak: add hooks to pro version new features. | ||
* Tweak: code improvements. | ||
= 1.5.1 = | ||
* Tweak: mask with 9 digits improved. | ||
* Tweak: update and minify jQuery mask lib. | ||
= 1.5 = | ||
* New: support for Pro version. | ||
* Tweak: improve JS mask files. | ||
* Tweak: improve plugin code structure. | ||
= 1.4.2 = | ||
* Suppor to WordPress 5.8. | ||
= 1.4.1 = | ||
* Fix: active mask on popup is called by link, button and others. | ||
= 1.4 = | ||
* Support for Elementor Popup. | ||
= 1.3 = | ||
* Add new mask - Credit card and Credit card date. | ||
= 1.2 = | ||
* Add new mask - Phone 9 digits. | ||
= 1.1 = | ||
* Update the mask control. | ||
= 1.0 = | ||
* Initial release. | ||
``` |
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
class inputMask { | ||
constructor(mappedMasks) { | ||
this.inputs = null; | ||
this.init(); | ||
this.mappedMasks = mappedMasks || null; | ||
this.tokens = { | ||
'0': { | ||
validateRule: /\d/, | ||
}, | ||
}; | ||
} | ||
|
||
init() { | ||
if (document.readyState !== 'complete') { | ||
window.addEventListener('load', this.init.bind(this)); | ||
return; | ||
} | ||
|
||
this.initModalListener(); | ||
this.getInput(); | ||
} | ||
|
||
initModalListener() { | ||
const body = document.body; | ||
|
||
const observer = new MutationObserver((mutations) => { | ||
mutations.forEach((mutation) => { | ||
if (mutation.type === 'childList') { | ||
mutation.addedNodes.forEach((node) => { | ||
if ( | ||
node.classList && | ||
node.classList.contains('elementor-popup-modal') | ||
) { | ||
this.getInput(); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
|
||
observer.observe(body, { childList: true }); | ||
} | ||
|
||
getInput() { | ||
this.inputs = document.querySelectorAll('input[data-mask]'); | ||
this.inputs.forEach((input) => { | ||
this.handleMappedMasks(input); | ||
input.addEventListener('input', this.maskInput.bind(this)); | ||
input.addEventListener('keydown', this.handleBackspace.bind(this)); | ||
}); | ||
} | ||
|
||
handleMappedMasks(input) { | ||
if (!this.mappedMasks) { | ||
return; | ||
} | ||
|
||
const replaceMaks = this.mappedMasks[input.dataset.mask]; | ||
if (!replaceMaks) { | ||
return; | ||
} | ||
|
||
input.dataset.mask = replaceMaks.mask; | ||
input.dataset.maskReverse = replaceMaks.reverse; | ||
input.inputmode = replaceMaks.inputmode; | ||
} | ||
|
||
maskInput(event) { | ||
const input = event.target; | ||
const mask = input.dataset.mask; | ||
const value = input.value; | ||
const unmaskedValue = this.removeMask(mask, value); | ||
const isReverse = input.dataset.maskReverse === 'true'; | ||
const maskedValue = this.applyMask(unmaskedValue, mask, isReverse); | ||
|
||
input.value = maskedValue; | ||
} | ||
|
||
removeMask(mask, value) { | ||
if (!mask || !value) { | ||
return value; | ||
} | ||
|
||
const allowTokens = Object.keys(this.tokens); | ||
const allowTokensRegex = new RegExp(`[${allowTokens.join('')}]`, 'g'); | ||
const maskLiteralsToRemove = mask.replace(allowTokensRegex, ''); | ||
return value.replace(new RegExp(`[${maskLiteralsToRemove}]`, 'g'), ''); | ||
} | ||
|
||
handleBackspace(event) { | ||
const input = event.target; | ||
if ( | ||
event.key === 'Backspace' && | ||
input.selectionStart === input.selectionEnd | ||
) { | ||
const pos = input.selectionStart; | ||
if (pos > 0) { | ||
const value = input.value; | ||
if (!/\d/.test(value[pos - 1])) { | ||
event.preventDefault(); | ||
input.value = value.slice(0, pos - 1) + value.slice(pos); | ||
input.setSelectionRange(pos - 1, pos - 1); | ||
} | ||
} | ||
} | ||
} | ||
|
||
applyMask(unmaskedValue, mask, isReverse) { | ||
if (!unmaskedValue) { | ||
return unmaskedValue; | ||
} | ||
|
||
let maskedValue = ''; | ||
let valueIndex = 0; | ||
let maskChars = mask.split(''); | ||
|
||
if (isReverse) { | ||
unmaskedValue = unmaskedValue.split('').reverse().join(''); | ||
maskChars = maskChars.reverse(); | ||
} | ||
|
||
for (let i = 0; i < maskChars.length; i++) { | ||
if (maskChars[i] === '0') { | ||
if ( | ||
new RegExp(this.tokens['0'].validateRule).test( | ||
unmaskedValue[valueIndex] | ||
) | ||
) { | ||
maskedValue += unmaskedValue[valueIndex]; | ||
valueIndex++; | ||
} else { | ||
break; | ||
} | ||
} else { | ||
maskedValue += maskChars[i]; | ||
} | ||
} | ||
|
||
if (isReverse) { | ||
maskedValue = maskedValue.split('').reverse().join(''); | ||
maskedValue = maskedValue.startsWith('.') | ||
? maskedValue.substring(1) | ||
: maskedValue; | ||
} | ||
|
||
return maskedValue; | ||
} | ||
} | ||
|
||
new inputMask({ | ||
'ev-tel': { | ||
mask: '0000-0000', | ||
reverse: false, | ||
inputmode: 'tel', | ||
}, | ||
'ev-tel-ddd': { | ||
mask: '(00) 0000-0000', | ||
reverse: false, | ||
inputmode: 'tel', | ||
}, | ||
'ev-tel-ddd9': { | ||
mask: '(00) 00000-0000', | ||
reverse: false, | ||
}, | ||
'ev-tel-us': { | ||
mask: '(000) 000-0000', | ||
reverse: false, | ||
inputmode: 'tel', | ||
}, | ||
'ev-cpf': { | ||
mask: '000.000.000-00', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-cnpj': { | ||
mask: '00.000.000/0000-00', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-money': { | ||
mask: '000.000.000.000.000,00', | ||
reverse: true, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-ccard': { | ||
mask: '0000-0000-0000-0000', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-ccard-valid': { | ||
mask: '00/00', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-cep': { | ||
mask: '00000-000', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-time': { | ||
mask: '00:00:00', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-date': { | ||
mask: '00/00/0000', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
'ev-date_time': { | ||
mask: '00/00/0000 00:00:00', | ||
reverse: false, | ||
inputmode: 'numeric', | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,244 +1,37 @@ | ||
// const path = require('path'); | ||
// const fs = require('fs'); | ||
// const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); | ||
// const MiniCssExtractPlugin = require("mini-css-extract-plugin"); | ||
|
||
// const orderJs = { | ||
// mode: 'production', | ||
// entry: './src/js/order/controller.js', | ||
// output: { | ||
// filename: 'order.min.js', | ||
// path: path.resolve(__dirname, 'assets/js'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.js$/, | ||
// exclude: /node_modules/, | ||
// use: { | ||
// loader: 'esbuild-loader', | ||
// options: { | ||
// loader: 'js', | ||
// target: 'es2016', | ||
// }, | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// }; | ||
|
||
// const srcJsAdminDirectory = path.resolve(__dirname, 'src/js/admin'); | ||
// const adminEntries = fs.readdirSync(srcJsAdminDirectory).reduce((entries, file) => { | ||
// if (file.endsWith('.js')) { | ||
// const entryKey = file.replace('.js', ''); | ||
// entries[entryKey] = path.resolve(srcJsAdminDirectory, file); | ||
// } | ||
// return entries; | ||
// }, {}); | ||
|
||
// const adminJs = { | ||
// mode: 'production', | ||
// entry: adminEntries, | ||
// output: { | ||
// filename: '[name].min.js', | ||
// path: path.resolve(__dirname, 'assets/js/admin'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.js$/, | ||
// exclude: /node_modules/, | ||
// use: { | ||
// loader: 'esbuild-loader', | ||
// options: { | ||
// loader: 'js', | ||
// target: 'es2016', | ||
// }, | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// }; | ||
|
||
// const srcJsCustomFieldsDirectory = path.resolve(__dirname, 'src/js/admin/custom-fields'); | ||
// const customFieldsEntries = fs.readdirSync(srcJsCustomFieldsDirectory).reduce((entries, file) => { | ||
// if (file.endsWith('.js')) { | ||
// const entryKey = file.replace('.js', ''); | ||
// entries[entryKey] = path.resolve(srcJsCustomFieldsDirectory, file); | ||
// } | ||
// return entries; | ||
// }, {}); | ||
|
||
// const customFieldsJs = { | ||
// mode: 'production', | ||
// entry: customFieldsEntries, | ||
// output: { | ||
// filename: '[name].min.js', | ||
// path: path.resolve(__dirname, 'assets/js/admin/custom-fields'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.js$/, | ||
// exclude: /node_modules/, | ||
// use: { | ||
// loader: 'esbuild-loader', | ||
// options: { | ||
// loader: 'js', | ||
// target: 'es2016', | ||
// }, | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// }; | ||
|
||
// const srcJsGeneralDirectory = path.resolve(__dirname, 'src/js/'); | ||
// const generalEntries = fs.readdirSync(srcJsGeneralDirectory).reduce((entries, file) => { | ||
// if (file.endsWith('.js')) { | ||
// const entryKey = file.replace('.js', ''); | ||
// entries[entryKey] = path.resolve(srcJsGeneralDirectory, file); | ||
// } | ||
// return entries; | ||
// }, {}); | ||
|
||
// const generalJs = { | ||
// mode: 'production', | ||
// entry: generalEntries, | ||
// output: { | ||
// filename: '[name].min.js', | ||
// path: path.resolve(__dirname, 'assets/js'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.js$/, | ||
// exclude: /node_modules/, | ||
// use: { | ||
// loader: 'esbuild-loader', | ||
// options: { | ||
// loader: 'js', | ||
// target: 'es2016', | ||
// }, | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// }; | ||
|
||
// const srcJsOrdersPanelDirectory = path.resolve(__dirname, 'src/js/orders-panel'); | ||
// const ordersPanelEntries = fs.readdirSync(srcJsOrdersPanelDirectory).map((file) => { | ||
// if (file.endsWith('.js')) { | ||
// return path.resolve(srcJsOrdersPanelDirectory, file); | ||
// } | ||
// }, []); | ||
|
||
// const ordersPanelJs = { | ||
// mode: 'production', | ||
// entry: ordersPanelEntries, | ||
// output: { | ||
// filename: 'frontend.min.js', | ||
// path: path.resolve(__dirname, 'assets/js/orders-panel'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.js$/, | ||
// exclude: /node_modules/, | ||
// use: { | ||
// loader: 'esbuild-loader', | ||
// options: { | ||
// loader: 'js', | ||
// target: 'es2016', | ||
// }, | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// }; | ||
|
||
// const deliveryPageCSS = { | ||
// mode: 'production', | ||
// entry: './src/css/delivery-page/style.css', | ||
// output: { | ||
// filename: 'style.bundle.js', | ||
// path: path.resolve(__dirname, 'assets/css/'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.css$/, | ||
// use: [MiniCssExtractPlugin.loader, 'css-loader'], | ||
// }, | ||
// ], | ||
// }, | ||
// optimization: { | ||
// minimizer: [new CssMinimizerPlugin()], | ||
// }, | ||
// plugins: [ | ||
// new MiniCssExtractPlugin({ | ||
// filename: 'delivery-frontend.min.css', | ||
// }), | ||
// ], | ||
// }; | ||
|
||
// const orderPanelPageCSS = { | ||
// mode: 'production', | ||
// entry: './src/css/order-panel/style.css', | ||
// output: { | ||
// filename: 'style.bundle.js', | ||
// path: path.resolve(__dirname, 'assets/css/'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.css$/, | ||
// use: [MiniCssExtractPlugin.loader, 'css-loader'], | ||
// }, | ||
// ], | ||
// }, | ||
// optimization: { | ||
// minimizer: [new CssMinimizerPlugin()], | ||
// }, | ||
// plugins: [ | ||
// new MiniCssExtractPlugin({ | ||
// filename: 'order-panel-frontend.min.css', | ||
// }), | ||
// ], | ||
// }; | ||
|
||
// const trackOrderPageCSS = { | ||
// mode: 'production', | ||
// entry: './src/css/track-order/style.css', | ||
// output: { | ||
// filename: 'style.bundle.js', | ||
// path: path.resolve(__dirname, 'assets/css/'), | ||
// }, | ||
// module: { | ||
// rules: [ | ||
// { | ||
// test: /\.css$/, | ||
// use: [MiniCssExtractPlugin.loader, 'css-loader'], | ||
// }, | ||
// ], | ||
// }, | ||
// optimization: { | ||
// minimizer: [new CssMinimizerPlugin()], | ||
// }, | ||
// plugins: [ | ||
// new MiniCssExtractPlugin({ | ||
// filename: 'track-order-frontend.min.css', | ||
// }), | ||
// ], | ||
// }; | ||
|
||
// module.exports = [ | ||
// orderJs, | ||
// adminJs, | ||
// customFieldsJs, | ||
// generalJs, | ||
// ordersPanelJs, | ||
// deliveryPageCSS, | ||
// orderPanelPageCSS, | ||
// trackOrderPageCSS, | ||
// ]; | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
|
||
const srcJsGeneralDirectory = path.resolve(__dirname, 'src/js/'); | ||
const generalEntries = fs.readdirSync(srcJsGeneralDirectory).reduce((entries, file) => { | ||
if (file.endsWith('.js')) { | ||
const entryKey = file.replace('.js', ''); | ||
entries[entryKey] = path.resolve(srcJsGeneralDirectory, file); | ||
} | ||
return entries; | ||
}, {}); | ||
|
||
const generalJs = { | ||
mode: 'production', | ||
entry: generalEntries, | ||
output: { | ||
filename: '[name].min.js', | ||
path: path.resolve(__dirname, 'assets/js'), | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.js$/, | ||
exclude: /node_modules/, | ||
use: { | ||
loader: 'esbuild-loader', | ||
options: { | ||
loader: 'js', | ||
target: 'es2016', | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
|
||
module.exports = [generalJs]; |