Author: Peter Knight

Adding Drag And Drop Support To wp_editor / TinyMce Part 1

Since WordPress 3.3 a nice new drag and drop uploader was included. It works great because it has fallbacks for older browsers that don’t support the newer HTML5 api. Accessing the file uploader still requires bringing up the media uploader via the upload button. Wouldn’t it be even nicer if we could directly drag and drop our files into our WYSIWYG editor?

The newish wp_editor function also makes it easy to include additional tinymce editors for our plugins and themes. I was looking for a way to add the tinymce editor to P2 and include a quicker way to drag and drop files. Adding the editor is relatively easy now but and it even lets you add the media upload button to the front end, but I want to remove the need for clicking that button.

Possible solutions:

My first thought was to insert the new native uploader inline below the editor so that we could directly drop files into a dropzone without having to navigate to the media uploader. I’m sure it can be done, but it was going to take me too long to do it properly and cleanly.

My second idea was to look for existing plugins that could do all the work, but there don’t seem to be any functional ones in existence that are straightforward to implement and integrate. It also seems a bit overkill to include another uploader when WordPress already can do everything I need.

After that I thought about digging into the filereader api for HTML5 and making my own solution…but then I thought of a shortcut that would be the best of all worlds.

Providing you have the upload buttons enabled for your editor, it’s possible to detect a drag event when a file is being dragged into the editor and automatically fire the native media uploader.

The great thing about this is:

  1. It streamlines the uploading process without adding loading scripts unnecessarily.
  2. It removes one mouse click operation and feels more intuitive than navigating to the uploader manually.
  3. It relies on the native uploader which deals with all the complex stuff, such as fallbacks, inserting the file into the post, setting parameters, attaching the file to the post and so forth. No reinventing the wheel!
  4. It removes the need for a separate ‘drop zone’, which takes up space. Instead, the editor itself is the drop zone.

Implementation:

All we need is a few lines of javascript. What is needed:

– A way of detecting when a file is dragged into our editor that works across all modern browsers

– The id attribute of our editor

– A trigger event to activate the native uploader when a file drag (or drop) is detected. For this we need to know how to select the media upload button with a selector.

optional:

some extra magic to add some css styling during the drag and drop operation.

Part 2 will cover the actual code…which I haven’t written up yet. Want to see the final solution? Sign up to the newsletter and you’ll get a notification when it is published.

Access The Main Post ID Anywhere based on the Current WordPress Page

There’s a number of ways to retrieve the post id of a post, but what if your page has multiple loops and you want to retrieve the main post id of the page? In my case I wanted to insert social buttons only on the main content of the page. If you are using the_content filter to add the html for your social buttons, it will show every time any kind of post content is displayed. Some page designs often use several loops to display various pieces of content (especially front pages), so you could end up with an abundance of social buttons – not exactly ideal. My solution then involved checking to see if the currently outputted content was the main content of the page by comparing post ids.

So I looked to see if there was a simple way to access the main post id – even if we are inside a secondary loop. Surprisingly, there doesn’t really seem to be a function for this. The closest thing is a function called get_page_by_path, but that works just for pages. Another idea is to access the $wp_query global variable, but this can be altered when other queries are made. What we can do is store the ID in our global variable when we are certain that $wp_query contains the main post id.

[php]
function main_post_id() {
global $wp_query;
global $main_post_id;
if( is_singular () ) { // ignores index pages for posts, categories, tags, archives etc
$main_post_id = $wp_query->post->ID;
}
}
add_action( ‘wp_head’,’main_post_id’ );
[/php]

Now we can quickly access the post id anywhere on the page, even if you are in a custom loop.

[php]
ID ) {
// do stuff
}
?>
[/php]

Loading CSS mid-page, HTML5, WordPress & Passing Validation Part 2

With HTML5 it’s possible to declare CSS stylesheet inside the body tag. This gives WordPress developers a better solution for including CSS on the fly, such as via a shortcode. It instantly makes several workarounds redundant. The native WordPress function wp_enqueue_style can now be called mid-page, which will print a stylesheet in the footer. Two disadvantages arise from this method and here is an alternative solution that solves it.

In part 1 we learned that

<link>

elements inside the body tag don’t validate at the moment. While browsers handle them just fine, it’s always nice to pass validation without errors. An alternative to this was to alter the output and use the style tag with the new scoped attribute instead. Then, the code will show up valid like:

<style scoped>@import url(stylesheet.css); </style>

