Contact

For any request, please use this form:

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()

html
Copy
<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

js
Copy
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

js
Copy
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_express
  • bancontact
  • maestro
  • mastercard
  • visa

2. Appelez cette fonction sur l'événement onInput du champ de saisie du numéro de carte, dans votre intégration hostel-fields

js
Copy
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

css
Copy
#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 :

html
Copy
<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>
css
Copy
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é :

css
Copy
// 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 :

js
Copy
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 :

css
Copy
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 :

css
Copy
.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 :

css
Copy
@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.


Commentaires

Participer ?

S'il vous plaît, prenons soin de nos écrits et soyons respectueux et constructifs.