Feed aggregator

Friendly Machine: Drupal 8 and Backdrop CMS - A Brief Comparison

Drupal News - December 14, 2014 - 9:28am

I recently had the opportunity to see Nate Haug deliver a presentation about the Backdrop CMS project and it's upcoming 1.0.0 release (Jan. 15). It had been a while since I had taken a look at Backdrop and I came away quite impressed with both its progress and direction.

Many of you reading this will be familiar with Backdrop, but for those of you who haven't heard of the project, it is the first fork of the Drupal project, and the source of a great deal of controversy and angst in the Drupal community.

Backdrop has been perceived as a threat by many Drupalists, but I think as we step through the features and approaches of the two projects, those fears will be at least somewhat allayed. My own take is that the two systems seem complementary instead of competitive.

As a bit of background for the origin of Backdrop CMS, Nate told the story of his reaction to the massive changes in Drupal 8. He realized that his own business, Webform.com, was going to have major issues with the upgrade path.

It was going to take a huge effort to upgrade his site - we're talking many, many months - to simply replicate the work he had already done in Drupal 7. He didn't want to throw away the huge investment he had already made in his business and start over. His solution to the problem was forking Drupal to create Backdrop CMS.

And then...all hell broke loose.

Feature Comparison

I'll set the controversy behind Backdrop aside and get straight into a comparison of the features. Keep in mind, however, I'm using the term "features" here a bit loosely. That's because I also want to talk about how Backdrop is managed as well as other differences between the two projects. This list is not exhaustive. It just has some of the things that seem to me the most significant or interesting.

Target Market

I know many will squirm uncomfortably when I say this, but the target market for Drupal 8 is large enterprises. By contrast, the target for Backdrop is small to medium size businesses and non-profits - really the original market of the Drupal project. As we go through this list, you'll see how this targeting plays out in some of the decisions the two projects have made.

Configuration Management

This has been widely touted as the killer feature of Drupal 8. If you've dreamed of having all the cool configuration management features in D8 available for Drupal 7, then Backdrop may be tempting because that is essentially what it offers. Instead of using YAML files to store configuration data, however, Backdrop uses JSON. Otherwise, it's pretty much the same.

Theming

Another one of the major additions to Drupal 8 is the Twig template engine. This is a big plus for many front-end folks and it's something that is not available in Backdrop at this time - and I'm not sure I would look for it in the near future. Backdrop currently uses the Drupal 7 PHPTemplate theme engine.

Responsive Images

As a front-end developer, I have a particular interest in this one. Drupal 8 includes the Responsive Image module, which is essentially a reworking of the Picture module in D7.

At this writing, Backdrop doesn't have a responsive image solution. I asked Nate about this and he's not a fan of the Picture module approach (he favors using srcset, something that may possibly be added in versions 1.1 or 1.2 of Backdrop), so if that is something you require, it will need to be added as either a custom or contributed module.

Contributed Modules

Speaking of contrib, most of you reading this will be familiar with Drupal's massive collection of contributed modules. The contributed modules for Backdrop CMS will be hosted on GitHub and managed similar to how the jQuery project organizes its plugin registry. I don't think there have been any ports as of yet (all the energy is going to the 1.0.0 release), so this is pending.

Some of you may have heard that Drupal 7 modules will be compatible with Backdrop. This isn't true, primarily due to modules needing to be rewritten to support configuration management. Porting a Drupal 7 module should be fairly straightforward, however. Instead of storing config in the variables table, it needs to be in JSON files. Here's a video that will help get you started.

As a quick aside, having Backdrop (and eventually the contrib modules) hosted on GitHub seems like it will be a more familiar and friendly environment for potential project contributors.

Project Organization

The "do-ocracy" that is the Drupal project has been much discussed lately. Nate has organized the Backdrop CMS project along the same lines as the Project Management Committee of the Apache project. That was very wise in my opinion. It bodes well for the project.

WYSIWYG

Another really nice thing in Drupal 8 is the inclusion of a default WYSIWYG editor. Love them or hate them, virtually every client wants one, so now with D8 you won't have to add one yourself for every project. As of version 1.0.0, Backdrop doesn't have this functionality, but look for it in version 1.1 or 1.2.

I remember Nate saying something about it being ironic that Backdrop was launching both without Twig or a WYSIWYG since he and Backdrop co-founder Jen Lampton had been instrumental in bringing those to Drupal 8.

I suppose I should mention that Backdrop minor versions - from 1.0 to 1.1, for example - will occur regularly at an interval of about three or four months. So for the features mentioned that may be in version 1.1 or 1.2, it means they can be expected in either late spring or late summer.

Panels and Views

How about Panels and Views in core? Yeah, I like it! And that's what you get with Backdrop. Drupal 8 provides Views in core, but not Panels. It may be a while before Panels is ready for D8, but it may also be a while before D8 is ready, so I guess that's not a problem.

System Requirements and Backwards Compatibility

It may seem odd to group these two, but this is one point where the intended audiences (enterprise vs small organizations) are put into stark contrast. For example, Backdrop is intentionally friendly to cheap hosting. Drupal 8, by contrast, is almost certainly going to use more server resources than Drupal 7, potentially causing issues for those on shared hosting plans. 

For large organizations, the cost of hosting is not a big deal, but for some small organizations, it can be. So a solution architected to work well with limited resources may be attractive and also serves to highlight the different approaches between the two projects.

With backwards compatibility, we see the same philosophical divergence. Drupal has never focused much on backwards compatibility, making it a pain in the ass (and often expensive) to upgrade across major versions. The benefit of that approach is that Drupal has been able to innovate without being constrained by past decisions.

