MonthMarch 2008

How to load JavaScript in WordPress plugins

If you want to load some JavaScript files from your WordPress plugin you have at least two options.

Head hooks

When building up a page, just before the closing tag of the head element, a theme should call actions hooked on wp-head. Those actions only need to output what they want to include into the head element, like script files.

What if a theme does not do that? Well, I’d include it into the so called “known issues”. For example, my last WordPress plugin, won’t work in this case. I think it’s better not to find a workaround, so that theme authors understand that they must follow WordPress standards.

On the other hand, there is also an admin-head hook, which is the wp-head hook counterpart when building up admin pages. For example, you could use the following function.

<?php

function load_into_head() { 
	$ADMIN_VIEW = "alert( 'Hello Admin!' );";
	$USERS_VIEW = "alert( 'Hello World!' );";
	?>
<script type="text/javascript">
	<?php
		if( is_admin() ) { echo $ADMIN_VIEW; }
		else             { echo $USERS_VIEW; } 
	?>
</script>
	<?php 
}

add_action( is_admin() ? 'admin_head' : 'wp_head', 'load_into_head' );

?>

Script API

WordPress provides also a good Script API that will let you do anything you want with script files, following WordPress standards. These are the main functions:

  1. wp_deregister_script
  2. wp_register_script
  3. wp_enqueue_script
  4. wp_print_scripts (action hook)
  5. print_scripts_array (filter hook)

The general idea is that you write a function for loading your scripts using wp_deregister_script, wp_register_script, and wp_enqueue_script, and hook it on wp_print_scripts. If you also need to fine tune the order in which files are loaded or if they have to be loaded at all, then you can write another function and hook it on print_scripts_array.

deregister, register, and enqueue

wp_register_script let’s you create an alias and define dependencies for each script file. If a script file with the same alias was already registered, then your registration is ignored. This is a policy for conflict resolution (the first registration wins) that may help you, if you know it.

wp_deregister_script let’s you remove an alias. If the alias you give doesn’t exist, nothing happens. Tipically you use this function for forcing a new registration of an already registered alias: first you deregister and then register again.

wp_enqueue_script prepares the loading of a script. If the script was registered with some dependencies, this function automatically prepares their loading too, recursively, making sure each script will be loaded only once and before any script depending on it.

For example, jQuery 1.2.3 is registered by WordPress 2.5, but let’s say that you want to always download the latest version. You could use the following function.

<?php

function load_with_api() {
	wp_deregister_script( 'jquery' );
	wp_register_script( 'jquery', 'http://code.jquery.com/jquery-latest.pack.js', false, '' );

	//keep jQuery and Prototype compatible
	$url = get_bloginfo('wpurl').'/wp-content/plugins/my-plugin';
	wp_register_script( 'jquery_no_conflict', $url . '/jquery_no_conflict.js', array( 'jquery' ), '' );	
	wp_enqueue_script( 'jquery_no_conflict' );
}

add_action( 'wp_print_scripts', 'myOwnTheme_init' );

?>

Keeping jQuery and Prototype compatible is a needed functionality, because WordPress uses both and they both use $ as a global symbol. In fact, the jQuery file packed with WordPress includes the compatibility setting.

Fine tuning

If you want your scripts to be loaded in a particular order, with one script before or after another, maybe with respect to one that was registered by WordPress itself, or by other plugins, then you can write a function for the print_scripts_array filter.

For example, to load the jquery_no_conflict file just after the jquery file, you can use the following function.

<?php

function jquery_no_conflict_follows_jquery( $js_array ) {
	if ( false === $jquery = array_search( 'jquery', $js_array ) )
		return $js_array;

	if ( false === $jquery_no_conflict = array_search( 'jquery_no_conflict', $js_array ) )
		return $js_array;

	if ( $jquery_no_conflict == $jquery + 1 )
		return $js_array;

	array_splice( $js_array, $jquery + 1, 0, 'jquery_no_conflict' );

	unset($js_array[$jquery_no_conflict + ($jquery_no_conflict < $jquery ? 0 : 1)]);

	return $js_array;
}

add_filter( 'print_scripts_array', 'jquery_no_conflict_follows_jquery' );

?>

My Own Theme

If you want to see all this in action, you can install the My Own Theme plugin.

How to force jQuery.extend deep recursion

jQuery.extend extends a target object with properties from other objects and it’s widely used in every piece of jQuery code.

Really it’s very useful and simple to undestand and use for flat properties.

jQuery.extend( 
  { a:1, b:'2' }, 
  { a:'1', c:3 } 
) == 
  { a:'1', b:'2', c:3 }

On the contrary, if the involved objects have object properties, jQuery.extend is less intuitive and less useful too.

jQuery.extend( 
  { a:{ x:1 }, b:'2' }, 
  { a:{ y:'1' }, c:3 } 
) == 
  { a:{ y:'1' }, b:'2', c:3 }

Luckily, an undocumented feature (deep) makes jQuery.extend recurr object properties.

jQuery.extend( true, 
  { a:{ x:1 }, b:'2' }, 
  { a:{ y:'1' }, c:3 } 
) == 
  { a:{ x:1, y:'1' }, b:'2', c:3 }

