HTML

SharePoint get by Rest List Role DefinitionBindings

On 28/10/2024


let currentSort = { column: null, direction: 'asc' }; // Store the current sort state

// Creates the style element
function createStyleElement(id, content) {
    var style = document.createElement("style");
    style.type = "text/css";
    style.id = id;
    style.innerHTML = content;

    if (style.styleSheet) {
        style.styleSheet.cssText = content;
    } else {
        let st = document.getElementById(id);
        if (st == undefined) {
            var head = document.head || document.getElementsByTagName("head")[i];
            head.appendChild(style);
        } else {
            st.innerHTML = content;
        }
    }
    return style;
}


// Function to filter the table based on dropdown selection
function filterTable(columnIndex, value) {
    let table, tr, td, i, select, selectedValue, txtValue;
    table = document.querySelector("table");
    tr = table.getElementsByTagName("tbody")[0].getElementsByTagName("tr");
    select = table.getElementsByTagName("select")[columnIndex];
    //debugger;
    selectedValue = value;

    // Loop through all table rows and hide those that don't match the filter
    for (i = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[columnIndex];
        if (td) {
            txtValue = td.textContent || td.innerText;
            if (selectedValue === "" || txtValue === selectedValue) {
                tr[i].style.display = "";
            } else {
                tr[i].style.display = "none";
            }
        }
    }
}
function sortTable(columnIndex, direction) {
    let table, rows, switching, i, x, y, shouldSwitch;
    table = document.querySelector("table");
    switching = true;
    let tbody = table.querySelector("tbody");

    // Set the current sort state
    currentSort.column = columnIndex;
    currentSort.direction = direction;

    while (switching) {
        switching = false;
        rows = tbody.rows;

        for (i = 0; i < rows.length - 1; i++) {
            shouldSwitch = false;
            x = rows[i].getElementsByTagName("td")[columnIndex];
            y = rows[i + 1].getElementsByTagName("td")[columnIndex];
            let isNumber = false;


            if (!isNaN(x.innerHTML)) {

                // Check if rows should switch based on ascending or descending order
                if (direction === 'asc') {
                    if (parseFloat(x.innerHTML) > parseFloat(y.innerHTML)) {
                        shouldSwitch = true;
                        break;
                    }
                } else if (direction === 'desc') {
                    if (parseFloat(x.innerHTML) < parseFloat(y.innerHTML)) {
                        shouldSwitch = true;
                        break;
                    }
                }
            }
            else {
                // Check if rows should switch based on ascending or descending order
                if (direction === 'asc') {
                    if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
                        shouldSwitch = true;
                        break;
                    }
                } else if (direction === 'desc') {
                    if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
                        shouldSwitch = true;
                        break;
                    }
                }
            }
        }
        if (shouldSwitch) {
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
            switching = true;
        }
    }
}
// Function to generate the table
function generateTableFromJson2(jsonArray, select, addHeaders = true) {
    const style = `
    table {
            width: 100%;
            border-collapse: collapse;
        }

        th, td {
            padding: 8px 12px;
            text-align: left;
            border: 1px solid #ddd;
        }

        tbody tr{
           max-height: 15px;
        }

        th {
            background-color: #f4f4f4;
            color: #000;
        }

        /* Scrollable table wrapper */
        .table-wrapper {
            max-height: 800px;
            overflow-y: auto;
            border: 1px solid #ddd;
        }
        /* Style for dropdowns in header */
        select {
            width: 100%;
            padding: 4px;
            margin-top: 5px;
        }

        /* Style for the sorting arrows */
        .sort-arrows {
            cursor: pointer;
            margin-left: 5px;
        }    
        `;
    createStyleElement("fdiStyle", style);





    // Create table element
    let table = document.createElement('table');

    // Create table header
    let header = table.createTHead();
    let headerRow = header.insertRow(0);

    // Get keys (headers) from the first object in the JSON array
    //let keys = Object.keys(jsonArray[0]);
    let keys = select.split(",");
    if (addHeaders) {
        keys.forEach((key, index) => {
            if (key !== "__metadata") {

                let th = document.createElement('th');
                th.innerHTML = key;

                // Create a dropdown (select) for filtering
                let select = document.createElement('select');

                select.addEventListener('change', function () {
                    const selectedValue = select.value;
                    filterTable(index, selectedValue);
                });

                // Populate dropdown with unique values from the JSON data
                let uniqueValues = [...new Set(jsonArray.map(item => item[key]))];

                // Add a default "All" option for no filter
                let optionAll = document.createElement('option');
                optionAll.value = "";
                optionAll.text = `All`;
                select.appendChild(optionAll);

                // Create an option for each unique value
                if (typeof (uniqueValues[0]) === typeof (1)) {
                    const pp = uniqueValues.sort((a, b) => {
                        if (a < b) {
                            return -1;
                        }
                        if (a > b) {
                            return 1;
                        }
                        return 0;
                    });
                    pp.forEach(value => {
                        let option = document.createElement('option');
                        option.value = value;
                        option.text = value;
                        select.appendChild(option);
                    });
                } else
                    uniqueValues.sort().forEach(value => {
                        let option = document.createElement('option');
                        option.value = value;
                        option.text = value;
                        select.appendChild(option);
                    });
                // Sort arrows for sorting the columns
                let upArrow = document.createElement('span');
                upArrow.innerHTML = '⬆️';
                upArrow.classList.add('sort-arrows');
                upArrow.onclick = () => sortTable(index, 'asc');

                let downArrow = document.createElement('span');
                downArrow.innerHTML = '⬇️';
                downArrow.classList.add('sort-arrows');
                downArrow.onclick = () => sortTable(index, 'desc');

                th.appendChild(select);  // Append the dropdown to the header
                th.appendChild(upArrow);  // Append the dropdown to the header
                th.appendChild(downArrow);  // Append the dropdown to the header
                headerRow.appendChild(th);
            }
        });
    }

    // Create table body and populate rows with data
    let tbody = document.createElement('tbody');
    jsonArray.forEach((item) => {
        let row = tbody.insertRow();
        keys = select.split(",");
        keys.forEach((key) => {
            let cell = row.insertCell();
            if (key !== "__metadata") {
                cell.setAttribute("nowrap", "nowrap");
                if (key === "RoleDefinitionBindings") {
                    cell.appendChild(generateTableFromJson2(item.RoleDefinitionBindings.results, "Name,Id", false));
                } else if (key.indexOf("/") > 0) {
                    cell.innerHTML = item[key.split("/")[0]][key.split("/")[1]]
                } else
                    cell.innerHTML = item[key];  // Insert each value from the JSON into the table cell
            }
        });
    });

    // Append the body to the table
    table.appendChild(tbody);


    return table;
}

