JavaScript
Article
By Almir Bijedic

Using Polymer in WordPress: Build a Custom Google Maps Component

By Almir Bijedic

Web components are a set of standards for creating custom, reusable HTML elements. Polymer is an open-source JavaScript library for building web applications using web components. Created by those clever folks at Google, it provides a number of additional features over vanilla web components and when used with a polyfill, supports the latest version of all major browsers.

In this tutorial I’m going to show you how easy it is to make use of web components and Polymer in WordPress. I’m going to start by showing you how to integrate Polymer into your WordPress install, then I’m going to demonstrate how to add a working Google Maps component to your site’s side bar. This might be useful for any site (e.g. that of a restaurant) which needs to provide visitors with directions to their premises.

After reading, you’ll be able to employ this technique on a site of your own. And you’ll not be limited to a Google Map widget, you’ll be able to choose from the wide range of pre-made components, or even write your own.

As ever, all of the code for this tutorial is available in a GitHub repository.

--ADVERTISEMENT--

Why Polymer?

As native support for web components is growing ever better, you might be forgiven for asking if Polymer is still relevant. The short answer to that question is Yes!

Polymer does make use of a variety of web component polyfills—which will hopefully one day full by the wayside—but it is a lot more than that. Polymer is a wrapper around the web components API that allows us to develop and implement new components at a much greater speed than we would otherwise be able. It offers various additional features over vanilla web components, such as one-way and two-way data binding, computed properties and gesture events. It comes with a very polished CLI which can be used for such tasks as scaffolding out a project, running tests, or running a local server, and it can make use of a wide range of pre-built elements, such as the much loved material design elements library.

In short, Polymer is still very relevant. It is a powerful framework, which is used in production by large companies such as USA Today, Coca Cola and Electronic Arts.

Setting Up WordPress

Before we start, we need to setup our environment that is going to be running WordPress. For this tutorial, I’ll be using the ScotchBox Vagrant VM, equipped with some pre-installed tools to kickstart your WordPress installation.

If you have WordPress installed already, or would prefer to use a different method, you can skip this bit. If you need a bit of help with the setup, but don’t want to go the vagrant route described below, try Googling “install WordPress locally” and looking for an up-to-date tutorial.

We start of by making sure that Git, Vagrant and Virtual Box are installed on our system. We can then clone the GitHub repo with ScotchBox’s pre-populated Vagrantfile.

git clone https://github.com/scotch-io/scotch-box sitepoint-wp-polymer

Now we are ready to run vagrant up. After our machine has booted, we have to remove the default /public/index.php static file and install WordPress.

cd sitepoint-wp-polymer/public
rm index.php
git clone https://github.com/WordPress/WordPress.git .

Now we have to make a duplicate of the wp-config-sample.php file. Name it wp-config.php.

cp wp-config-sample.php wp-config.php

and edit the following values:

// wp-config.php

// ...

define('DB_NAME', 'scotchbox');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');

// ...

Now you are ready to fire up your browser and visit http://192.168.33.10. You will be prompted to enter the admin account credentials and site title. Feel free to fill these out as you see fit.

Using Polymer in WordPress: WordPress installation

Adding the SitePoint Base Theme

So we’ve got WordPress set up, now we need a theme. Out of the box, this will be the Twenty Seventeen theme, but this is pretty generic and includes much more than you normally need. A good alternative here, is to use the SitePoint WordPress base theme.

This theme was created in response to the question “What would the perfect WordPress base theme look like?”. Its features include:

  • No fat. No cruft. Speedy.
  • Minimal design. It’s your job to make it pretty.
  • No ‘cute’ features you never actually use.
  • SEO friendly to its core.
  • Super Mobile-friendly.
  • 100% Open Source and free to use.

The SitePoint WordPress base theme is a great starting point for new projects. It’s mobile friendly, easy to use and 100% free. To follow along with the rest of tis tutorial, head over to the theme’s homepage and download it now.

And while you’re there, you might like to check out the suite of paid themes SitePoint offers, too. These are all built on top of the base theme and include an ecommerce theme, restaurant theme, portfolio theme, business theme and construction theme.

