LESS Compiler for WordPress

It uses the Less.php Compiler.

Installation

  1. Download the latest release
  2. Unzip it into your wp-content/plugins directory
  3. Activate the plugin in WordPress

Compiler

This first page allows you to write and compile LESS. The resulting stylesheet is automatically enqueued.

Compiler page

Variables

This second page lists all registered variables, and allows you to edit their values upon compiling.

Variables Page after configuration

PHP Configuration

add_filter( 'less_configuration', 'my_less_config' );
function my_less_config( $config ) {
  $my_variables = array( 'less/variables.less' );
  $my_imports = array(
    'less/bootstrap.less',
    'less/theme.less'
  );
  return array_merge_recursive( $config, array(
    'variables' => $my_variables,
    'imports'   => $my_imports
  ) );
}

Configuration of the plugin is optional, but you should at least register your variables if you are using a CSS framework.

Paths to LESS files are relative to the theme directory.

Use the filter 'less_configuration' to return your configurations array.

  • variables(array)
    In order to list and edit your LESS variables on the plugin dedicated page, it is necessary to register their “definition” file(s). It is assumed that those files’ only role is to declare variables and their values.
  • imports(array)
    It will prepend the code to compile with an @import directive for each listed file. Useful to compile dependencies, and to “hide” them from the Compiler page. It is necessary to hit the “Compile” button once for these imports to be compiled.
  • cache(string)
    Allows you to define the path to your cache directory. This directory has to be writable (0755). The default cache directory path is wp-content/cache.
  • search(boolean)
    Wether or not to display the “Search Variables” filter box. It can come handy if you have a lot of variables. Default is true.

Once registered, you can access any variables with the function less_get( 'my-variable' );, or override its value (upon what has been set on the Variables page) with less_set( 'my-variable', 'my-value' ).

It is also possible to use @import directives, as well as any LESS language features, straight from the Compiler page.

Enqueuing external LESS

Out of the main stylesheet, simply use the WordPress wp_enqueue_style function to enqueue separated LESS files.

add_action( 'wp_enqueue_scripts', 'my_other_less_enqueue' );
function my_other_less_enqueue() {
  wp_enqueue_style( 'my-other-handle', get_template_directory_uri() . '/my-other-file.less', array( 'wm-less' ) );
}

It will be compared to the cached version, compiled if changes occurred, and the resulting stylesheet will be enqueued.
Don’t forget to set the main LESS stylesheet handle 'wm-less' as a dependency (… if it is one).

Floating Labels for Bootstrap 3

As I’m working quite a lot with Bootstrap these days, I wrote a jQuery plugin to apply a “floating” effect on the framework’s horizontal forms labels.

Plugin

The jQuery plugin is very simple. Here is the full code.

(function ($) {
  'use strict';
  $.fn.bsPeekabooLabel = function () {
    var input = $(this),
      control = input.closest('[class*="col-"]'),
      label = control.siblings('.control-label'),
      show = false,
      place = function (d) {
        var m;
        if ($(control).css('float') === 'left') {
          m = '0 0 0 ' + label.outerWidth() + 'px';
          label.animate({ margin: show ? 0 : m, opacity: show ? 1 : 0 }, d);
          control.animate({ margin: m }, d);
        } else {
          label.animate({ margin: 0, opacity: 1 }, d);
          control.animate({ margin: show ? label.outerHeight() + 'px 0 0' : 0 }, d);
        }
      };
    label.css({ position: 'absolute' });
    place(0);
    input.keyup(function () {
      if (show === !input.val()) {
        show = !show;
        place(400);
      }
    });
    $(window).resize(function () { place(0); });
  };
}(jQuery));

How To Use

First, make sure your horizontal form respects Bootstrap’s HTML structure, and that your inputs have a placeholder attribute. Then, target each input you want to apply the effect to.

$('.form-control[placeholder]', '.form-horizontal').each(function () {
  $(this).bsPeekabooLabel();
});

WordPress Settings Framework for Options Pages

Settings are really useful to provide an easy configuration of themes and plugins to our users within their administration panel. But the creation of options pages often ends up in a messy and repetitive use of the great WordPress Settings API.

The option page generated with our really basic example.

Considering generic form fields, I wrote a class to clean and simplify the process. It’s something light that shall be used on the admin side.
https://github.com/WebMaestroFr/wm-settings

