f w h

WordPress Development Environment Scripts

It is useful to have certain items or scripts available to you while developing that you may not want present in production. Forgetting to remove these items before you go to production can be dangerous.

When developing with WordPress, a short script in your functions.php can add these tools when you’re developing locally, but hide them when live.

Create your scripts in a separate file in the js directory of your theme. I called mine dev.js. Then, add the following to your functions.php file:


function add_dev_class( $classes ) {
 
    $classes[] = 'dev';
     
    return $classes;
     
}

function enqueue_dev(){

    wp_register_script( 'Dev', get_stylesheet_directory_uri() . '/js/dev.js', [ 'jquery' ], NULL, true );
    wp_enqueue_script( 'Dev' );

}

// Here comes the magic
if( $_SERVER[ 'SERVER_NAME' ] == "localhost" ){

    add_filter( 'body_class', 'add_dev_class' );
    add_action( 'wp_enqueue_scripts', 'enqueue_dev' );

}

The first function will add a class called “dev” to the body tag, so you can hook it with JavaScript or add development-centric CSS styles.

The second function will enqueque the dev.js script file.

Finally, the conditional at the end will check what the current base address is and if it matches, will execute the functions. I’ve used localhost here, but you can use whatever your development domain is.

I use this to load a variation of my viewport size bookmarklet that sits at the bottom of the window with a plethora of information to help inform my decisions when designing for responsiveness.

Mark Your Spot on a Page – Bookmarklet

Recently, I was trying to work my way through an HTML-based online book. It became a pain to find my spot again when I had to close the browser or reboot the computer for various reasons. So, I created a bookmarklet to help me find my spot again when I return to the page. The bookmarklet adds a small box in the upper right corner of the window with buttons to add or clear bookmarks. When you click the ADD button, you’ll be prompted to name the bookmark, which will then be added to the list. Bookmarks are stored in local storage, so they will persist from session to session. You’ll just have to click the bookmarklet again to reload them.

Go HERE to get the bookmarklet. Full code is below:


function bm_go(){

  var bm_block;

  bm_block = document.createElement('div');
  bm_block.classList.add('bm_class');
    bm_block.style.width = '100px';
    bm_block.style.minHeight = '33px';
    bm_block.style.position = 'fixed';
    bm_block.style.padding = '5px';
    bm_block.style.top = '10px';
    bm_block.style.right = '10px';
    bm_block.style.backgroundColor = 'white';
    bm_block.style.fontFamily = 'Arial, sans-serif';
    bm_block.style.color = 'black';
    bm_block.style.borderRadius = '5px';
    bm_block.style.border = '1px solid #999';
    bm_block.style.zIndex = '10000000';

  var bm_add_button = document.createElement('div');
  	bm_add_button.classList.add('bm_add_button');
    bm_add_button.style.display = 'inline-block';
    bm_add_button.style.height = '33px';
    bm_add_button.style.width = '45%';
    bm_add_button.style.border = '1px solid #999';
    bm_add_button.style.fontSize = '15px';
    bm_add_button.style.textAlign = 'center';
    bm_add_button.style.lineHeight = '33px';
    bm_add_button.style.cursor = 'pointer';
    bm_add_button.style.boxShadow = '2px 2px #666';
    bm_add_button.innerText = 'ADD';
  bm_block.appendChild(bm_add_button);

  var bm_clr_button = document.createElement('div');
  	bm_clr_button.classList.add('bm_clr_button');
    bm_clr_button.style.display = 'inline-block';
    bm_clr_button.style.height = '33px';
    bm_clr_button.style.width = '45%';
    bm_clr_button.style.border = '1px solid #999';
    bm_clr_button.style.fontSize = '15px';
    bm_clr_button.style.textAlign = 'center';
    bm_clr_button.style.lineHeight = '33px';
    bm_clr_button.style.cursor = 'pointer';
    bm_clr_button.style.boxShadow = '2px 2px #666';
    bm_clr_button.style.marginLeft = '5%';
    bm_clr_button.innerText = 'CLR';
  bm_block.appendChild(bm_clr_button);

  var bm_message = document.createElement('div');
  	bm_message.classList.add('bm_message');
    bm_message.style.marginTop = '5px';
    bm_message.style.marginBottom = '5px';
    bm_message.style.fontSize = '10px';
    bm_message.style.textAlign = 'center';
    bm_message.innerText = 'Click "ADD" to set bookmark at current scroll position.';
  bm_block.appendChild(bm_message);
    
  	document.body.appendChild(bm_block);
  
  var bm_list_init = JSON.parse(localStorage.getItem('bm_list')) || [];
   
  function bm_pop_list(list){
  	
    var rm_bm = document.querySelector('.bm_bm_list');
    if (rm_bm) rm_bm.parentNode.removeChild(rm_bm);
    
    var bm_bm_list = document.createElement('ul');
    bm_bm_list.classList.add('bm_bm_list');
    bm_bm_list.style.paddingLeft = '0';
    
    for (var i = 0; i < list.length; i++){

      var bm_list_item = document.createElement('li');
      bm_list_item.classList.add('bm_list_item');
      bm_list_item.innerText = list[i].name;
      bm_list_item.setAttribute('data-x', list[i].x);
      bm_list_item.setAttribute('data-y', list[i].y);
      bm_list_item.style.marginLeft = '0';
      bm_list_item.style.listStyleType = 'none';
      bm_list_item.style.cursor = 'pointer';

      bm_list_item.addEventListener('click', function(){

      	bm_go_to_location(bm_list_item);

      });

      bm_bm_list.appendChild(bm_list_item);

    }
    
    bm_block.appendChild(bm_bm_list);

  }
  
  bm_pop_list(bm_list_init);
  
  function bm_go_to_location(item){

  	window.scrollTo(item.getAttribute('data-x'), item.getAttribute('data-y'));

  }
  
  function bm_add_item(){

  	var bm_get_name = prompt('Enter Bookmark Name', 'bookmark'),
      	bm_get_x = window.pageXOffset,
        bm_get_y = window.pageYOffset;
    var bm_list = JSON.parse(localStorage.getItem('bm_list')) || [];

    bm_list.push({
    	name: bm_get_name,
      x: bm_get_x,
      y: bm_get_y
    });

    localStorage.setItem('bm_list', JSON.stringify(bm_list));
    bm_pop_list(bm_list);

  }
  
  function bm_clear(){

  	localStorage.removeItem('bm_list');
    bm_pop_list([]);

  }
  
  bm_add_button.addEventListener('click', bm_add_item);

  bm_clr_button.addEventListener('click', bm_clear);
  
}