function removeSlasches(select, datas) {
    const ret = [];
    const fields = select.split(',');
    for (let i = 0; i < datas.length; i++) {
        const toAdd = {};

        for (let j = 0; j < fields.length; j++) {
            if (fields[j].indexOf('/') > 0) {
                const splitted = fields[j].split('/');
                toAdd[splitted.join('')] = datas[i][splitted[0]][splitted[1]];
            } else
                toAdd[fields[j]] = datas[i][fields[j]];
        }
        ret.push(toAdd);
    }
    console.log("removeSlasches", ret);
    return ret;
}

// Function to get permissions for a SharePoint group
async function getSharePointPermissions(siteUrl, select) {

    // REST API endpoint to get group permissions
    const endpoint = `${siteUrl}`;

    // Fetch options with headers for authentication and response format
    const fetchOptions = {
        method: 'GET',
        headers: {
            'Accept': 'application/json;odata=verbose'
        }
    };

    console.log("endpoint", endpoint);
    // Send the asynchronous GET request to the REST API endpoint
    const response = await fetch(endpoint, fetchOptions);

    // Check if the response is OK (status code 200)
    if (!response.ok) {
        throw new Error(`Error fetching permissions: ${response.statusText}`);
    }

    // Parse the JSON response to extract permission data
    const data = await response.json();

    // Extract role assignments (permissions)
    const roleAssignments = data.d.results;
    console.log('roleAssignments', roleAssignments);
    console.log(JSON.stringify(roleAssignments));

    const D1 = removeSlasches(select, roleAssignments)
    const pattern2 = /\//g;
    console.log("json111", JSON.stringify(D1));
    const table = generateTableFromJson2(D1, select.replace(pattern2, ""));
    // Append the table to the container
    document.getElementById('tableContainer').appendChild(table);
}

// Usage example: Replace 'your-group-id' and 'your-site-url' with actual values
const select = "Member/Title,Member/Id,Member/LoginName,RoleDefinitionBindings";
let siteUrl = 'https://mySite.sharepoint.com/sites/Dev_wf';
siteUrl += `/_api/web/roleassignments/?$expand=RoleDefinitionBindings,Member&$select=${select}`; // Replace with the actual site URL
document.body.innerHTML = `<div id="tableContainer" class="table-wrapper"></div>`; await getSharePointPermissions(siteUrl, select); 

 

Permissions

In HTML

CSS FlexBox tutorial

On 06/09/2024

Le modèle Flexbox est une technique puissante et flexible pour créer des mises en page en CSS. Il permet de contrôler facilement l'alignement, la direction et la répartition des éléments dans un conteneur, qu'il s'agisse d'un site web simple ou d'une interface utilisateur plus complexe.

