• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

[ERLEDIGT] Grafik- und Textviewer bauen

colaholiker

Mitglied
Hallo,
ich bin dabei einen Viewer für Bilder und Texte erstellen und habe dazu einige Fragen.

Die Funktion: mit einem Button in einer Tabelle wähle ich das File in derselben Zeile aus.
Wenn ein Image oder ein Textfile erkannt wird soll der Content angezeigt werden.

Ich hab das bisher für Images geschafft. Die Code-Teile:

Code:
    <h1 id= 'h1_id'>Directory: SD/a-Arbeitsfiles/images</h1>   
        <dialog id='view-dialog'>
            <img id='view-img' alt='nicht darstellbar. ' />
            <button class='dia3btn' id='close-dialog3'>schließen</button>
        </dialog>
    <script>
        function showFile (fileName) {
            var
            host = window.location.hostname,
            posPkt = fileName.lastIndexOf('.'),
            fnEnd = fileName.substring(posPkt);
            h1txt = document.getElementById('h1_id').textContent,
            posPkt = h1txt.lastIndexOf(':'),
            path = h1txt.substring(posPkt+4);
            if ( fnEnd == '.jpg' ||
                fnEnd == '.png' ||
                fnEnd == '.bmp' ||
                fnEnd == '.gif' ) {
                    var
                    a = document.getElementById('view-img'),
                    src = 'http://' + host + path + '/' + fileName;
                    a.src = src;
                    console.log('==========my ges.path: ');
                    console.log(src);
            }
            if ( fnEnd == '.txt' ) {
                var
                h1txt = document.getElementById('h1_id').textContent,
                posPkt = h1txt.lastIndexOf(':'),
                path = h1txt.substring(posPkt+2),
                readFile = path + '/' + fileName;
            }
        }
    </script>

Erklärungen:
Den Pfad muß ich (leider) aus einer Angabe in <h1> filtern, da er in der URL nicht auftaucht.
Ich nutze eine Dialogbox für die Anzeige.
Der Code unter if ( fnEnd == '.txt' ) ist nur ein Dummy, das ist noch Baustelle.

Fragen:
- Die Möglichkeit, diese Dialogbox auch zum Anzeigen der Texte zu nutzen würde mich interessieren, aber auch ein anderer/ besserer Ansatz um die vorhandene Webseite durch den "View" nicht zu beeinflussen.

- Kann man Element- Eigenschaften in der Dialogbox (visible) mit Javascript umschalten? Dann kämen Elemente für die Textausgabe dazu und "visible" müßte für Text/Grafik gegenläufig umgeschaltet werden.

- beim Test des oberen Codes: bei Aufruf einer nächsten Grafik (die Dialogbox war schon geschlossen) wird erst kurz das vorherige Bild gezeigt. Wie kann ich das verhindern (Tests mit Cache löschen waren erfolglos)?
-vielen Dank!-
 

Sclero2004

Mitglied
beim Test des oberen Codes: bei Aufruf einer nächsten Grafik (die Dialogbox war schon geschlossen) wird erst kurz das vorherige Bild gezeigt. Wie kann ich das verhindern (Tests mit Cache löschen waren erfolglos)?
Das liegt wohl daran, dass das neue Bild ja zunächst geladen werden muss, bevor es angezeigt werden kann, und das dauert einen kurzen Moment. Es gibt verschiedene Möglichkeiten, das zu verbergen, eine davon: Einen Eventlistener für "load" auf das Bild registrieren und die Dialogbox erst sichtbar machen, wenn das Bild fertig geladen ist:
Code:
            if ( fnEnd == '.jpg' ||
                fnEnd == '.png' ||
                fnEnd == '.bmp' ||
                fnEnd == '.gif' ) {
                    var
                    a = document.getElementById('view-img'),
                    src = 'http://' + host + path + '/' + fileName;
                    a.onload = event => {
                        // jetzt die Dialogbox sichtbar machen
                    }
                    a.src = src;
                    console.log('==========my ges.path: ');
                    console.log(src);
            }

Ich finde, eine Dialogbox für diesen Zweck ist vollkommen OK wenn Du vermeiden willst, dass das Anzeigefenster auf der Seite zusätzliche Platz ein nimmt.

