Back to Android: First Impressions

As my iPhone 4S became painfully slow after updating to iOS 7 I didn’t want to pay another fortune to Apple just to get a modern OS running smoothly. Also, there are some things really annoying me more and more on iOS, some of the worst being not to have an option to set a default browser and email client and not having global sharing/send-to-app options for third party apps. Also, I really like using GMail a lot and the performance of the iOS app is just a major PITA.

So, I got myself a new Nexus 5 and here are my first impressions as well as a little overview of the apps I quite liked so far.

Camera

I didn’t expect to buy a device that’s able to compete with the iPhone camera wise, so my expectations weren’t too high. Still, in low light conditions I’m a bit underwhelmed by the quality it produces (a lot of noise). Also, I still haven’t found the perfect camera replacement app suited for my needs. I think I’ll get used to it and fiddle my way around. As with most cameras when light conditions are good image quality seems satisfying.

Battery Life

I’m not sure yet as I’ve been using my Nexus extensively, installed apps, played games and fooled around, so, granted, the battery got drained really quick. Still, my feeling is that it’s not enough capacity. Haven’t tried any battery saving apps yet though.

Apps

Just some of the apps I find myself using a lot.

Press / 2,25 €

A really beutifully designed RSS reader that syncs with Feedly, Feed Wrangler, Feedbin and Feed a Fever. In my opinion on par with Reeder for iOS.
Besides the good design Pocket/Instapaper and image caching for offline reading were important to me.
https://play.google.com/store/apps/details?id=com.twentyfivesquares.press

VSCO Cam / free + IAP

Being a big fan of VSCO the release of their great app for Android was actually a reason for me to dare jumping off the iOS ship! The UI is basically the same as on iOS but with the new processing power of the Nexus it’s way faster. Probably true for the iPhone 5S, too. I was really impressed that my In-App purchases I bought on iOS could be re-downloaded to Android without paying again. Awesome!
https://play.google.com/store/apps/details?id=com.vsco.cam

SwiftKey / 1,99 € (currently on sale)

Everybody tells you to use SwiftKey so I gave it a shot – and I won’t go back. Besides still having to learn to handle the bigger device predictions and corrections are WAY better than on iOS. You can keep your thumb on the screen and swipe around the letters you’d like to write and, with surprising precision, SwiftKey recognizes what you’d like to say. Of course you can just type conventionally. Even though you can switch the main input language predictions and auto corrections for other languages will always be presented, which is a major relief if you ever tried throwing in some English words into your otherwise German text. There’s a free lite version available to give it a shot.
https://play.google.com/store/apps/details?id=com.touchtype.swiftkey

Carbon / free

I haven’t tried lots of Twitter clients yet, Carbon seems ok so far. If you know an alternative that feels a bit more like TweetBot please tell me. I miss the swipe gestures on a single tweet to show conversations/replies.
https://play.google.com/store/apps/details?id=com.dotsandlines.carbon

Whatsapp / free for the first year

Yea, nothing special here. But: this is the first app where I find home screen widgets a useful feature. You can put shortcuts to contacts on your homescreen and directly jump into conversations. Awesome!
https://play.google.com/store/search?q=whatsapp&c=apps

AirDroid / free

This one I still remember from the not-so-good old days of Android 2.x. AirDroid allows you to access your device from a web browser to manage files and write text messages. Coming from iOS I just love the simplicity of quickly uploading some music without the hassle of iTunes.
https://play.google.com/store/apps/details?id=com.sand.airdroid

Smart Audiobook Player / free + IAP

Granted, the icon is horrible and the UI kind of a mess. But if you enjoy audio books I think it’s still a must have (and it’s not as ugly as Mort Player at least). Smart Audiobook Player lets you choose your main audiobook folder,and shows its contents even if there’s a .nomedia file inside (if you put such a file inside a folder it won’t be shown by default media players and image viewers). You can add bookmarks, set a sleep timer and even decide to stop playback when your device wasn’t moved for a certain amount of time.
https://play.google.com/store/apps/details?id=ak.alizandro.smartaudiobookplayer