1. Concepts de base de Flexbox
Flexbox se compose de deux types d'éléments principaux :

  • Conteneur flex : L'élément parent qui applique le comportement Flexbox.
  • Éléments flex (ou enfants flex) : Les éléments directs du conteneur flex, qui sont disposés selon les règles Flexbox.

Propriétés du conteneur Flexbox

  • display: flex; : Active Flexbox pour le conteneur.
  • flex-direction : Définit l'axe principal et la direction dans laquelle les éléments sont placés (ligne, colonne).
  • justify-content : Aligne les éléments le long de l'axe principal.
  • align-items : Aligne les éléments le long de l'axe croisé.
  • flex-wrap : Définit si les éléments doivent rester sur une seule ligne ou se renvoyer sur plusieurs lignes.

Propriétés des éléments flex

  • flex-grow : Indique si un élément doit croître pour occuper plus d’espace.
  • flex-shrink : Indique si un élément doit rétrécir pour libérer de l’espace.
  • flex-basis : Indique la taille initiale de l'élément avant que l'espace supplémentaire ne soit distribué.
  • order : Contrôle l’ordre de disposition des éléments.
  • align-self : Permet de surcharger align-items pour un élément spécifique.

 

Flexbox - Alignement de base

<style>


.flex-container {
	display: flex;
	justify-content: space-between;
	align-items: center;
	background-color: #f2f2f2;
	height: 150px;
}

.flex-item {
	background-color: #ff6b6b;
	padding: 20px;
	color: white;
	font-weight: bold;
}
</style>

<div class="flex-container">
     <div class="flex-item">Item 1</div>
     <div class="flex-item">Item 2</div>
     <div class="flex-item">Item 3</div>
 </div>
Result :
Item 1
Item 2
Item 3

Explication :

Le conteneur .flex-container utilise display: flex, activant le modèle Flexbox. justify-content: space-between répartit les éléments avec un espace égal entre eux. align-items: center centre verticalement les éléments à l'intérieur du conteneur.

Rendu : Les trois éléments sont alignés horizontalement, avec des espaces égaux entre eux, et centrés verticalement dans le conteneur.

 

Exemple 2 : Direction en colonne : Flexbox - Colonne

<style>
.flex-container {
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    align-items: center;
    background-color: #d3d3d3;
    height: 300px;
}

.flex-item {
    background-color: #3498db;
    padding: 15px;
    color: white;
    width: 60%;
    text-align: center;
}
</style>

<div class="flex-container">
    <div class="flex-item">Item 1</div>
    <div class="flex-item">Item 2</div>
    <div class="flex-item">Item 3</div>
</div>

Rendu : 

 

Item 1
Item 2
Item 3

 

Explication :

flex-direction: column dispose les éléments verticalement dans une colonne.
justify-content: space-around crée des espaces égaux autour des éléments (au-dessus et en dessous).
align-items: center centre les éléments horizontalement dans la colonne.


Rendu : Les éléments sont empilés verticalement au centre du conteneur avec des espaces égaux autour d'eux.

 

Exemple 3 : Flex-grow et flex-shrink

<style>
.flex-container3 {
    display: flex;
    background-color: #e9ecef;
    height: 100px;
}

.flex-item3 {
    background-color: #007bff;
    padding: 10px;
    color: white;
    text-align: center;
    flex-grow: 1; /* Tous les éléments prennent de l'espace disponible */
}

.flex-item3:first-child {
    flex-grow: 2; /* Le premier élément prend deux fois plus de place */
}
</style>

<div class="flex-container">
    <div class="flex-item">Item 1 (flex-grow: 2)</div>
    <div class="flex-item">Item 2</div>
    <div class="flex-item">Item 3</div>
</div>

 

 

Item 1 (flex-grow: 2)
Item 2
Item 3

 

Explication :

flex-grow détermine combien un élément doit prendre de l'espace disponible. L'élément Item 1 prend deux fois plus d'espace que les autres.
Rendu : Le premier élément occupe une plus grande largeur que les deux autres, qui occupent l'espace restant de manière égale.

 

3. Mode responsive avec Flexbox

Flexbox est naturellement responsive. En ajustant les propriétés comme flex-wrap et media queries, vous pouvez créer des mises en page flexibles adaptées à différents écrans.

Exemple 4 : Flexbox responsive avec flex-wrap