The second disadvantage is that our CSS now loads at the end of the page, after the content we want to style. This may cause some styling issues during pageload. Since we can load the CSS anywhere inside the body tag, there is no real reason why it needs to be printed in the footer. If we do that, we also limit the styling issues on pageload.

We can write a function that prints the stylesheet declaration immediately. Let’s say you have a shortcode that inserts a slider, your shortcode would include a special function that prints the CSS before the rest of the slider output. The easy way would be simply to write a function that outputs the required html directly and this is what many developers tend to do. WordPress has specific ways of dealing with styles and scripts to help reduce conflicts and redundancies, so it is important we take advantage of that. So what we are going to do is tap into the API WordPress uses.

The first step is to register your CSS stylesheet with wp_register_style by wrapping it into a function and loading it into the wp_enqueue_scripts hook. Here is an example where we are including the Media Element Player.
<pre>
function register_mediaelementjs() {
wp_register_script( ‘mediaelementjs’, get_bloginfo(‘template_url’).’/inc/mediaelementjs/mediaelement-and-player.js’, array(‘jquery’), ‘2.6.3’, true );
wp_register_style( ‘mediaelementjs’, get_bloginfo(‘template_url’).’/inc/mediaelementjs/mediaelementplayer.css’ );
}
add_action( ‘wp_enqueue_scripts’ , ‘register_mediaelementjs’ );

Next we want to make a function that runs through the styles API. In other words, we want to check if our style has been registered (this is important because a user might decide to deregister your style) and hasn’t been printed already. We also have to make sure that WP knows we printed the style to avoid duplication.

function print_inline_stylesheet( $handle ) {
	// continue only if the style has been registered and hasn't been printed yet. 
	if ( wp_style_is( $handle, 'registered') && ! wp_style_is( $handle, 'done' ) ) {
		// gain access the wp_styles object 
		global $wp_styles;
		// make sure the style is formatted with html 5 markup
		add_filter( 'style_loader_tag', 'html5_inline_stylesheet', 10, 2 );
		$print = $wp_styles->do_item( $handle );
		// set this style to 'done' status
		$wp_styles->done[] = $handle;
		// remove from to do just in case the style was invoked elsewhere for the footer.
		$to_do = $wp_styles ->to_do;
		if ( is_array( $to_do ) ) {
			foreach( $to_do as $key => $to_do_handle ) {
				if( $to_do_handle == $handle ) {
					unset( $wp_styles->to_do[$key] );
				}
			}
		}
	}	
}

If you are outputting functionality via a shortcode you will want to call print_inline_stylesheet before your output. The handle argument needs to be passed to it and coincide with the handle you passed to register_style for your stylesheet. All that is left here is our function for modifying the standard WordPress output.

function html5_inline_stylesheet( $output ) {
	$url = preg_match("/(href=')(.+)(' type)/", $output, $styleurl);
	$output = '<style scoped>@import url('.$styleurl[2].');</style>';
	return $output;
}

Notes:
– I haven’t tested this with CSS stylesheet dependencies – the code may need some alterations for that.
– If you are including the functions in your project, remember to add a prefix unique to your theme or plugin in front of all the functions.
– I haven’t tested this is in all browsers, but from what I’ve researched this should work universally.
– HTML5 is still in a working draft, the scoped attribute hasn’t been set in stone – it’s possible things may change.
– To validate, you need to make sure the validator is set to HTML5.

If you have thoughts on improving this solution or the code, please leave some feedback below!

UPDATE 5/05/2013
For copy pasters, in the above example I used Media Element JS which is now shipped by default with WP 3.6+. While the example was for demonstration purposes, if you are using media element js, don’t enqueue your own version, load the one that ships with WP.

Loading Javascript and CSS mid-page, HTML5, WordPress & Passing Validation Part 1

Since WordPress version 3.3 it has been made a lot easier to load javascript and stylesheets mid-page.

Why would you want to do this in the first place?

Well a lot of plugins load their own CSS and Javascript files on the page and some of them do so at times when it’s not really necessary. As a plugin or theme developer if you are loading styles that only need to be loaded in certain cases (not on every single page), you want to avoid loading them when they are not needed.

If you’re not sure on which pages your scripts and styles will be needed, it presents a bit of a conundrum. This is a common problem for plugins that let a user add its functionality via a shortcode. Common examples are sliders, media players, galleries and forms.