- Kann man Element- Eigenschaften in der Dialogbox (visible) mit Javascript umschalten? Dann kämen Elemente für die Textausgabe dazu und "visible" müßte für Text/Grafik gegenläufig umgeschaltet werden.
Selbstverständlich ist das möglich, Du brauchst nur die Eigenschaft "display" umzuschalten:
Code:
            document.getElementById('view-img').style.display = 'none';
            document.getElementById('view-txt').style.display = 'none';
            if ( fnEnd == '.jpg' ||
                fnEnd == '.png' ||
                fnEnd == '.bmp' ||
                fnEnd == '.gif' ) {
                    var
                    a = document.getElementById('view-img'),
                    src = 'http://' + host + path + '/' + fileName;
                    a.onload = event => {
                        // jetzt das Bild sichtbar machen:
                        document.getElementById('view-img').style.display = 'inline-block';
                    }
                    a.src = src;
                    console.log('==========my ges.path: ');
                    console.log(src);
            }
            if ( fnEnd == '.txt' ) {
                document.getElementById('view-txt').style.display = 'inline-block';
                var
                h1txt = document.getElementById('h1_id').textContent,
                posPkt = h1txt.lastIndexOf(':'),
                path = h1txt.substring(posPkt+2),
                readFile = path + '/' + fileName;
            }

(alles ungetestet)
 

colaholiker

Mitglied
Hi Sclero2004,
Einen Eventlistener für "load" auf das Bild registrieren und die Dialogbox erst sichtbar machen, wenn das Bild fertig geladen ist:
Das habe ich eingebaut. Mit 'auf das Bild registrieren' meinst Du wohl, onload muß in diese Funktion rein?
Ich hatte das Öffnen der Dialogbox erst in der 'function handleFileName' aufgerufen, das führt zum Absturz.

Inzwischen habe ich mich komplett auf das <Object>- Tag verlegt. Das sieht aktuell so aus:

Code:
        <dialog id='view-dialog'>
            <object id='view-obj' width='500' style='height: 300px'></object>
            <button class='dia3btn' id='close-dialog3'>schließen</button>
        </dialog>
        
    <script>
        function showFile (fileName) {
            var
            host = window.location.hostname,
            posPkt = fileName.lastIndexOf('.'),
            fnEnd = fileName.substring(posPkt);
            h1txt = document.getElementById('h1_id').textContent;
            posPkt = h1txt.lastIndexOf(':');
            path = h1txt.substring(posPkt+4);
            src = 'http://' + host + path + '/' + fileName;
            var a = document.getElementById('view-obj');
            a.data = src;
            if ( fnEnd == '.htm'  ||
                 fnEnd == '.html'  ||
                 fnEnd == '.css') {
                a.type = 'text/plain'
            }
            a.onload = event => {document.getElementById('view-dialog').showModal();}
        }
    </script>
Die Dateiendungen nutze ich nun, um z.B. '.html' als Text angezeigt zu bekommen, sonst soll sich <Object> den Dateityp selbst wählen.
Das war jedenfalls der Plan!
Leider bekomme ich Webseiten immer noch wie im Browserbild angezeigt.
Schade!
Eine '.css' Datei wurde vorher ignoriert, jetzt wird sie als Text angezeigt.