<style>
    .flex-container {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
    }

    .flex-item {
        background-color: #28a745;
        padding: 20px;
        margin: 10px;
        color: white;
        width: 30%; /* Chaque élément occupe 30% de la largeur */
        box-sizing: border-box;
        text-align: center;
    }

    /* Media query pour les petits écrans */
    @media (max-width: 768px) {
        .flex-item {
            width: 45%; /* Sur les petits écrans, chaque élément prend 45% de la largeur */
        }
    }

    /* Media query pour les très petits écrans */
    @media (max-width: 480px) {
        .flex-item {
            width: 100%; /* Sur les très petits écrans, chaque élément prend 100% de la largeur */
        }
    }
</style>
<div class="flex-container">
    <div class="flex-item">Item 1</div>
    <div class="flex-item">Item 2</div>
    <div class="flex-item">Item 3</div>
    <div class="flex-item">Item 4</div>
    <div class="flex-item">Item 5</div>
    <div class="flex-item">Item 6</div>
</div>
 

 

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6

 

 

 

Explication :

flex-wrap: wrap permet aux éléments de passer à la ligne lorsqu'il n'y a plus assez de place sur une seule ligne.

  • Les media queries ajustent la largeur des éléments sur les petits écrans.
  • Sur les grands écrans, chaque élément prend 30% de la largeur. Sur les écrans plus petits, ils prennent 45%, puis 100% sur les très petits écrans.

Rendu : Les éléments s'adaptent à la taille de l'écran et se réorganisent automatiquement sur plusieurs lignes en fonction de la largeur disponible.

 

4. Bonnes pratiques Flexbox

  • Utiliser flex-wrap pour la flexibilité : Permettez aux éléments de passer à la ligne lorsque nécessaire. Cela empêche que les éléments ne soient trop petits ou trop compressés.
  • Limiter l'utilisation de flex-basis fixe : Utilisez des unités relatives (%, fr) plutôt que des valeurs fixes (px) pour garantir un comportement fluide et responsive.
  • Éviter l’utilisation excessive de order : L’ordre naturel des éléments devrait être suffisant dans la plupart des cas.

 

 

In HTML

css grid-template-columns

On 05/09/2024

Dans un contexte CSS responsive, grid-template-columns est une propriété CSS puissante utilisée avec CSS Grid Layout pour définir la disposition des colonnes dans une grille.

Elle permet de spécifier le nombre, la taille et le comportement des colonnes dans un conteneur de grille. Voici une explication détaillée de son fonctionnement avec des exemples variés.

1. Comprendre `grid-template-columns

La propriété grid-template-columns permet de définir la largeur des colonnes dans une grille. Vous pouvez utiliser des unités de mesure variées telles que `px`, `%`, `fr` (fraction), `auto`, et des mots-clés comme `min-content` et `max-content`.

2. Syntaxe de Base


grid-template-columns: [valeur] [valeur] ...;

- Chaque valeur dans la liste représente la taille d'une colonne dans la grille. - Les valeurs peuvent être de tailles absolues (`px`, `em`), relatives (`%`), des fractions (`fr`), ou automatiques (`auto`).

3. Exemples d'Utilisation Exemple

1: Définir des Colonnes de Tailles Fixes

.container {
  display: grid;
  grid-template-columns: 100px 200px 150px;
}

Dans cet exemple, le conteneur de grille aura trois colonnes de largeurs fixes : 100 pixels, 200 pixels, et 150 pixels respectivement.

Exemple 2: Utiliser des Fractions (`fr`)


.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
}

- Ici, la grille est divisée en quatre parties égales (`1fr + 2fr + 1fr = 4fr`).

- La première colonne occupe `1/4` de l'espace disponible, la deuxième colonne `2/4` (ou `1/2`), et la troisième colonne `1/4`.

Exemple 3: Combiner Tailles Fixes et Fractions


.container {
  display: grid;
  grid-template-columns: 150px 2fr 1fr;
}

- La première colonne a une largeur fixe de 150 pixels.

- Les colonnes suivantes utilisent la taille fractionnelle, où la deuxième colonne est deux fois plus large que la troisième.

Exemple 4: Colonnes Automatiques avec `auto


.container {
  display: grid;
  grid-template-columns: auto auto auto;
}

- Chaque colonne prendra seulement l'espace nécessaire pour s'adapter à son contenu

Exemple 5: Utiliser des `minmax()` pour une Grille Responsive


.container {
  display: grid;
  grid-template-columns: repeat(3, minmax(100px, 1fr));
}

- Utilise la fonction minmax() pour définir la taille minimale et maximale des colonnes.

