Resetting the omega Mixin in Bourbon Neat

While having a hard time making automatic rows with Bourbon Neat I stumbled upon this awesome little mixin, thankfully shared by Josh Fry.

It allows you to reset the nth-child margins and clearings, most helpful when you want to create different sized automatic rows at various breakpoints.

I just keep it here for my own future reference:

1.) Set the flexgrid column and gutter in your grid settings:

$fg-column: $column;
$fg-gutter: $gutter;

2.) Save the omega-reset mixin:

@mixin omega-reset($nth) {
  &:nth-child(#{$nth}) { margin-right: flex-gutter(); }
  &:nth-child(#{$nth}+1) { clear: none }
}

3.) Use it:

.drupal-features {
  li {  
    @include media($desktop) {
      @include span-columns(4);
      @include omega(3n);
    }
    @include media($medium) {
      // reset the previoulsy set omega(3n) so it won't conflict 
      // with the omega(2n) used at this breakpoint
      @include omega-reset(3n);
      @include span-columns(6);
      @include omega(2n);
    }
  }
}

Help the GNOME project defend its trademark!

Groupon has announced a product called Gnome, trying to claim the name of the popular desktop for Linux and BSD desktops that has been around for 17 years. This is outrageous!

Even if you don’t use the GNOME desktop yourself (I don’t do neither) please consider donating to the GNOME Foundation to help them protect their trademark and set a signal that FLOSS projects will be protected.

This legal defense is not just about protecting GNOME’s trademark; it is about asserting to the corporate world that FLOSS trademarks can and will be guarded. Not just by the project in question, but by the community as a whole. As a result, all FLOSS trademarks will be strengthened at once.

— Lucas Nussbaum, Debian Project Leader

Keeping your Local Sites after Updating to OS X 10.10 Yosemite

As my iMac is my primary work station I’m always a bit hesitant when it comes to major OS upgrades.

Here are the experiences and issues I had when upgrading form Mavericks (10.9) to Yosemite (10.10).

  1. All important applications run without any problems so far
  2. Homebrew and installed bottles kept on working
  3. Ruby (installed via Rbenv) and installed Gems keep on working
  4. Node.js and installed modules kept on working
  5. My hosts file stayed untouched
  6. MySQL kept on working, including all database data, of course (simply had to start the service again)
  7. Apache Virtual hosts didn’t work anymore, but it was easily fixed be re-including my httpd-vhosts.conf file from httpd.conf
  8. PHP wasn’t enabled anymore, but it was simply fixed by re-including the Apache module from httpd.conf
  9. When trying to access my local virtual hosts I got loads of permission denied errors with the apache log file talking about AH01630: client denied by server configuration. This is caused by Apple updating Apache to 2.4. It’s simply fixed by adding Require all granted to your vhosts. (replaces Order allow,deny and Allow from all from Apache 2.2, see http://httpd.apache.org/docs/2.4/upgrading.html)
  10. SSH-Config and keys kept on working
  11. Drush (installed via Composer) kept on working

So, everything was up and running again within 10 minutes tops after the upgrade \o/

Responsive Sticky Footer with flexible height

Thanks a lot to Galen Gidman for sharing his solution to create Responsive, Flexible-Height Sticky Footers in CSS – works like a charm.

Update
Turned out this causes Firefox and Internet Explorer to ignore max-width: 100% on images. To solve this we need to add table-layout: fixed; to the body tag (CSS below updated).

Markup

<header class="page-row">
  <h1>Site Title</h1>
</header>

<main class="page-row page-row-expanded">
  <p>Page content goes here.</p>
</main>

<footer class="page-row">
  <p>Copyright, blah blah blah.</p>
</footer>

CSS

html,
body { 
  height: 100%; 
}
body {
  display: table;
  width: 100%;
  /* Fix for Firefox and IE to keep correct max-width behaviour on images: */
  table-layout: fixed;
}
.page-row {
  display: table-row;
  height: 1px;
} 
.page-row-expanded { 
  height: 100%; 
}

Setting up and Using Environments with htaccess

This .htaccess snippet does the following:

  1. Create two environments called staging and development based on the host name
  2. Set up ht authentication only on the stage server (Deny from env=staging)
  3. Rewrite all requests to the main domain (www.mysite.com) if we’re not on either the development nor staging environment and the host doesn’t already equal the main domain
AuthName „Staging Server"
AuthType Basic
AuthUserFile /var/sites/mysite/.htpasswd
AuthGroupFile /dev/null
require valid-user

SetEnvIf Host mysite.klickreflex.com env=staging
SetEnvIf Host mysite.dev env=development

Order Allow,Deny
Allow from all
Deny from env=staging

Satisfy Any

<IfModule mod_rewrite.c>
  RewriteBase /

  RewriteCond %{ENV:env} !development
  RewriteCond %{ENV:env} !staging
  RewriteCond %{HTTP_HOST} !^mysite\.dev$ [NC]
  RewriteCond %{HTTP_HOST} !^www.mysite\.com$ [NC]
  RewriteRule ^(.*)$ http://www.mysite.com [R=301,L]
</IfModule>

On github: https://gist.github.com/klickreflex/779683dcc62a7776dcab

Drupal: Keep EXIF orientation and allow manual cropping of images

Wow, this is more troublesome than expected.

Goal: Let users upload images straight from a camera and manually select an area of the image that should be cropped.

Issue: nearly all modern cameras use EXIF information to tell an images orientation. Drupal image actions ignore this information and all images in landscape format resulting in flipped portrait images. Imagecache Actions module provides an action to rotate images based on EXIF data. But: this doesn’t work if the image was resized to the maximum dimensions straight after the upload. And: it doesn’t play nice with most image cropping modules.

I’ve been fighting this issue for some hours now and have something that seems to work for me. It’s not extensively tested yet, though. Here’s what I came up with:

Modules:

  • ImageMagick instead of GD as Image Toolkit (because GD strips EXIF data)
  • Imagecache Autorotate, part of [Imagecache Actions](Imagecache Autorotate) that provides an Image Action that automatically rotates pictures according to their EXIF orientation
  • EPSA Crop module: EPSA crop was the only cropping module that allowed me to use its after the Autorotate action in my image style preset (I tried at least with manualcrop, imagefield_crop, simplecrop)

In my image style I use the following actions:

  1. Autorotate image based on its EXIF data
  2. EPSA Image Crop, 150×150 (with Aspect Ratio of one, as the resulting image has a square AR)
  3. Scale and Crop, 150×150, scale and crop it even if it wasn’t manually cropped.

Only drawback so far:
EPSA Crop doesn’t show you the cropped image on the thumbnail of the edit page, so users might be confused if their cropping was successful after all.

Originally posted on DrupalAnswers, might be interesting to follow the discussion

Hope this helps others saving some hours of research.

Hover Intent for CSS-only Dropdown Menus

Looking for a way to improve on my pure CSS dropdown menus I found an article by Chris Poteet where he shared his thoughts simulating an hover intent effect by using CSS transitions. The snippet had a big drawback, though: anything that is under the dropdown menu, even when it’s not dropped down, cannot be focused anymore. The solution is to simply not trigger the dropdowns opacity property but it’s visibilty. I forked Chris’ snippet on Codepen with my little change: Pen

The HTML

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li class="children"><a href="#">About</a>
      <ul>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
      </ul>
    </li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>
<p>Text wiht <a href="http://www.wentsch.me/">A</a> and other text.</p>

The CSS

body {
    background-color: #283B4F;
    font: 0.8em arial,sans-serif;
    padding-top: 10px;
}

a {
    color: #fff;
    text-decoration: none;
    text-transform: uppercase;
    background-color: #96A4AB;
    padding: 10px;
    -webkit-transition: background-color 200ms linear;
    transition: background-color 200ms linear;
}

a:hover {
  background-color: #7e919b;
}

ul > li {
    float: left;
    list-style-type: none;
    margin-left: 0;
}

li.children {
    position: relative;
}

li.children a {
  padding-right: 20px;
}

li.children > a:after {
    content: "";
    border-width: 5px;
    border-style: solid;
    border-color: #fff transparent transparent;
    position: absolute;
    right: 3px;
    top: 6px;
}

li.children:hover ul {
    visibility: visible;
    position: absolute;
    top: 20px;
    left: 10px;
}

ul ul {
    margin-left: 0;
    padding-left: 0;
    visibility: hidden;
    -webkit-transition: visibility 100ms linear 700ms;
    transition: visibility 100ms linear 700ms;
    position: absolute;
    top: 20px;
    left: 10px;
}

ul ul li {
    float: none;
    margin-left: 0;
    margin-top: 15px;
}

p { clear: both; margin: 5em; }

Generate and display preview images for your PDF files with Drupal

When serving PDF files it’s always nice to show a little preview image of the document.

These are the steps I needed to take to get a preview image of the first page of any uploaded PDF document.

  1. Make sure you have ImageMagick available on your server and that the convert executable can be called from PHP (As my hosting company provides a precompiled version of ImageMagick I only needed to enable the extension by adding extension="imagick.so" to my php.ini)
  2. Install the ImageMagick module for Drupal
  3. Make ImageMagick your default image toolkit and make sure you have set the correct path to ImageMagick’s convert binary on admin/config/media/image-toolkit (for me that is /usr/bin/convert)
  4. Check if ImageMagick works correctly (e.g. Upload an image and check if derivative images are generated without errors)
  5. Install the PDF Preview module for Drupal
  6. Go to admin/config/media/pdfpreview and hit save (change your preview image dimensions if desired, but keep it big, we can later use other presets to display the image). It’s important so save this page, no matter if you changed any setting at all, otherwise the image generation won’t work (see https://www.drupal.org/node/2223677)
  7. Choose the PDF Preview formatter in the display settings of a file field that contains your PDF files and choose your desired image preset.
  8. Done!

Update: Accessing preview images from PDF Preview programmatically

After I was happy with the functionality provided by the modules it turned out I needed to access the preview images from my templates in order to show additional information about the file, such as download links and file size and description. Turns out it’s quite easy using _pdfpreview_create_preview(). Just throw your file object as a parameter and you’ll get the desired preview image of that file returned! Here’s a little snippet that iterates all files of a multi-value file field and outputs each field as a list item with the preview image rendered with an image preset (katalog in this case) and shows the file description below (file links are still missing but easy to implement):

<?php if($field_produkt_kataloge): ?>
  <ul class="field-produkt-kataloge">
    <?php foreach($field_produkt_kataloge as $katalog): ?>
      <li>
        <?php $katalog_preview_url = _pdfpreview_create_preview($katalog);?>
        <?php $katalog_preview_image = theme('image_style', array('style_name' => 'katalog', 'path' => $katalog_preview_url)); ?>
        <?php print $katalog_preview_image; ?>
        <?php print $katalog['description']; ?>
      </li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

Drupal Base Theme Mothership breaks Contextual Links

Simple CSS solution. Set the trigger to display: block;:

// Contextual links
.contextual-links-region:hover a.contextual-links-trigger {
  display: block;
 }

Instead of patching mothership as it’s suggested in the source link, I’d recommend doing this in your own subtheme.
As soon as mothership-7.x-3.0 gets a stable release it shouldn’t be needed anymore as it has been committed to dev already.

Source: https://www.drupal.org/node/1677374

Drupal Custom View Modes & Templates per View Mode

Just a quick reminder how to programmatically create your own Drupal 7 View Modes.
Replace superdrop_helpers with the name of your own module and listing with the desired name of your Drupal View Mode.

<?php 
/**
* Implements hook_entity_info_alter().
* Creates a new view mode called <listing>
*/
function superdrop_helpers_entity_info_alter(&$entity_info) {
  $entity_info['node']['view modes']['listing'] = array(
    'label' => t('Auflistung'),
    'custom settings' => TRUE,
  );
}

/**
* Implements hook_preprocess_node().
* Template file suggestion for the previously generated view mode
* e.g.: node--article--listing.tpl.php
*/
function superdrop_helpers_preprocess_node(&$vars) {
  if($vars['view_mode'] == 'listing') {
    $vars['theme_hook_suggestions'][] = 'node__' . $vars['type'] . '__listing';
  }
} 

Thanks to wunderkraut for their article on this topic, check it out if you need more explanation than just the snippet:
http://www.wunderkraut.com/blog/drupal-7-custom-node-view-modes/2010-12-20

Drupal Module Comparison: Publish Button vs Safe Draft

To publish and unpublish content in Drupal you ususually have to tick or untick the Published checkbox before hitting the Save button. Sparing your users a click is alway a good idea, so why not considering a module that simplifies the action of publishing and unpublishing content.

Please welcome Publish Button and Safe Draft.

Both modules will simply add button actions to your nodes to publish/unpublish content instead of ticking that clumsy checkbox.

Here’s why I opted for Publish Button over Safe Draft:

  • Publish Button is actively maintained, Safe Drafts was last updated in 2011
  • Publish Button can be enabled per-content type whereas Safe Drafts is always enabled globally
  • Publish Button features per-content type permissions
  • Publish Button hides empty vertical tabs opposed to Safe Draft, which shows the Publishing options tab even when it’s completely empty

Drupal User Registration and Login with Email instead of Username

Drupal’s default registration process is more complicated than it should be. To simplify the process I like my users to sign up and log in with only their email address and password.

There are various ways to deal with that issue, with Login Toboggan being one of the most popular ones. However, I rarely need all the other stuff that comes with this module and I prefer small modules that focus on a single task. Besides, Login Toboggan only allows to login with an email address as an alternative to the username, it doesn’t remove the need to create a username in the first place.

So what I found best for my needs is a combination of the Email Registration module and a tiny custom module.

E-Mail registration enables registration and login with email address only. It also auto-generates a username with the fist part of the user’s email address. Almost what I wanted, but I prefer to have username and email the exact same value. Luckily, Email Registration provides a hook called hook_email_registration_name(). So we can implement this hook in our own module to alter the username as we wish.

To exactly match the username with the user’s email address that is as easy as:

<?php
/* 
 * Implements hook_email_registration_name(). 
 */
function MYMODULE_email_registration_name($edit,$account) {
  return $account->mail;
}

Output a Field Collection’s Item ID and build a Jump Navigation

It just took me a while to figure this out, as I needed the Field Collection’s ID to build anchors for a (views built) jump navigation. Here’s how I’m wrapping each Field Collection item with a section tag that has a CSS ID with each Field Collection item’s unique identifier.

<section id="section-<?php print $elements['#entity']->item_id; ?>">
  <?php print render($content); ?>
</section>

For future reference here’s also the (simple) View that builds the jump navigation from Field Collection titles. It takes the node ID as an contextual filter from the URL. So you just get a jump navigation for the Field Collection items from the host node that’s currently being displayed. Note that this View expects a field named field_section_title to use for the menu item.

$view = new view();
$view->name = 'jumpnav';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'field_collection_item';
$view->human_name = 'Sprungnavigation';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Sprungnavigation';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['use_more_text'] = 'mehr';
$handler->display->display_options['access']['type'] = 'none';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['exposed_form']['options']['submit_button'] = 'Anwenden';
$handler->display->display_options['exposed_form']['options']['reset_button_label'] = 'Zurücksetzen';
$handler->display->display_options['exposed_form']['options']['exposed_sorts_label'] = 'Sortieren nach';
$handler->display->display_options['exposed_form']['options']['sort_asc_label'] = 'Aufsteigend';
$handler->display->display_options['exposed_form']['options']['sort_desc_label'] = 'Absteigend';
$handler->display->display_options['pager']['type'] = 'none';
$handler->display->display_options['style_plugin'] = 'list';
$handler->display->display_options['style_options']['default_row_class'] = FALSE;
$handler->display->display_options['style_options']['row_class_special'] = FALSE;
$handler->display->display_options['style_options']['wrapper_class'] = '';
$handler->display->display_options['row_plugin'] = 'fields';
/* Beziehung: Field collection item: Entity with the Abschnitt (field_section) */
$handler->display->display_options['relationships']['field_section_node']['id'] = 'field_section_node';
$handler->display->display_options['relationships']['field_section_node']['table'] = 'field_collection_item';
$handler->display->display_options['relationships']['field_section_node']['field'] = 'field_section_node';
/* Feld: Field collection item: Field collection item ID */
$handler->display->display_options['fields']['item_id']['id'] = 'item_id';
$handler->display->display_options['fields']['item_id']['table'] = 'field_collection_item';
$handler->display->display_options['fields']['item_id']['field'] = 'item_id';
$handler->display->display_options['fields']['item_id']['exclude'] = TRUE;
/* Feld: Field collection item: Titel */
$handler->display->display_options['fields']['field_section_title']['id'] = 'field_section_title';
$handler->display->display_options['fields']['field_section_title']['table'] = 'field_data_field_section_title';
$handler->display->display_options['fields']['field_section_title']['field'] = 'field_section_title';
$handler->display->display_options['fields']['field_section_title']['label'] = 'Title Raw';
$handler->display->display_options['fields']['field_section_title']['exclude'] = TRUE;
$handler->display->display_options['fields']['field_section_title']['alter']['strip_tags'] = TRUE;
$handler->display->display_options['fields']['field_section_title']['element_type'] = '0';
$handler->display->display_options['fields']['field_section_title']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['field_section_title']['element_wrapper_type'] = '0';
$handler->display->display_options['fields']['field_section_title']['element_default_classes'] = FALSE;
$handler->display->display_options['fields']['field_section_title']['field_api_classes'] = TRUE;
/* Feld: Field collection item: Titel */
$handler->display->display_options['fields']['field_section_title_1']['id'] = 'field_section_title_1';
$handler->display->display_options['fields']['field_section_title_1']['table'] = 'field_data_field_section_title';
$handler->display->display_options['fields']['field_section_title_1']['field'] = 'field_section_title';
$handler->display->display_options['fields']['field_section_title_1']['label'] = '';
$handler->display->display_options['fields']['field_section_title_1']['alter']['alter_text'] = TRUE;
$handler->display->display_options['fields']['field_section_title_1']['alter']['text'] = '<a href="#section-[item_id]" title="Zu [field_section_title] springen">[field_section_title]</a>';
$handler->display->display_options['fields']['field_section_title_1']['element_type'] = '0';
$handler->display->display_options['fields']['field_section_title_1']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['field_section_title_1']['element_wrapper_type'] = '0';
/* Kontextfilter: Inhalt: Beitrags-ID */
$handler->display->display_options['arguments']['nid']['id'] = 'nid';
$handler->display->display_options['arguments']['nid']['table'] = 'node';
$handler->display->display_options['arguments']['nid']['field'] = 'nid';
$handler->display->display_options['arguments']['nid']['relationship'] = 'field_section_node';
$handler->display->display_options['arguments']['nid']['default_action'] = 'default';
$handler->display->display_options['arguments']['nid']['exception']['title'] = 'Alle';
$handler->display->display_options['arguments']['nid']['default_argument_type'] = 'node';
$handler->display->display_options['arguments']['nid']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['nid']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['nid']['summary_options']['items_per_page'] = '25';

/* Display: Subnavigation */
$handler = $view->new_display('block', 'Subnavigation', 'block');
$translatables['jumpnav'] = array(
  t('Master'),
  t('Sprungnavigation'),
  t('mehr'),
  t('Anwenden'),
  t('Zurücksetzen'),
  t('Sortieren nach'),
  t('Aufsteigend'),
  t('Absteigend'),
  t('field_section'),
  t('Field collection item ID'),
  t('.'),
  t(','),
  t('Title Raw'),
  t('<a href="#section-[item_id]" title="Zu [field_section_title] springen">[field_section_title]</a>'),
  t('Alle'),
  t('Subnavigation'),
);

Using Bolt CMS SimpleForms on 1&1 Hosting

Of course I’d highly recommend not using 1and1 (1und1 in Germany) at all, but if you are forced to and wonder why Bolt CMS’ nice SimpleForms extension won’t send any email and instead throws a Swiftmailer Exception: you have to set the host of the mailoptions configuration in your main config.yml to mrvnet.kundenserver.de.

Remove indentation for Gumby Fancy Tiles

A great feature of the Gumby Framework is its ability to easilycreate responsive tiles. They call those Fancy Tiles. For example you can use the following mixin to create a equally distributed grid with 5 columns on a desktop, 3 on a tablet and 2 on a mobile screen.

ul.fancy { 
  @include fancytiles (5,3,2);
}

What kept bugging me with that is that each tile gets a padding on both its left and the right side. This makes the entire Fancy Tiles show up indented compared to the columns of Gumby’s regular grid system.

To get rid of that indentation and align my Fancy Grids with the rest of the page layout I forked _fancytiles.scss and called it _fancytilesoutside.scss. Opposed to the original Fancy Tiles it must be applied to the container of your tiles, eg the <ul> tag if your <li>s are supposed to be tiled. Triggering the outer elmenet allows us to apply a negative margin on the left and right side that is of the exact size as the tile’s padding, thus pulling the entire tile set outside. Then the styling of the tiles themselves happens by applying the original fancytiles scss to every direct descendant of the container.

@function divide-cols($colnum) {
  @return 100%/$colnum;
}

@mixin fancytilesoutside($desktop-columns, $tablet-columns: $desktop-columns, $mobile-columns: 1, $small-break: 0px, $medium-break: $tablet-device-width, $large-break: $row-max-width) {
  margin-left: -$gutter / 2;
  margin-right: -$gutter / 2;
  > *{
    // These styles apply to all shift-columns
    display: inline-block;
    float: left;
    padding-left: $gutter / 2;
    padding-right: $gutter / 2;

    // IE8 fallback
    width: divide-cols($mobile-columns);

    @include respond("min-width: #{$small-break}") {
      width: divide-cols($mobile-columns);
    }

    @include respond("min-width: #{$medium-break}") {
      width: divide-cols($tablet-columns);
    }

    @include respond("min-width: #{$large-break}") {
      width: divide-cols($desktop-columns);
    }
  }
}

Update

The following mixin will work with later versions of Gumby (my current project runs on 2.6.3). The renaming of the mixin to fancytilesunindented is only for aesthetic reasons.

@function divide-cols($colnum) {
  @return 100%/$colnum;
}

@mixin fancytilesunindented($desktop-columns, $tablet-columns: $desktop-columns, $mobile-columns: 1, $small-break: 0px, $medium-break: $tablet-device-width, $large-break: $row-max-width) {
  clear: both;
  margin-left: -$gutter / 2;
  margin-right: -$gutter / 2;
  overflow: hidden;
  > *{
    // These styles apply to all shift-columns
    display: inline-block;
    float: left;
    padding-left: $gutter / 2;
    padding-right: $gutter / 2;

    // IE8 fallback
    width: divide-cols($mobile-columns);

    @include respond("min-width: #{$small-break}") {
      width: divide-cols($mobile-columns);
    }

    @include respond("min-width: #{$medium-break}") {
      width: divide-cols($tablet-columns);
    }

    @include respond("min-width: #{$large-break}") {
      width: divide-cols($desktop-columns);
    }
  }
}

Link a Drupal Image Field to the destination of a Link Field

By default, Drupal’s image fields don’t allow to dynamically link them to the path set inside another field. There are module to tackle this such as Image Link Formatter and Link Image Field.

I prefer keeping display settings in code. It’s really easy to wrap any Image Field with the destination of a Link Field of your choice inside a node template using l() the function:

// If there's an image and a link we wrap the link around it
if($field_pub_bild && $field_pub_link) {
  $linked_image = l(render($content['field_pub_bild']), $field_pub_link[0]['url'], array('html'=> TRUE, 'attributes' => array('target' => '_blank')));
}

Just make sure you set html to TRUE, otherwise the image tag will get escaped. For further options look at the documentation of the l() function: https://api.drupal.org/api/drupal/includes!common.inc/function/l/7