Una galleria immagini con FileMaker e JavaScript
6 min read

Una galleria immagini con FileMaker e JavaScript

Una galleria immagini con FileMaker e JavaScript

In questo articolo costruiremo una galleria immagini da utilizzare in FileMaker e questa galleria dovrà leggere i dati da FileMaker ed essere responsive, ovvero dovrà riarrangiare automaticamente i contenuti quando interveniamo sulla dimensione della finestra.

Per completare il quadro delle funzionalità, saranno presenti due pulsanti che richiameranno degli script FileMaker per la visualizzazione a dettaglio e per la modifica.

Gli strumenti

Per tenere la parte JavaScript il più semplice possibile useremo Vue.js e ci faremo aiutare da Vue.js e da una libreria molto semplice da integrare: Vue Light Gallery.

Preparare CSS, HTML e JavaScript

Per prima cosa, predisponiamo predisponendo i collegamenti verso le librerie JavaScript e i CSS che utilizzeremo per definire l’aspetto grafico della nostra applicazione.

<!DOCTYPE HTML>
<html>
<head>
<!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.6/css/all.css">

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
</body>
</html>

Ora siamo pronti per iniziare a costruire la nostra mini-applicazione

Iniziamo con l’inserimento del consueto ciclo di loop gestito dalla direttiva v-for di Vue, che ci creerà una voce per ogni record che FileMaker passerà, quando invierà i dati sotto forma di JSON.

<body>
    <div id="app" class="container">
        <div class="row">
            <image-component v-for="image in images" :image="image" />
        </div>
    </div>

In pratica, per ogni record (image) contenuto nel gruppo di record inviato da FileMaker (images) crea una riga.

E qui affrontiamo la parte più interessante di questo lavoro di sviluppo, quindi soffermiamoci sull’argomento per spiegarlo più approfonditamente.

Se dobbiamo mostrare una lista valori, come abbiamo visto in altri articoli di questo blog, la parte di UI sarà molto contenuta, perché ci basterà attribuire uno stile ed eventualmente un metodo a ogni elemento, per consentire ai nostri utenti di fare clic sulla riga e vedere i dettagli, dopodiché il nostro lavoro sarà finito.

In casi del genere possiamo inglobare tutto quanto nel ciclo di loop senza complicare troppo la leggibilità del nostro codice.

Ma in questa esercitazione ogni elemento della nostra galleria non sarà costituito semplicemente dall’immagine - se questo è il vostro caso d’uso, va benissimo l’approccio utilizzato per le liste valori: qui vogliamo creare una galleria che mostri un’immagine, una descrizione, un indicatore della dimensione e un paio di pulsanti che invocheranno degli script FileMaker, ognuno di essi magari visualizzato con uno stile differente.

Quindi avremo una struttura, composta da tag HTML e codice JavaScript, oltre a qualche inevitabile riferimento alle classi CSS che daranno l’aspetto voluto al tutto, molto più elaborata di una semplice riga.

Come possiamo evitare di riversare tutto questo codice dentro al nostro ciclo di loop? Non è possibile creare una sorta di modello della nostra applicazione e poi farlo riempire con i dati dal nostro loop?

Fortunatamente sì: Vue ci consente di usare un component, quindi un oggetto riutilizzabile, che sarà definito da un template, ovvero un modello che conterrà tutte le informazioni per costruirlo.

In questo modo potremo definire, in separata sede e una volta per tutte, la struttura del componente, che in pratica rappresenterà un singolo elemento della galleria.

Per usare un’analogia con FileMaker, è come se predisponessimo un formato scheda per poi richiamarlo popolandolo di dati quando serve.

    Vue.component('image-component', {
        template: `
                        <div class="col-md-4">
                            <div class="card mb-4 shadow-sm">
                                <img class="bd-placeholder-img card-img-top" width="100%" height="225"
                                    :src="'data:image/jpeg;base64,'+image.fieldData.c_base_64" alt="Image">

                                <div class="card-body">
                                    <p class="card-text">{{image.fieldData.descrizione}}</p>
                                    <div class="d-flex justify-content-between align-items-center">
                                        <div class="btn-group">

                                            <button v-bind:id="image.fieldData.id_img" type="button" onclick="window.componentInstance.showCard( id )"
                                                class="btn btn-sm btn-outline-primary">Apri</button>
                                                <button v-bind:id="image.fieldData.id_img" type="button" onclick="window.componentInstance.editCard( id )"
                                                class="btn btn-sm btn-outline-secondary">Mod.</button>
                                        </div>
                                        <small class="text-muted">Dim. {{image.fieldData.c_size}}K.</small>
                                    </div>
                                </div>
                            </div>
                        </div>
        `,

        props: {
            image: Object
        }
    });

