Carregando condicionalmente JavaScript / CSS para códigos de acesso

36

Eu lancei um plug-in que cria um shortcode e requer um arquivo JavaScript e um arquivo CSS para carregar em qualquer página que contenha esse shortcode. Eu poderia apenas fazer o script / estilo carregar em todas as páginas, mas essa não é a melhor prática. Eu só quero carregar os arquivos em páginas que chamam o shortcode. Eu encontrei dois métodos de fazer isso, mas ambos têm problemas.

O método 1 define um sinalizador como true dentro da função de manipulador shortcode e verifica esse valor dentro um retorno de chamada wp_footer . Se for verdade, ele usa wp_print_scripts() para carregar o JavaScript. O problema com isso é que ele só funciona para JavaScript e não para CSS, porque o CSS deve ser declarado dentro de <head> , o que você só pode fazer durante um gancho inicial como init ou wp_head .

Método 2 dispara cedo e" avança "para ver se o shortcode existe no conteúdo atual da página. Eu gosto deste método muito melhor do que o primeiro, mas o problema com ele não vai detectar se o modelo chama do_shortcode() .

Então, estou inclinado a usar o segundo método e, em seguida, tentar detectar se um modelo está atribuído e, em caso afirmativo, analisá-lo para o shortcode. Antes de fazer isso, porém, queria verificar se alguém sabe de um método melhor.

Atualização: integrei a solução no meu plugin. Se alguém estiver curioso para ver isso em um ambiente ao vivo, você pode fazer o download ou pesquise .

Atualização 2: No WordPress 3.3, agora é possível chamar wp_enqueue_script() diretamente dentro de um retorno de chamada de shortcode , e o arquivo JavaScript será chamado dentro do rodapé do documento. Isso é tecnicamente possível também para arquivos CSS, mas deve ser considerado uma prática ruim, pois a saída de CSS fora da tag <head> viola as especificações do W3C, pode processar FOUC e pode forçar o navegador a renderizar novamente a página.

    
por Ian Dunn 23.06.2011 / 17:07
fonte

8 respostas

10

Com base em minha própria experiência, usei uma combinação do método 1 & 2 - os scripts de arquitetura e rodapé de 1 e a técnica de 'look-ahead' de 2.

Para o look-ahead, eu uso regex no lugar de stripos ; preferência pessoal, mais rápido, e pode procurar por shortcode 'malformado';

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

Se você estiver preocupado com autores usando do_shortcode manualmente, eu optaria por instruí-los a usar uma chamada de ação enfileirar seu estilo pré-registrado manualmente.

UPDATE : Para o autor preguiçoso que nunca faz RTFM, envie uma mensagem para destacar o erro de suas maneiras;)

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;
}
    
por TheDeadMedic 23.06.2011 / 20:23
fonte
8

Estou atrasado em responder a esta pergunta, mas desde que a Ian começou este tópico na lista wp-hackers de hoje me fez pensar que vale a pena responder especialmente considerando que eu tenho planejado adicionar esse recurso a alguns plugins em que estive trabalhando.

Uma abordagem a considerar é verificar o carregamento da primeira página para ver se o shortcode é realmente usado e, em seguida, salvar o status de uso do shortcode em uma chave post meta. Veja como:

Como fazer a passo a passo

  1. Defina um sinal $shortcode_used como 'no' .
  2. Na própria função de código de acesso, defina o $shortcode_used como 'yes' .
  3. Defina uma 'the_content' de prioridade de gancho 12 , que é depois que o WordPress processou códigos de acesso e verifique pós meta para um '' usando a chave "_has_{$shortcode_name}_shortcode" . (Um valor de '' é retornado quando não existe uma chave meta meta para o ID do post.)
  4. Use um gancho 'save_post' para excluir a postagem meta limpando o sinalizador persistente para a postagem, caso o usuário altere o uso do código de acesso.
  5. Também no 'save_post' hook use wp_remote_request() para enviar um HTTP GET sem bloqueio para o permalink do próprio post para acionar o carregamento da primeira página e a configuração do sinalizador persistente.
  6. Por fim, defina um 'wp_print_styles' e verifique a meta meta para um valor de 'yes' , 'no' ou '' usando a chave "_has_{$shortcode_name}_shortcode" . Se o valor for 'no' , não atenda ao externo. Se o valor for 'yes' ou '' , vá em frente e exiba o externo.