Unluckily, deep only works for the first level. (not really a ‘bug’)

jQuery.extend( true, 
  { a:{ x:1, z:{ m: '' } }, b:'2' }, 
  { a:{ y:'1', z:{ n: 0 } }, c:3 } 
) == 
  { a:{ x:1, y:'1', z:{ n:0 } }, b:'2', c:3 }

If you need deep recursion use jQuery.extend_deep instead.

jQuery.extend_deep( true, 
  { a:{ x:1, z:{ m: '' } }, b:'2' }, 
  { a:{ y:'1', z:{ n: 0 } }, c:3 } 
) == 
  { a:{ x:1, y:'1', z:{ m:'', n:0 } }, b:'2', c:3 }

Here is the jQuery.extend_deep plugin:

/**
 * Implement deep object extension 
 * by replacing the line 599 of jQuery-1.2.3.js
 * (commented out in this function)
 */
jQuery.extend_deep = function() {
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	if ( target.constructor == Boolean ) {
		deep = target;
		target = arguments[1] || {};
		i = 2;
	}

	if ( typeof target != "object" && typeof target != "function" )
		target = {};

	if ( length == 1 ) {
		target = this;
		i = 0;
	}

	for ( ; i < length; i++ )
		if ( (options = arguments[ i ]) != null )
			for ( var name in options ) {
				if ( target === options[ name ] )
					continue;

				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
//					target[ name ] = jQuery.extend( target[ name ], options[ name ] );
					target[ name ] = jQuery.extend_deep( true, target[ name ], options[ name ] );

				else if ( options[ name ] != undefined )
					target[ name ] = options[ name ];

			}

	return target;
};

Metaobjects 1.5 Released

Changes
  • Added support for easy namespacing
  • Added support for jQuery 1.2.3 cache
  • Rewritten the manual from scratch
Download

You can download metaobjects from Google Code

How to highlight code in WordPress

WordPress Editing Tabs

Although it’s easy to use WP Chili out of the box, WordPress does have some limitations, like the following:

  • you need to change to the Code editor before adding a snippet to your post
  • you need to make your snippet postable yourself, escaping all HTML entities
  • even if snippets are very short, they are intermingled with their explanations and it’s tricky to concentrate on writing the best post with so many distractions in between

Using WP Chili & Enzymes

Now I’ll show you a better approach by using together WP Chili 1.0 and Enzymes 2.2.
All you need to be up and running is the classical roundtrip: download, unzip, upload, and activate.

How to highlight code snippets

You can start by writing a simple enzyme for automating things, like the following hilite custom field:

return 
'<pre><code class="' . $this->substrate . '">'
. htmlspecialchars( $this->pathway ) 
. '</code></pre>';

hilite can be used with the following patterns:

  1. {[ =snippet= | .hilite( =language= ) ]}
  2. {[ .snippet | .hilite( =language= ) ]}

The first pattern comes in handy when you want to highlight some very short and naive snippet
{[ =echo htmlentities( $name );= | .hilite( =php= ) ]} renders

echo htmlentities( $name );

So far, so good, but if the snippet has a character that WP texturizes, then hilite seems to fail. In fact
{[ =$welcome = “Hello “.$name;= | .hilite( =php= ) ]} renders {[ =$welcome = “Hello “.$name;= | .hilite( =php= ) ]}

The above issue is not a hilite‘s bug but it could be fixed by adding new code to it, or with new enzymes along the pathway, like the following requote custom field:

$from = array( '&#8216;', '&#8217;', '&#8220;', '&#8221;' );
$to = array( "'", "'", '"', '"' );
return str_replace( $from, $to, $this->pathway );

which makes that
{[ =$welcome = “Hello “.$name;= | .requote() | .hilite( =php= ) ]}
renders {[ =$welcome = “Hello “.$name;= | .requote() | .hilite( =php= ) ]}

The best option is to add another custom field for hosting your snippet and use the second pattern: in fact hilite‘s snippet has been rendered by {[ .hilite | .hilite( =php= ) ]} and requote‘s one by {[ .requote | .hilite( =php= ) ]}.

How to highlight code files

Sometimes you have a file that you want to show in its entirety, and having to copy it into a custom field is annoying or maybe not an option, if the file is alive, for example.

In such cases you can use an enzyme like the following file custom field:

return file_get_contents( $this->substrate );

It’s use is again very simple and very similar to the above patterns:
{[ .file( =blog/wp-content/plugins/hello.php= ) | .hilite( =php= ) ]} renders

WP Chili Released

A couple of days ago I released WP Chili, a simple WordPress plugin that installs Chili into WordPress and let’s you add client-side code highlighting to your posts, with extreme simplicity.

After activating WP Chili, it’s just a matter of wrapping your snippets into code or pre-code elements, with the programming language of the snippet as a class, like in the following example:

<pre><code class="php">
echo &quot;Hello $name&quot;;
</code></pre>

When the post reaches your readers, the snippet is unescaped by their browser and highlighted by Chili 1.9 (downloaded from your server). Your readers will see the example rendered as:

echo "Hello $name";

© 2017 Notes Log

Theme by Anders NorenUp ↑