{"id":970,"date":"2015-01-16T23:38:52","date_gmt":"2020-02-18T06:53:26","guid":{"rendered":"https:\/\/redfrontdoor.org\/blg2\/?p=970"},"modified":"2020-02-19T16:18:24","modified_gmt":"2020-02-19T16:18:24","slug":"post-964","status":"publish","type":"post","link":"https:\/\/redfrontdoor.org\/blog\/?p=970","title":{"rendered":"Post-specific Javascript and CSS in WordPress"},"content":{"rendered":"<p>A couple of recent posts here \u2014<\/p>\n<ul>\n<li><a title=\"An oscillator from a jam-jar lid\" href=\"\/blog\/?p=546\">An oscillator from a jam-jar lid<\/a><\/li>\n<li><a title=\"The value of a second opinion\" href=\"\/blog\/?p=925\">The value of a second opinion<\/a><\/li>\n<\/ul>\n<p>\u2014 required some post-specific Javascript and CSS styling. It took me a little while to figure out how to achieve this, given my limited exposure to PHP in general and WordPress programming in particular. This is how I went about it; there may well be better ways.<\/p>\n<h2>Start writing post<\/h2>\n<p>At this point your draft is assigned a post-ID. This is the value at the end of the post&#8217;s URL. For example, this post has URL<\/p>\n<pre>https:\/\/redfrontdoor.org\/blog\/?p=970<\/pre>\n<p>and its post-ID is 970.<\/p>\n<h2>Write post-specific Javascript<\/h2>\n<p>Make a self-contained Javascript file, wrapping the logic in<\/p>\n<pre>jQuery(document).ready(function($) {\n  \/\/ [... code goes here ...]\n});\n<\/pre>\n<p>A reasonable location for this file within your WordPress installation is a &#8216;<code>js<\/code>&#8216; subdirectory of the theme directory. In my case, this is<\/p>\n<pre><em>[WP root]<\/em>\/wp-content\/themes\/donovan\/js\/<em>filename<\/em>.js\n<\/pre>\n<p>where I choose <code><em>filename<\/em><\/code> to represent the title of the post.<\/p>\n<h2>Write post-specific PHP functions<\/h2>\n<p>Using WordPress&#8217;s <tt><a href=\"http:\/\/codex.wordpress.org\/Function_Reference\/wp_enqueue_script\">wp_enqueue_script<\/a><\/tt> and <tt><a href=\"http:\/\/codex.wordpress.org\/Function_Reference\/wp_enqueue_style\">wp_enqueue_style<\/a><\/tt> functions, write a function for the post which enqueues the required JS or CSS. For example, the jam-jar-lid oscillator depends on jQuery, and so required:<\/p>\n<pre>function bn_js_for_546() {\n    wp_enqueue_script(\n        'jam-jar-lid-oscillator',\n        get_template_directory_uri()\n          . '\/js\/jam-jar-lid-oscillator.js',\n        array('jquery'));\n}\n<\/pre>\n<p>This is inserted at the end of the theme&#8217;s <code>functions.php<\/code> file. The PHP for post 925 is more involved and enqueues the &#8216;slider&#8217; jQuery-UI component and its styling, the D3 library, and my own custom Javascript and CSS. (Without the styling, the Javascript correctly turns the element into a slider, but it is not rendered. Here I downloaded a copy of the CSS files into the WordPress directory, but see also <a href=\"http:\/\/snippets.webaware.com.au\/snippets\/load-a-nice-jquery-ui-theme-in-wordpress\/\">this post by Ross McKay<\/a>.) The result is<\/p>\n<pre>function bn_js_for_925() {\n    wp_register_script(\n        'd3',\n        'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/d3\/3.5.2\/d3.min.js',\n        false, null);\n    wp_enqueue_script(\n        'interactive-graphs',\n        get_template_directory_uri()\n          . '\/js\/interactive-graphs.js',\n        array('jquery', 'jquery-ui-slider', 'd3'));\n    wp_enqueue_style(\n        'post-925-css',\n        get_template_directory_uri()\n          . '\/js\/second-opinion.css',\n        false, null);\n    wp_enqueue_style(\n        'jquery-ui-theme',\n        get_template_directory_uri()\n          . '\/css\/jquery-ui-themes-1.10.4'\n          . '\/themes\/smoothness\/jquery-ui.css',\n        false, null);\n}\n<\/pre>\n<p>Excuse the fudge of putting the post-specific CSS into the &#8216;<code>js<\/code>&#8216; directory.<\/p>\n<h2>Write PHP to hook the post-specific function<\/h2>\n<p>A dispatching PHP function checks whether this post requires custom JS or CSS and adds the appropriate function as an &#8216;<code>wp_enqueue_scripts<\/code>&#8216; action if so. The test for requiring custom JS or CSS is whether a function named &#8216;<code>bn_js_for_<em>NNN<\/em><\/code>&#8216; exists, where <code><em>NNN<\/em><\/code> is the post-ID. This is not especially elegant, but it avoids repeating myself, and this is PHP so there&#8217;s no huge incentive to strive for elegance anyway.<\/p>\n<p>The code<\/p>\n<pre>function bn_maybe_enqueue_scripts()\n{\n    global $post;\n    $post_ID = $post-&gt;ID;\n    $post_js_fun_name = 'bn_js_for_' . $post_ID;\n    if (function_exists($post_js_fun_name))\n        add_action('wp_enqueue_scripts', $post_js_fun_name);\n}\n<\/pre>\n<p>does what we need.<\/p>\n<h2>Add hook function where post-ID is available<\/h2>\n<p>I did not reach a full understanding of the details, it seems that you can add functions to be called by WordPress at various stages of its rendering of your post. According to <a href=\"http:\/\/code.hyperspatial.com\/1656\/get-post-id-and-enqueue-scripts\/\">a blog post on HyperSpatial<\/a>, the &#8216;<code>wp<\/code>&#8216; action is suitable for this. The final step, then, is to hook our <code>bn_maybe_enqueue_scripts<\/code> function into the &#8216;<code>wp<\/code>&#8216; action.<\/p>\n<p>Adding<\/p>\n<pre>add_action('wp', 'bn_maybe_enqueue_scripts');\n<\/pre>\n<p>to the end of <code>functions.php<\/code> completes the process.<\/p>\n<h2>Conclusions<\/h2>\n<p>This approach requires shell access to the host, is quite clunky, and does not scale well. Nonetheless for my purposes it does the job.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A couple of recent posts here \u2014 An oscillator from a jam-jar lid The value of a second opinion \u2014 required some post-specific Javascript and CSS styling. It took me a little while to figure out how to achieve this, given my limited exposure to PHP in general and WordPress programming in particular. This is how I went about it; there may well be better ways. Start writing post At this point your draft is assigned a post-ID. This is the value at the end of the post&#8217;s URL. For example, this post has URL https:\/\/redfrontdoor.org\/blog\/?p=970 and its post-ID is 970. Write post-specific Javascript Make a self-contained Javascript file, wrapping the logic in jQuery(document).ready(function($) { \/\/ [&#8230; code goes here<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-970","post","type-post","status-publish","format-standard","hentry","category-uncategorized","comments-off"],"_links":{"self":[{"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/970","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=970"}],"version-history":[{"count":4,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/970\/revisions"}],"predecessor-version":[{"id":3769,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/970\/revisions\/3769"}],"wp:attachment":[{"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=970"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/redfrontdoor.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}