Chargement conditionnel de JavaScript / CSS pour les codes courts

36

J'ai publié un plugin qui crée un shortcode et nécessite un fichier JavaScript et un fichier CSS à charger sur toute page contenant ce shortcode. Je pourrais simplement faire en sorte que le script / style soit chargé sur toutes les pages, mais ce n'est pas la meilleure pratique. Je veux seulement charger les fichiers sur les pages qui appellent le shortcode. J'ai trouvé deux méthodes pour le faire, mais les deux ont des problèmes.

Méthode 1 définit un indicateur sur true dans la fonction du gestionnaire de code court, puis vérifie cette valeur à l'intérieur un wp_footer callback. Si c'est vrai, il utilise wp_print_scripts() pour charger le code JavaScript. Le problème avec ceci est que cela ne fonctionne que pour JavaScript et pas pour CSS, car CSS doit être déclaré à l'intérieur de <head> , ce que vous ne pouvez faire que lors d'un hook précoce tel que init ou wp_head .

Méthode 2 se déclenche tôt et" jette un coup d'œil "pour voir si le shortcode existe dans le contenu de la page en cours. J'aime cette méthode beaucoup mieux que la première, mais le problème qu'elle pose ne détecte pas si le modèle appelle do_shortcode() .

Donc, je suis plutôt enclin à utiliser la deuxième méthode, puis à essayer de détecter si un modèle est attribué et, le cas échéant, à l’analyser pour le shortcode. Avant de faire cela, cependant, je voulais vérifier si quelqu'un connaissait une meilleure méthode.

Mise à jour: j'ai intégré la solution dans mon plug-in. Si quelqu'un est curieux de le voir se développer dans un environnement réel, vous pouvez le le télécharger ou parcourez-le .

Mise à jour 2: À partir de WordPress 3.3, il est désormais possible d’ appeler wp_enqueue_script() directement dans un rappel de code court , et le fichier JavaScript sera appelé dans le pied de page du document. C'est techniquement possible pour les fichiers CSS également, mais cela devrait être considéré comme une mauvaise pratique, car sortir du CSS en dehors de la balise <head> enfreint les spécifications du W3C, peut casse FOUC et peut forcer le navigateur à rendre la page à nouveau.

    
posée Ian Dunn 23.06.2011 - 17:07
la source

8 réponses

10

Sur la base de ma propre expérience, j’ai utilisé une combinaison de méthode 1 & 2 - l’architecture et les scripts de pied de page de 1, et la technique de prévision 2.

Pour l’avenir, j’utilise regex à la place de stripos ; préférence personnelle, plus rapidement et peut rechercher un shortcode "mal formé";

preg_match( '#\[ *shortcode([^\]])*\]#i', $content );

Si vous craignez que les auteurs utilisent do_shortcode manuellement, je voudrais leur demander de l'utilisation d'un appel d'action et de mettre en file d'attente manuellement votre style préenregistré.

UPDATE : pour l'auteur paresseux qui n'a jamais RTFM, envoyez un message soulignant la erreur de son comportement;)

function my_shortcode()
{
    static $enqueued;
    if ( ! isset( $enqueued ) )
        $enqueued = wp_style_is( 'my_style', 'done' ); // cache it so we don't repeat if called over and over

    // do shortcode
    $output = '';

    if ( ! $enqueued )
        // you can output the message on first occurence only by wrapping it in the previous if
        $output .= <<<HTML
<p>Attention! You must enqueue the shortcode stylesheet yourself if calling <code>do_shortcode()</code> directly!</p>
<p>Use <code>wp_enqueue_style( 'my_style' );</code> before your <code>get_header()</code> call inside your template.</p>
HTML;

    return $output;
}
    
réponse donnée TheDeadMedic 23.06.2011 - 20:23
la source
8

Je réponds tardivement à cette question, mais depuis que Ian a commencé, ce fil Sur la liste des wp-hackers aujourd’hui, cela m’a amené à penser que cela valait la peine de répondre, surtout que j’ai prévu d’ajouter une telle fonctionnalité à certains plugins sur lesquels je travaille.

Une approche à considérer consiste à vérifier lors du premier chargement de la page si le shortcode est réellement utilisé, puis à enregistrer le statut d'utilisation du shortcode dans une clé méta de publication. Voici comment:

Comment procéder étape par étape

  1. Définissez un indicateur $shortcode_used sur 'no' .
  2. Dans la fonction shortcode, définissez l'indicateur $shortcode_used sur 'yes' .
  3. Définissez une priorité d'accrochage 'the_content' 12 après que WordPress a traité les codes abrégés et vérifiez la méta-mission pour un '' à l'aide de la clé "_has_{$shortcode_name}_shortcode" . (Une valeur de '' est renvoyée lorsqu'une clé méta de publication n'existe pas pour l'ID de publication.)
  4. Utilisez un crochet 'save_post' pour supprimer la publication meta, effacez l'indicateur persistant de cette publication au cas où l'utilisateur modifierait l'utilisation du code court.
  5. Également dans le 'save_post' hook, utilisez wp_remote_request() pour envoyer un HTTP GET non bloquant au permalien de la publication afin de déclencher le chargement de la première page et le paramétrage de l'indicateur de persistance.
  6. Enfin, définissez un 'wp_print_styles' et vérifiez dans post-méta la valeur 'yes' , 'no' ou '' à l'aide de la clé "_has_{$shortcode_name}_shortcode" . Si la valeur est 'no' ne sert pas l'externe. Si la valeur est 'yes' ou '' , continuez et servez l'externe.

Et cela devrait le faire. J'ai écrit et testé un exemple de plug-in pour montrer comment tout cela fonctionne.

Exemple de code de plug-in

Le plugin se réveille sur un shortcode [trigger-css] qui définit les éléments <h2> de la page en blanc sur rouge afin que vous puissiez facilement le voir fonctionner. Il suppose un sous-répertoire css contenant le fichier style.css contenant ce CSS:

/*
 * Filename: css/style.css
 */
h2 {
  color: white;
  background: red;
}

Et ci-dessous, le code dans un plugin fonctionnel:

<?php
/**
 * Plugin Name: CSS on Shortcode
 * Description: Shows how to conditionally load a shortcode
 * Author: Mike Schinkel <mike@newclarity.net>
 */
class CSS_On_Shortcode {

  /**
   * @var CSS_On_Shortcode
   */
  private static $_this;

  /**
   * @var string 'yes'/'no' vs. true/false as get_post_meta() returns '' for false and not found.
   */
  var $shortcode_used = 'no';

  /**
   * @var string
   */
  var $HAS_SHORTCODE_KEY = '_has_trigger-css_shortcode';
  /**
   *
   */
  function __construct() {
    self::$_this = $this;
    add_shortcode( 'trigger-css', array( $this, 'do_shortcode' ) );
    add_filter( 'the_content', array( $this, 'the_content' ), 12 ); // AFTER WordPress' do_shortcode()
    add_action( 'save_post', array( $this, 'save_post' ) );
    add_action( 'wp_print_styles', array( $this, 'wp_print_styles' ) );
  }

  /**
   * @return CSS_On_Shortcode
   */
  function this() {
    return self::$_this;
  }

  /**
   * @param array $arguments
   * @param string $content
   * @return string
   */
  function do_shortcode( $arguments, $content ) {
    /**
     * If this shortcode is being used, capture the value so we can save to post_meta in the 'the_content' filter.
     */
    $this->shortcode_used = 'yes';
    return '<h2>THIS POST WILL ADD CSS TO MAKE H2 TAGS WHITE ON RED</h2>';
  }

  /**
   * Delete the 'has_shortcode' meta value so that it can be regenerated
   * on first page load in case shortcode use has changed.
   *
   * @param int $post_id
   */
  function save_post( $post_id ) {
    delete_post_meta( $post_id, $this->HAS_SHORTCODE_KEY );
    /**
     * Now load the post asynchronously via HTTP to pre-set the meta value for $this->HAS_SHORTCODE_KEY.
     */
    wp_remote_request( get_permalink( $post_id ), array( 'blocking' => false ) );
  }

  /**
   * @param array $args
   *
   * @return array
   */
  function wp_print_styles( $args ) {
    global $post;
    if ( 'no' != get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * Only bypass if set to 'no' as '' is unknown.
       */
      wp_enqueue_style( 'css-on-shortcode', plugins_url( 'css/style.css', __FILE__ ) );
    }
   }

  /**
   * @param string $content
   * @return string
   */
  function the_content( $content ) {
    global $post;
    if ( '' === get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * This is the first time the shortcode has ever been seen for this post.
       * Save a post_meta key so that next time we'll know this post uses this shortcode
       */
      update_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, $this->shortcode_used );
    }
    /**
     * Remove this filter now. We don't need it for this post again.
     */
    remove_filter( 'the_content', array( $this, 'the_content' ), 12 );
    return $content;
  }

}
new CSS_On_Shortcode();

Exemple de captures d'écran

Voici une série de captures d'écran

Éditeur de base de publication, pas de contenu

Affichagedepost,pasdecontenu

Éditeur de publication de base avec [trigger-css] Shortcode

Affichagedepublicationavec[trigger-css]Shortcode

Pas sûr si c'est 100%

Je pense que ce qui précède devrait fonctionner dans presque tous les cas, mais comme je viens d'écrire ce code, je ne peux pas être sûr à 100%. Si vous pouvez trouver des situations où cela ne fonctionne pas, j'aimerais vraiment savoir si je peux corriger le code dans certains plugins auxquels j'ai ajouté ceci. Merci d'avance.

    
réponse donnée MikeSchinkel 02.01.2013 - 07:57
la source
5

Google m'a trouvé un potentiel répondre . Je dis "potentiel", car cela a l'air bien et devrait fonctionner, mais je ne suis pas convaincu à 100% que c'est la meilleure façon de le faire:

add_action( 'wp_print_styles', 'yourplugin_include_css' );
function yourplugin_include_css() {
    // Check if shortcode exists in page or post content
    global $post;

    // I removed the end ' ] '... so it can accept args.
    if ( strstr( $post->post_content, '[yourshortcode ' ) ) {
        echo $csslink;
    }
}

Cela devrait pouvoir vérifier si la publication actuelle utilise un shortcode et ajouter une feuille de style à l'élément <head> de manière appropriée. Mais je ne pense pas que cela fonctionnera pour une page d'index (c.-à-d. Plusieurs publications dans la boucle) ... Elle provient également d'un ancien blog de 2 ans. Je ne suis donc même pas sûr que cela fonctionnera avec WP 3.1.X. .

    
réponse donnée EAMann 23.06.2011 - 17:34
la source
2

En utilisant une combinaison de la réponse de TheDeadMedic et de la documentation (qui n'a pas trouvé mes codes courts), J'ai créé une fonction simple utilisée pour mettre en file d'attente les scripts de plusieurs codes courts. Wp_enqueue_script () dans les codes courts n’ajoute que le pied de page, ce qui peut être utile car il peut gérer les scripts d’en-tête et de pied de page.


function add_shortcode_scripts() {
    global $wp_query;   
    $posts = $wp_query->posts;
    $scripts = array(
        array(
            'handle' => 'map',
            'src' => 'http://maps.googleapis.com/maps/api/js?sensor=false',
            'deps' => '',
            'ver' => '3.0',
            'footer' => false
        ),
        array(
            'handle' => 'contact-form',
            'src' => get_template_directory_uri() . '/library/js/jquery.validate.min.js',
            'deps' => array( 'jquery' ),
            'ver' => '1.11.1',
            'footer' => true
        )   
    );

    foreach ( $posts as $post ) {
        foreach ( $scripts as $script ) {
            if ( preg_match( '#\[ *' . $script['handle'] . '([^\]])*\]#i', $post->post_content ) ) {
                // enqueue css and/or js
                if ( wp_script_is( $script['handle'], 'registered' ) ) {
                    return;
                } else {
                    wp_register_script( $script['handle'], $script['src'], $script['deps'], $script['ver'], $script['footer'] );
                    wp_enqueue_script( $script['handle'] );
                }
            }
        }
    }
}
add_action( 'wp', 'add_shortcode_scripts' );
    
réponse donnée Sean Michaud 30.11.2013 - 20:52
la source
1

Enfin, j’ai également trouvé une solution de chargement css conditionnel qui fonctionne pour mon plugin www.mapsmarker.com et je souhaite partager avec toi. Il vérifie si mon shortcode est utilisé dans le fichier de modèle actuel et dans l'en-tête / footer.php et, si oui, met la feuille de style nécessaire dans l'en-tête:

  function prefix_template_check_shortcode( $template ) {
    $searchterm = '[mapsmarker';
    $files = array( $template, get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'header.php', get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'footer.php' );
    foreach( $files as $file ) {
        if( file_exists($file) ) {
            $contents = file_get_contents($file);
            if( strpos( $contents, $searchterm )  ) {
                wp_enqueue_style('
leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css');
                  break; 
            }
        }
    }
  return $template;
  }  
  add_action('template_include','prefix_template_check_shortcode' );
    
réponse donnée robertharm 12.12.2012 - 22:29
la source
1

En ce qui concerne mon plug-in, j'ai constaté que les utilisateurs avaient parfois un générateur de thème dont le shortcode était stocké dans publier des métadonnées . Voici ce que j'utilise pour détecter si mon shortcode de plug-in est présent dans les publications en cours ou les métadonnées en cours :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );
    
réponse donnée zdenekca 06.11.2015 - 01:24
la source
0
  

car CSS doit être déclaré à l'intérieur de <head>

Pour les fichiers CSS, vous pouvez les charger dans la sortie de votre shortcode:

<style type="text/css">
  @import "path/to/your.css"; 
</style>

Définissez une constante ou quelque chose après cela, tel que MY_CSS_LOADED (n'incluez le CSS que si la constante n'est pas définie).

Vos méthodes sont plus lentes que d'aller de cette façon.

Pour les fichiers JS, vous pouvez faire la même chose si le script que vous chargez est unique et n’a pas de dépendances extérieures. Si ce n'est pas le cas, chargez-le à l'intérieur du pied de page, mais utilisez la constante pour déterminer si elle doit être chargée ou non ...

    
réponse donnée onetrickpony 23.06.2011 - 17:22
la source
0

Script Logic est un plugin WordPress qui vous donne un contrôle total sur tous les fichiers JavaScript et CSS. En utilisant ce plugin, vous pouvez conditionnellement charger le fichier CSS et JS uniquement sur les pages où vous en avez besoin.

enlace

    
réponse donnée Tahir Yasin 17.06.2014 - 09:44
la source

Lire d'autres questions sur les étiquettes