- Chaque colonne aura une taille minimale de `100px` et peut s'étendre jusqu'à `1fr` (une fraction de l'espace disponible).

Exemple 6: Grille Répétée avec `repeat()


.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

- Utilise la fonction repeat() pour créer une grille avec 4 colonnes, chacune occupant une fraction égale (`1fr`) de l'espace disponible.

Exemple 7: Grille Auto-Adaptative avec `auto-fit` et `minmax()


.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

- auto-fit remplit automatiquement la grille avec autant de colonnes qu'il peut en fonction de l'espace disponible. - Les colonnes auront une taille minimale de `150px` et s'étendront jusqu'à remplir l'espace disponible (`1fr`).

Exemple 8: Mélange de Unités pour une Grille Complexe


.container {
  display: grid;
  grid-template-columns: 200px 1fr 3fr min-content;
}

- La première colonne a une largeur fixe de `200px`.

- La deuxième colonne utilise `1fr` pour occuper une fraction de l'espace disponible.

- La troisième colonne occupe `3fr`, soit trois fois plus d'espace que la deuxième colonne.

- La dernière colonne prend seulement l'espace nécessaire pour son contenu avec `min-content`.

. Utilisation de `grid-template-columns` pour des Designs Responsives Pour créer des mises en page responsives, vous pouvez combiner CSS Grid avec des Media Queries :


.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

@media (max-width: 768px) {
  .container {
    grid-template-columns: 1fr;
  }
}

- Sur les écrans plus larges, la grille ajuste le nombre de colonnes en fonction de l'espace disponible, chaque colonne ayant au moins `200px`. - Sur les écrans plus petits (moins de `768px` de large), la grille passe à une seule colonne (`1fr`), ce qui est idéal pour les appareils mobiles.

5. Conclusion

La propriété grid-template-columns est extrêmement versatile et puissante pour créer des mises en page flexibles et responsives avec CSS Grid. Elle vous permet de contrôler précisément le nombre et la taille des colonnes dans une grille, en s'adaptant aux différents besoins de design et aux tailles d'écran. En combinant cette propriété avec d'autres fonctionnalités CSS comme `minmax()`, `auto-fit`, et `repeat()`, ainsi qu'avec des Media Queries, vous pouvez créer des interfaces utilisateur modernes qui s'adaptent de manière fluide à différents appareils et résolutions.

In HTML

SFPX React From Css

On 05/09/2024

Introduction
Le développement de composants pour SharePoint Framework (SPFx) en utilisant React nécessite une attention particulière aux pratiques CSS pour garantir que vos interfaces sont responsives et adaptées à tous les types d'écrans, que ce soit sur mobile, tablette ou desktop. 

1. Principes de Base pour des CSS Responsives

1. Unité Relative :
   - Utilisez des unités relatives comme `%`, `em`, `rem`, `vh`, et `vw` pour les marges, les paddings, et les dimensions. Cela permet aux éléments de s’adapter dynamiquement à la taille de l'écran.

2. Media Queries :
   - Utilisez des media queries pour ajuster les styles en fonction de la taille de l'écran. Par exemple, pour les écrans de moins de 768px de largeur (taille de tablette), vous pouvez ajuster les layouts.
   css
   @media (max-width: 768px) {
       .container {
           flex-direction: column;
       }
   }
   

3. Flexbox :
   - Utilisez Flexbox pour créer des layouts flexibles qui peuvent s'adapter facilement aux différentes tailles d'écran. Flexbox est particulièrement utile pour les barres de navigation, les formulaires, et les mises en page de cartes.
   css


   .form-container {
       display: flex;
       flex-wrap: wrap;
   }

   .form-group {
       flex: 1 1 300px; /* Les groupes de formulaire s'ajustent avec un minimum de 300px */
       margin: 10px;
   }
   

4. Grid Layout :
   - Pour des mises en page plus complexes, comme des tableaux de données ou des calendriers, utilisez CSS Grid. Cela permet de contrôler avec précision la disposition des éléments sur la page.

2. Exemple de Formulaire Responsive

Voici un exemple de formulaire avec différents types d'entrées HTML, construit en React et avec une mise en page responsive.

HTML/JSX pour le Formulaire

jsx
import * as React from 'react';
import './Form.css';

const ResponsiveForm = () => {
    return (
        <form className="form-container">
            <div className="form-group">
                <label htmlFor="name">Nom:</label>
                <input type="text" id="name" name="name" placeholder="Votre nom" />
            </div>
            <div className="form-group">
                <label htmlFor="email">Email:</label>
                <input type="email" id="email" name="email" placeholder="Votre email" />
            </div>
            <div className="form-group">
                <label htmlFor="date">Date:</label>
                <input type="date" id="date" name="date" />
            </div>
            <div className="form-group">
                <label htmlFor="color">Couleur:</label>
                <input type="color" id="color" name="color" />
            </div>
            <div className="form-group">
                <label>Sexe:</label>
                <input type="radio" id="male" name="gender" value="male" />
                <label htmlFor="male">Homme</label>
                <input type="radio" id="female" name="gender" value="female" />
                <label htmlFor="female">Femme</label>
            </div>
            <div className="form-group">
                <label>Langues:</label>
                <input type="checkbox" id="english" name="language" value="english" />
                <label htmlFor="english">Anglais</label>
                <input type="checkbox" id="french" name="language" value="french" />
                <label htmlFor="french">Français</label>
            </div>
            <div className="form-group">
                <label htmlFor="people-picker">Personne:</label>
                <input type="text" id="people-picker" name="people-picker" placeholder="Sélectionner une personne" />
            </div>
            <div className="form-group">
                <button type="submit">Envoyer</button>
            </div>
        </form>
    );
};

export default ResponsiveForm;

CSS pour le Formulaire

css
.form-container {
    display: flex;
    flex-wrap: wrap;
    margin: 20px;
}

.form-group {
    flex: 1 1 300px;
    margin: 10px;
}

.form-group label {
    display: block;
    margin-bottom: 5px;
}

.form-group input[type="text"],
.form-group input[type="email"],
.form-group input[type="date"],
.form-group input[type="color"],
.form-group input[type="radio"],
.form-group input[type="checkbox"] {
    width: 100%;
    padding: 8px;
    margin-bottom: 10px;
    box-sizing: border-box;
}

button[type="submit"] {
    background-color: #0078d4;
    color: white;
    padding: 10px 20px;
    border: none;
    cursor: pointer;
}

button[type="submit"]:hover {
    background-color: #005a9e;
}

@media (max-width: 768px) {
    .form-container {
        flex-direction: column;
    }
}

Rendu Visuel

L'utilisation de Flexbox ici permet aux groupes de formulaire de se réarranger dynamiquement en fonction de la largeur de l'écran. Sur des écrans larges, les groupes se placent côte à côte, tandis que sur les petits écrans (comme les mobiles), ils s'empilent verticalement.

3. Exemple de Grille Responsive avec les Jours de la Semaine

Voici un exemple de grille responsive affichant les jours de la semaine.

HTML/JSX pour la Grille

jsx
import * as React from 'react';
import './WeekGrid.css';

const WeekGrid = () => {
    return (
        <div className="week-grid">
            <div className="day">Lundi</div>
            <div className="day">Mardi</div>
            <div className="day">Mercredi</div>
            <div className="day">Jeudi</div>
            <div className="day">Vendredi</div>
            <div className="day">Samedi</div>
            <div className="day">Dimanche</div>
        </div>
    );
};

export default WeekGrid;

CSS pour la Grille

css
.week-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 10px;
    margin: 20px;
}

