Sep 27 2018
Sep 27

There are couple of online tools, and integration modules to get sharing widget to your site. They rely on JavaScript and the security of your users is questionable. This article will show you how to create a simple yet flexible and safer service sharing widget without line of JavaScript.


The main reason why not to use some of the tools like AddToAny is the security. This is often a case for government or other public facing project such as GovCMS. Sharing widget of these services is not connecting directly to the social service, but it is processed on their servers first. And they can track the user on through the web because of the fingerprint they made. Another reason is that the JS code is often served from a CDN so you don’t know when the code changes and how? Have they put them some malicious script? I don’t want this on my site. And clients often as well. :)

Thankfully each service provide a simple way how to share content and we will use that.

Final example

You can see the final result in action with different styling applied at our example GovCMS 8 demo page (scroll down to the bottom of page).

Site build

First we need to prepare the data structure. For our purpose we will need to create a custom block type, but it can be easily done as a paragraph too.

Custom block name: Social Share
Machine name: [social_share]

And throw in few Boolean fields. One for each service.

Field label: [Human readable name] e.g. “Twitter”
Machine name: [machine_name] e.g. “social_share_twitter” – this one is important and we will use it later.

Go to the manage display screen of the block (/admin/structure/block/block-content/manage/social_share/display) and change the Output format to Custom. Then fill in the Custom output for TRUE with the text you like to see on the link e.g. "Share to twitter".

Now we are able to create a new block of the Social share type and check some of these checkboxes. Users will see only the Labels as result.


The fun part is changing the output of the field from simple label to actual share link.
First we need to know how the final link looks like.
Links examples:

Facebook: http://www.facebook.com/share.php?u=[PAGE_URL]&title=[PAGE_TITLE] Twitter: http://twitter.com/intent/tweet?status=[PAGE_TITLE]+[PAGE_URL] LinkedIn: http://www.linkedin.com/shareArticle?mini=true&url=[PAGE_URL]&title=[PA…] E-mail: mailto:?subject=Interesting page [PAGE_TITLE]&body=Check out this site I came across [PAGE_URL]

To get it work we need a current page Page URL, Page title, and Base path. Only the page URL is directly accessible from TWIG template. The other two needs to be prepared in preprocess. Lets add these in the theme_name.theme file.

/** * Implements template_preprocess_field(). */ function theme_name_preprocess_field(&$variables, $hook) { switch ($variables['field_name']) { case 'field_social_share_twitter': $request = \Drupal::request(); $route_match = \Drupal::routeMatch(); $title = \Drupal::service('title_resolver') ->getTitle($request, $route_match->getRouteObject()); if (is_array($title)) { $variables['node_title'] = $title['#markup']; } else { $variables['node_title'] = (string) $title; } $variables['base_path'] = base_path(); break; } }

As we probably will have more then one service we should use the DRY approach here. So we create extra function for the variable generation.

/** * Preprocess field_social_share. */ function _theme_name_preprocess_field__social_shares(&$variables) { $request = \Drupal::request(); $route_match = \Drupal::routeMatch(); $title = \Drupal::service('title_resolver') ->getTitle($request, $route_match->getRouteObject()); if (is_array($title)) { $variables['node_title'] = $title['#markup']; } else { $variables['node_title'] = (string) $title; } $variables['base_path'] = base_path(); }

And we than call it for various cases. If some service will need more variables it will be easy to add it in different function. So we don’t process whats not required.

/** * Implements template_preprocess_field(). */ function theme_name_preprocess_field(&$variables, $hook) { switch ($variables['field_name']) { case 'field_social_share_facebook': _theme_name_preprocess_field__social_shares($variables); break; case 'field_social_share_twitter': _theme_name_preprocess_field__social_shares($variables); break; case 'field_social_share_linkedin': _theme_name_preprocess_field__social_shares($variables); break; case 'field_social_share_email': _theme_name_preprocess_field__social_shares($variables); break; } }

Now we have the Node title and Base path prepared to be used in field templates.

Enable twig debug and look in the markup for the checkbox. You will see couple of suggestions, the one we are looking for is field--field-social-share-twitter.html.twig.