After downloading SitePoint WordPress base theme, unzip it and copy/paste to thewp-content/themes folder. Then create a new folder called sitepoint-base-child, in wp-content/themes. In that directory create a style.css file and a functions.php file.

cd wp-content/themes/
mkdir sitepoint-base-child
cd sitepoint-base-child
touch functions.php style.css

Open up style.css and copy this into it:

/*
 Theme Name:   SitePoint Base Child
 Author:       Almir B.
 Author URI:   http://almirbijedic.rocks
 Template:     sitepoint-base
 Version:      1.0.0
 Text Domain:  ab-sitepoint-base
*/

And into functions.php:

<?php
//functions.php

add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}

This will enqueue the base CSS from the parent theme.

We just created a child theme, whose role is to implement functionalities on top of the base theme without having to modify the base files. All of the customisations go into this child theme.

One last step is to go to the admin dashboard, then to Appearance > Themes from the main side menu, and click Activate under, Sitepoint Base Child theme.

Using Polymer in WordPress: Activate Sitepoint Base Child Theme

Including Polymer in WordPress

Now that’s done, we have to install Polymer with bower. Make sure you are in the public/wp-content/themes/sitepoint-base-child folder, and then run:

bower init

You can answer with default answer to every question. Next we need to install the dependencies:

bower install --save Polymer/polymer#^2.0.0 PolymerElements/paper-input#2.0-preview

This will install Polymer and the paper-input component, so that we can have a fancy material designed input component out of the box. It is important to use the #2.0-preview tag for the paper input and also for the Google Map element later, as it will not work with the latest version of Polymer (version 2.0) otherwise.

In order to user Polymer, we have to include it using an HTML import, and we will also include the polyfill for web components, so as to support older browsers.

Head to the functions.php file in the child theme, and add an enqueue to the existing enqueue function.

<?php
//functions.php

add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
  wp_enqueue_script( 'polymer', get_stylesheet_directory_uri() . '/bower_components/webcomponentsjs/webcomponents-lite.js' );
}

WordPress does not have an enqueue function for enqueueing HTML imports, but we can hook into the wp_head hook which outputs into the <head> element of the page.

<?php
//functions.php

add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
  wp_enqueue_style( 'polymer', get_stylesheet_directory_uri() . '/bower_components/webcomponentsjs/webcomponents-lite.min.js' );
}

add_action( 'wp_head', 'include_polymer_elements' );
function include_polymer_elements() {
  ?>

  <link rel="import"
        href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/polymer/polymer.html">
  <link rel="import"
        href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/paper-input/paper-input.html">
  <?php
}

That’s all we needed to start using Polymer elements in WordPress. Now let’s create a WordPress widget so we can take this out for a test ride.

Registering a Widget

In order to create a new widget, we will create a new child class from the WP_Widget class and then register it with the widgets_init hook.

Create a new folder in your child theme, name it lib, and add it a file named sitepoint-map-widget.php.

mkdir lib
cd lib
touch sitepoint-map-widget.php

Copy the following into that file:

<?php 
// lib/sitepoint-map-widget.php

class SitepointMapWidget extends WP_Widget {

  function __construct() {
    // Instantiate the parent object
    parent::__construct( false, 'Google Paper Input' );
  }

  function widget( $args, $instance ) {
    echo '<paper-input raised always-float-label label="Floating label"></paper-input>';
  }
}

All we did here is create a new child class of WP_Widet and called the parent constructor in order to give the widget a custom name. Additionally, the widget function is the one that does the actual output. For now, we will simply output a <paper-input> element, which is an element from the paper-input-elements collection.

Last but not least, we need to include this new PHP file at the top of our functions.php file:

<?php
// functions.php
require_once( 'lib/sitepoint-map-widget.php' );

// ...

and then register a widget at the end of the file:

<?php
// functions.php

// ...

add_action( 'widgets_init', 'sp_register_widgets' );
function sp_register_widgets() {
  register_widget( 'SitepointMapWidget' );
}

Now we can go into the admin dashboard of WordPress. From the main menu, go into Appearance > Widgets, and there you should see a widget named Google Paper Input on the left.