.day {
    background-color: #f4f4f4;
    padding: 20px;
    text-align: center;
    font-weight: bold;
    border: 1px solid #ddd;
}

@media (max-width: 768px) {
    .week-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 480px) {
    .week-grid {
        grid-template-columns: 1fr;
    }
}

Rendu Visuel

- Grille par Défaut : Les jours de la semaine sont affichés côte à côte sur des écrans larges, en 7 colonnes.
- Tablette : La grille passe à 2 colonnes, ce qui permet de voir deux jours par ligne.
- Mobile : La grille devient une seule colonne, chaque jour étant affiché dans une ligne distincte.

Conclusion

Les bonnes pratiques pour des CSS responsives dans le développement SPFx avec React incluent l'utilisation de Flexbox et CSS Grid pour créer des mises en page adaptatives, l'utilisation judicieuse des media queries, et la préférence pour des unités relatives pour la taille des éléments. Ces techniques permettent de créer des interfaces utilisateurs qui sont à la fois élégantes et fonctionnelles sur tous types de dispositifs.

In HTML

Css Best Practices For SPFX React

On 04/09/2024

Créer des CSS responsives pour une solution SPFX (SharePoint Framework) avec React nécessite une approche structurée et l'utilisation de bonnes pratiques. Voici quelques recommandations pour vous aider à y parvenir :

1. Utiliser des Media Queries

Les media queries sont essentielles pour créer des designs responsives. Elles permettent d'appliquer des styles différents en fonction de la taille de l'écran.

@media (max-width: 600px) { .container { flex-direction: column; } }

2. Frameworks CSS Responsive

Utiliser des frameworks CSS comme Bootstrap, Tailwind CSS ou Material-UI peut simplifier la création de designs responsives. Ces frameworks offrent des classes utilitaires et des composants pré-stylisés qui sont déjà responsives.

3. Flexbox et Grid Layout

Utilisez Flexbox et CSS Grid pour créer des mises en page flexibles et responsives.

.container { display: flex; flex-wrap: wrap; } .item { flex: 1 1 100%; } @media (min-width: 600px) { .item { flex: 1 1 50%; } }