The best way to load your scripts is to enqueue it with native functions WordPress provides. There are a number of advantages to this. For one, you can avoid scripts from being injected more than once, you can control where the script loads (in the head or in the footer) and it offers ways to deregister scripts and styles from loading altogether without resorting to hacks.

The problem with enqueueing used to be its inflexibility in relation to the load sequence of WordPress. Prior to WP 3.3 you had to enqueue your scripts and styles before the page content is constructed. While there were good methods for calling javascript mid-page and having it load in the footer, there were no palatable equivalents for loading CSS stylesheets. What you could do was:

1) Include the CSS on all pages
2) Rely on inline styles
3) Parse the page content for shortcodes before styles are enqueued and include your CSS with conditionals.
4) Use javascript to dynamically add your stylesheet to the head section
5) Set a postmeta field that is checked when a shortcode is added to a post and include a condition that loads your css if the postmeta field is present

Now it’s possible to enqueue scripts and styles mid-page through wp_enqueue_script() and wp_enqueue_style(), it will load your scripts and styles in the footer as a result.

By now you might be wondering, wait, can you have stylesheet links at the bottom of a page? Yes and no. Browsers are okay with this but validators are not. So while, in the wild it will work ok, your page isn’t going to validate.

But you’re theme is HTML5 you say? Good news, HTML5 is supposed to be fine with styles inside the body of the HTML…or is it? After some experimentation I found that my stylesheet reference in the footer was still bringing up validation errors for HTML5. The LINK element can’t be used for stylesheets in the BODY it seems…but you can use STYLE, in fact there is a new attribute on the horizon called “scoped” which will allow style declarations for certain sections of a page. It has virtually no browser support at present…but the code does validate according to HTML5 specs and the browser will recognize the style declarations itself. The trick then is to use the import statement to load your css file instead of using the LINK element, like so
[css]

[/css]
But how do we do this?

We could still use wp_enqueue_style and modify our output with a custom function. WordPress will output a LINK element by default but you can adjust the output by hooking into the ‘style_loader_tag’ filter.

[php]
function print_html5_style( $output ) {
// some regex to find the url to the stylesheet
$url = preg_match(“/(href=’)(.+)(‘ type)/”, $output, $styleurl);
// the new output based on a HTML5 valid

‘;
return $output;
}
[/php]
Because we only want to modify those CSS styles that are placed in the footer, we make our filter run conditionally.
[php]
function html5_style_filter (){
add_filter( ‘style_loader_tag’, ‘print_html5_style’, 10, 2 );
}
add_action( ‘wp_head’, ‘html5_style_filter’); // the wp_head hook runs after the header scripts are printed
[/php]

And voilá now we can load our CSS mid-page by calling wp_enqueue_style and get validating markup for our HTML5 page.

There’s just one disadvantage…

Because the CSS is loaded later in the page, the HTML you are wanting to style may not show proper styling straightaway, it has to wait for the CSS to load. But since we’re allowed to in HTML5 we might as well load our CSS right before we render the rest of our shortcode output. So let’s say you have a slider somewhere on your page, the STYLE element can be placed just before your slider is printed. That resolves a lot of the styling issues a visitor might see during pageload, because your CSS is loading much earlier.

How do we do this? We can’t rely solely on wp_enqueue_style because it just prints styles in the header or footer. We’ll need another custom function and we also want to make sure we retain all the benefits of enqueuing a style with wp_enqueue_style. This is covered in part 2.

Using CSS3 PIE with WordPress Plugins and Themes

UPDATE: I have posted an updated method for the latest version of PIE (v2)

CSS3 PIE is a fantastic tool to achieve support for CSS3 styles in versions of Internet Explorer, such as IE& and IE8. If you have been trying to include PIE with your WordPress project you might have had some problems with the way PIE is loaded. Below is an effective solution that works for plugins and themes without having to move “PIE.htc” into the root directory of a site and also without needing to dynamically insert the path to PIE using php in your CSS.

In our css, instead of using

[css]

behavior: url(PIE.htc);

[/css]

we use:

[css]

behavior: url(/?pie=true);

[/css]

If your website is located at http://yourwebsite.com/, the browser will look for the PIE file here http://yourwebsite.com/?pie=true, no matter what page you are on. What we need to do is make sure it retrieves the file based on that url. To do that we are going to add a Query variable for PIE and include a template redirect that checks to see if PIE is being called.

[php]

function css_pie ( $vars ) {

$vars[] = ‘pie’;

return $vars;

}

