Organizzazione HTML e iframe per dashboard [chiuso]

1

Ho bisogno di costruire un piccolo sito web per il mio team operativo che avrà una serie di iframe che puntano a un paio di grafici Kibana. Il sito Web avrà, diciamo, 4 link, ognuno dei quali punta a una pagina di un sito Web specifico con X iframe in ciascuno, con diversi URL iframe.

Il fatto è che non voglio digitare in modo statico gli URL e la larghezza / altezza di tutti gli iframe, poiché l'URL e le dimensioni hanno un strong potenziale di cambiamenti in futuro.

Quale sarebbe un buon approccio per l'organizzazione e l'immissione dinamica di questi valori sugli iframe? Stavo pensando di avere un file di costanti per ottenere quei valori. Dovrei farlo tramite JavaScript o forse un motore di template come Jinja2 lo farebbe?

    
posta user3682983 04.07.2017 - 18:01
fonte

1 risposta

2

Panoramica

Raccomando l'approccio "javascript". Se non hai mai usato javascript in precedenza, ti consiglio caldamente di prendere una pausa da questo progetto per un anno come imparare javascript (ho trovato che W3Schools è un punto di partenza davvero utile e MDN è un riferimento davvero utile ).

Creazione automatica dei collegamenti

Ora, per quanto riguarda l'enorme quantità di link diversi. Se non vuoi doverli digitare tutti, ma seguono uno schema comune, puoi usare javascript per generare automaticamente i nomi dei percorsi. Vedi l'esempio qui sotto.

<!doctype html><html><head><title>Iframe Auto-Generation</title></head><body>
<script>/*<![CDATA[*/ (function(){ // so that we don't pollute the global scope
    'use-strict'; // I always 'use-strict' for best practices
    /***************************************************************/
    var generatePathURL = function( i ){
            return '/path/to/file_' + i + '.html'; // example usage
        }, // you can process the value of the iterator here
        i=100; // number of pages you want to generate
    /***************************************************************/
    var HTMLcont = '',
        // live node list (auto-updated)
        autoIFrames = document.getElementsByName('autogenframe'),
        // set this to false to load them all at once
        synchronouslyLoadIFrames = true,
        loadNextIframeOptimized,
        loadNextIframe = function(){
            autoIFrames[i] && (autoIFrames[i].style.display = '');
            if (!autoIFrames[++i]) { 
               return; // code in here will run after all IFrames loaded
            } // loading the iframe:
            autoIFrames[i].src = autoIFrames[i].getAttribute('thesrc');
            autoIFrames[i].removeAttribute('thesrc');
            if (synchronouslyLoadIFrames){
               autoIFrames[i].addEventListener('load', loadNextIframeOptimized);
               autoIFrames[i].addEventListener('error', loadNextIframeOptimized);
            } else loadNextIframe();
        };
    while (i--)
        HTMLcont += '<iframe name="autogenframe" frameBorder="0" thesrc="' + 
            generatePathURL( i ) + '" style="display:none"></iframe>'
    document.body.insertAdjacentHTML('afterbegin', HTMLcont);
    if (window.requestAnimationFrame){ // helps avoid expensive thrashing
     loadNextIframeOptimized=requestAnimationFrame.bind(window,loadNextIframe);
    } else loadNextIframeOptimized = loadNextIframe;
    window.addEventListener('load', loadNextIframeOptimized);
})(); //]]></script></body></html>

Si noti come nell'esempio precedente, gli iframe vengono caricati in modo sincrono (uno alla volta). Questo per evitare di sovraccaricare il server con richieste ogni volta che un client lo riceve. Ecco un esempio più complesso di cosa potresti fare per generare un nome di percorso per aiutarti a iniziare.

var animalTypes = ['dogs', 'cats', 'rats', 'snakes', 'lizards'],
    animalTypesSize = animalTypes.length,
    animalAgeGroups = ['baby', 'child', 'teenager', 'adolescent', 'elder'],
    generatePathURL = function( i ){
        return animalTypes[i%animalTypesSize] + '/' + 
                animalAgeGroups[Math.floor(i/animalTypesSize)] + '/';
    },
    i = animalTypesSize * animalAgeGroups.length;

Ridimensionamento automatico Gli iframe

Gli iframe non si dimensionano automaticamente per motivi di sicurezza (che in realtà è una cosa piuttosto buona). C'è stata una proposta per seamless attributo che cambierebbe il comportamento dell'iframe, tra l'altro, con il ridimensionamento automatico. Ma, non è riuscito a ottenere la trazione . Quindi, il modo più semplice per navigare tra i browser sarebbe utilizzare javascript. Ho creato due script separati che, se inseriti nella pagina destra (come mostrato di seguito), ridimensioneranno automaticamente le pagine.

Inserisci il seguente script nella pagina padre esterna che contiene l'iframe.

