window.print() schneidet Hyperlinks ab

  • Hallo Zusammen,


    ich habe auf meiner Seite die onclick Funktion "window.print()" eingebaut.


    Auf der Seite befinden sich Dokumente, bei denen ein Link hinterlegt ist. Der dahinter liegende Link wird beim drucken mit angezeigt, aber abgeschnitten.


    Ich hatte ein zweites Problem, dabei ging es um einen Button der die Benutzer auf Outlook weiterleitet, den konnte ich einfach über CSS mit @media ausblenden.

    Gibt es eine Möglichkeit, die anderen Links komplett darzustellen? Wenn man sie ausblenden kann, sollte man sie ja eigentlich auch komplett einblenden können. Ich habs mit !important probiert aber funktioniert nicht.. Hab dazu leider nichts verwendbares bislang gefunden..


    Vielen Dank

  • Danke für die schnelle Antwort. den <a> Tag kann ich schwer du den ganzen Text ersetzen, weil es über 1500 verschiedene Links gibt. Die hab ich alle in einer Datenbank liegen und frage die über PHP nur ab

    <Code=PHP>


    echo '<a href='.$line4['public_link'].' target="_blank" >'.addslashes($line4['document_title']).'</a><br>';

    </Code>

  • Regular Expressions?

    <a\s+href="(?<linktext>[^"]+)"\s+target="_blank">[^<]+<\/a>


    Einfach jeden mit der Gruppe linktext ersetzen und feddich. Geht in einem Rutsch, ganz egal ob 15, 150, 1.500, 15.000 oder wie viele auch immer.

  • Hey Bodaggnmo,


    es kann daran liegen, dass deine Seite zu groß ist. Obwohl. Eigentlich sollte es dann eingerückt werden und dadurch mehrere Seiten entstehen.

    Auch würde ich dir raten nicht die Function addslashes zu verwenden. Verwende die Function htmlspecialchars um die Ausgabe zu maskieren. Diese Funktion solltest du auf alle DB-Ausgaben bis auf IDs anwenden.


    Kannst du uns bitte mehr von deinem Code zeigen, damit wir es testen können ?


    Vielen Dank.


    Grüße,

    Stef

  • Ich erkenne das Problem nicht:

    JavaScript
    document.body.innerHTML = document.body.innerHTML.replace(
            /<a href=\"([^"]+)\" target=\"_blank\">[^<]+<\/a>/ig
            , '<span class="print-link">$1</span>'
        );
  • Auch würde ich dir raten nicht die Function addslashes zu verwenden. Verwende die Function htmlspecialchars um die Ausgabe zu maskieren. Diese Funktion solltest du auf alle DB-Ausgaben bis auf IDs anwenden.

    Da habe ich jetzt mal algemein eine Frage zu. Mir wurde oftgenug gesagt das man alles in htmlspecialchars packensoll was ausgegeben werden soll. Wieso sind den id's da jetzt ausgeschlossen ?

    Ehrlich gesagt ich verstehe die Welt nicht mehr .

  • Ich erkenne das Problem nicht:

    JavaScript
    document.body.innerHTML = document.body.innerHTML.replace(
            /<a href=\"([^"]+)\" target=\"_blank\">[^<]+<\/a>/ig
            , '<span class="print-link">$1</span>'
        );

    Ich hab das ganze mal auf codepen probiert und da liest er den Link einwandfrei aus. Danke!


    Daraufhin hab ichs in mein php Skript zwischen die <script> tags eingebaut, da hat sich nichts getan, also hab ichs in eine neue Datei kopiert, als .js gespeichert und über den link im head Bereich eingebunden. Da tut sich auch nichts. Ich hab versucht den Syntax von diesem Skript mit Google zu verstehen, aber ich blick da nicht durch was die ganzen "/", eckigen klammern usw da machen. Ich hab nämlich probiert in Codepen (da hat es ja einwandfrei funktioniert) dein Skript so umzubauen, dass Dokumentenname + Link angezeigt werden, so brauch ich das dann nämlich im print. Falls du noch Zeit und Lust hast, erklär mir mal bitte die Syntax nach dem replace(, als was die ganzen Sonderzeichen da bewirken.. danke dir!

  • Naja, an der Stelle findet er ja nichts, weil das DOM noch nicht komplett ist.

    Wenn Du es im Head einbindest, egal ob über <style> oder externer Datei, musst Du sowas benutzen:

    JavaScript
    document.addEventListener( 'DOMContentLoaded', function() {
    
        // ... hier kommt das Script rein
    
    });


    Die Parameter des replace sind einfach nur der RegEx-Pattern, also die Maske, nach der gesucht werden soll: /<a href=\"([^"]+)\" target=\"_blank\">[^<]+<\/a>/ig. RegEx ausführlich zu erklären wäre hier wohl zu viel Overhead ;)


    Der zweite Parameter ist die Zeichenkette, mit der das gefundene ersetzt werden soll, dabei steht das $1 für die erste Backreference, was in dem Fall der erste geklammerte Ausdruck in dem Pattern ist: ([^"]+). Ich habe dann nur ein <span> mit einer CSS-Klasse drum rum gebaut, damit Du das im Print-CSS entsprechend stylen kannst, wie Du magst.


    Ich hab nämlich probiert in Codepen (da hat es ja einwandfrei funktioniert) dein Skript so umzubauen, dass Dokumentenname + Link angezeigt werden, so brauch ich das dann nämlich im print.

    Kannst ja mal Deine Versuche zeigen, dann kann man bestimmt helfen, das umzubauen.


    Um das ganze nur für die Druckausgabe zu ersetzen, bietet sich übrigens folgende Logik an:

    So hast Du das Original-Dokument nach dem Druck wieder hergestellt.

    Kapselst Du das in die Events beforeprint und afterprint, benötigst Du für den Fall auch das obige DOMContentLoaded nicht.

  • Hier mal kurz das Pattern /<a href=\"([^"]+)\" target=\"_blank\">[^<]+<\/a>/igerklärt:


    / ... /ig

    Die beiden Slash sind sog. Delimiter, die einen RegEx-Pattern umschließen.

    Die Buchstaben i und g sind sog. Modifier. Über diese kann man das Verhalten der RegEx steuern.

    i bedeutet, dass mir Groß-/Kleinschreibung egal sind ( case insensitive ).

    g bedeutet, dass ich mehr als nur den ersten Treffer meine ( global ).


    Der Pattern-Ausdruck besteht also eigentlich nur aus dem, was zwischen den Delimitern steht:

    <a href=\"([^"]+)\" target=\"_blank\">[^<]+<\/a>


    Das kannst Du als ganz normale Zeichenkette betrachten, wobei bestimmte Zeichen durch einen Backslash maskiert werden müssen, damit diese korrekt interpretiert werden, hier zu sehen an den DoubleQuotes: \" oder auch dem Slash beim schließenden <\/a>-Tag.

    Ohne spezielle RegEx-Logik würde dort also völlig unspektakulär folgendes stehen:

    <a href="" target="_blank"></a>


    Damit würde er aber nichts finden, weil es so etwas im Dokument nicht gibt. Da kommen jetzt die regulären Ausdrücke zum Zuge, bspw. suchen wir ja alle <a>-Tags, mit beliebigem Text und href, die wir beide natürlich nicht exakt kennen.

    Das erledigt in dem Fall das [^<]+ für uns. Die eckigen Klammern stellen eine Zeichenklasse dar, nach der gesucht werden soll. Das Dach leitet an der Stelle eine Negation ein und bedeutet am Ende nur, dass an der Stelle alles stehen darf, außer ein <.

    Mit dem + hinter der Zeichenklasse definieren wir, dass mindestens eins bis beliebig viele Zeichen der Klasse gematched werden können.


    Das gleiche gilt für den href, in dem wir die URL des Link finden: ([^"]+).

    Hier verhält es sich genau wie zuvor, nur dass wir hier alle Zeichen außer einem DoubleQuote matchen wollen.

    Der wichtigste Unterschied ist die runde Klammerung. Über diese legen wir eine Backreference fest. Die erste Klammerung stellt die erste Backreference mit Index 1 dar.


    Auf diese Backreferences können wir in dem Replacement-String zugreifen, in dem wir den Index beginnend mit einem $ angeben: <span>$1</span>.


    Das ist die ganze Magie in Kürze erklärt, wenns hilft?

    Ansonsten: Tutorials büffeln

    :P

  • Sehr gut danke für deine Mühe, jetzt hab ich das Grundprinzip verstanden.

    Ich habs alles eingebaut und er ersetzt auch den Linknamen mit der URL.

    Was jedoch trd noch ist, ist dass der Link in der Druckversion abgeschnitten wird. Ich schätze mal das liegt an der window.print Funktion. Deine Code funktioniert nämlich einwandfrei :) ich bemüh mal googel weiter, sobald ich die Lösung hab meld ich mich, um es dir oder euch mitzuteilen. Danke vielmals!

  • Hey,


    basti1012 & Arne Drews :


    ich finde, dass man trotzdem aus Sicherheit die Ausgabe maskieren soll. Es kann ja vorkommen, dass ein Hacker in die Datenbank kommt und schädlichen Code platziert. Nun wenn du die Ausgabe nicht maskierst wird diese schädliche Code ausgeführt.


    Die Gefahr besteht und da sichere ich dann lieber mehrmals meine Anwendung ab als das was passiert.


    Grüße,

    Stef

  • Die Seite befindet sich im Intranet meiner Firma, also da müsste ich schon von einem Angriff aus dem Inneren ausgehen, und das ist glaub ich nicht der Fall. Danke aber für den Hinweis.

    Stef Sorry, hab gestern deinen Post irgendwie überlesen. Hier ist mal der relevante Code Teil:


    Hier wird jetzt der Informationstitel durch die URL ersetzt, wie ich gestern schon gesagt hab wollt ich ja aber eigentlich, dass der ganze Link angezeigt wird und nicht abgeschnitten wird sobald ich auf den Printbutton geh. Dass es replaced wird ist ja auch klar, weil ja document.body.innerHTML.replace angewendet wird. Das soll aber auch erstmal nicht mein Hauptproblem sein, sondern einfach dass ich es echt nicht hinbekomme, dass der Link dann eben mit Zeilenumbruch oder wie auch immer komplett angezeigt wird..

  • http://test123.com:1050/SAPIKS…9A&_CLASS=QM_LINKTEXTENDE


    Solang ist bei mir ungefähr ein Link, hab zum Schluss mal extra LINKTEXTENDE hingeschrieben, dass man es sofort sieht.

    Hab gerade noch ein verwandtes Thema im php.de Forum gefunden.

    https://www.php.de/forum/weben…her-zeilenumbruch-im-link


    Hab mir meiner table data dann die Klasse test gegeben um im CSS zu probieren.


  • HTML
    <a href='.$line2['public_link'].' target="_blank" class="print-link">'.addslashes($line2['document_title']).'</a><br>

    Des ist doch alles was ich normal machen muss, inklusive deiner CSS Anweisung? Ändert sich bei mir leider überhaupt nichts, ob ich des jetzt in den CSS Block


    @media print mit rein nehm oder auch einfach außerhalb des blockes mit .print-link {word-wrap:break-word;} mache..

  • Naja, die Klasse .print-link muss in die Ersetzung, nicht in das ursprüngliche <a>-Tag, das wird doch ersetzt und existiert gar nicht in der Druckversion.

    Sofern Du die RegEx daraufhin nicht anpasst, wird da eigentlich auch gar nichts mehr ersetzt.


    Schau Dir doch den Quelltext auf meinem Beispiel an, da passiert doch genau das, was Du willst.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!