Backdrop, however, places a lot of value on carefully managing change so that existing sites can be upgraded affordably. I would recommend looking at Backdrop's philosophy, because it's there where you really find the motivations for the project and how it differs (and will differ more in the future) from the Drupal project. From system requirements, to upgrade path, to reaching out to hear voices not found in the issue queue, Backdrop CMS is consistently friendly to the needs of the little guy.

Wrap Up

Again, this isn't a comprehensive list of all the features or differences between the two systems. There is an issue on GitHub that might be of some help in learning more as well as this Drupal 8 feature list.

To me, these two projects don't compete with one another. Sure, some enterprises may use Backdrop and many small organizations may use Drupal 8. But really, the changes in Drupal 8 are a move toward the enterprise and the talk around Drupal 8 has reinforced that message. Having an alternative for small organizations on a budget and with a need to preserve software investments isn't a bad thing.

You may politely leave any comments below.

Drupal

Paul Booker: Updating a user role when a class (group) is flagged as finished

Drupal News - December 14, 2014 - 5:38am
function mymodule_training_class_node_form_submit($form, &$form_state) { if ($form_state['input']['field_class_is_finished']['und'] == 1) { $nid = $form_state['values']['nid']; $query = db_select('og_membership', 'ogm') ->condition('ogm.gid', $nid, '=') ->fields('ogm', array('etid')); $result = $query->execute(); foreach ($result as $record) { $uid = $record->etid; _mymodule_training_class_assign_alumni_role($uid); } } } function _mymodule_training_class_assign_alumni_role($uid){ $rid = db_select("users_roles", "ur") ->fields("ur", array("rid")) ->condition('ur.uid', $uid, '=') ->execute() ->fetchField(); if (empty($rid)) { db_insert('users_roles') ->fields(array( 'uid' => $uid, 'rid' => ALUMNI, )) ->execute(); } } mysql> describe field_data_field_class_is_finished -> ; +-------------------------------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------------------+------------------+------+-----+---------+-------+ | entity_type | varchar(128) | NO | PRI | | | | bundle | varchar(128) | NO | MUL | | | | deleted | tinyint(4) | NO | PRI | 0 | | | entity_id | int(10) unsigned | NO | PRI | NULL | | | revision_id | int(10) unsigned | YES | MUL | NULL | | | language | varchar(32) | NO | PRI | | | | delta | int(10) unsigned | NO | PRI | NULL | | | field_class_is_finished_value | int(11) | YES | MUL | NULL | | +-------------------------------+------------------+------+-----+---------+-------+ 8 rows in set (0.00 sec) mysql> mysql> describe og_membership; +-------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | type | varchar(255) | NO | | | | | etid | int(10) unsigned | NO | MUL | 0 | | | entity_type | varchar(32) | NO | | | | | gid | int(11) | NO | MUL | NULL | | | group_type | varchar(32) | NO | MUL | | | | state | varchar(255) | YES | | | | | created | int(11) | NO | | 0 | | | field_name | varchar(255) | NO | | | | | language | varchar(12) | NO | | | | +-------------+------------------+------+-----+---------+----------------+ 10 rows in set (0.00 sec) mysql> select * from og_membership where gid=1304; +------+----------------------------+-------+-------------+------+------------+-------+------------+--------------+----------+ | id | type | etid | entity_type | gid | group_type | state | created | field_name | language | +------+----------------------------+-------+-------------+------+------------+-------+------------+--------------+----------+ | 8275 | og_membership_type_default | 1 | user | 1304 | node | 1 | 1402485115 | og_user_node | en | | 8276 | og_membership_type_default | 10106 | user | 1304 | node | 1 | 1402485280 | og_user_node | en | | 8277 | og_membership_type_default | 10113 | user | 1304 | node | 1 | 1402485286 | og_user_node | en | | 8278 | og_membership_type_default | 10114 | user | 1304 | node | 1 | 1402485292 | og_user_node | en | +------+----------------------------+-------+-------------+------+------------+-------+------------+--------------+----------+ 4 rows in set (0.00 sec) mysql> describe users; +------------------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------------+------+-----+---------+-------+ | uid | int(10) unsigned | NO | PRI | 0 | | | name | varchar(60) | NO | UNI | | | | pass | varchar(128) | NO | | | | | mail | varchar(254) | YES | MUL | | | | theme | varchar(255) | NO | | | | | signature | varchar(255) | NO | | | | | signature_format | varchar(255) | YES | | NULL | | | created | int(11) | NO | MUL | 0 | | | access | int(11) | NO | MUL | 0 | | | login | int(11) | NO | | 0 | | | status | tinyint(4) | NO | | 0 | | | timezone | varchar(32) | YES | | NULL | | | language | varchar(12) | NO | | | | | picture | int(11) | NO | MUL | 0 | | | init | varchar(254) | YES | | | | | data | longblob | YES | | NULL | | +------------------+------------------+------+-----+---------+-------+ 16 rows in set (0.01 sec) mysql> select * from users where uid=10106; +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+------------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | uid | name | pass | mail | theme | signature | signature_format | created | access | login | status | timezone | language | picture | init | data | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+------------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | 10106 | user_authenticated_1 | $S$DBGDqh770IDr09aztKD8Ey8aNGxwx8iiCaYo/rGCcBpa5XzNKnDF | identity+user_authenticated_1@paulbooker.co.uk | | | full_html | 1401792983 | 1401794533 | 0 | 1 | America/New_York | | 0 | identity+user_authenticated_1@paulbooker.co.uk | NULL | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+------------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ 1 row in set (0.00 sec) mysql> select * from users where uid=10113; +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | uid | name | pass | mail | theme | signature | signature_format | created | access | login | status | timezone | language | picture | init | data | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | 10113 | user_authenticated_2 | $S$DeG84e0QP/H2h2rGv6cw93krL3CDoQ6CZOzhiSQCZa4OpZOAeP21 | identity+user_authenticated_2@paulbooker.co.uk | | | full_html | 1402485227 | 0 | 0 | 1 | America/New_York | | 0 | identity+user_authenticated_2@paulbooker.co.uk | NULL | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ 1 row in set (0.00 sec) mysql> select * from users where uid=10114; +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | uid | name | pass | mail | theme | signature | signature_format | created | access | login | status | timezone | language | picture | init | data | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ | 10114 | user_authenticated_3 | $S$D4xWR53hWUcyoZmIuZOLv7K8oasOsPCmqWaQGT.kpMQiX9k7XpfD | identity+user_authenticated_3@paulbooker.co.uk | | | full_html | 1402485256 | 0 | 0 | 1 | America/New_York | | 0 | identity+user_authenticated_3@paulbooker.co.uk | NULL | +-------+----------------------+---------------------------------------------------------+------------------------------------------------+-------+-----------+------------------+------------+--------+-------+--------+------------------+----------+---------+------------------------------------------------+------+ 1 row in set (0.00 sec) mysql> select rid from users_roles where uid=10106; +-----+ | rid | +-----+ | 7 | +-----+ 1 row in set (0.00 sec) Tags:

nielsdefeyter.nl: Setup Entity Translation the right way

Drupal News - December 13, 2014 - 5:36am

This article contains a detailed instruction on how to setup the Entity Translation module for Drupal 7 websites.
Entity Translation is part of Drupal 8 core and its approach is to translate fields instead of full nodes/entities.

Goal of this tutorial is to set up a multilingual website that can be navigated in multiple languages by visitors and to enable the content to be easily manageable by editors / cms administrators.
To get multilingual right, it’s critical that you configure your content-types and fields with care and precision and upfront, because if content is already in your database it is almost impossible to change these configurations.
So let's go.

Pixelite: Adding Apple and Android favicons to Drupal

Drupal News - December 12, 2014 - 4:00pm

As you end up building more and more websites that target mobile devices (e.g. iPhone, iPad, Android, Windows), you need to supply an ever increasing amount of favicons. This process can be complex if done by hand, luckily there is an easy way to introduce these into your Drupal site.

What you will need

Before we start you will need a high quality icon to begin with, the icon should be:

  • 260x260px (i.e. square)
  • a PNG with transparency as needed
  • recognizable when shrunk right done to your browser favicon (so don’t use your entire logo complete with words).
Generating the favicons

This is where the really handy realfavicongenerator.net website comes into play. I have used many other websites that offer similar functionality, but this seems to be the best, and is dead simple to use.

You will need to upload the 260x260px PNG file, and also select a hex color for the Windows 8 tile, but this should be straight forward.

I also opt for the option “I will place favicon files (favicon.ico, apple-touch-icon.png, etc.) at the root of my web site.” as this seems the most sensible place for them anyway.

When you complete the process, you will be able to download a zip file containing a whole bunch of icons and XML files, this is fine, extract them to your docroot for Drupal.

Adding the favicons to Drupal

You now will need to edit your html.tpl.php inside your theme, and add the code that the generator provides. The code should resemble something like this:

1 <link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png"> 2 <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png"> 3 <link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png"> 4 <link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png"> 5 <link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png"> 6 <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png"> 7 <link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png"> 8 <link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png"> 9 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png"> 10 <link rel="icon" type="image/png" href="/favicon-192x192.png" sizes="192x192"> 11 <link rel="icon" type="image/png" href="/favicon-160x160.png" sizes="160x160"> 12 <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96"> 13 <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16"> 14 <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32"> 15 <meta name="msapplication-TileColor" content="#b91d47"> 16 <meta name="msapplication-TileImage" content="/mstile-144x144.png">

You will notice though that Drupal likes to place it’s default favicon into the <head> section of the page, we need to remove this in order for it not to mess up the above code you inserted.

<link rel="shortcut icon" href="http://[YOURSITE]/misc/favicon.ico" type="image/vnd.microsoft.icon" />

The following code below can be inserted into your template.php file for your theme to remove the default favicon from Drupal:

1 <?php 2 /** 3 * Remove the unneeded favicon from the head section. 4 */ 5 function YOURTHEME_html_head_alter(&$head_elements) { 6 foreach ($head_elements as $key => $element) { 7 if (!empty($element['#attributes'])) { 8 if (array_key_exists('href', $element['#attributes'])) { 9 if (strpos($element['#attributes']['href'], 'misc/favicon.ico') > 0) { 10 unset($head_elements[$key]); 11 } 12 } 13 } 14 } 15 } 16 ?>

There you have it all done.

Extra for experts - Google’s theme-color meta tag

Google recently announced that from Chrome 39 onwards on Android Lollipop (5.0+), a new meta tag will be supported

<meta name="theme-color" content="#b91d47" />

This is what your site’s title bar now looks like (instead of boring and grey).

This meta tag can be added to your html.tpl.php file as above.

Comments

Let me know if this has helped you, and also if you have any other tips and tricks when it comes to favicons on your mobile devices.