Ansonsten sieht es schon sehr gut aus. Morgen werde ich probieren, ob ich beim <Object> Tag ein Anzeigeproblem ausgeben kann (etwa wie bei <img ...alt= 'nicht darstellbar'>.

Danke noch für den Tip mit dem 'visible' umschalten. Auch wenn jetzt obsolet, ist gut zu wissen daß es machbar ist.
 

Sclero2004

Mitglied
Leider bekomme ich Webseiten immer noch wie im Browserbild angezeigt.
Versuche, ein view-source: vor die URL zu stellen, wie der Browser es macht, wenn er den Quelltext anzeigt:
Code:
src = 'view-source:http://' + host + path + '/' + fileName;
Ebenfalls ungetestet und ich weiß auch nicht auf Anhieb, ob das browserspezifisch ist.
 
Zuletzt bearbeitet:

colaholiker

Mitglied
Beim Firefox funktioniert's wenn ich es selbst in die Adressleiste setze.
Vom Code her geht es nicht. Es kommt nicht zum Absturz, da weitere Eingaben möglich sind:
Code:
        function showFile (fileName) {
            var
            host = window.location.hostname,
            posPkt = fileName.lastIndexOf('.'),
            fnEnd = fileName.substring(posPkt),
            h1txt = document.getElementById('h1_id').textContent;
            posPkt = h1txt.lastIndexOf(':');
            path = h1txt.substring(posPkt+4);
            src = 'http://' + host + path + '/' + fileName;
            var a = document.getElementById('view-obj');
            if ( fnEnd == '.htm' ||
                 fnEnd == '.html' ) {
                    src = 'view-source:' + src;
            }
            a.data = src;
            a.onload = event => {document.getElementById('view-dialog').showModal();}
        }
Die '.css'-Dateien lassen sich doch ohne Weiteres anzeigen (falsche Erkenntnis aus "Vor-onload-Zeiten").

Da man den View-Button bei der mackigen HTML-->Text Variante nur drückt ohne daß was passiert gucke ich mal ob ich was mit 'obj.typeMustMatch' anfangen kann...
 

colaholiker

Mitglied
--> "typeMustMatch" bringt nichts, weil es die Angabr 'type=...' im Objekt voraussetzt.

Zu 'view-source:' denke ich, daß das <object'-Tag den Ausdruck als "Medium" nicht unterstützt.
Evtl. ginge es sehr umständlich, indem der HTML-Code nochmal mit '.txt'-Endung gespeichert und dann gelesen würde.
Aber ich glaube das sprengt den Rahmen.
 

Sclero2004

Mitglied
Ich habe das mal untersucht. Es funktioniert, indem man das HTML als value in eine Textarea einträgt oder als textContent in ein pre-Element. Demo:
Code:
    <main>
        <h1 class="uebermich">Über Mich</h1>
        <div class="lower">
            <img class="imglogouebermich01" src="images/busleft.png" alt="" />
            <p class="uebertext pt-4 py-4 px-4">
                Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam quam
                fugit quibusdam, a possimus dolor aliquam repellat. Vel qui, ad iusto
                asperiores voluptatibus numquam deleniti sunt illo officia! Suscipit
                accusamus debitis quos
            </p>
        </div>
    </main>
    <textarea></textarea>
    <pre id="code"></pre>
    <script>
        const
            txt = document.querySelector('main').outerHTML;
        document.querySelector('textarea').value = txt;
        document.querySelector('#code').textContent = txt;
    </script>
 

Sclero2004

Mitglied
... oder mit fetch:
Code:
    <textarea class="code"></textarea>
    <pre class="code"></pre>
    <script>
        fetch('thread1171-display-source-2.html')
            .then(response => response.text())
            .then(txt => {
                document.querySelector('textarea.code').value = txt;
                document.querySelector('pre.code').textContent = txt;
            });
    </script>
 

colaholiker

Mitglied
Hallo Sclero2004,
der Fetch-Code läuft jetzt bei mir, wobei ich die <textarea... Variante besser finde (Text ist linksbündig). Morgen werde ich gucken, wie ich die Ausgabe in die Dialogbox bekomme.
 

colaholiker

Mitglied
Guten Morgen,
ich habs doch genauso gemacht wie Du in #8:
Code:
            if ( fnEnd == '.htm' ||
                fnEnd == '.html' ) {
                fetch(src)
                .then(response => response.text())
                .then(txt => {
                    console.log('============ mytxt: ');
                    console.log(txt);
                });
                a.data = txt;
            } else {
                a.data = src;
            }
            a.onload = event => {document.getElementById('view-dialog').showModal();}
        }
Aber die Console sagt 'Uncaught ReferenceError: txt is not defined'
und gibt den Text 'txt' danach aus.
' a.data = txt;' in die Klammer zu 'console.log...' zu setzen hat auch nicht geholfen.
Ist 'txt' hier keine Variable? Aber vgl. mit #8... ???
 

Sclero2004

Mitglied
txt ist ein Parameter der anonymen Funktion im then-Zweig und nur dort verfügbar. Wenn Du es dort hinein setzt, müsste es funktionieren:
Code:
            if ( fnEnd == '.htm' ||
                fnEnd == '.html' ) {
                fetch(src)
                .then(response => response.text())
                .then(txt => {
                    console.log('============ mytxt: ');
                    console.log(txt);
                    a.data = txt;
                });
            } else {
                a.data = src;
            }
            a.onload = event => {document.getElementById('view-dialog').showModal();}
Wenn es das bei dir nicht tut, dann poste doch noch etwas mehr von dem Zusammenhang.
 

colaholiker

Mitglied
Genauso hatte ich es und hab es jetzt nochmal probiert.
Ich drücke den Button und die Dialogbox öffnet sich nicht.
In der Console bekomme ich die Webseite als 'txt' angezeigt, aber auch einen 404-Fehler.
Es gibt keinen Absturz, ich kann andere Dateien anzeigen lassen.

Ich lade mal den kompletten Code als Datei...

- Eins stört mich auch noch: bei Anzeigen von .txt (und vermutlich Anderem) werden Dateinamen mit Spaces nicht angenommen.
'src' ist in dem Fall ja ein Link, und in der Console wird dieser unterstrichen; aber nur bis ans erste Space. Läßt sich da was machen?

-ähm, Nachtrag: nein, die .htm- Dateien haben keine Spaces drin :cool:
 

Anhänge

  • 020b 001 html zu txt.txt
    15,9 KB · Aufrufe: 1

colaholiker

Mitglied
Trenne dich von dem object-Tag, das ist für ganz andere Zwecke gedacht:
<object> hatte ich zuerst für den Inhalt der -txt Dateien verwendet. Alles Weitere, wie .js, .css usw. waren dann willkommene Zugaben.