As the output should be single link item it is safe to assume we can remove all the labels condition and the single/multiple check as well. On the other hand we need to ensure that if the checkbox is unchecked it will not output any value. That is particularly hard in TWIG as it doesn’t have any universal information about the state of checkbox. It has only access to the actual value. But since we don’t know the value of custom label we cannot use it. However there is a small workaround we can use. Remember we hav not set the FALSE value.
We can check if the field is outputting any #markup. The empty FALSE value will not produce anything, hence the condition will fail.

{% if item.content['#markup'] %}

Here is the full code for field template:

{% set classes = [ 'social-share__service', 'social-share__service--twitter', ] %} {% for item in items %} {% if item.content['#markup'] %} <a {{ attributes.addClass(classes) }} href="http://twitter.com/intent/tweet?status={{ node_title }}+{{ url('<current>') }}" title="Share to {{ item.content }}">{{ item.content }}</a> {% endif %} {% endfor %}

For other services you need to adapt it. But it will still follow the same pattern.

And we are done. Now your block should return links to sharing current page to the service.

Pro tip:

So far we have not use any contrib module. But obviously your client would like to have some fancy staying applied. You can add everything in the theme, but that will be only one hardcoded option. For easier live of editors you can use Entity Class formatter module to easily add classes to the block from a select list. You can provide multiple select list for Size, Color, Rounded corners, Style etc.


At this point we have the simple social share widget ready. We can select which predefined services will show in each instance and how will they look. E.g. On blog post you can have sharing for Twitter, Facebook and Email styled as small rounded icons. But with another instance of the block you can have only large squared LinkedIn icon + label shown on Job offering content type.

Further notes

After I wrote first draft of this article new module appeared which work in very similar way. Give it a try at Better Social Sharing Buttons. It will be quicker to get up ad running as it has predefined styles and services, but that can be a drawback at the same time. If I need different style, or extra service it can be harder to add it.

Feb 12 2015
Feb 12

OpenLayers module is a popular solution for mapping in Drupal. The biggest benefit is the ability to use different map providers, complete Feature support and, last but not least, the simplicity of creating custom markers.

Good selection of markers can have a big influence on the overall success of the site. It can improve user experience because with good icons and color codes, the user can easily see what the marker is about without clicking it. The default set of markers in Open Layers is too generic, they are just basic points with no added value – and that is perfectly fine. For a simple site with few points and basic categorization, there is no need for fancy markers. But if the map needs to be clear to users and the markers look good on high resolution screens then you'll need to create custom markers.

OpenLayers Markers default

Creation of marker

Let's create a marker

The first step is to create your own marker images.

Open your favorite image editing or vector drawing application. It doesn’t matter which you use, what matters is the final exported file. I use Adobe Photoshop or Illustrator, but you can use Corel Draw, Gimp, Fireworks etc...

Create a new document, make it at least two times larger than your desired marker size in both directions. On the new blank canvas make sure the marker point is on the bottom border. In fact, the marker should fill the whole canvas.

Exporting the marker image

Once you have the image(s) ready, you have to export them in the correct format. OpenLayers works with PNG, GIF and SVG. Many of you will cheer that SVG is supported, but I strongly recommend to stick with PNG files. The time for SVG has not arrived. There are still some backward compatibility issues, and I’ve noticed jagged lines on some browsers/devices combination. If you create the PNG marker with alpha transparency and make it two times larger, the resulting PNG will be crisp everywhere.

Creating custom marker

Now that we have the image ready upload it to the site. You can store it in a simple module or add inside a Feature module.

Go to /admin/structure/openlayers/styles and from this page you can see all the current styles. Instead of creating a new marker, just clone an existing one. This will save you time because you won't have to fill out the whole form. 

Marker clone


In the marker edit form, you have to specify the correct path to the marker.

Marker path Open Layers

The most important part of this form is where you set the dimensions and offset for your image. Offset needs to be changed so the point of the marker is in the middle of the preview square on style list. This will require some trial and error to get right. Here, you also set half the real image size – we have created the images double the size, remember? This will provide us with crisp looking images on high resolution ('retina') devices.

OpenLayers Marker setup

Once you've finished configuring the marker, save the form and it's ready to be used in a map.

OpenLayers Custom Markers

As you can see, it's relatively easy to change the look and feel of a map using custom markers. It's now more readable and descriptive for users. You could further improve things by creating a legend which will explain the markers.

If you have any questions, or want to show others your new marker set, please leave a comment.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web