simple-phone-mask
Version:
A lightweight and customizable phone number input mask with country flags, search, validation and dark theme.
411 lines (382 loc) • 12.4 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Simple Phone Mask Demo v1.0.5</title>
<link rel="stylesheet" href="../dist/simple-phone-mask.min.css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" rel="stylesheet" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css"
rel="stylesheet"
/>
<style>
body {
font-family: Arial, sans-serif;
max-width: 640px;
margin: 40px auto;
padding: 0 20px;
}
h2 {
font-size: 18px;
margin: 0 0 6px;
color: #444;
}
.version-badge {
display: inline-block;
background: #4a90e2;
color: #fff;
font-size: 12px;
padding: 2px 8px;
border-radius: 20px;
vertical-align: middle;
margin-left: 8px;
}
.new-badge {
display: inline-block;
background: #38a169;
color: #fff;
font-size: 11px;
padding: 1px 6px;
border-radius: 20px;
vertical-align: middle;
margin-left: 6px;
font-weight: bold;
}
.input-group {
margin-bottom: 50px;
}
.input-group label {
font-weight: bold;
margin-bottom: 10px;
}
.social-buttons {
display: flex;
gap: 10px;
margin: 20px 0 40px;
flex-wrap: wrap;
}
.social-button {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
border-radius: 6px;
text-decoration: none;
font-weight: 500;
color: #fff;
transition: opacity 0.2s;
}
.social-button:hover { opacity: 0.9; }
.social-button img { width: 20px; height: 20px; }
.github { background: #24292e; }
.npm { background: #cb3837; }
.freelancehunt {
background: transparent;
border: 1px solid #ffb21b;
color: #333;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="tel"] {
padding: 8px;
font-size: 16px;
width: 220px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
pre {
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
margin-top: 12px;
position: relative;
overflow-x: auto;
}
code {
font-family: monospace;
font-size: 13px;
}
.copy-button {
position: absolute;
top: 5px;
right: 5px;
padding: 4px 8px;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.copy-button:hover { background: #f0f0f0; }
/* Dark demo section */
.dark-section {
background: #13131f;
padding: 20px;
border-radius: 10px;
margin-bottom: 50px;
}
.dark-section label {
color: #dde1f0;
font-weight: bold;
margin-bottom: 10px;
}
.dark-section input[type="tel"] {
background: #1e1e2e;
border-color: #3a3a52;
color: #dde1f0;
}
.dark-section pre {
background: #1e1e2e;
color: #dde1f0;
border: 1px solid #3a3a52;
}
.dark-section h2 {
color: #aab0d0;
}
</style>
</head>
<body>
<h1>Simple Phone Mask Demo <span class="version-badge">v1.0.5</span></h1>
<div class="social-buttons">
<a href="https://github.com/mykulyncom/simple-phone-mask" target="_blank" class="social-button github">
<img src="https://cdn.jsdelivr.net/npm/simple-icons@v7/icons/github.svg" alt="GitHub" style="filter:invert(1)" />
GitHub
</a>
<a href="https://www.npmjs.com/package/simple-phone-mask" target="_blank" class="social-button npm">
<img src="https://cdn.jsdelivr.net/npm/simple-icons@v7/icons/npm.svg" alt="npm" style="filter:invert(1)" />
npm
</a>
<a href="https://freelancehunt.com/freelancer/jixindev.html" target="_blank" class="social-button freelancehunt">
<img src="https://freelancehunt.com/static/images/freelancehunt/sm/plus.svg" alt="FreelanceHunt" />
FreelanceHunt
</a>
</div>
<!-- ════════════════════════════════════════
EXISTING DEMOS
════════════════════════════════════════ -->
<div class="input-group">
<label for="phone1">Default mask with flags and country selection (Ukraine):</label>
<input type="tel" id="phone1" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone1', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
});</code></pre>
</div>
<div class="input-group">
<label for="phone2">US Phone mask with flags only (no country selection):</label>
<input type="tel" id="phone2" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone2', {
countryCode: 'US',
showFlag: true,
allowCountrySelect: false,
});</code></pre>
</div>
<div class="input-group">
<label for="phone3">Polish mask without flags:</label>
<input type="tel" id="phone3" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone3', {
countryCode: 'PL',
showFlag: false,
});</code></pre>
</div>
<div class="input-group">
<label for="phone4">Polish mask with flags only (no country selection) and custom mask:</label>
<input type="tel" id="phone4" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone4', {
countryCode: '+48',
maskPattern: '___ ___ ___',
showFlag: true,
allowCountrySelect: false,
});</code></pre>
</div>
<div class="input-group">
<label for="phone5">Auto-detected country by IP:</label>
<input type="tel" id="phone5" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone5', {
detectIP: true,
showFlag: true,
allowCountrySelect: true,
});</code></pre>
</div>
<!-- ════════════════════════════════════════
NEW DEMOS v1.0.5
════════════════════════════════════════ -->
<h2>New in v1.0.5 <span class="version-badge" style="background:#e0a020;">✨ New</span></h2>
<br>
<!-- 1. Search in dropdown -->
<div class="input-group">
<label for="phone6">Search in dropdown: <span class="new-badge">NEW</span></label>
<input type="tel" id="phone6" />
<pre><code class="language-javascript">// Search field inside the country dropdown (enabled by default)
new SimplePhoneMask('#phone6', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
showSearch: true,
});</code></pre>
</div>
<!-- 2. Preferred countries -->
<div class="input-group">
<label for="phone7">Preferred (pinned) countries: <span class="new-badge">NEW</span></label>
<input type="tel" id="phone7" />
<pre><code class="language-javascript">// Pin frequently used countries at the top of the list
new SimplePhoneMask('#phone7', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
preferredCountries: ['UA', 'PL', 'US', 'GB'],
});</code></pre>
</div>
<!-- 3. Validation -->
<div class="input-group">
<label for="phone8">Phone validation on blur: <span class="new-badge">NEW</span></label>
<input type="tel" id="phone8" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone8', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
validate: true,
errorMessage: 'Введіть повний номер телефону.',
successMessage: '✓ Чудово!',
onValidate: (isValid, value) => {
console.log('Valid:', isValid, '| Value:', value);
},
});</code></pre>
</div>
<!-- 4. Programmatic validation -->
<div class="input-group">
<label for="phone9">Programmatic validation (submit button): <span class="new-badge">NEW</span></label>
<input type="tel" id="phone9" />
<br><br>
<button id="validateBtn" style="padding:8px 16px;cursor:pointer;border-radius:4px;border:1px solid #ccc;">
Validate on submit
</button>
<div id="submitResult" style="margin-top:8px;font-size:13px;"></div>
<pre><code class="language-javascript">const mask9 = new SimplePhoneMask('#phone9', {
countryCode: 'US',
showFlag: true,
allowCountrySelect: true,
validate: true,
});
document.querySelector('#validateBtn').addEventListener('click', () => {
const valid = mask9.validate();
// valid === true when number is complete
});</code></pre>
</div>
<!-- 5. Dark theme -->
<div class="dark-section">
<h2>Dark theme: <span class="new-badge">NEW</span></h2>
<br>
<label for="phone10">Dark theme with search & preferred countries:</label>
<input type="tel" id="phone10" />
<pre><code class="language-javascript">new SimplePhoneMask('#phone10', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
darkTheme: true,
showSearch: true,
preferredCountries: ['UA', 'PL', 'DE'],
validate: true,
});</code></pre>
</div>
<script src="../dist/simple-phone-mask.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script>
<script>
/* ── Copy buttons ── */
document.querySelectorAll('pre code').forEach((block) => {
const button = document.createElement('button');
button.className = 'copy-button';
button.textContent = 'Copy';
button.addEventListener('click', () => {
navigator.clipboard.writeText(block.textContent).then(() => {
button.textContent = 'Copied!';
setTimeout(() => (button.textContent = 'Copy'), 2000);
});
});
block.parentNode.appendChild(button);
});
/* ── Existing demos ── */
new SimplePhoneMask('#phone1', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
});
new SimplePhoneMask('#phone2', {
countryCode: 'US',
showFlag: true,
allowCountrySelect: false,
});
new SimplePhoneMask('#phone3', {
countryCode: 'PL',
showFlag: false,
});
new SimplePhoneMask('#phone4', {
countryCode: '+48',
maskPattern: '___ ___ ___',
showFlag: true,
allowCountrySelect: false,
});
new SimplePhoneMask('#phone5', {
detectIP: true,
showFlag: true,
allowCountrySelect: true,
});
/* ── New demos v1.0.5 ── */
// Search
new SimplePhoneMask('#phone6', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
showSearch: true,
});
// Preferred countries
new SimplePhoneMask('#phone7', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
preferredCountries: ['UA', 'PL', 'US', 'GB'],
});
// Validation on blur with custom messages
new SimplePhoneMask('#phone8', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
validate: true,
errorMessage: '❌ Phone number is incomplete.',
successMessage: '✅ Phone is valid!',
onValidate: (isValid, value) => {
console.log('Valid:', isValid, '| Value:', value);
},
});
// Programmatic validation
const mask9 = new SimplePhoneMask('#phone9', {
countryCode: 'US',
showFlag: true,
allowCountrySelect: true,
validate: true,
});
document.getElementById('validateBtn').addEventListener('click', () => {
const valid = mask9.validate();
const result = document.getElementById('submitResult');
result.textContent = valid ? '✅ Phone is valid! Form submitted.' : '❌ Phone number is incomplete.';
result.style.color = valid ? '#38a169' : '#e53e3e';
});
// Dark theme
new SimplePhoneMask('#phone10', {
countryCode: 'UA',
showFlag: true,
allowCountrySelect: true,
darkTheme: true,
showSearch: true,
preferredCountries: ['UA', 'PL', 'DE'],
validate: true,
});
</script>
</body>
</html>