Drag and drop it into the Main Sidebar section to the right, above the rest of the default widgets from the SitePoint Base theme.

Using Polymer in WordPress: Widget to sidebar

Now you can visit the homepage, and on the right side right above the search box, you will see a material design input with a label.

Using Polymer in WordPress: Paper Input

And thus we have concluded Polymer’s Hello, World! example. We’ve covered a lot of ground already—installing Polymer, integrating it with WordPress and including a sample widget, all in just a few lines of code—but in the next section we will take this further and implement our Google Map component.

Watch WordPress Theme Development

Make your own theme — from design, to a professional theme

Introducing the Web Components Library

Now we will make use of the collection of out-of-the-box web components, available on WebComponents.org. Searching for “Google Map” will lead us to the element we need. By looking at the final part of that page’s URL, we can find out the name of the package in bower.

Make sure you are in the sitepoint-base-child directory and run the following command:

bower install --save GoogleWebComponents/google-map#2.0-preview

Now create a new folder in your sitepoint-base-child directory and name it webcomponents. This is where we will be keeping all of our Polymer related stuff.

mkdir webcomponents

Creating a New Polymer Component

Create a new file in the webcomponents folder and name it sitepoint-map.html.

cd webcomponents
touch sitepoint-map.html

Each Polymer component is organised into separate HTML files, representing a new custom HTML tag. This HTML file is composed of three notable sections:

1. The Import of Dependencies

// sitepoint-map.html

<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">

Here we have the Google Maps element we installed moments ago, as well as the paper-input element from our Hello, World! example.

2. The Template

// sitepoint-map.html

<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">

<dom-module id="sitepoint-map">
  <template>
    <style>
      google-map {
        height: 300px;
      }
    </style>
    <google-map id="spMap"
                fit-to-marker
                mouse-events="true"
                on-google-map-mousemove="trackCoords"
                on-google-map-mouseout="resetCoords"
                api-key="[[clientId]]">
      <google-map-marker latitude="37.78"
                         longitude="-122.4"
                         draggable="true"></google-map-marker>
    </google-map>
    <paper-input raised id="coords" label="Coordinates"></paper-input>
  </template>
</dom-module>

The ID of the <dom-module> element is the actual name of the element—i.e. its tag name. The best practice is to give it the same name as the name of the file. Inside of that we have a <template> tag, which represents what the new custom element will consist of. This can always be broken down to basic HTML elements. The <google-map> tag is nothing other than a collection of scripts, standard HTML elements and other custom HTML elements which can be broken down again the same way.

The ID of the element allows us to easily access it from the script (see next section) using a this.$.id syntax. In our case we will use this.$.coords to reference to the input element.

Then the next attributes on the <google-map> tag are two events, google-map-mouseover which is triggered when a user mouses over our widget, and google-map-mouseout which is triggered when the mouse leaves the map. This doesn’t serve much practical purpose here, rather demonstrates how we bind to events fired from the component. All we have to do is add the on-event-name keyword, and pass in the name of the function from our component which we wish to be triggered. This is a recommended best practice, as we remove the need to add an ID to the element solely for the purpose of targeting it to add an event listener. You can see a full list of available methods, events and properties here.

We also pass in the fit-to-marker attribute, which tells the map to resize and re-centre so as to show all markers inside the map.

You’ll also notice that we’re specifying a client-id attribute. You’ll have to fill this out with a client ID of your own. In order to obtain one of these, please follow the official Google instructions. When you visit that link, start by clicking the GET A KEY button.

  1. The script
// sitepoint-map.html

<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">

<dom-module id="sitepoint-map">
  <template>
    ...
  </template>

  <script>
    class SitepointMap extends Polymer.Element {
      static get is() { return 'sitepoint-map'; }
      static get properties() {
        return {
          clientId: String
        }
      }
      trackCoords(e) { 
        this.$.coords.value = e.detail.latLng.lat() + ", " + e.detail.latLng.lng(); 
      }
      resetCoords() { this.$.coords.value = "" }
    }

    window.customElements.define(SitepointMap.is, SitepointMap);
  </script>
</dom-module>

The bare minimum to create an element is just this part:

class SitepointMap extends Polymer.Element {
  static get is() { return 'sitepoint-map'; }
}
window.customElements.define(SitepointMap.is, SitepointMap);

Where the name of the class should be the same as the ID of the <dom-template> element. It’s a best practice to camel case this name, and return the ID of the <dom-template> element from the static is function.

Next there is the properties object, which is a reserved function name for registering any attributes on the element. The important thing to note here is that any attributes consisting of more than one word that are dashed, like this:

<sitepoint-map client-id="..."></sitepoint-map>

Will be referenced as clientId, i.e. camel cased inside of the component.

Had we used camel case, like this:

<sitepoint-map clientId="..."></sitepoint-map>

Then inside of the component, the attribute gets flattened to all lowercase, so the reference would be clientid instead.

After the properties, we have two custom methods, which are used as callbacks for the mousemove and mouseout events, respectively. The trackCoords method simply takes the longitude and the latitude position of the mouse on the map and displays it in the input.

Now that we have a web component in place, there are a couple of things left to do.

Import the <sitepoint-map> Component

First let’s create an index.html file inside of the webcomponents folder. This will be used to import all of our custom components. We will enqueue this file once, so we do not have to worry about enqueueing an HTML import every time we add a new component. Instead we can just import it in the index.html file, which is a more convenient syntax than echoing it with PHP to wp_head.

Then, paste this inside the newly created index.html file:

// webcomponents/index.html

<link rel="import" href="sitepoint-map.html">

Go back into the functions.php file, to where we include the paper button and polymer HTML imports in the head. We do not need the paper button import anymore, so remove that, then include index.html from the webcomponents directory instead:

<?php
// functions.php

add_action( 'wp_head', 'include_polymer_elements' );
function include_polymer_elements() {
  ?>
  <link rel="import"
        href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/polymer/polymer.html">
  <link rel="import"
        href="<?php echo get_stylesheet_directory_uri() ?>/webcomponents/index.html">
  <?php
}

From now on, you can add all of your custom components to index.html. E.g. if we also had a custom Google Calendar component, or just have to use an out of the box component, like paper-progress, we would do it like this

// webcomponents/index.html

<link rel="import" href="sitepoint-map.html">
<link rel="import" href="sitepoint-calendar.html">
<link rel="import" href="../bower_components/paper-progress/paper-progress.html">

Do not copy this in, it is just an example.

Output a <sitepoint-map> HTML Tag

Now we need to output a <sitepoint-map> HTML Tag in place of the paper input we were using previously.

<?php
// lib/sitepoint-map-widget.php

class SitepointMapWidget extends WP_Widget {

  function __construct() {
    // Instantiate the parent object
    parent::__construct( false, 'Google Map' );
  }

  function widget( $args, $instance ) {
    echo '<sitepoint-map client-id="' . GOOGLE_MAP_API_KEY . '"></sitepoint-map>';
  }
}

Also, do not forget to define your own GOOGLE_MAP_API_KEY constant. The best place for this is at the top of the functions.php file in our child theme.

<?php
// functions.php

require_once( 'lib/sitepoint-map-widget.php' );
define('GOOGLE_MAP_API_KEY', '<your-key-here>');

And voila! We now have a fully functional Google Map widget for WordPress. Usually plugins that offer this kind of functionality can contain a few hundreds lines of PHP code. And here we have a very nice setup in our webcomponents folder, where everything is centralized and easily extensible and customizable.

Using Polymer in WordPress: Result Google Map

Conclusion

And with that, we come to the end of the tutorial. By now you should know how to integrate Polymer into your WordPress install and how to add a custom component. If you wish to further sharpen your skills, the next step for our Google Maps component would be to map the WordPress widget attributes to the attributes of the component. In this way you would be able to pass in arguments such as marker position, client ID etc. from the Appearance > Widgets configuration screen. Why not have a try at implementing that yourself and let me know how you get on.

And while you’re at it, please take some time to dig into the beautiful world of web components, browse around the library and find something fun to integrate into WordPress. Please share your discoveries with us in the comments below. I will be on the lookout!

This article was peer reviewed by Simon Codrington. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be![/special]

The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account