add_filter( ‘query_vars’ , ‘css_pie’); //WordPress will now interpret the PIE variable in the url

function load_pie() {

if ( get_query_var( ‘pie’ ) == “true” ) {

header( ‘Content-type: text/x-component’ );

wp_redirect( get_bloginfo(‘template_url’).’/inc/PIE.htc’ ); // adjust the url to where PIE.htc is located, in this example we are fetching in the themes includes directory

// Stop WordPress entirely since we just want PIE.htc

exit;

}

}

add_action( ‘template_redirect’, ‘load_pie’ );

[/php]

All you have to do is add the above functions in your functions.php or in your plugin file and adjust the path accordingly. If you are running into rendering issues in IE check with the other known issues documented on the CSS3 PIE site.

Updated 8 March 2012:

Changed example to use wp_redirect instead of an include statement.

How to truncate your WordPress RSS Feed at the More Tag

The More tag is a marker you can place in your WordPress posts that breaks up the post into two sections. It’s used to manually determine where the ‘read more’ link is placed when presenting a teaser of a post. WordPress doesn’t respect the More tag in RSS feeds by default, so if your rss feed is set to full or summary, it won’t break your posts as specified by the More tag. I have tried plugins that remedy this, but they fell short so I created my own function.
Read more

How To Query Multiple Custom Post Types with query_posts [WordPress Tip]

A very common WordPress function to modify the posts that are fetched on a page is called query_posts(). There are two ways to pass parameters to query_posts; you can pass an array or you can use the concatenated version. To display multiple post types on a page, the easiest way to do that is to pass parameters as an array argument to query_posts, like so:

$args = aray(
'post_type' => array ( 'post', 'page','event')
);
query_posts($args);

In some case you may want to use the concatenated version instead, for example because you are fetching posts using Ajax and are using GET variables. This is pretty straightforward if you are querying a single post type:

query_posts('post_type=event');

The question is, how do you query multiple post types? Looking at the WordPress codex, it doesn’t quite tell you how this works for post types. You could try similar examples for querying multiple category ids or tags, like this:

// like multiple category ids: doesn't work
query_posts('post_type=post,page,event');
// like multiple tags: also doesn't work
query_posts('post_type=post+page+event');

But you’ll quickly find neither of these examples work. I was about to give up and just use a serialized array for my use case, when I tried another simpler method for passing an array via a GET string:

query_posts('post_type[]=post&post_type[]=page&post_type[]=event');

Lo and behold, it works! In hindsight, this is a common way of passing arrays via a GET string, it just didn’t occur to me as an option because it wasn’t in the Codex.

If you have multiple post types on your WordPress site you can try it quickly by entering this as the url: ‘http://yoursite.com/?post_type[]=post&post_type[]=page’.

CSS Transition Problems with Display, Height 100% And Workarounds

CSS transitions are an exciting development in the world of web development, but it’s still a work in progress. I wanted to have a content block appear and hide on a hover event with pure CSS and a nice animation. My first thought was to animate the display property from display: hidden to display: block, but you can’t set a transition on the display property. In fact, if between the begin and end state there is a change in the display property, no transitions will work at all.

Looking for the next best thing, I decided to set a transition on the height property. Unfortunately that didn’t work as intuitively as it sounds either. If you have a content block with a variable height, you’ll want to use height 100% for the expanded state, but currently the CSS3 transitions don’t work with auto / height 100%, only with a fixed height.

Work Around

I needed my variable content blocks to fully display, so setting a fixed height was out of the question. A workaround to this is to set a transition on max-height instead and set the height to 100%. You need to set the max-height for both states (both need to be fixed) and on the expanded state you also set height: 100%. Now we have a working transition, as shown here: Demo

Quirk #2

I was happy to find the workaround, but in my case the transition still wasn’t working. I was driving myself nuts. The transition was expanding nicely, but not collapsing properly back to the begin state. The cause? I had set the height property on the collapsed state and this was causing the transitions to hiccup (at least in Chrome). Removing the height property on the first state solved the matter. See what makes the difference in another live example: Demo Comparison

Another limitation

The max-height trick works but it’s not always convenient. You will have a problem if your content is larger than the maximum height that has been set. If you set a very large max-height to prevent this, it messes with the transition timing and the transition behaves less reliable – it gets worse the larger the difference between the actual height and the max-height.

Showing and Hiding Content By Clicking A Menu Link (jQuery Tutorial)