Mediacurrent: Protect thyself! Don&#039;t send TESTING emails to REAL users

Drupal News - December 12, 2014 - 1:05pm

Have you ever accidentally triggered emails to real users while working in a development environment? Or how about accidentally pushed data to a "live" third party service from a development environment?

Drupal Watchdog: Migrate API

Drupal News - December 12, 2014 - 10:29am
Article

The migrate API works with plugins and stores the configuration for those plugins in a configuration entity. There are a number of plugin types offered: source, process, and destination are the most important. Source merely provides an iterator and identifiers, and most of the time the destination plugins provided by core are adequate, so this article will focus on process plugins.

Process plugins

Nothing gets into the destination unless it is specified under the top level process key in the configuration entity. Each key under process is a destination property and the value of it is a process pipeline. Each “stage” of this pipeline is a plugin which receives the output of the previous stage as input, does some transformation on it, and produces the new value of the pipeline.

There are a few plugins which indeed only use the pipeline value as input – for example, the machine name plugin transliterates the input (presumably a human name) and replaces non-alphanumeric characters with underscores. However, if that was all plugins could do they wouldn’t be too useful. Instead, every plugin receives the whole row and the name of the destination property currently being created.

Each stage in the process pipeline is described by an array, where the plugin key is mandatory and the rest is just the plugin configuration. For example:

process: vid: - plugin: machine_name source: name - plugin: dedupe_entity entity_type: taxonomy_vocabulary field: vid

The above mentioned machine name transformation is run on name and then the entity deduplication plugin adds a numeric postfix ensuring the vid field of the taxonomy_vocabulary entity is unique. That is the canonical format of the process pipeline.

Coding in Schools

Drupal News - December 12, 2014 - 8:49am

In this episode, Amber Matz and her guests Eric Schneider and Matthew Tift talk about the successes and challenges on how parents and school officials worked together to get coding into the curriculum in Minnetonka Schools. Eric Schneider is the Assistant Superintendent for Instruction, Minnetonka Public Schools and Matthew Tift is a Senior Developer at Lullabot and a Minnetonka parent.

Lullabot: Coding in Schools

Drupal News - December 12, 2014 - 8:49am

In this episode, Amber Matz and her guests Eric Schneider and Matthew Tift talk about the successes and challenges on how parents and school officials worked together to get coding into the curriculum in Minnetonka Schools. Eric Schneider is the Assistant Superintendent for Instruction, Minnetonka Public Schools and Matthew Tift is a Senior Developer at Lullabot and a Minnetonka parent.

ThinkShout: Oregon Zoo Small Actions

Drupal News - December 12, 2014 - 8:00am
Oregon Zoo: Small Actions

The Oregon Zoo in Portland approached us to develop an action portal component for their Drupal web site. The action portal is a tool that suggests real-world actions that anyone can take to help wildlife survive and flourish. A social sharing component is important for spreading these tips organically. Pun intended. Like wildflowers.

Many sites integrate social sharing, but there are a couple of things that make the Zoo's action portal different. The main difference is that by sharing an action, you are saying that you've actually done that action in the real world, and you are encouraging your friends and followers to take the same action. The aim is not just to generate site traffic, but rather to encourage people to make real change that has a tangible impact on wildlife. Also, the shared content is more personalized, since it's a combination of a single species and the action that you've taken, plus custom messaging the visitor would like to add.

The original intent was to enable visitors to share an action on several social channels: Facebook, Twitter, etc. During technical planning, it was decided that Facebook alone would be the best place to start. We would integrate directly with Facebook and track the shares internally with a custom integration code interacting with Facebook's API.

When we began implementation, we spent a little more time exploring options for sharing on multiple channels, compared to Facebook only. There would be a couple of benefits of sharing directly on Facebook. Using their API would pave the way for deeper integration in the future, taking advantage of Open Graph properties as a starting point. We would have better control over messaging, and we would have complete control over how logging happens in Drupal. And I must say, the Facebook developer documentation is top notch.

But adding the ability later to share on other social networks would require additional API integration for each site. We wanted to consider paving a clearer path forward, so we looked into existing services for sharing on multiple sites. There are many: Gigya, AddThis, ShareThis, and more. For something to work for us, it would need to be free or very inexpensive, allow us to customize the shared message, and provide some statistics, mainly for a share count to display on the site. The ShareThis service ended up working best for us. When using any of these services, there is less control over how shares are logged.

We presented the client with these options along with the pros & cons of each and, ultimately, it was decided that we'd use ShareThis. Having approximate share counts was an acceptable tradeoff in exchange for the benefit of being able to share to multiple social networks.

So, back to how we actually did this...

Structurally, we started with two content types: Action (for the action we want people to take) and Animal (Species that relate to the actions). These each have mostly common field types, such as image and body text.

On the Action content type, we added an Animals entityreference field in order to make the connection between the two content types.

There are three new pages for this feature: the main landing page, the animal detail page, and the action detail page. We created an Animals view for the landing page and action detail page, and we created an Actions view also for the Explore by Action tab of the landing page and for the animal detail page. For the tabs on the landing page, we created a simple block using hook_block_info() and hook_block_view().

Something that's easy to miss when initially planning lists of things is how sorting should be controlled. Since an action references multiple animals, we use that order for displaying animals on the action detail page. But we were pretty limited in how to control the order of actions on an animal detail page. We needed independent sorting control between animals on action pages, and actions on animal pages. We opted to stay with the native drag and drop sorting of entityreference fields, so we added a matching entityreference field on animals to reference actions, and added the Corresponding Entity References to keep these references in sync with each other. Now we have native draggable sorting on both content types. There are several other methods that could have been used, such as adding a weight field, using the draggable views module, or using nodequeue, but using CER with a pair of entityreference fields kept complexity at a minimum.

