Les champs de saisie étant hébergés sur une autre page, affichée dans une iframe, il n'est pas possible d'utiliser l'attribut classique for pour les labels, en raison de la Same-Origin Policy. (Strict cloisonnement cross-origin entre le domaine parent et le contenu de l'iframe)
Il est toutefois possible de simuler cette propriété de la manière suivante :
1. Ajoutez un événement onclick sur les labels qui appellent une fonction focusIframe()
<p>
<label id="card-label" onclick="focusIframe(\'hosted-fields-frame-card\');">Card number</label>
<!-- Card number container -->
</p>
<p>
<label id="expiry-label" onclick="focusIframe(\'hosted-fields-frame-expiry\');">Expiry</label>
<!-- Card expiry container -->
</p>
<p>
<label id="cryptogram-label" onclick="focusIframe(\'hosted-fields-frame-cryptogram\');">Cryptogram</label>
<!-- Card cryptogram container -->
</p>
Le paramètre passé en argument dans la fonction doit désigner l'id de la frame correspondant au <label>
| Label | Iframe id |
|---|---|
card-label |
hosted-fields-frame-card |
expiry-label |
hosted-fields-frame-expiry |
cryptogram-label |
hosted-fields-frame-cryptogram |
Astuce
Cet événement onclick peut être ajouté sur les conteneurs eux-mêmes, afin d'éviter les zones mortes non cliquables autour des iframes.
2. Ajoutez cette fonction focusIframe() en JavaScript
function focusIframe(id)
{
var iframe = document.getElementById(id);
iframe.contentWindow.focus();
return true;
}
Cette fonction a pour effet de relayer le click sur le <label> vers l'iframe, qui a pour seul contenu l' <input type="text"> correspondant.
Personnalisez votre formulaire selon le type de carte
1. Créez une fonction pour appliquer une classe en fonction du type de carte
function formCustom(cardType)
{
// Customize your form as you wish, for example by adding a pictogram of the type of card used
var picto= document.getElementById("cardPictogram");
picto.className = cardType;
}
Rappel
Les valeurs disponibles pour le paramètre cardType, retourné par Dalenys, sont les suivantes :
american_expressbancontactmaestromastercardvisa
2. Appelez cette fonction sur l'événement onInput du champ de saisie du numéro de carte, dans votre intégration hostel-fields
var hfields = be2bill.hostedFields({
key: {
id: "Your API Key",
value: "Your API Key value"
},
fields: {
'card': {
id: 'card-container',
onInput: function(event) {
if(event.cardType) {
formCustom(event['cardType']);
}
}
}
3. Gérez vos classes dans votre CSS
#cardPictogram.mastercard {
background-image: url("mastercard-logo.svg");
}
...
Imitez l'effet de label flottant du Material Design
Comme vu précédemment, les champs de saisie étant hébergés sur une page externe, hors du DOM, il est proscrit d'animer leurs attributs placeholder.
Une ruse permet toutefois de le simuler, en donnant aux labels l'apparence de placeholders.
1. Pour commencer, vous devez afficher les labels flottants au-dessus des champs de saisie :
<p>
<label id="card-label" onclick="focusIframe(\'hosted-fields-frame-card\');">Card number</label>
<span class="input-container" id="card-container" onclick="focusIframe(\'hosted-fields-frame-card\');"></span>
</p>
<p>
<label id="card-label" onclick="focusIframe(\'hosted-fields-frame-expiry\');">Expiry</label>
<span class="input-container" id="expiry-container" onclick="focusIframe(\'hosted-fields-frame-expiry\');"></span>
</p>
<p>
<label id="card-label" onclick="focusIframe(\'hosted-fields-frame-cryptogram\');">Cryptogram</label>
<span class="input-container" id="cryptogram-container" onclick="focusIframe(\'hosted-fields-frame-cryptogram\');"></span>
</p>
form p {
/* The position of each paragraph will be used as a reference to
* set the absolute position of the child elements <label> */
position: relative;
height: 40px;
}
label {
/* Gives an absolute position based on the parent elements <p> */
z-index: 1;
position: absolute;
padding: 10px 7px;
left: 0;
bottom: 0;
/* Labels must be superimposed on the input fields */
display: block;
width: 100%;
height: 40px;
box-sizing: border-box;
/* Simulates a placeholder style */
fonts-style: italic;
color: #bbb;
/* Simulates an on hover input text cursor */
cursor: text;
/* Smooth transition effect */
transition: all 250ms ease-in-out;
}
2. N'oublions pas que l'utilisateur peut cliquer sur les labels et aussi utiliser la touche [TAB] pour cibler les iframes.
Ajoutez donc des listeners onclick et onkeydown pour être sûr de ne manquer aucune commande ciblant un champ hébergé :
// Detects the use of any key, especially the TAB key, to focus on a hosted field.
document.onkeydown = function(){
formDynamics();
};
// Detects the use of the mouse
document.onclick = function(){
formDynamics();
};
3. Si un listener est déclenché, délayez 100 ms avant de vérifier si la class d'un conteneur a changé, indiquant le déplacement du focus sur un champ hébergé.
Si c'est le cas, ajoutez des classes sur tous les <label> pour déclencher leurs animations :
function formDynamics() {
var cardField = document.getElementById("card-container");
var cardLabel = document.getElementById("card-label");
var expiryField = document.getElementById("expiry-container");
var expiryLabel = document.getElementById("expiry-label");
var cryptogramField = document.getElementById("cryptogram-container");
var cryptogramLabel = document.getElementById("cryptogram-label");
// Hold on 100ms before checking for the presence of a "focus" class on the hosted-fields containers
setTimeout(function() {
// If the focus is confirmed on any hosted-field...
if( cardField.className.indexOf("hosted-fields-focus-state") > -1
|| expiryField.className.indexOf("hosted-fields-focus-state") > -1
|| cryptogramField.className.indexOf("hosted-fields-focus-state") > -1
) {
// ...Then add classes on the labels to trigger their animations
cardLabel.classList.add("up");
expiryLabel.classList.add("up");
cryptogramLabel.classList.add("up");
}
}, 100);
}
4. Gérez les animations CSS :
label.up {
padding: 0;
bottom: 42px;
height: 20px;
fonts-size: 75%;
}
Animation d'un champ de saisie avec des données incorrectes
Gérez simplement la classe CSS .hosted-fields-invalid-state :
.hosted-fields-invalid-state {
border: 2px solid red;
animation-name: wriggle;
animation-duration: 75ms;
animation-iteration-count: 2;
animation-direction: normal;
animation-timing-function: linear;
}
Et créez une animation de secousse :
@keyframes wriggle {
from { transform: translateY(-3px); }
to { transform: translateY(0); }
}
Exemple pratique
Attention
La démo de formulaire de paiement suivante est hébergée sur un environnement de préproduction, aucun mouvement bancaire réel n'aura lieu.
Cependant, ne connaissant pas la politique de confidentialité des informations bancaires soumises sur Codepen, je déconseille vivement d'utiliser de vraies données de carte bancaire ; utilisez plutôt l'une de celles-ci :
- VISA: 4111 1111 1111 1111
- MasterCard: 5111 1111 1111 1118
- American Express: 3444 444444 44447
- Bancontact: 67777777777777775
N'importe quelle date d'expiration et n'importe quel cryptogramme à 3 chiffres seront acceptés.