While working on the user interface of the WordPress Plugin I’m building, I needed to have something akin to a drop down menu. A user clicks on a menu item, and a related list appears elsewhere on the page (in my case it’s a tool menu). To achieve this functionality I first looked at existing jQuery scripts and plugins and considered Superfish, which I was already using for the tab navigation. Using multiple instances of Superfish on the same page didn’t look as straightforward as it should be so I looked to build my own jQuery script, how hard could it be?

On my first attempt I worked with my limited jQuery knowledge and wrote a lot of code. It worked, it was logical but I knew I wasn’t being efficient. One of the most common mistakes for beginners to jQuery is to assign click handlers more generously than needed. My first attempt resulted in a lot of redundant code – I had assigned click handlers to every link in the menu.

Later I revisited my first attempt (which did work) and went about refactoring the code to get something more efficient. My secondary goal was to lose the need for Superfish on my other tab nagivation as well. My first step was to apply event delegation properly. Instead of assigning click handlers to each link in the menu, I assign a handler to the menu. There are a couple of functions to achieve that in jQuery, such as click(), bind(), live(), delegate() and on(). They all have their own merits and optimal use cases. On() seemed the most attractive to me for my interface, but since it has only recently been introduced in jQuery 1.7 I’m using delegate() in my plugin since the current WordPress ships with an older version*. I’ll show how it works for both, since the difference is minimal.
* WordPress 3.3 will come with jQuery 1.7

with delegate():
[javascript]
$(“#divtoggle”).delegate(“a”,”click”, function(e) {
// do stuff
});
[/javascript]
with on():
[javascript]
$(“#divtoggle”).on(“click”, “a”, function(e) {
// do stuff
});
[/javascript]

#divtoggle is the id assigned to the menu containing the links. In my case, the menu with the links are separate from the content I want to show on a mouse click. I have the content in a separate div lower on the page, hence giving the menu the id of divtoggle. As a sidenote, you might be wondering why I´m using ID attributes. On my first attempt, I gave my elements classes to make it easy to target them with CSS styling and jQuery. If you have an element you need to specifically identify with jQuery/Javascript, it´s more efficient to select it based on an ID compared to a class name. The ID attribute is meant to be a unique identifier, which means there will be only one element on the page with that specific ID. If you have to search through a document looking for an ID, you can stop as soon you found it, if you´re looking for an element with a certain class, you have to go through the entire document because there may be multiple elements with that class name.

Here is example HTML markup of the scenario.:

[html]

This is the content inside the first container

This is the content inside the second container

This is the content inside the third container

[/html]

The links also have unique ID’s as this will give me a way of linking the id to the container.
[html]show div 1[/html]

What we want to have happen is to recognize when a link inside the menu was clicked and then ascertain what link it was. We can grab the id of the link that was pressed and then use it to identify what container to show. We can use the prop() function to get the ID properity of the link.

[javascript]
$(“#divtoggle”).delegate(“a”,”click”, function(e) {
// get the ID of the clicked link
var toggled = ($(this).prop(“id”));
});
[/javascript]

Now we know what link has been clicked there are a number of ways to set the visibility of our div content. In this scenario, I wanted to have only one of the three containers displaying at the same time. On my first attempt, I was assigning a css class directly to the div containers that toggled their visibility. I found this a little laborious, as you have to assign and remove classes for each of the relevant div containers. On my second attempt, I decided to simply set a class for the parent container, which in the example is the div with the ID ‘wrap’. In the CSS, we can then set the visibility of the div containers based on the class of the parent container.

[css]
// hide menu related content by default
#div1, #div2, #div3 {
display:none;
}
// display content related to menu item
.togglediv1 #div1, .togglediv2 #div2, .togglediv3 #div3 {
display:block;
}
[/css]

Now in our jQuery, we assign a class to the parent div container based on the link that was pressed.

[javascript]
$(“#divtoggle”).delegate(“a”,”click”, function(e) {
// get the ID of the clicked link
var toggled = ($(this).prop(“id”));
// assign the value of the link id as a class to the parent container
$(“div#wrap”).prop(“class”, toggled);
});
[/javascript]

Basically this is what happens when you click the first link in the menu:

1) menu link was clicked
2) the link had the id ‘togglediv1’
3) the class of ‘togglediv1’ was set to the ‘div#wrap’ element, which automatically makes the appropriate div content display because of our CSS rules.

Check the DEMO on jsfiddle.net.