An essential goal of this feature is sharing an action. The requirement was to have the sharing widget appear on individual actions only when listed on an animal detail page. The shared message is a combination of elements from both content types: the image and name of the animal, plus the contents of a Sharing Message text field from the action. The the URL shared is related to the action.

Message when sharing the FSC action from the Chimpanzee page:

Here's how we put that together. We start by including the global stuff for the ShareThis widget. An implementation of hook_views_pre_render() adds some javascript settings and includes the ShareThis javascript library. To add the unique things to each action, we add a new variable "sharethis_attributes" in hook_preprocess_views_view_field(). This variable contains a string of pseudo attributes: st_url="http://example.com/the-page" st_title="Example Page Title" st_image="http://example.com/image.jpg" st_summary="This is the text that will be shared." st_via="OregonZoo". We use that variable in a very specifically-named template file that takes effect for only this field in this view. The rest of the markup and classes placed in that field template came from ShareThis.

<?php print $output; ?> <div class="sharethis-custom"> <span class='st_sharethis_vcount' displayText='ShareThis' <?php print $sharethis_attributes; ?>></span> </div>

All of this work: content types, fields, image styles for the image fields, views, and the handful of custom hook implementations are bundled together in a new custom feature.

Check out the small actions pages at the Oregon Zoo site and see if there is a small action you can take that will have an impact on a wild animal you care about. There are some great tips that will help you live cleaner and sustain our irreplaceable wildlife.

Stanford Web Services Blog: Adaptive Architecture: Leave Room to Evolve

Drupal News - December 12, 2014 - 6:55am

All forward-thinking technologies share one attribute: the original designers intentionally build in opportunities for future users to innovate. It requires humility and a belief in the creativity of others. This is true for buildings, computers, networks, and other tools.

Gábor Hojtsy: The Drupal 8 configuration schema cheat sheet

Drupal News - December 12, 2014 - 2:20am

After over a month of concentrated work, Drupal 8 was ready today to finally flip the switch and enforce strict configuration schema adherence in all TestBase derived tests in core. See the announcement in the core group.

If you are a Drupal 8 contrib developer and provided some configuration schema earlier (or you integrate with an existing core system like blocks, views, fields, etc.) then your tests may now fail with configuration schema errors. Unless of course all your configuration schema is correct: #highfive for you then.

Otherwise I thought you'll have questions. There is of course the existing configuration schema documentation that I helped wrote. However if you are a visual person and want to get an understanding of the basics fast, I thought a cheat sheet would be a great tool. So sat down today and produced this one in the hopes it will help you all! Enjoy!

Blair Wadman: Programmatically assign roles to users in Drupal

Drupal News - December 12, 2014 - 12:24am

This post is part of a series of posts on making changes in Drupal programmatically rather than in the Drupal interface.

In this tutorial, we will be programmatically assigning role(s) to user(s). You would typically do this in a site deployment module in order to automate this task rather than having to manually assign the roles in the Drupal UI.

Bluespark Labs: 10 Challenges You Face when Designing for Locations

Drupal News - December 11, 2014 - 9:00pm

Designing a website for an organization with multiple locations is challenging. Especially when those locations have their own needs, goals, and identities. Libraries, in all shapes and sizes, face many challenges when building or redesigning their website. They need to build something that students and patrons can use for research as well as something that actually helps people interact with the library’s various locations. This becomes especially difficult when the library is spread across several buildings and departments — and the people that work at the different libraries often have very different ideas about how their library should be represented on the Web.

Building a great library website is an ambitious project with the ultimate goal of serving the students, faculty, staff, and community.

On the surface, building a library website might feel like just another web project, but when you dig into it, you see there are many, many unique challenges stemming from the unique relationship the library has with it’s virtual and physical spaces. In this article, I explore 10 of those challenges and some possible solutions. Like any web project, though, every situation is unique. I prefer to focus on guidelines and considerations rather than describe actual solutions.

Challenge #1 - Who is our primary audience and what is their context of use?

What’s interesting about Universities—and Libraries fall victim to this, too—there are plenty of audiences to go around and each of their needs must be met for the website to be considered a success. Unfortunately, having too many audiences is like having too many cooks—you end up with something bland that no one likes.

Once you know who your primary audience is, you can explore their Contexts of Use. Contexts of Use are the place, time, and situation in which they will be using the website.

  • When will they need help finding a location?

  • What in the space are they looking for? (A building? Equipment? Something else?)

  • Where are they when they need to find that location?

Sidenote: When we talk about audiences, we also often talk about their goals. Multiple audiences might have similar goals. (How many audiences for a University Library have “Conduct independent research” as a primary goal?) Contexts of Use, though, differentiate these goals across the audiences. A student who needs to conduct independent research at the library website will approach it differently than a faculty member.

So why are contexts of use important? Well, they reveal things like why people are searching for a location (meeting a group, or maybe they need a copy machine, or maybe they want a quiet place to study) and allow you to design experiences for those contexts.

Challenge #2 - Are we a library? Or do we have libraries?

University Libraries are spread all over campus. There’s almost always “The Library” — the one building that everyone thinks about when you tell them to meet you at “The Library” but that is probably just one location of many.