var bm_ = new bm_go();

Display Viewport Size Bookmarklet

Chrome has a nice little overlay shows the viewport size when you resize if you have the developer tools open. For whatever reason, it stopped working on me for a short while. It was a bit frustrating, because of course it would decide not to work right when I needed it most.

So, why not recreate the magic?

Get the bookmarklet here

Original, uncompressed code below:


function vp_getViewport(){
  this.w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  this.h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

  this.output = {
    w: this.w,
    h: this.h
  };

  return this.output;
}
function vp_init(){
  var e = document.createElement('div');
  e.classList.add('vp_vpElement');
  e.style.backgroundColor = '#aaa';
  e.style.border = '1px solid black';
  e.style.padding = '2px';
  e.style.fontSize = '12px';
  e.style.position = 'fixed';
  e.style.top = '10px';
  e.style.right = '10px';
  e.style.zIndex = '1000000';
  document.body.appendChild(e);
}
vp_init();
function vp_showSize(viewport){
  var e = document.querySelector('.vp_vpElement');
  e.innerHTML = viewport.w + ' x ' + viewport.h;
}
window.addEventListener('load', function(){vp_showSize(vp_getViewport());});
window.addEventListener('resize', function(){vp_showSize(vp_getViewport());});

Simple Mobile Detection for JavaScript

One common question I see asks how one might conditionally run JavaScript based on screen size. There are a number of use cases for this, and there are a couple ways to go about it.
One easy way, as I wrote about almost exactly three years ago is to detect a CSS property based on a media query.
Another possibility is to use JavaScript to pull the size of the browser’s viewport. To make things easy, we can package everything in a neat little function that returns an object with the viewport details.


function viewport(){
  this.w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  this.h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  
  this.orientation = this.w > this.h ? 'landscape' : 'portrait';

  this.output = {
    w: this.w,
    h: this.h,
    orientation: this.orientation
  };

  return this.output;
}

The function can then be used in a number of ways.



// Conditionally do a thing inside a function
function doAThing(){
  if(viewport().w < 480){
    // Do a thing
  }
}

// Do a thing when the browser is resized
window.onresize = function(){
  if(viewport().orientation == 'portrait'){
    // Do a thing
  }
}

UPDATE July 2017: JS matchMedia API

Recently, SitePoint updated one of their 2011 posts to recommend this API.
In short, matchMedia returns a mediaQueryList object, which has a .matches() method attached to it. Passing a media query formatted the same as a CSS media query will return a boolean based on whether the query matches.
Read more about it on SitePoint’s How to use Media Queries in JavaScript.

NiceMenu – A JavaScript Responsive Menu for Multiple Menus

On a recent build, I needed a menu system like the impressive MeanMenu. Unfortunately, MeanMenu doesn’t support multiple menus. One fork of MeanMenu allows for multiple menus, though they present as multiple mobile menus, which I thought looked horrible. So, I thought, I’ll just roll my own.

NiceMenu isn’t, perhaps as polished as MeanMenu as far as presentation, but it will convert multiple menus into one responsive mobile menu.

Check out this Gist. Intructions for use are in the comments in the head of the JavaScript file.

« Previous PageNext Page »