JSFiddle - React, Tailwind, and code Playground

by Dedi Wibisono

HTML

<h1>Credit Card Validation</h1>
<form>
  <h2>Card number</h2>
  <input id="card_number" type="text" placeholder="1234 5678 9012 3456">
  <small class="help">
    <p>This demo supports Visa, Visa Electron, Maestro, MasterCard and Discover. 
    + <a href="#card-types">many more...</a></p>
  </small>
</form>

<div class="cards">
  <h2>Some Card types</h2>
  <p>
    Visa: <a href="4000 0000 0000 0002">4000 0000 0000 0002</a><br>
    Visa Electron: <a href="4026 0000 0000 0002">4026 0000 0000 0002</a><br>
    Maestro: <a href="5018 0000 0009">5018 0000 0009</a><br>
    Master card: <a href="5100 0000 0000 0008">5100 0000 0000 0008</a><br>
    Discover: <a href="6011 0000 0000 0004">6011 0000 0000 0004</a><br>
  </p>
</div>

<div id="card-types" class="card-types">
  <ul>
    <li>American Express — <code>amex</code></li>
    <li>Diners Club Carte Blanche — <code>diners_club_carte_blanche</code></li>
    <li>Diners Club International — <code>diners_club_international</code></li>
    <li>Diners Club United States &amp; Canada — <code>mastercard</code></li>
    <li>Discover Card — <code>discover</code></li>
    <li>JCB — <code>jcb</code></li>
    <li>Laser — <code>laser</code></li>
    <li>Maestro — <code>maestro</code></li>
    <li>MasterCard — <code>mastercard</code></li>
    <li>Visa — <code>visa</code></li>
    <li>Visa Electron — <code>visa_electron</code></li>
  </ul>
</div>

CSS

body {
  background-color: #eee;
}

h1 {
  color: #222;
  font-size: 40px;
  font-weight: 400;
  text-align: center;
  font-family: sans-serif;
}

h2 {
  color: #222;
  font-size: 20px;
  font-weight: 100;
  margin-bottom: 10px;
  text-align: left;
  font-family: sans-serif;
}

form {
  border-radius: 2px;
  margin: 0 auto 0;
  padding: 13px 20px;
  width: 290px;
}
form label {
  visibility: hidden;
}
form input {
  background-color: #fff;
  border: 2px solid #777;
  border-radius: 5px;
  color: #222;
  display: block;
  font-size: 18px;
  height: 32px;
  padding: 0 5px;
  width: 275px;
  margin: 5px 0;
}
form input:-moz-placeholder {
  color: #222;
  opacity: 1;
}
form input:-ms-input-placeholder {
  color: #222;
}
form input:focus {
  border: 2px solid #0079ff;
}
form input::-webkit-input-placeholder {
  color: #222;
}
form input::-moz-placeholder {
  color: #222;
  opacity: 1;
}
form #card_number {
  background-image: url(http://jquerycreditcardvalidator.com/images/images.png), url(http://jquerycreditcardvalidator.com/images/images.png);
  background-position: 2px -121px, 260px -61px;
  background-size: 120px 361px, 120px 361px;
  background-repeat: no-repeat;
  padding-left: 54px;
  width: 225px;
}
form #card_number.visa {
  background-position: 2px -163px, 260px -61px;
}
form #card_number.visa_electron {
  background-position: 2px -205px, 260px -61px;
}
form #card_number.mastercard {
  background-position: 2px -247px, 260px -61px;
}
form #card_number.maestro {
  background-position: 2px -289px, 260px -61px;
}
form #card_number.discover {
  background-position: 2px -331px, 260px -61px;
}
form #card_number.valid.visa {
  background-position: 2px -163px, 260px -87px;
}
form #card_number.valid.visa_electron {
  background-position: 2px -205px, 260px -87px;
}
form #card_number.valid.mastercard {
  background-position: 2px -247px, 260px -87px;
}
form #card_number.valid.maestro {
  background-position: 2px -289px, 260px -87px;
}
form #card_number.valid.discover {
 ...

JavaScript

// Credit to: http://jquerycreditcardvalidator.com

// Generated by CoffeeScript 1.8.0
(function() {
  /* http://prismjs.com/download.html?themes=prism&languages=clike+javascript */
var self = (typeof window !== 'undefined') ? window : {};

/**
 * Prism: Lightweight, robust, elegant syntax highlighting
 * MIT license https://www.opensource.org/licenses/mit-license.php/
 * @author Lea Verou http://lea.verou.me
 */

var Prism = (function(){

// Private helper vars
var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;

var _ = self.Prism = {
	util: {
		encode: function (tokens) {
			if (tokens instanceof Token) {
				return new Token(tokens.type, _.util.encode(tokens.content));
			} else if (_.util.type(tokens) === 'Array') {
				return tokens.map(_.util.encode);
			} else {
				return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
			}
		},

		type: function (o) {
			return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
		},

		// Deep clone a language definition (e.g. to extend it)
		clone: function (o) {
			var type = _.util.type(o);

			switch (type) {
				case 'Object':
					var clone = {};

					for (var key in o) {
						if (o.hasOwnProperty(key)) {
							clone[key] = _.util.clone(o[key]);
						}
					}

					return clone;

				case 'Array':
					return o.slice();
			}

			return o;
		}
	},

	languages: {
		extend: function (id, redef) {
			var lang = _.util.clone(_.languages[id]);

			for (var key in redef) {
				lang[key] = redef[key];
			}

			return lang;
		},

		// Insert a token before another token in a language literal
		insertBefore: function (inside, before, insert, root) {
			root = root || _.languages;
			var grammar = root[inside];
			var ret = {};

			for (var token in grammar) {

				if (grammar.hasOwnProperty(token)) {

					if (token == before) {

						for (var newToken in insert) {

							if (insert.hasOwnProperty(newToken)) {
								ret[newToken] =...