Example

// Define the page
$my_page = create_settings_page(
  'my_page_id',
  __( 'My Page' ),
  array(
    'title' => __( 'My Menu' )
  ),
  array(
    'my_setting_id' => array(
      'title'       => __( 'My Setting' ),
      'description' => __( 'This is my section description.' ),
      'fields'      => array(
        'my_option_name' => array(
          'label'        => __( 'My Option' ),
          'description'  => __( 'This is my field description.' )
        )
      )
    )
  )
);
// Access the values
$my_value = get_setting( 'my_setting_id', 'my_option_name' );

Installation

  1. Download the last release
  2. Unzip it into your theme or plugin
  3. require_once( 'path/to/wm-settings/wm-settings.php' );

Documentation

Create an Options Page and its Menu

$page = create_settings_page( $page_id, $page_title, $menu, $fields, $args );

  1. $page_id(string) A unique identifier
  2. $page_title : (string) A title for your page
  3. $menu : (array) (Optional) An array of menu parameters. Set to false if you don’t want to display any page.
    • parent‘ : (string) The slug name for the parent menu. Use false to create a top level menu item.
      Default : ‘themes.php’
    • title‘ : (string) The text to be used for the menu.
      Default : value of $page_title
    • capability‘ : (string) The capability required for this menu to be displayed to the user.
      Default : ‘manage_options’
    • icon_url‘ : (string) (for top level menu item) The icon for this menu.
      Default : ‘dashicons-admin-generic’
    • position‘ : (integer) (for top level menu item) The position in the menu order this menu should appear.
      Default : bottom of menu structure
  4. $fields : (array) (Optional) An array of sections and fields (See Settings Sections and Options Fields).
  5. $args : (array) (Optional) An array of miscellaneous arguments.
    • tabs‘ : (boolean) Whether to display the different sections as “tabs” or not. There must be several sections, and they must have a title.
      Default : false
    • submit‘ : (string) Text of the submit button.
      Default : ‘Save Settings’
    • reset‘ : (string) Text of the reset button. Set to false to disable the reset button.
      Default : ‘Reset Settings’
    • description‘ : (string) Page description.
    • updated‘ : (string) Message of the success notice. Set to false to disable the notice.
      Default : ‘Settings saved.’
// A top level page
$my_top_page = create_settings_page(
  'my_top_level_page',
  __( 'My Top Level Page' ),
  array(
    'parent'   => false,
    'title'    => __( 'Top Level Menu' ),
    'icon_url' => 'dashicons-admin-generic',
    'position' => '63.3'
  ),
  array(
    'my_standard_section' => array(
      'title'  => __( 'Standard' ),
      'description' => __( 'My section description.' ),
      'fields' => array(
        'my_input'    => array(
          'label' => __( 'Input example' )
        ),
        'my_checkbox' => array(
          'type'  => 'checkbox',
          'label' => __( 'Checkbox example' )
        ),
        'my_textarea' => array(
          'type'  => 'textarea',
          'label' => __( 'Textarea example' )
        )
      )
    )
  ),
  array(
    'tabs'        => true,
    'submit'      => __( 'My Submit' ),
    'reset'       => __( 'My reset' ),
    'description' => __( 'My page description.' ),
    'updated'     => __( 'My success message !')
  )
);
// And a sub-page
$my_sub_page = create_settings_page(
  'my_sub_page',
  __( 'My Sub Page' ),
  array(
    'parent' => 'my_top_level_page',
    'title'  => __( 'Sub Level Menu' )
  )
);
Top level page after blank submit

Apply Settings Sections and Options Fields