4. Variables CSS

Utilisez des variables CSS pour gérer les valeurs récurrentes comme les couleurs, les marges et les tailles de police.

:root { --primary-color: #3498db; --font-size: 16px; } .button { background-color: var(--primary-color); font-size: var(--font-size); }

5. Unités Relatives

Utilisez des unités relatives comme em, rem, % et vw/vh pour créer des designs qui s'adaptent aux différentes tailles d'écran.

.container { width: 90%; max-width: 1200px; margin: 0 auto; }

6. Mobile-First Approach

Adoptez une approche mobile-first en écrivant d'abord les styles pour les petits écrans, puis en utilisant des media queries pour ajuster les styles pour les écrans plus grands.

.container { display: flex; flex-direction: column; } @media (min-width: 600px) { .container { flex-direction: row; } }

7. Utiliser des Composants React Responsive

Il existe des bibliothèques comme react-responsive qui permettent de créer des composants React responsives.

import { useMediaQuery } from 'react-responsive'; const MyComponent = () => { const isMobile = useMediaQuery({ query: '(max-width: 600px)' }); return ( <div className={isMobile ? 'mobile-container' : 'desktop-container'}> {/* Your content here */} </div> ); };

8. Optimiser les Images

Utilisez des images responsives avec les attributs srcset et sizes pour servir des images de différentes tailles en fonction de la résolution de l'écran.

<img src="image.jpg" srcset="image-320w.jpg 320w, image-640w.jpg 640w" sizes="(max-width: 600px) 100vw, 50vw" alt="Responsive Image">

9. Utiliser des Outils de Développement

Utilisez des outils comme les DevTools de Chrome pour tester et déboguer vos designs responsives.

10. Documentation et Tests

Documentez vos styles et testez-les sur différents appareils et navigateurs pour vous assurer qu'ils fonctionnent correctement.

En suivant ces bonnes pratiques, vous pouvez créer des CSS responsives efficaces pour votre solution SPFX avec React, garantissant ainsi une expérience utilisateur optimale sur tous les appareils.

In HTML

Inject Html In Page With Json Datas

On 31/10/2023

Display json datas in your existing html page to debug

 


class fdiRender {
    constructor(element_id) {
        if (element_id == undefined)
            this.TARGETELEMENTID = "fdiPopup";
        else
            this.TARGETELEMENTID = element_id;
        this.element = document.getElementById(this.TARGETELEMENTID);
        //debugger;
        if (this.element == null) {
            let body = document.getElementsByTagName("body")[0];
            body.insertAdjacentHTML("afterbegin", "<div id='" + this.TARGETELEMENTID + "'>coucou</div>");
            this.element = document.getElementById(this.TARGETELEMENTID);
        }

        /*beforebegin (before an element)
        afterbegin (first child)
        beforeend (last child)
        afterend (after an element)*/

        this.buildCss();
        this.render();
    }

    buildCss() {

        this.css = {};
        this.css.container = "width: 100%;margin-right: auto;margin-left: auto;";
        this.css.row = "display: flex;flex-wrap: wrap;margin-top: calc(0);margin-right: 0.75rem;margin-left: 0.75rem;";
        this.css.col = "flex: 0 0 auto;width: 50%;";
        this.css.colArray = "flex: 0 0 auto;";
        this.css.border = "border: 1px solid black;padding: 0.15rem;";
    }

    render(obj) {

        if (obj != undefined && obj != null) {

            let keys = Object.keys(obj)

            let html = [];
            html.push("<div style='" + this.css.container + "' id='" + this.TARGETELEMENTID + "'>");
            for (let i = 0; i < keys.length; i++) {
                //rows
                html.push("<div style='" + this.css.row + "'>");

                //columns
                if (typeof (obj[keys[i]]) != typeof ([])) {
                    html.push("<div style='" + this.css.col + "'>");
                    html.push("<div style='" + this.css.border + "'>" + keys[i] + "</div>");
                    html.push("</div>");
                    html.push("<div style='" + this.css.col + "'>");
                    html.push("<div style='" + this.css.border + "'>" + obj[keys[i]] + "</div>");
                    html.push("</div>");
                } else {
                    html.push("<div style='" + this.css.col + "'>");
                    html.push("<div style='" + this.css.border + "'>" + keys[i] + "</div>");
                    html.push("</div>");
                    const css = this.css.colArray + "width: " + 100 / keys.length + "%;"
                    html.push("<div style='" + this.css.col + "'>");
                    html.push(this.renderArray(obj[keys[i]], true));
                    html.push("</div>");
                }

                html.push("</div>");//end row
            }
            html.push("</div>");
            this.element.innerHTML = html.join("");
            return;
        }

        this.element.innerHTML = "<div style='" + this.css.container + "' id='" + this.TARGETELEMENTID + "'>yes</div>";
    }

    renderArray(obj, isChild, exportCSV) {

        if (obj != undefined && obj != null && obj.length != undefined && obj.length > 0) {

            let keys = Object.keys(obj[0]);
            let exportCSVSTR = "";

            let html = [];
            if (isChild == undefined)
                html.push("<div class='demo' style='" + this.css.container + "' id='" + this.TARGETELEMENTID + "'>");
            const css = this.css.colArray + "width: " + 100 / keys.length + "%;"
            html.push("<div class='demo2' style='" + this.css.row + "'>");
            for (let i = 0; i < keys.length; i++) {//columns
                html.push("<div style='" + css + "'>");
                html.push("<div style='" + this.css.border + "'>" + keys[i] + "</div>");
                html.push("</div>");
                if (exportCSV != undefined)
                    exportCSVSTR += keys[i] + exportCSV;
            }
            exportCSVSTR += "\r\n";
            html.push("</div>");//end row


            for (let j = 0; j < obj.length; j++) {//elements in array
                html.push("<div style='" + this.css.row + "'>");
                for (let i = 0; i < keys.length; i++) {//columns
                    if (typeof (obj[j][keys[i]]) != typeof ([])) {
                        html.push("<div style='" + css + "'>");
                        html.push("<div style='" + this.css.border + "'>" + obj[j][keys[i]] + "</div>");
                        html.push("</div>");
                        if (exportCSV != undefined)
                            exportCSVSTR += obj[j][keys[i]] + exportCSV;
                    } else {
                        html.push("<div style='" + css + "'>");
                        html.push(this.renderArray(obj[j][keys[i]], true));
                        html.push("</div>");
                        if (exportCSV != undefined)
                            exportCSVSTR += "array" + exportCSV;
                    }
                }
                exportCSVSTR += "\r\n";

                html.push("</div>");//end row
            }

            //end div
            if (isChild == undefined)
                html.push("</div>");
            if (isChild == undefined)
                this.element.innerHTML = html.join("");
            console.log(exportCSVSTR);
            return html.join("");
        }
        this.element.innerHTML = "<div style='" + this.css.container + "' id='" + this.TARGETELEMENTID + "'>yes</div>";
    }
}

function test() {
    let fdi = new fdiRender();
    let obj1 = {
        "name": "toto",
        "age": 23,
        "town": "fontenay sous bois",
        "pays": "france"
    }
    let arr2 = [];
    arr2.push(obj1);
    arr2.push(obj1);
    arr2.push(obj1);

    let obj = {
        "name": "tata popo",
        "age": 28,
        "town": "Selestat",
        "pays": "france",
        "monTableau": arr2,
        "department": "Alsace"
    }
    let arr = [];
    arr.push(obj);
    arr.push(obj);
    arr.push(obj);
    arr.push(obj);
    //fdi.render(obj);
    fdi.renderArray(arr, undefined, ";");

}

Table
In HTML

Inject CSS with javascript in html page

On 30/10/2023

How to inject css in your page with javascript

 


// The content of the stylesheet
const styleSheetContent = `
    .demo{
        background:red;
        color: yellow;
    }

    .demo2 {
        font-size: 1.2rem;
        color: black;
    }
`;

// Creates the style element
function createStyleElement(id, content) {
    var style = document.createElement("style");
    style.type = "text/css";
    style.id = id;
    style.innerHTML = content;

    if (style.styleSheet) {
        style.styleSheet.cssText = content;
    } else {
        let st = document.getElementById(id);
        if(st == undefined){
            var head = document.head || document.getElementsByTagName("head")[0];
            head.appendChild(style);
        } else {
            st.innerHTML = content;
        }
    }
    return style;
}

createStyleElement("fdiStyle", styleSheetContent);

 

In HTML

SPFX React Override Native CSS

On 12/07/2023

How to override native SharePoint css in SPFX react webparts 

 


:global .webPartContainer{
  display: none;
}

 

In HTML

Css Add a Line Above

On 05/12/2018

Add a line with css above an html element

 

salut Fred

html
 
 
css
 

When the text is too long and goes outside the div or span, add this : white-space: normal;

 

ul li in line



<ul style="display:inline; list-style: none;">
          <li  style="display:inline;"><div style="background-color: #FF0000;width: 8px;height: 8px;">&nbsp;</div></li>
          <li style="display:inline;">plop</li>
          <li style="display:inline;">plop</li>
          <li style="display:inline;">plop</li>
        </ul>
 display: inline; list-style: none;
In HTML

HTML templates

On 03/11/2018

my html clipboard tool