Camera FV-5 / 2,99 €

I’m still looking for an appropriate alternative to my beloved iOS app ProCamera. This is so far the only app I could find that allows you to set focus and exposure separately using your fingers. It works, but it feels a bit sluggish and it’s unfortunately really not comparable with its competitors on iOS. There’s a ton of other features I don’t really care about too much.
https://play.google.com/store/apps/details?id=com.flavionet.android.camera.pro

And of course there are some apps that probably don’t need any further description:

  • Snapseed
  • Pocket (missing swipe gestures to quickly mark articles as read from the overview)
  • GMail (way better than on iOS)
  • Chrome
  • Spotify (seems to use too much background data, keep watching it)
  • Facebook
  • Instagram
  • DB Navigator
  • Dropbox
  • dict.cc
  • Quizduell Premium (ugly as hell, but still fun playing)
  • VLC
  • Zattoo

Different Image Presets depending on the number of images in a Drupal multi-field

The other day I had the task to display the image of a multi-upload image field with a bigger image style if there was only one image uploaded.

I solved it by using a combination of the following modules:

In the display settings of my content type I created a duplicate of my image gallery field using Display Suite‘s Dynamic Field. (You could also achieve this by using Display Suite’s Code Field or creating a Computed Field that just outputs the value of your gallery field.)

For that new instance of my gallery field I set the desired bigger image style and the instruction to only show the first image if there are multiple.

Now I had the small gallery thumbnails and the big image being shown on node view.

Detect the number of images uploaded to a multi value field

To count the number of images uploaded to the gallery field I created a new Computed Field that I named field_detect_single_image with the following Computed code:

if(isset($entity->field_bildergalerie['und'])) {
  $image_counter = count($entity->field_bildergalerie['und']);
  if($image_counter == "1") {
     $entity_field[0]['value'] = 'single-image';
  }

Note that field_bildergalerie is the name of my original gallery field, so change it accordingly.

This code simply counts the number of array elements inside my gallery field and saves it to $image_counter. If $image_counter has the value 1it simpy saves the string single-image to the computed field. This is the value we will now check agains using Field formatter conditions

The Display Code is just left with the default value:

$display_output = $entity_field_item['value'];

Note: you’ll have to re-save all existing nodes for the computed field’s code to run. I recommend using Views Bulk Operations if you have lots of nodes to re-save.

Checking field values to conditionally hide fields using Field formatter conditions

Now we can go back to the display settings of our node and add conditions to both our original gallery field and the mirrored one with the bigger image style.

Hide the gallery field when there’s only one image uploaded

Simply open the Conditons fieldset for the original instance of the gallery field and add the following conditon:

  1. Hide when target field does not contain a string
  2. Select target field: Detect Single Gallery Image (e.G. the name of your computed field)
  3. Enter target string: single-image

Hide the big single image when there’s more than one image uploaded

On the copy of our field instance which shows the bigger image simply add the reverse condition (Hide when target field does not contain a string):

That’s basically it.

Can’t re-download previously purchased Program on the Mac AppStore

Mac AppStore failure

Today the Mac AppStore was bugging me quite a bit. I wanted to download and install an app that I had purchased some months ago. It failed with some message telling me I should try it from the Purchases tab of the AppStore. This looked like in the screenshot, the button didn’t do anything (see screenshot). In the Applications folder there was an icon with an unfinished progress bar of the app I was about to install. I deleted it, but alone that didn’t help.

Clean the AppStore caches

What did the trick was deleting the AppStore caches. To find their location open a Terminal window and enter open $TMPDIR../C/. A new Finder window will pop up and bring you to some crazy directory structure where you’ll find a directory called com.apple.appstore. I deleted it, restarted my Mac and voilà, I could redownload my desired App. It didn’t show up with an Install button as usually with already bought programs but with the price tag and the Buy button. I felt adventurous though, accepted it and entered my password. Luckily the AppStore now told me that this “Update” was free to install as I had bought it previously. Phu!

Keep navigation bar fixed after scrolling to a certain element

Say you want to tack younav bar fixed at the top of the browser’s viewport after a user has scrolled to a certain element in the DOM. In my example this is the menu itself. This snippet checks the vertical position of my main menu and adds a class to it after a visitor has been scrolling that far that it reached the top of the page.

$(document).ready(function() {
  var navpos = $('#mainnav').offset();
  console.log(navpos.top);
    $(window).bind('scroll', function() {
      if ($(window).scrollTop() > navpos.top) {
        $('#mainnav').addClass('fixed');
       }
       else {
         $('#mainnav').removeClass('fixed');
       }
    });
});

Source

Add proper mime types for web fonts

In case you’re using web fonts and notice Chrome warning you with something along Resource interpreted as Font but transferred with MIME type application/octet-stream: ".../Content/Fonts/iconFont.ttf". you need to add the following to your .htaccess file:

# transfer fonts as proper mime types
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-font-woff .woff

Found on StackOverflow

Display Drupal Nodes that share the same Taxonomy Term using Views 3

Yesterday I found a great little guide that comes in handy if you want to display nodes that share the same taxonomy term as a block, for instance to show related articles directly when viewing an article:
Show related nodes in a block based on taxonomy terms with Views 3 and Drupal 7. It’s originally based on another article at Metachunk: Adding a related content view in Drupal 7.

I just copied the steps over here for future me:

  1. Create view (block)
  2. Add fields (title, a small image, date, whatever you like). Or teasers, what works as well.
  3. “Arguments” is from now on called “Contextual filters”, so go there.
  4. Add the filters: “Content: Has taxonomy term ID (with depth)” and “Content: Has taxonomy term ID depth modifier”
  5. Configuration on this filter: → When the filter value is NOT in the URL: → Provide default value → Type: Taxonomy Term ID from URL → under that, check the box “Load default filter from node page, that’s good for related taxonomy blocks.” → now check the boxes of the taxonomies you want involved here
  6. Now you need to add the second filter in order to exclude the current node from the list. Click [+] button of the contextual filters section.
  7. Select Content: Nid
  8. Set the ‘when argument is not present’ to ‘Provide default argument’
  9. Set the ‘Default argument type’ to ‘Content ID from URL’
  10. Go to “MORE” , and check the “Exclude” box.
  11. Move the filter “Content: Nid” to the top position.
  12. Add a block to your view and embed the block on your node pages
  13. Save your view

Thanks to Nicholas G. Maloney and Scito for sharing!

Override Drupal’s form “required” asterisk to an arbitrary string

Great tip on overriding Drupal’s required string using form api. Just put into your theme’s template.php:

<?php
function THEME_form_required_marker($variables) {
  // This is also used in the installer, pre-database setup.
  $t = get_t();
  $attributes = array(
    'class' => 'form-required',
    'title' => $t('This field is required.'),
  );
  return '<span' . drupal_attributes($attributes) . '>(required)</span>';
}
?>

Source and further reading: http://knackforge.com/blog/selvam/drupal-form-api-overriding-required-field-asterisk

Drupal 7 and Views 3: Date granularity for Grouping

Say you try to group events by date and you have several events at the same day but at different times. I thought I’d just add another date field to my view, set it to d.m.Y and group by that. Didn’t work out, for every time of the day there will still appear a new group. The solution is simple: just strip all html tags for the date field you want to group by. This will remove any RDF attributes from the field, thus really having the same grouping values on a per-day-granularity. This will work for any other granularity as well, just add the desired date format and you’re good to go!

Drupal 7: Search inside Field Collections

Field collections are awesome, but they have a serious drawback: anything that’s stored inside field collection fields isnt’t indexed by Drupal’s core search.

Here are just some quick & dirty notes of what I did to get those fields searchable:

  • disable core search
  • Install search_api, search_api_page and all dependencies
  • Install search_api_db (no search result summaries), fuzzysearch (sometimes weird results) or zend_lucene (just testing, zend as a requirement) as search server
  • add search server
  • add index (and configure all entities to search in)
  • add search page and according block

On installing Zend within Drupal (on a managed server provided by DomainFactory):

  • installed zend module (7.x-3.0-alpha-1)
  • installed composer using curl -sS https://getcomposer.org/installer | php53
  • installed zend php53 composer.phar install (from inside sites/all/modules/zend
  • having lots of errors
  • updated to zend module 7.x-3.x-dev (2012-10-30)
  • ran php53 composer.phar update
  • status report says zend 2.2.1 is installed correctly

Installing Zend Lucene:

  • Install module
  • create new server

Zend Lucene was still not working though. Haven’t had time to investigate further.

Drupal 7: Hide a Block for a certain content type

Per default block configuration you can only decide to show a block for certain content types, the other way around requires a little bit of PHP. The following snippet hides a block on nodes of type article and blog:

<?php
  // Only show if $match is true
  $match = true;

  // Which node types to NOT show block
  $types = array('article', 'blog');

  // Match current node type with array of types
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $nid = arg(1);
    $node = node_load($nid);
    $type = $node->type;
    if(in_array($type, $types)) {$match=false;}
  }
  return $match;
?>

jQuery scrollTo without a Plugin

Today, when I quickly needed a solution to smoothly scroll to another position on the same page I was hesitant to just throw another jQuery plugin into my site so I started looking for a more lightweight solution. Here’s what I found:

$('html, body').animate({
    scrollTop: $("#elementID").offset().top
}, 2000);

It can just be put inside any callback function, e.g. click(). The following example will scroll to an ID called page-title upon clicking a link with the class scroll-to-title (in 500 ms):

$("a.scroll-to-title").click(function() {
  $('html, body').animate({
    scrollTop: $("#page-title").offset().top
  }, 500);
});

Thanks to A Beautiful Site for sharing!

Render desired image presets as colobox links from within Drupal templates

Updated: 2014/04/16

A little helper function I almost forgot about and dug out today again. For future me:

<?php
/**
 * Get Colorbox Link
 * Takes an image object and two styles and creates an image tag with the first style
 * that opens the the second style inside a colorbox
 * @param array $image Image object that will be displayed
 * @param string $style_name Image style to display the image
 * @param string $style_name_colorbox Image style to be displayed inside the colobox overlay
 */
  function _colorbox_link($image, $style_name = 'medium', $style_name_link = 'large') {
    if(isset($image)) :
    $image_style = theme('image_style', array(
      'style_name' => $style_name,
      'path'       => $image['uri'],
      'alt'        => $image['alt'],
      'title'      => $image['title']
    ));

    $url = image_style_url($style_name_link, $image['uri']);

    $link = l($image_style, $url, array(
      'html' => TRUE,
      'attributes' => array(
        'rel' => array('colorbox-gallery'),
        'class' => array('colorbox colobox-template')
    )
    ));

    return $link;
    endif; //if isset
  }

// Little variation of _colorbox_link(): Takes an image object and displays it with the desired preset
  function _get_image_style($image, $style_name) {
    $image_link = theme('image_style', array(
      'style_name' => $style_name,
      'path'       => $image['uri'],
      'alt'        => $image['alt'],
      'title'      => $image['title'],
      'attributes' => array('class' => 'no-colorbox')

    ));
    return $image_link;
  }

Just put this into your theme’s template.php and use it from whichever template file you like.

Update

I just added a fourth parameter $show_caption that, if set to TRUE, allows to print the image’s title attribute as a caption below the image

<?php
/**
 * Get Colorbox Link
 * Takes an image object and two styles and creates an image tag with the first style
 * that opens the the second style inside a colorbox
 * @param array $image Image object that will be displayed
 * @param string $style_name Image style to display the image
 * @param string $style_name_colorbox Image style to be displayed inside the colobox overlay
 * @param bool $show_caption Set to TRUE to show the title attribute as a caption below the image, defaults to FALSE
 */
function _colorbox_link($image, $style_name = 'medium', $style_name_link = 'large', $show_caption = FALSE) {
  if(isset($image)) :
    $image_style = theme('image_style', array(
      'style_name' => $style_name,
      'path'       => $image['uri'],
      'alt'        => $image['alt'],
      'title'      => $image['title']
    ));

    $url = image_style_url($style_name_link, $image['uri']);

    $link = l($image_style, $url, array(
      'html' => TRUE,
      'attributes' => array(
        'rel' => array('colorbox-gallery'),
        'class' => array('colorbox colobox-template')
    )
    ));
    if($show_caption) {
      $link .= '<p class="image-caption">'.$image['title'].'</p>';
    }

    return $link;
  endif; //if isset
}

Keep your social content yours – using Drupal?

Granted, most stuff spread across various social networks doesn’t seem important.
But I must confess that, from time to time, I simply like scrolling through my timelines at Facebook, Twitter, Instagram and the like and I wouldn’t find it too cool, if all that was gone. I don’t want to talk about the actual risk of my data vanishing, rather thinking about alternatives. I remember ideas of online applications like Sweetcron, which had its primary focus on collecting the data you created across social networks and gather them in one place.

Why shouldn’t we do it the other way around? Having you own self hosted platform for Tweets, Images, Blogposts, Links, Quotes – you name it. These would be translated to some basic content types, quite similar to Tumblr. And then simple publishing options checkboxes to decide, to which social stream(s) you want to share your update. Which fantastic open source software has most of the bits and pieces readily available for exactly that? Yep, that’s Drupal.

At least to me a Social Media Hub Drupal Distribution seems really worth a shot. What do you think? Have there possibly even some efforts been made?

Fluxkraft is most definitely the project to watch when it comes to connecting various platforms and services.

Of course, thinking about mobile is crucial. Besides Drupal 8’s native mobile efforts Drupad shows, that it’s well possible to have a universal app to use with any kind of Drupal installation.

This is just some brainstroming, collecting ideas and possible tools. I’m just excited about going back to a more open and distributed web, keeping what’s yours under your control while using existing networks for distribution and interaction. And yes, removing Facebook comments in favor of Drupal’s own comment system is a step that’s overdue for me here personally.

I’d be glad to hear some opinions.

Htaccess-Authentication based on Host name

Let’s say you have a multisite installation with several (sub)domains pointing to the same document root. Now, you want to protect private.domain.com with ht-authentication while www.domain.com stays publicly available.
Please welcome Apache’s setEnvIf as your friend:

AuthName "Private" 
AuthType Basic 
AuthUserFile /var/www/.htpasswd
require valid-user

SetEnvIf Host private.domain.com secure_content

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

Satisfy Any

Source: http://stackoverflow.com/a/6953716/93261

Debugging Cron

I guess most Drupal site builders have had issues with cron being stuck from time to time. On a recent project I again had this issue and it seemed to be really relunctant to go away by just deleting some cron_last entries.
So I dug deeper and found the Cron Debug module. Cron Debug allows you to run each cron hook individually and track the time needed to execute each hook. This helped me to quickly identify the search index hook being the cause of my troubles, as it always caused an error 500.

So it seemed pretty obvious that some or several bad nodes were causing the problems. Thanks to this blog post on tappetyclick I found the following snippet which simply writes a watchdog entry for every node being indexed. So when cron gets stuck, the last node mentioned in your log is highly probable to be some kind of problematic. For me it was a node that had some base64-encoded images inside a textarea. Probably some crazy CKeditor feature that tries to enable copy & paste for images, but that’s a different story.

Anyways, here’s the snippet for modules/node/node.module:
Notice: you just have to add the line watchdog ('cron', "indexing node {$node -> nid}"); at the right place.
Don’t forget to revert your changes when you’re done identifying your evil nodes!

/**
 * Implements hook_update_index().
 */
function node_update_index() {
  $limit = (int)variable_get('search_cron_limit', 100);

  $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit, array(), array('target' => 'slave'));

  foreach ($result as $node) {
    watchdog ('cron', "indexing node {$node -> nid}"); // ADD THIS LINE
    _node_index_node($node);
  }
}