Eine andere Variante war PHP mit include. Das hat für mich aber den Nachteil, PHP erst installieren zu müssen.

Momentan, ohne <object> und PHP, bekomme ich wieder nur Grafiken in die Dialogbox :-(
Gibt es denn weitere Möglichkeiten?
Dateinamen mit Leerzeichen besser ganz vermeiden.
Das mache ich ja auch, aber ich hatte eine Test.txt- Datei 'zigmal mit Windows kopiert, da entstanden die Spaces (Text - Kopie (10).txt).
 

colaholiker

Mitglied
HTML, CSS, JS, TXT indem Du den Inhalt mit fetch holst und in eine Textarea oder ein pre-Tag einträgst.
Darum geht es. Jetzt hab ich endlich mal Text ins <textarea> bekommen:
Code:
        <dialog id='view-dialog'>
            <img id='view-img' alt='nicht darstellbar ' />
            <textarea class='area-txt' id='view-txt'></textarea>
            <button class='dia3btn' id='close-dialog3'>schließen</button>
        </dialog>
        
        <script>
            function showFile (fileName) {
                var
                host = window.location.hostname,
                posPkt = fileName.lastIndexOf('.'),
                fnEnd = fileName.substring(posPkt),
                h1txt = document.getElementById('h1_id').textContent;
                posPkt = h1txt.lastIndexOf(':');
                path = h1txt.substring(posPkt+4);
                src = 'http://' + host + path + '/' + fileName;
                console.log('============ mysrc: ');
                console.log(src);
                if ( fnEnd == '.bmp' ||
                    fnEnd == '.jpg' ||
                    fnEnd == '.gif' ||
                    fnEnd == '.png' ||
                    fnEnd == '.ico' ) {
                    var a = document.getElementById('view-img');
                    a.src = src;
                    a.onload = event => {
                        document.getElementById('view-dialog').showModal();
                    }
                }
                if ( fnEnd == '.txt' ||
                    fnEnd == '.html' ||
                    fnEnd == '.htm' ||
                    fnEnd == '.js' ||
                    fnEnd == '.html' ||
                    fnEnd == '.css' ) {
                    var a = document.getElementById('view-txt');
                    fetch(src)
                    .then(response => response.text())
                    .then(txt => {
                        console.log('============ mytxt: ');
                        console.log(txt);
                        document.querySelector('textarea.area-txt').value = txt;
                        a.onload = event => {
                            document.getElementById('view-dialog').showModal();
                        }
                    })
                }
            }
        </script>
Das Umschalten von 'visible' ist noch auskommentiert.
Das Textfeld wird gefüllt, die Dialogbox im unteren IF() aber nicht geöffnet.

Wähle ich danach ein Bild aus, geht die Dialogbox auf und zeigt beide Tags an
(weil 'visible'...), aber dabei das gefüllte (!) Textfeld.

- warum öffnet die Dialogbox im Textmodus nicht (bzw. kann ich da die Variable 'a' sparen, und damit auch die ID von <textarea>)?

-warum wird der Inhalt des Textfelds noch dargestellt obwohl das Bild angezeigt wird? (Anderer Speicherbereich? Wird wohl später nicht stören...)
 

Sclero2004

Mitglied
- warum öffnet die Dialogbox im Textmodus nicht (bzw. kann ich da die Variable 'a' sparen, und damit auch die ID von <textarea>)?
Der Grund ist, dass eine Textarea kein load-Event hat. Das Laden passierte ja durch fetch und dabei haben wir schon abgewartet, bis der Text vom Server da ist. Die Variable "a" wirst Du aber brauchen weil Du ja den Text dort hinein schreiben willst.

-warum wird der Inhalt des Textfelds noch dargestellt obwohl das Bild angezeigt wird? (Anderer Speicherbereich? Wird wohl später nicht stören...)
Ja, es sind ja verschiedene DOM-Elemente, einmal img und dann textarea. Wenn Du die Sichtbarkeit umschaltest, wie früher beschrieben, wird das das Problem lösen.
 

colaholiker

Mitglied
Die Variable "a" wirst Du aber brauchen weil Du ja den Text dort hinein schreiben willst.
Den Satz verstehe ich nicht.
Inzwischen habe ich aber, wegen des Weglassens von onload, den Durchbruch geschafft.
Die 'visible'- Umschaltung klappt wunderbar, und die Auskommentierung der Variablen 'a' im unteren IF-Zweig hat keine Nachwirkung.
Ich habe nur noch die Größe von <textarea> festgelegt.

Damit dürfte der Abschnitt "Bild- und Textviewer" (bis aufs Styling) fertig sein.
viellen Dank!
 
Oben