Not to mention the many affiliated libraries—the independent collections managed by departments—the literature collection tucked away in the basement of the Humanities building. How are these related to the library and does your audience understand that relationship? Often this is a question much bigger than a website design project—venturing into your overall strategy, but the answer (and its trickle down effects) can hinder or help your audience accomplish its goals.

And all that leads to the question: Are you a University Library—or are you the University Libraries? It’s an identity question that affects your brand, the representation of that brand online, and the freedom you give the individual libraries.

Challenge #3 - Libraries are not Buildings

Repeat after me: Libraries are not buildings. For some of your libraries, this is painfully obvious. A special collection might be tucked into the corner of a building—be considered its own department, have its own hours and staff. That library is located within a building.

For other libraries, though, it’s less obvious. For example, at the UCLA Library, the Powell Library is located in the Powell Library building, but so are several special collections. You see the confusion? In the physical world, libraries have a special connection to the information they hold—that is the only place you can access that information. It goes without saying that, in the virtual world, these boundaries no longer exist. But because our understanding of physicality (that, and the trend of naming a building after its current use) lead to a tendency to conflate the actual library with the building that houses it.

Where it becomes painfully obvious is when a library is spread across multiple buildings—something that can often happen in space-starved Universities. (And let’s be honest, no matter how large the University, there is always a need for more space.)

There are several key instances when confusing the building with the library will actually create project over-runs. Buildings need to be managed separately from the libraries. The buildings, like the libraries themselves, may have unique names and will definitely have physical locations.

Even more challenging, though, is that this misunderstanding can also lead to poor decision-making about how to structure content. Just like the books and journals of a library live within the physical walls of building, some library staff might think their content should live within the virtual walls of their particularly library’s sitelet. This is where having well-defined persona with prioritized goals and contexts of use become critical to the success of the project. You can use these to explore whether people are first finding a specific library before beginning their search OR are they expecting to search for relevant research from a centralized research section OR something else entirely. (And, of course, stir in a healthy dose of usability testing to verify your hypothesis.)

Challenge #4 - Finding the right location

Here’s a fun one.

How do you know people are getting the right location?

It’s easy when you have a library called The Humanities Library and people are searching for the Humanities Library. But what happens when you have The John Doe Library of the Humanities and people refer to it as the Hum. Or some people call it the Hum and others call it the Humanities Library. It can get confusing real quick if you don’t have an option to add nicknames to your libraries (add nicknames to your buildings while you’re at it, too).

Challenge #5- When the library doesn’t matter, but the location does...

Finding a location is pretty easy when people are searching for a specific location—whether that be a library or a building. But there are plenty of contexts in which a user needs something that is location-agnostic.

Maybe they need a copier or a printer or a computer. Most libraries will have copiers spread all over campus—and some with different pricing. Keeping track of all the amenities that each location offers can be no easy task, but can go a long way to helping your audience actually get what they need from the library.

Tip: Think beyond equipment and things like wifi. Do some libraries offer study rooms? Or some places might offer a group study area where you don’t need to keep your voice down. These are all important amenities that people will be looking for. Taking note of the questions your students are asking about your locations will give you insight into the types of amenities you should be offering and how you should be categorizing your various locations.

Challenge # 6 - Is it open?

One of the biggest challenges seems like it would be the simplest. Students (and all of your audiences, really) need to know one of two things: 1) Is it open now? 2) Will it be open when I need it?

Of course, answering these questions is tricky. You’ve got your normal hours, your holiday hours, your end-of-the-semester hours, your summer hours—so many special circumstances, how do manage them all, much less present them to the user in an easy to read format? There’s really no simple answer other than to keep it as simple as possible and to conduct usability testing on sketches and prototypes with real users.

One of the useful, yet tricky, things we did with UCLA was to add “Open Now” as a search facet, so that all results returned only buildings that were open now—particularly useful for the students that needed a late night copy machine (context of use!) as well as including an “Open Now” indicator right in the location pages’ navigation bar.

Challenge #7 - Destinations within a location

“Is it open?” is not always an easy question to answer. Often, you will have destinations within a location that have separate hours than the main location. While the library will be open, the computer room might not be.

The solution we implemented for UCLA Library was to allow each location to have Destinations with their own descriptions, contact information, and hours. A future iteration of this should also include walking directions from various entrances—assuming that those entrances are clearly designated.

Challenge #8 - What’s going on at the Library?

Libraries host some great events that need to be listed on the website. There are, though, two challenges you face with events.

The first part of this challenge comes from conflating the building and the library as illustrated by this story:

Once upon a time, there was a librarian that worked at the Library of Biological Sciences. She took it upon herself to organize a lecture series from visiting scientists. The first event’s popularity took her by surprise; she had reserved the largest room in her library’s space, but it was still standing room only. So, for the second event, she opted to host the event at the Humanities Library who had a space twice the size of her largest space.

Challenge part 1: If the Library of Biological Sciences is hosting an event at the Humanities Library space, does the event display on the Library of Biological Sciences sitelet?

Challenge part 2: The Library of Biological Sciences is hosting an event at the Humanities Library space, should that event display on the Humanities Library sitelet?

And the answer (drumroll, please): it’s complicated. Ideally, it displays in both areas. Both libraries have an interest in promoting the event (and it should be the same content—not two different entries), though they have different reasons for doing so. The Library of Biological Sciences wants to promote an event they have spent a lot of time and resources organizing while the Humanities Library wants to let people know what’s going on in their space.

The real answer: It should be up to the sitelet moderators to determine what events they promote. They should have strong guidelines generated from Engagement and Content strategies, but the final decision comes from the autonomy you give the libraries themselves. (More on that to come.)