Il nostro componente verrà quindi utilizzato dal ciclo di for e, per ogni elemento presente nell’array di dati che passa FileMaker, verrà costruito un oggetto composto dalla struttura descritta nel modello e popolato con i dati del record elaborato in quel momento.

Gestire i dati in JavaScript

Ora che abbiamo ciò che ci serve per creare la struttura della nostra galleria, vediamo come gestire il passaggio dati da FileMaker alla nostra applicazione.

Per richiedere i dati useremo sempre la funzione loadData() usata in altri articoli di questa serie: in pratica FileMaker recupera i dati mediante le Data API e li passa a questa funzione mantenendo il formato JSON con cui le API restituiscono il risultato; a questo punto la funzione loadData() riceverà questi dati e li renderà disponibili a Vue per il ciclo di for che creerà la galleria.

Sempre in questa sezione troveremo i metodi, ovvero l’equivalente JavaScript degli script FileMaker, che il nostro modello assocerà ai pulsanti APRI e MOD., e che richiameranno due diversi script FileMaker.

    window.loadData = (fm_data) => {
        var obj;
        try {
            obj = JSON.parse(fm_data)
        } catch (e) {
            obj = fm_data;
            console.log('Dati hard coded non stringa', e)
        } finally {
            console.log('Dati caricati')
        }
        var data = obj.data;

        new Vue({
            el: '#app',
            data: {
                images: data
            },
            methods: {      
                showCard: function (id_img) {
                    FileMaker.PerformScript('mostraCard',id_img)
                },
                editCard: function (id_img) {
                    FileMaker.PerformScript('modificaCard',id_img)
                }
            },
            created() {
                window.componentInstance = this
                //https://stackoverflow.com/questions/42157168/use-method-in-template-out-of-instance-vue
            }
        })
    };

Gestire i dati in FileMaker

Passiamo ora alla parte FileMaker: come accennato in precedenza, FileMaker cerca i dati servendosi dell’istruzione Esegui FileMaker Data API, carica il codice HTML e infine passa i dati alla funzione JavaScript loadData() tramite Esegui JavaScript in Visualizzatore Web.

Per gestire in maniera più semplice il passaggio dei dati, abbiamo scelto di convertire la nostra immagine in Base64, quindi in pratica di trasformarla in un testo per poi includerla nel JSON, utilizzando la funzione FileMaker: Base64EncodeRFC().

Sarà poi il nostro modello a riconvertire il testo in immagine.

template: `
                        <div class="col-md-4">
                            <div class="card mb-4 shadow-sm">
                                <img class="bd-placeholder-img card-img-top" width="100%" height="225"
                                    :src="'data:image/jpeg;base64,'+image.fieldData.c_base_64" alt="Image">

                                <div class="card-body">
                                    <p class="card-text">{{image.fieldData.descrizione}}</p>
                                    <div class="d-flex justify-content-between align-items-center">
                                        <div class="btn-group">

                                            <button v-bind:id="image.fieldData.id_img" type="button" onclick="window.componentInstance.showCard( id )"
                                                class="btn btn-sm btn-outline-primary">Apri</button>
                                                <button v-bind:id="image.fieldData.id_img" type="button" onclick="window.componentInstance.editCard( id )"
                                                class="btn btn-sm btn-outline-secondary">Mod.</button>
                                        </div>
                                        <small class="text-muted">Dim. {{image.fieldData.c_size}}K.</small>
                                    </div>
                                </div>
                            </div>
                        </div>
        `

Vediamo ora il risultato all’opera: come possiamo notare, se cambiamo un dato in FileMaker e ricarico i dati (posso anche automatizzare l’intero processo, chiaramente) il tutto si aggiorna e, al contempo, i pulsanti di ogni immagine della galleria richiamano gli script di FileMaker per la visualizzazione e la modifica.