Klasse auf jeden Absatz anwenden, der ein Bild enthält?

7

Wenn Sie einer Seite oder einem Beitrag ein Bild hinzufügen, fügt Wordpress automatisch ein Absatz-Tag <p>als übergeordnetes Element hinzu, das das Bild enthält. Wie so:

<p><img src="my-image.jpg" alt=""></p>

Da es in CSS keinen übergeordneten Selektor gibt, würde ich gerne eine Lösung finden, um einen bestimmten Klassennamen auf die Absätze anzuwenden, die ein tatsächliches Bild enthalten. Das obige Beispiel würde also ergeben:

<p class="my-class"><img src="my-image.jpg" alt=""></p>

Irgendeine Idee, ob ich add_filter()einen Klassennamen auf jeden anwenden kann p, der ein Bild enthält?

Mathiregister
quelle

Antworten:

7

Sie können jQuery verwenden, wenn Sie sich beim Hinzufügen der Klasse nicht auf JavaScript verlassen möchten.

$(document).ready(function() {
    $('p:has(img)').addClass('image');
});

Update: Die .has()Methode ist wahrscheinlich schneller, siehe diesen jsperf.com-Test .

$(document).ready(function() {
    $('p').has('img').addClass('image');
});
Geert
quelle
11

Wenn Sie dies als PHP-Lösung benötigen. Sie können so etwas mit dem Filter 'the_content' tun. Dadurch wird jedem Absatz, der nur ein Bild-Tag umschließt, der Klassenname "content-img-wrap" hinzugefügt, wenn Wordpress Ihren Beitragsinhalt druckt. Dies wird also keinen Absatz mit einem Bild und einer Spanne umschließen. Siehe Update, wenn Sie danach suchen.

add_filter( 'the_content', 'img_p_class_content_filter' ,20);
function img_p_class_content_filter($content) {
    // assuming you have created a page/post entitled 'debug'
    $content = preg_replace("/(<p)(>[^<]*<img[^>]+>[^<]*)(<\/p>)/i", "\$1 class='content-img-wrap'\$2\$3", $content);

    return $content;
}

** UPDATE UNTEN: Als Reaktion auf die Notwendigkeit einer flexibleren Verpackung. Ich habe diesen regulären Ausdruck erstellt und schnell anhand von 3 automatisch umbrochenen Absätzen (dh ich habe die p-Tags nicht hinzugefügt, WP hat dies getan) mit Bildern am Ende eines Beitrags getestet. Sie enthielten jeweils auch einige zufällige Tags und Wagenrückläufe, um wahrscheinliche Fälle und Flexibilität zu testen. Die Idee ist, dass Sie nach dem <img> nichts mehr finden müssen, da das Vorhandensein eines <img> unseren Fall beweist. Dann fügen wir einfach unsere benutzerdefinierten Klassen hinzu (Verbesserungen sind mehr als willkommen):

function img_p_class_content_filter($content) {
    // assuming you have created a page/post entitled 'debug'
    $content = preg_replace("/(<p[^>]*)(\>.*)(\<img.*)(<\/p>)/im", "\$1 class='content-img-wrap'\$2\$3\$4", $content);

    return $content;
}
OnethingSimple
quelle
Wenn ich mir den regulären Ausdruck kurz anschaue, denke ich, dass er [^<]*zu eng ist, da er die in Absätzen auftretenden Spannen nicht berücksichtigt.
Bram Vanroy
@BramVanroy, ich habe nicht einmal geahnt, dass Sie ein Kopfgeld auf eine Frage setzen können, die nicht Ihre eigene ist. IMO sollten Sie eine Frage stellen, da diese gelöst ist, und ich werde überrascht sein, wenn sich viele Leute die Mühe machen, sie zu lesen.
Mark Kaplun
6
@ MarkKaplun Du denkst also, ich hätte lieber noch einmal genau den gleichen Beitrag geschrieben? Ich fürchte, es wäre als Duplikat markiert worden.
Bram Vanroy
@BramVanroy, ja, es ist umständlich, aber ich weiß nicht, ob Sie das Kopfgeld überhaupt vergeben können, und wie gesagt, die meisten Leute sehen sich wahrscheinlich keine gelösten Fragen an.
Mark Kaplun
@ MarkKaplun I + kann das Kopfgeld zuweisen, kein Problem. Ich denke auch, dass viele Leute, die Kopfgelder suchen, sich die Kopfgeldkategorie ansehen, damit sie hier ihren Weg finden.
Bram Vanroy
1

Ich verstehe zwar, dass das Frontend so schlank wie möglich sein soll, und sage daher, dass Sie eine PHP-Lösung wünschen ...

Persönlich habe ich viel Zeit damit verbracht, nur zum Spaß, und ich habe mir immer wieder Möglichkeiten ausgedacht, um den Regex-Abgleich zu unterbrechen (warum also nicht PHP ohne ein Bibliotheks-Add-On verwenden, das speziell für das Durchlaufen von HTML entwickelt wurde, wie in erwähnt) der Link oben) ...

Zum Beispiel:

Die Regel dieses Screenshots stimmt überein <p>oder sogar <P >(die einfachste Übereinstimmung, die noch nicht für P-Tags versucht wurde, die bereits eine Klasse oder andere Attribute, aber keine Klasse haben), aber es muss innerhalb des gesamten Blocks der schließenden Tags (wo) übereinstimmen PHP Regex für HTML fällt auseinander an den Nähten) ... der Pfeil auf dem ein Schließen P - Tag und Öffnung P - Tag sind auf der gleichen Linie und daher , wenn Sie dies als FIND zählen waren , und dann ersetzen die <pmit <p class="my-class", Sie‘ d my-classzum falschen Absatz hinzufügen .