In the above challenge, the Library of Biological Sciences is hosting an event related to Biology in the Humanities Library space. It’s pretty clear cut as to why the two might want to promote the event. But what if the Humanities Library were to invite the author of a crime thriller that paid exquisite attention to the forensic details of the case—something that many people from the Library of Biological Sciences might be interested in? Should the event display on the Library of Biological Sciences sitelet?

The answer is not a simple one. Probably, yes, it should. Again, though, it should be up to the sitelet moderator who would be following Engagement and Content strategies.

Challenge #9 - Balancing autonomy and control

How unique are your locations? From the space they contain to the style of signage and posters used throughout the library. Maybe some of the smaller libraries don’t have a unique brand while the larger ones do. Or, perhaps, your library system has a style guide that all of your staff rigorously apply in everything they create.

Ideally you find a nice balance between command-and-control and complete anarchy. You want each location to feel part of the same family without taking away the things that make them feel unique. There are several ways to do this, including allowing each location to:

  • control the type of content they include on their homepage.

  • customize some of the visual styles on their page -- perhaps background image and other areas that can affect the basic feel of the site.

  • control the layout of their homepage.

You want to give your staff enough autonomy that they can ensure their library sitelet best represents the unique branding and style they have crafted in their space.

Challenge #10 - Consistency between the virtual and the physical

On the flip side of giving your staff autonomy, we have the need to give your audiences a consistent experience across locations and on the website. At its simplest, this means that you display the same information in the same way across sites. An event should look the same across all sites.

It goes deeper than this, though, even into the branding and labeling across your entire Library system, which is really a much larger project than the website redesign. But if you think about it (and I know librarians have!), a key part of finding your way through the physical location is the signage. As much as possible, you should create consistency between the signage in your spaces -- meaning that all libraries are consistent in the labeling and iconography.

Designing location search becomes so much easier when all libraries refer to the place with all the computers as the same thing. Keep labels the same across the different locations. If you call it a “Computer Lab” at one location, resist the urge to call it the “Computer carrels” at another location. (This might mean some overall discussions within the libraries—nothing like a joint project to surface all the inconsistencies that might be confusing your audience.)

Controlled Vocabularies are your friend—both in labels and in iconography. Further, this consistency also helps your audience understand what’s available at a location (as presented on the location pages and search results) and even navigate to those destinations within the space.

Take the UCLA Library as an example. The UCLA Library used some custom made icons to designate various destinations in their libraries, creating consistency across the various locations, the main website, and the location sitelets. Once we started creating the Destinations for each location, we realized that not all Destinations had iconography, so our creative director spent some time expanding on their visual vocabulary. It was critical that everything used on the website feel like it could also be dropped onto library signage without appearing out of place.

Here you can see some of their signage and how iconography plays an important role in conveying what’s available at the destination.

Both the locations and destinations on the website use these same icons to communicate the available amenities.

Sidenote: Consistency can be useful when it’s helpful. But it can also get in the way of communicating important differences—whether those differences come from the brand or facility. Divergence can be a good thing. You just need to ensure that the divergence is meaningful and useful for your audience. Perhaps there is a difference in a Computer Lab (a place where students can use computers) and Computer Carrels (a place designed for laptop use -- no computers provided). However, subtle differences may not be important to people and calling attention to them may only serve to confuse them more.

Bonus Challenge - Who owns what

One last, very important aspect of any web project: who is responsible for editing and maintaining the content on the website. Even if you have a copywriter or two, you are still faced with the gargantuan task of maintaining a mountain of information. (And sadly, this is no exaggeration.) No matter your process for editing and creating content, you need to identify the owner of each content and what their responsibilities entail. (Are they editing the content as needed? Are they filing change requests to the copywriter?)

In Conclusion...

Reconciling the needs of these varied and diverse stakeholders, libraries, locations, and library users can be a daunting task.  Hopefully, if you take the time to address the challenges in this series your end result will meet the needs of the most important audience—as well as many of the needs of your secondary and tertiary audiences.  With such a large network of stakeholders and users, you won’t please everyone, but with good user research and usability testing, you’ll get a lot closer to that goal, and you’ll have a firm foundation for the choices you make.

Tags: Drupal Planet

Propeople Blog: Drupal UX Improvements: When Node Forms are a Nuisance

Drupal News - December 11, 2014 - 3:16pm

Node forms can be big. With field collections, reference fields, tags, taxonomies, location fields, and others, node forms can actually be really big. This can make an editor’s experience so frustrating that it’s a surprise she doesn’t have a heart attack when she sees how much data she needs to enter in order to save the form.

Sound familiar? Well, in this article we will share some tips and tricks that we use to simplify editors’ lives and to make the Drupal editing experience more user-friendly.

Split a form into tabs

If you have too many fields on one screen, it’s nearly impossible for an editor to remember what he entered in the beginning by the time he’s reached the end of the page. The answer to this quandary is simple: it’s time to split up the form.

It is possible to use different criteria to split forms into more manageable sections, or tabs. The criteria you’ll use will depend on the type of form and its intended purpose. Forms can be split up by field types, required vs. optional fields, priority rank, more vs. less frequently used; the list goes on. To create an even better user experience, ask the editors themselves about how they’d like forms to be organized. If they have been using a particular form for a while, it’s likely they’ll have plenty of valuable feedback regarding the best way to make the forms more intuitive and improve the efficiency of their workflow.