<script>/*<![CDATA[*/(function(){'use-strict';
    // if the iframe is on a different domain or protocal, then change
    // iframepageorigin to the domain and protocal of the iframe, an array
    // of domains and protocals, or "*" to allow all (which I don't recommend).
    // You can also use regexps (for case-insensitivity) in place of strings
    var iframepageorigin = location.origin,
    observedEles = [ ];
    function run_main_script(){
        var observeFunc,
            firstContactFunc = function(e){
                var msgcnt = 'parentiframeid' + observedEles.indexOf(e.target),
                    cntWin = e.target.contentWindow;
                if (iframepageorigin instanceof Array){
                    var i = iframepageorigin.length;
                    while(i--) cntWin.postMessage(msgcnt,
                            iframepageorigin[i].source||iframepageorigin[i]);
                } else cntWin.postMessage(msgcnt,
                        iframepageorigin.source||iframepageorigin);
            },
            eleObserver = new MutationObserver(observeFunc = function(MOlst){
                var iCur = MOlst.length;
                morep: while (iCur--){
                    target = MOlst[iCur].target || MOlst[iCur];
                    if (target.nodeName !== 'IFRAME' ||
                        ~observedEles.indexOf( target )) continue morep;
                    observedEles.push( target );
                    target.addEventListener('load', firstContactFunc);
                }
            });
        /*window.*/addEventListener('message', function(e){
            var srcOrig = e.target.origin.toLowerCase(),
                msgcnt = e.data.slice('resize'.length).split('X');
            if (msgcnt.length !== 3) return;
            if (iframepageorigin instanceof Array){
                var i = iframepageorigin.length;
                while (i--) if (e.target.origin.match( iframepageorigin[i] ))
                            observedEles[+msgcnt[0]].width = msgcnt[1] + 'px',
                            observedEles[+msgcnt[0]].height = msgcnt[2] + 'px';
            } else if (e.target.origin.match(iframepageorigin[i]) ||
                        iframepageorigin ==='*' )
                observedEles[+msgcnt[0]].width = msgcnt[1] + 'px',
                observedEles[+msgcnt[0]].height = msgcnt[2] + 'px';
        });
        eleObserver.observe( document.body,
          { subtree: true, attributes: true, attributeFilter: ['src'] } );
        addEventListener('load', 
            observeFunc.bind(0, document.getElementsByName('iframe')) );
    };
    if (!window.MutationObserver){ // polyfill for IE9 & IE10
        var script=document.createElement('script');
        script.onload=run_main_script, script.async=true, script.src= 
 'https://www.dropbox.com/s/ft95wfv4ahow63u/mutationobserverpolyfill.js?dl=1';
        document.head.appendChild(script);
    } else run_main_script();
})(); //]]></script>

Inserisci il seguente script nella pagina iframe interna. Si noti che questo script, oltre al ridimensionamento automatico, imposta la visualizzazione dell'elemento HTML sulla tabella. Questo è necessario perché funzioni correttamente.

<script>/*<![CDATA[*/ (function(){'use-strict';
    // if the iframe is on a different domain or protocal, then 
    // change parentorigin to the domain and protocal of the iframe, an array
    // of domains and protocals, or "*" to allow all (which I don't recommend).
    // You can also use regexps (for case-insensitivity) in place of strings
    var parentorigin = location.origin,
        pariframeID,
        HTML = document.documentElement,
        prevSize = [],
        whenresize = function(){ try {
            (window.requestAnimationFrame||setTimeout)( whenresize );
            if (!((prevSize[0]!==(prevSize[0]=HTML.scrollWidth)) +
                (prevSize[1]!==(prevSize[1]=HTML.scrollHeight))))return;
            var curMes = 'resize'+pariframeID+'X'+prevSize[0]+'X'+prevSize[1];
            if (parentorigin instanceof Array){
                var i=parentorigin.length;
                while (i--) parent.postMessage(curMes,
                                    parentorigin[i].source||parentorigin[i])
            } else parent.postMessage(curMes,
                            parentorigin.source||parentorigin);
        } catch (e) {} };
    /*window.*/addEventListener('message', function(e){ try{
        var theData = e.data.slice('parentiframeid'.length);
        if (!e.data.startsWith('parentiframeid')) return;
        if (parentorigin instanceof Array){
            var i = parentorigin.length;
            while (i--) if (e.target.origin.match(parentorigin[i]))
                            pariframeID = theData, whenresize();
        }else if(parentorigin==='*'||e.target.origin.match(parentorigin))
            pariframeID = theData, whenresize();
    } catch(e) {} });
    HTML.style.overflow = 'hidden', HTML.style.display = 'table';
})();//]]></script>

Demo

Una demo esemplificativa di tutti i contenuti di cui sopra può essere trovata sul mio sito web, jackgiffin.com facendo clic su questo link . Non dimenticare di ispezionare la pagina con gli strumenti di sviluppo in modo da avere una migliore percezione del suo funzionamento.

Soluzione lato server

Se non si è contrari all'utilizzo di una soluzione lato server, è possibile utilizzare PHP per integrare il contenuto degli iframe nella pagina prima che i dati vengano inviati al client. Il più grande vantaggio di questo è che sarà molto più facile per i motori Serarch analizzare il tuo sito perché non tutti i motori di ricerca sono i migliori con l'esecuzione di javascript. Il disadvatage è che tasserà il server un po 'di più rispetto al contrario. E non sarai in grado di generare automaticamente i nomi dei percorsi senza sapere come programmare PHP, il che significa che dovrai digitare tutte le pagine a mano. In sostanza, sostituisci tutti gli iframe con questo:

<?php
   @readfile('/path/to/file/')
?>

Se usi questo approccio, dovresti sbarazzarti di tutte le cose fuori dal corpo nelle pagine che aggiungi. Questo perché usare la funzione di readfile veloce in PHP sarà solo copia-incolla nel il contenuto dei file, con conseguenti effetti collaterali potenzialmente indesiderati come un doctype nel mezzo della pagina, se non lo si elimina nel file collegato. Quindi, basicamente, basta fare questo alle tue iframe potenziali pagine se stai usando questa soluzione lato server:

Prima:

<!doctype HTML>
<html>
    <head>
        <title>Tab Title</title>
    </head>
    <body>
        <h1>BIG Title</h1>
        <p>Some example text</p>
    </body>
</html>

Dopo:

<h1>BIG Title</h1>
<p>Some example text</p>

Dichiarazioni finali

Codifica felice :)! Spero che tu abbia successo nei tuoi sforzi.

    
risposta data 09.07.2017 - 05:42
fonte

Leggi altre domande sui tag