$page->apply_settings( $settings );
Append sections and fields to a form, with an associative array where each setting is a section, and each option is a field. Each key of $settings defines a new setting id.

  • title‘ : (string) (Optional) Section title
  • description‘ : (string) (Optional) Section description
  • fields‘ : (array) (Optional) An array of options field declarations.
    Each key of this new array defines a new option name.

    • type‘ : (string) (Optional) Field type (checkbox, textarea, radio, select, multi, media, action, color or any valid HTML5 input type attribute).
      Default : ‘text’
    • label‘ : (string) (Optional) Field label. Use false to hide the label column on this field.
    • description‘ : (string) (Optional) Field description.
    • default‘ : (string) (Optional) Option’s default value.
    • sanitize‘ : (callback) (Optional) A function to apply in place of the default sanitation of this field’s type. Receive the input value and the option name as parameters, and is expected to return a properly sanitised value.
    • attributes‘ : (array) (Optional) An array( 'my_attribute' => 'my_value', ... ) of HTML attributes. Useful for placeholder or pattern for instance.
    • options‘ : (array) (Optional) Only for radio, select and multi field types, an array( 'my_value' => __( 'My Label' ), ... ) of predefined values.
    • action‘ : (callback) (Optional) Only for action field type. Expect a response sent with either wp_send_json_success (success) or wp_send_json_error (failure), where $data (Optional) is either the message to display (string), or array( 'reload' => true ) if the page needs to reload on action’s success.
$my_top_page->apply_settings( array(
  'my_formatted_section' => array(
    'title'  => __( 'Formatted' ),
    'fields' => array(
      'my_email'  => array(
        'type'  => 'email',
        'label' => __( 'Email example' )
      ),
      'my_url'    => array(
        'type'  => 'url',
        'label' => __( 'URL example' )
      ),
      'my_number' => array(
        'type'  => 'number',
        'label' => __( 'Number example' )
      )
    )
  ),
  'my_multi_section'    => array(
    'title'  => __( 'Multiple Options' ),
    'fields' => array(
      'my_radio'  => array(
        'type'    => 'radio',
        'label'   => __( 'Radio example' ),
        'options' => array(
          'one'   => __( 'First option'),
          'two'   => __( 'Second option'),
          'three' => __( 'Third option')
        )
      ),
      'my_select' => array(
        'type'    => 'select',
        'label'   => __( 'Select example' ),
        'options' => array(
          'one'   => __( 'First option'),
          'two'   => __( 'Second option'),
          'three' => __( 'Third option')
        )
      ),
      'my_multi'  => array(
        'type'    => 'multi',
        'label'   => __( '"Multi" example' ),
        'options' => array(
          'one'   => __( 'First option'),
          'two'   => __( 'Second option'),
          'three' => __( 'Third option')
        )
      )
    )
  )
) );

Formatted and multiple fields, sections displayed as tabs

Apply settings anywhere, but in order to sanitise the data properly and to run the eventual callbacks, do it before ‘admin_init‘ is hooked.

$my_sub_page->apply_settings( array(
  'my_advanced_section' => array(
    'title'  => __( 'Advanced' ),
    'fields' => array(
      'my_media'  => array(
        'type'  => 'media',
        'label' => __( 'Media Example' )
      ),
      'my_color'  => array(
        'type'  => 'color',
        'label' => __( 'Color Example' )
      ),
      'my_action' => array(
        'type'        => 'action',
        'label'       => __( 'Action Example' ),
        'description' => __( 'Will call the PHP function "do_my_action" with AJAX.'),
        'action'      => 'do_my_action'
      )
    )
  ),
  'my_custom_section'   => array(
    'title'  => __( 'Custom' ),
    'fields' => array(
      'my_custom'   => array(
        'label'       => false,
        'description' => __( 'Will be sanitized through the PHP function "do_my_sanitation".'),
        'default'     => __( 'DEFAULT' ),
        'attributes'  => array(
          'style'   => 'font-family: "Comic Sans MS";',
          'pattern' => '[A-Z]*'
        ),
        'sanitize'    => 'do_my_sanitation'
      )
    )
  )
) );
function do_my_action() {
  // If error
  wp_send_json_error( __( 'Error !' ) );
  // If success
  wp_send_json_success( __( 'Success !' ) );
  // If the page needs to reload
  wp_send_json_success( array(
    'reload'  => true,
    'message' => __( 'This message is only displayed if "reload" => false.' )
  ) );
}
function do_my_sanitation( $input, $name ) {
  return sanitize_text_field( strtoupper( $input ) );
}
Advanced and Custom Fields

Get the values

Every setting is recorded as an array of options values. An easier way to get the data back, from anywhere in the code, is to use the function get_setting( $setting_id, $option_name );.

$my_attachment_id = get_setting( 'my_advanced_section', 'my_media' );
// ... is the same than :
$my_setting = get_option( 'my_advanced_section' );
$my_attachment_id = $my_setting['my_media'];

Callback after settings are updated