From a technical perspective, there are multiple ways to achieve more manageable forms. The one we use most frequently utilizes vertical tabs. An example of this is shown in the screenshot below.

 

Vertical tabs help editors to concentrate on one thing at a time and improves the navigation experience when working with especially large forms. A good rule of thumb is to divide the form into chunks that won’t require users to scroll through more than 1 to 1.5 pages to complete all the elements on any given section.

In addition to vertical tabs, you have the option to set up horizontal ones. This can easily be achieved with the Field Group module.

Split a form into columns

Some editors set up their workstations to use fairly wide screens. In this case, another practical approach is to have multiple columns. This solution can be used to nicely group fields together so they can be viewed side by side.

Drupal's Panels module make it easy to configure forms that use columns. Simply set up the layout for a node’s edit form and arrange the fields however you like.

Warn editors about unsaved changes

If you use JIRA or Google Docs, you’ve probably seen a warning message like the one shown below.

 

For a busy editor juggling multiple tasks, this friendly little pop-up can be a lifesaver. And of course… there’s a module for that.

Allow us to introduce Node Edit Protection. It helps editors to remember to save their changes before navigating away from a form. This becomes especially handy if you’ve split your forms into multiple tabs, as editors may think that simply switching to another tab automatically saves their changes.

Taxonomy tag widgets

You won’t hear any complaints from us about the standard autocomplete feature and the way it enables editors to quickly select appropriate tags. There are multiple widgets, however, that put the icing on the autocomplete cake. One of these that we particularly like is Chosen.


 

Another good one is Autocomplete Deluxe.

 

Links

Sometimes editors need some help building links in WYSIWYG or when using link fields. This is especially true when editors need to search for and quickly locate the content or URL they want to reference. Enter the Linkit module, which acts as a link-specific autocomplete function.

 

With the Linkit Picker module, we can even have a custom view to search for the content we would like to link to. This allows us to configure additional filters to help editors find content more effectively.

 

References

If you are using reference fields, there is a nifty module called References Dialog. This module allows editors to create a referenced entity while working within a node using a dialog box.

 

This comes in very handy, especially when your referenced entities include only a handful of fields and can fit comfortably into the dialog pop-up.

May we suggest...

For more great ideas that will have editors singing your praises, check out this presentation from DrupalCon Amsterdam 2014 about building a better backend, as well as our colleague Boyan Borisov’s presentation about improving Drupal's editorial experience.

Interested in learning even more about how Propeople can create a Drupal platform with user-friendly backend functionality for you? Don't hesitate to contact us.

Tags: DrupalUXcontent managementService category: TechnologyCheck this option to include this post in Planet Drupal aggregator: planetTopics: Tech & Development

Drupal core announcements: All TestBase derived tests now enforce strict configuration schema adherence by default

Drupal News - December 11, 2014 - 1:03pm

Configuration schema was originally introduced to help describe configuration for translations. Then it expanded considerably and is now used to export configuration entities automatically for example (unless you want to write code to manually define what to export). Configuration schema is also used to automatically typecast values to their expected types. This ensures that although PHP and web forms in general favour strings over all other types, the right types are used when saving configuration. That is important so when deploying configuration, only actual changes will show up in the difference, no random type changes. Schema enforces certain rules and best practices of configuration on its users, for example that each piece in the active configuration should have an owner. Finally configuration schema based configuration validation helps find several types of bugs in code that is otherwise not or incorrectly tested.

Therefore after a month+ of work to make all core tests pass strict configuration schema checking, we are making TestBase default to strictly check all configuration against configuration schemas. There are only a few tests exempt from this in the testing of the configuration system itself. This affects all contributed module developers writing TestBase (WebTestBase, KernelTestBase, etc.) extending tests. This may result in new test failures which indicate either issues in your schema, your configuration, your tests, migrations, etc. Either way it indicates that in some cases unexpected data structures are generated.

Read more in the change notice.

Mediacurrent: Upcoming Webinar: Migrating The Weather Channel Onto Drupal

Drupal News - December 11, 2014 - 8:39am

The Weather Channel (TWC) has one of the most trafficked websites in the world, which makes it one of the largest Drupal sites in the world.

Blink Reaction: Creating Custom Search Pages with Search404 and Apache Solr Search

Drupal News - December 11, 2014 - 8:19am

Imagine somewhere deep in your site that you have a page with the alias:

/how-to-build-drupal-site.

Now, let’s imagine this page is not a link in your site’s menu. Your visitor remembers that they have seen this page on your site and starts typing in the address line:

Acquia: 5 PHP Components every Drupal 8 Developer should know: Part 2 -- Guzzle

Drupal News - December 11, 2014 - 7:15am

In our previous blog post, we took a look at Composer, a PHP-based class autoloader and dependency management tool, and used it to begin managing some dependencies and downloaded Guzzle. Guzzle is a PHP-based HTTP client library that greatly simplifies the process of consuming RESTful web services. In this blog, we’re going to explore some of Guzzle’s basic abilities, and use it to begin building a simple SDK of sorts.

Code Karate: Drupal 7 Sweaver Module: Change your theme style with no CSS code

Drupal News - December 11, 2014 - 5:49am
Episode Number: 185

The Drupal 7 Sweaver module makes it easy to change the style of your Drupal theme without having to write any CSS code or dig through any template files. The Sweaver module provides a simple to use designer toolbar that sits at the bottom of the page and allows you to instantly change the look of your Drupal theme.

Tags: DrupalDrupal 7Theme DevelopmentDrupal PlanetUI/DesignCSS
Syndicate content