E isso deve ser feito. Eu escrevi e testei um plugin de exemplo para mostrar como tudo isso funciona.

Exemplo de código de plug-in

O plug-in é ativado em [trigger-css] shortcode, que define os elementos <h2> na página como branco-em-vermelho para que você possa vê-lo funcionando facilmente. Ele assume um subdiretório css contendo o arquivo style.css com este CSS:

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

E abaixo está o código em um plug-in funcional:

<?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();

Screenshots de exemplo

Aqui está uma série de capturas de tela

Editor de postagem básico, sem conteúdo

Exibirpostagem,semconteúdo

Editor de postagem básico com [trigger-css] Shortcode

Exibirpostagemcom[trigger-css]Shortcode

Não tem certeza se é 100%

Eu acredito que o acima deve funcionar em quase todos os casos, mas como eu acabei de escrever este código eu não posso ter 100% de certeza. Se você puder encontrar situações em que não funciona, eu realmente gostaria de saber para poder corrigir o código em alguns plugins que acabei de adicionar. Agradecemos antecipadamente.

    
por MikeSchinkel 02.01.2013 / 07:57
fonte
5

O Google encontrou-me um potencial answer . Eu digo "potencial", como parece bom, deve funcionar, mas não estou 100% convencido de que é a melhor maneira de fazê-lo:

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;
    }
}

Isso deve ser capaz de verificar se a postagem atual está usando um shortcode e adicionar uma folha de estilo ao elemento <head> apropriadamente. Mas eu não acho que funcionará para uma página de índice (isto é, várias postagens no loop) ... Também é de um post antigo de dois anos, então eu nem tenho certeza se vai funcionar com o WP 3.1.X .

    
por EAMann 23.06.2011 / 17:34
fonte
2

Usando uma combinação da resposta do TheDeadMedic e da documentação do get_shortcode_regex () (que na verdade não encontrou meus códigos de acesso), Eu criei uma função simples usada para enfileirar scripts para vários códigos de acesso. Como o wp_enqueue_script () em códigos de acesso só é adicionado ao rodapé, isso pode ser útil, já que pode manipular os scripts de cabeçalho e rodapé.


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' );
    
por Sean Michaud 30.11.2013 / 20:52
fonte
1

Finalmente, também encontrei uma solução para o carregamento de CSS condicional que funciona para o meu plugin www.mapsmarker.com e gostaria de compartilhar contigo. Ele verifica se meu shortcode é usado dentro do arquivo de modelo atual e header / footer.php e, se sim, enfileira a folha de estilos necessária no cabeçalho:

  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' );
    
por robertharm 12.12.2012 / 22:29
fonte
1

Para meu plug-in, descobri que às vezes os usuários têm um criador de temas que possui shortcode armazenado em post meta data . Aqui está o que estou usando para detectar se o shortcode do meu plug-in está presente nos pós-dados atuais ou pós-meta :

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' );
    
por zdenekca 06.11.2015 / 01:24
fonte
0
  

porque o CSS deve ser declarado dentro de <head>

Para arquivos CSS, você pode carregá-los em sua saída de shortcode:

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

Defina uma constante ou algo assim, como MY_CSS_LOADED (inclua apenas o CSS se a constante não estiver definida).

Ambos os seus métodos são mais lentos do que seguir este caminho.

Para arquivos JS, você pode fazer o mesmo se o script que estiver carregando for único e não tiver dependências externas. Se este não for o caso, carregue-o dentro do rodapé, mas use a constante para determinar se precisa ser carregado ou não ...

    
por onetrickpony 23.06.2011 / 17:22
fonte
0

Script Logic é um plugin do WordPress que lhe dá controle total sobre todos os arquivos JavaScript e CSS. Usando este plug-in, você pode carregar condicionalmente arquivos CSS e JS somente em páginas onde for necessário.

enlace

    
por Tahir Yasin 17.06.2014 / 09:44
fonte