The class hooks actions tagged ‘(page_id)_settings_updated‘ when settings are updated.

add_action( 'my_top_level_page_settings_updated', 'do_my_page_callback' );
function do_my_page_callback() {
  // All settings of my_top_level_page have been updated.
}

You can also use the ‘update_option_(setting_id)WordPress action that will apply on every section update.

add_action( 'update_option_custom_fields_section', 'do_my_section_callback' );
function do_my_section_callback() {
  $my_custom_options = get_setting( 'my_custom_section' );
  // All options of custom_fields_section have been updated.
}

Custom notices

You can display custom notices on the options pages.

$my_page->add_notice( __( 'My info message.') );
$my_page->add_notice( __( 'My updated message.'), 'updated' );
$my_page->add_notice( __( 'My warning message.'), 'warning' );
$my_page->add_notice( __( 'My error message.'), 'error' );

Allowed types are info (default), updated, warning and error.

Custom notices

What do you think ?

I’ve been working on and using this with fun. Feel free to contact me for questions, feedback or suggestions. And you can find all of it, fork and contribute on GitHub. Peace out.

A jQuery Plugin to Fade In and Out with a Vertical Slide

JQuery’s .show() and .hide() effects are useful, but I’m not cool with their width resizing.
This plugin allows you to show and hide elements with a vertical slide and a fading effect.

You can use the .showDown(), .hideUp() and .verticalFade() functions the same way you would use jQuery’s .fadeIn(), .fadeOut() or .fadeToggle() effects.

$('#trigger-example').click(function () {
  $('#example').verticalFade({ duration: 'slow' });
});

https://gist.github.com/WebMaestroFr/9316374

Plugin

The jQuery plugin is very simple. Here is the full code.

(function ($) {
  var getUnqueuedOpts = function (opts) {
    return {
      queue: false,
      duration: opts.duration,
      easing: opts.easing
    };
  };
  $.fn.showDown = function (opts) {
    opts = opts || {};
    $(this).hide().slideDown(opts).animate({ opacity: 1 }, getUnqueuedOpts(opts));
  };
  $.fn.hideUp = function (opts) {
    opts = opts || {};
    $(this).show().slideUp(opts).animate({ opacity: 0 }, getUnqueuedOpts(opts));
  };
  $.fn.verticalFade = function (opts) {
    opts = opts || {};
    if ($(this).is(':visible')) {
      $(this).hideUp(opts);
    } else {
      $(this).showDown(opts);
    }
  };
}(jQuery));

A different Domain for each Language with qTranslate

Hey folks,

I like to use qTranslate for my multilingual websites. Today I had to set up a different language for each domain pointing on my WordPress installation. Here’s what was the simplest solution.

Multidomain qTranslate Settings

First, in your administration panel, in Settings > Languages, in Advanced Settings > URL Modification Mode, make sure you Use Pre-Path Mode.

Then, in your .htaccess (which shall be around your root directory), above the Rewrite Rules, redirect each one of those pre-paths to the wanted domain.

RedirectMatch 301 /fr/(.*) http://www.francais.fr/$1
RedirectMatch 301 /en/(.*) http://www.english.co.uk/$1

Too easy. Now in your theme’s functions.php file, configure qTranslate’s language settings according to the current domain. Let’s reset WordPress URLs as well, so it always link to the current domain.

define( 'WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] );
define( 'WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] );
$current_domain_lang = array_search( str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ), array(
'fr' => 'francais.fr',
'en' => 'english.co.uk'
) );
$q_config['language'] = $current_domain_lang;
$q_config['default_language'] = $current_domain_lang;

Should work like a charm… tell me if you notice an issue though.

Image Parallax Plugin for WordPress

Upload the layers of your image, and create a parallax effect !

It works great on smart devices too !

The first step is to create with your favorite picture editing software (Photoshop, GIMP…) an independent image for each ground composing your image. All these layers shall be the same size, and should be in .png format as they are meant to include transparency areas.

Then, on your post editing page in WordPress, click the Insert Media button, and (the same way you would create a gallery) upload your layers under the Create Parallax item. Reorganise the layers if needed, from the background to the front.
You can finally configure the animation (calibrate, invert, limit, scalar, friction), and publish !

Example WordPress Parallax

This plugin uses parallax.js by Matthew Wagerfield.