Wenn Sie nicht einen solchen Anwendungsfall für "jedes Szenario" wollten, ist dies über Regex möglich. Wenn Sie Ihren Anwendungsbereich etwas einschränken.

Wenn Sie sich entscheiden, Ihren Umfang einzuschränken, könnten Sie an folgenden Informationen interessiert sein:

    From wp-includes/default-filters.php
    these run on the_content with default priority (10):
        wptexturize
        convert_smilies
        convert_chars
        wpautop
        shortcode_unautop
        prepend_attachment
    shortcode renders may add new paragraphs and/or new images
        do_shortcode runs on the_content priority 11 so we hook in afterwards so $content already has shortcodes rendered
*/
add_filter('the_content', 'se_16033', 15); //a priority higher than 11

Hier ist ein Startcode, wenn Sie sich auf diese komplizierte Route zwingen (anstatt über jQuery):

    function se_16033($content) {
    if( !is_singular() || !is_main_query() //https://pippinsplugins.com/playing-nice-with-the-content-filter/
    ) {
        return $content;
    }

    $content = force_balance_tags($content); //We do not want to be REGEXing on unbalanced HTML tags so we must make sure they are balanced before we get started -- garbage in, worse garbage out -- http://codex.wordpress.org/Data_Validation#HTML

    $patterns = array();
    $patterns[0] = '/quick/'; //first match p tags with existing classes because we just want to add an additional class
    $patterns[1] = '/brown/'; //second, match p tags with space (e.g. style) but without class=""
    $patterns[2] = '/fox/'; //third, match <p> tags without attributes
    ksort($patterns);

    $replacements = array();
    $replacements[0] = 'slow';
    $replacements[1] = 'black';
    $replacements[2] = 'bear';
    ksort($replacements);

    preg_replace_all($patterns, $replacements, $content);

    return $content;

}

Beachten Sie die Verwendung von http://codex.wordpress.org/Function_Reference/force_balance_tags. Standardmäßig wird es im Auszug und in den Kommentaren verwendet. Wenn Sie sich die Quelle ansehen, wird tatsächlich REGEX verwendet: https: //core.trac.wordpress. org / browser / tags / 4.1 / src / wp-Includes / formatting.php # L1453

Nebenbei bemerkt Ich nehme an, der Grund , warum sie Rückfall (nicht ideal) zur Verwendung von REGEX wegen WP Bedürfnis zu laufen auf fast allen PHP - Konfiguration vorstellbar des Hosts (dh nicht wollen , eine Bibliothek für den Fall zu laden , die PHP - Erweiterung deaktiviert ist). Sie können eine PHP-Bibliothek laden, die dafür in Ihrer eigenen Lösung entwickelt wurde. /RANDNOTIZ

Es ist eine Menge Code, der jedes Mal ausgeführt werden muss is_singular(). Daher bin ich mir nicht sicher, ob es sich lohnt, sie als Inspiration für eine komplexe PHP-Lösung zu verwenden, wenn Ihre Site wahrscheinlich bereits JS / jQuery verwendet.

  • Muss diese P-Klasse irgendwie auch in nicht JS-fähigen Browsern funktionieren?
  • Bist du ein Überleistungsguru? Wenn ja, wird derzeit auf Ihrer Website jQuery verwendet (z. B. Schieberegler, Bewegung usw.)? Wenn ja, wird die dafür erforderliche minimalistische jQuery kein Aufblähen hinzufügen. Mach einfach mit.
  • Wenn Sie jQuery NICHT im Front-End geladen haben, können wir einen reinen JavaScript-Weg finden, um dies zu erreichen (dh nicht über jQuery).

Bitte teilen Sie Ihre Gedanken.

Cliff P.
quelle
0

Wordpress verwendet die autopFunktion, um <p></p>Zeilenumbrüche in Ihren Inhalten hinzuzufügen .

Die Autop-Funktion finden Sie in Zeile 373 in formatating.php . Eine Option besteht darin, das Standard-Autop zu deaktivieren (siehe unten), eine neue Version der Funktion zu erstellen, die Ihre Klasse hinzufügt, und sie dann auf Ihren Inhalt anzuwenden (siehe auch den Link unten). Ich denke, Sie würden einen regulären Ausdruck um Zeile 442 hinzufügen, um dies zu tun.

Wenn Sie nur den Effekt des Absatzes entfernen möchten, können Sie Folgendes deaktivieren autop:

remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );

Welche finden Sie auf der Autop-Seite :

Steven
quelle
Ich werde nicht abstimmen, aber mit Autop herumzuspielen ist eine sehr gefährliche Sache, und es wird nicht den Fall lösen, in dem das HTML durch einen Shortcode generiert wird.
Mark Kaplun
Ich schlage nicht vor, mit Autop herumzuspielen, sondern eine benutzerdefinierte Funktion basierend auf Autop zu erstellen, die völlig in Ordnung und nicht gefährlich ist. Ich sehe keinen in der Frage erwähnten Shortcode.
Steven
Das ist genau das gleiche wie das Herumspielen mit Autop, und Sie sehen auch keine erwähnten Bereiche und Links ...
Mark Kaplun
Wenn das Schreiben einer benutzerdefinierten Funktion als "Durcheinander" bezeichnet wird, haben Sie wahrscheinlich Recht.
Steven
1
Autop ist optional. Wenn Sie die Antwort sehen, wird ein Verweis auf das Entfernen von Autop angezeigt, das von Wordpress bereitgestellt wird. Wordpress ist flexibel aufgebaut und ermöglicht Entwicklern, das Verhalten an benutzerdefinierte Anforderungen anzupassen. Dies ist einer von ihnen. Wenn ich vorschlagen würde, die Kerndateien zu berühren, hätten Sie einen Punkt, aber da ich es nicht bin, tun Sie es nicht.
Steven