Tuesday, February 25, 2014

Drupal 7 - Creating a contentype with repeatable expandable fieldcollections

I want to make me a simple to manage contenttype containing fields and field collections that I can present as collapsible fields.
On page load the field value will be hidden and the labels will be shown as clickable links. Clicking them will expand the content of the field.
I want to use field collections in the same way, but there give the maintainer the power to edit the 'label'. Adding fieldcollections of the form (title, content) should do that. On page load the title will be shown as a clickable link, and clicking on that will expand the content.

For the collapsing functionality we use, as it is already there, ctools.

1. make a field display collapsible with ctools
In general using ctools it's very easy to make a field display collapsible.

1.a Put this function in your template file
function MyTheme_collapse_content($c_content, $collapse_heading) {
   print theme('ctools_collapsible', array('handle' => $collapse_heading, 'content' => $c_content, 'collapsed' => TRUE));
}

1.b  In the field template file simply put this code
<?php
   $collapse_heading = $label;
   foreach ($items as $delta => $item): 
     $c_content.='<div class="field-item ';
     $c_content.=$delta % 2 ? 'odd' : 'even'; 
     $c_content.='"';
     $c_content.=' '. $item_attributes[$delta].'>';
     $c_content.= render($item).'</div>';
   endforeach;
  MyTheme_collapse_content($c_content, $collapse_heading);
?>

1.b.1 template naming
If you worry what to name the field template files simply check https://api.drupal.org/api/drupal/modules!field!field.module/function/theme_field/7


Now, how to accomplish this task for the fieldcollections?

2. Add a fieldcollection field to the contenttype
In this example called Page or machinename field_event_sub_page
2.1 Add two fields to the fieldcollection
2.1.a text field page_title
2.1.b  and a textarea page_text (filtered html)

Now you can add field collections to the node consisting of a text field (page_title) and a textarea (page_text).
Now I want these text fields  (the page_title) to show as links, and clicking on these links should open the corresponding textarea's (page_text), giving me a single ode behaving more or less like a book with only two levels.

Using the ctools collapsing the problem is now reduced to getting the page_title and page_text field content in the $c_content and the $collapse_heading variables in a theme function like the above:

  MyTheme_collapse_content($c_content, $collapse_heading);

This is usually a very annoying deconstruction of the fieldcollection instance, I must say I get lost a lot of times.
But now I found this very elegant solution by Mike Minecki



2.2  put these functions in your template.php

function MyTheme_preprocess_field(&$vars, $hook) {
  $element = $vars['element'];
  if (isset($element['#field_name'])) {
    if ($element['#field_name'] == 'field_event_sub_page') {
    $vars['theme_hook_suggestions'][] = 'field__event_sub_page_collected';// waar is dit eigenlijk voor nodig

     $field_array = array('field_fesp_linktitle', 'field_fesp_text');//must match the fields you added to the field collection
    rows_from_field_collection($vars, 'field_event_sub_page', $field_array);
    }
  }
}

function rows_from_field_collection(&$vars, $field_name, $field_array) {
  $vars['rows'] = array();
  foreach($vars['element']['#items'] as $key => $item) {
    $entity_id = $item['value'];
    $entity = field_collection_item_load($entity_id);
    $wrapper = entity_metadata_wrapper('field_collection_item', $entity);
    $row = array();
    foreach($field_array as $field){
       $row[$field] = $wrapper->$field->value();
    }
    $vars['rows'][] = $row;
  }
 }


2.2   Put this rendering in your fieldcollection template file
In this example that would be the field--field_event_sub_page.tpl.php template file.
 <?php 
   foreach($rows as $row): 
      $collapse_heading $row['field_fesp_linktitle'];
      $c_content $row['field_fesp_text']['safe_value'];
      MyTheme_collapse_content($c_content, $collapse_heading);

   endforeach; ?>

Accessibility - Using images as a link conforming to Dutch webrichtlijnen overheid

As I always forget this, here is a micro-blog-post about this requirement for the Dutch Govermental organisations. Governmental sites need to comply with the 'Webrichtlijnen overheid versie 2'.

It is allowed to use an image as the content of a link, as long as the image has a useful and descriptive alt text.

Ref. criteria for succes 2.4.4, 2.4.9 en 4.1.2



Rejoice!







Thursday, February 6, 2014

Drupal - Accessibility: ways of adding language attributes to parts of your text that differ from the main page language


 One of the accessibility rules, especially targeted to screen readers, is that text parts written in a language different  from  the main page and navigation language should  be tagged (or more correctly 'attributed') with this other language, so the screen readers know when to use what language.

I remember the fun we had on the Institute for Plasmaphysics Rijnhuizen (Nieuwegein, the Netherlands) making the first Macs with screenreaders   read out  a Dutch text. As the reader was only able to read english texts a perfectly readable Dutch text came out as Jibberish spoken by someone who's been drinking Jenever (dutch booze) all day while eating a tuna-sandwich.....

Here I show two ways how to achieve this, (that is adding the attributes to the tags, not the tuna-sandwich part).
Case 1 in Drupal 6 wysiwyg with Tinymce, and Case 2 in Drupal 7 with CKEditor.  Goal is to select a part of the html,  and add a language attribute. Or to the containing tag or to add a span tag...

        <tag>Lorem ipsum and so forth</tag>

should become

      <tag lang="en">Lorem ipsum and so forth</tag>


CASE 1      Drupal 6                                                

D6 site, with the WYSIWYG module using tinymce
1. Add html attributes button to your RTE
1.1 Go to Administer > Site configuration > wysiwyg profiles
1.2 edit any of the profiles where you want the users to be able to add the language attribute
admin/settings/wysiwyg/profile/1/edit
1.3 Open 'Buttons and plugins'
1.4 Check 'HTML attributes'
1.5 Save



Result: How to add a language identifier
In your browser you can now find a new button

a. Select part of a text and click this button
This opens up a popup screen where you can add attributes




















b. Behind language add the language identifier for the language usedf.i. en (english), nl (dutch) etc.
See also http://www.w3schools.com/tags/ref_language_codes.asp
c. Click insert
And the language identifier is added to the tag containing the textpart.
NB!
If you add an identifier to a part where a mother tag already contains the same language identifier, the identifier is not added. This seems logical because there is no need for this identifier at all.



Problem: adding lang attribute to inline tags
You cannot add attributes to inline tags like <span>
This is really annoying cause you have lots of cases where the other language words or sentences are inline with the other text. Like when I tell you the Dutch word for annoying is irritant.


Solution: use <em>
But a solution is to use the <em> tag and css. The html attributes will be added to the <em> tag.
NB!
a. First make the text part italic!
b. Then select part of the inside italic text, not all, and add the language identifier.
c. Save

If you select the whole italic part (including the em tags), the system will find the nearest containing tag and add the language identifier to that one.
d. To avoid the other language being shown as italic, you can target this em element with the language selector in the css.
http://www.w3schools.com/cssref/sel_lang.asp

So like when you main language identifier is english

          em:lang(nl),em:lang(fr), em:lang(ge)
          {
             font-style:normal;   
          }                                  


NB!

Adding the em:lang(en) in the above css would change all em to normal, because the language selector simply looks for any language identification, may it be in the tag itselve, or in the header of the document like <html lang="en" dir="ltr" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">


<em lang="zh-Hant">希望對您有所助益<em>

PROBLEM!
There is a major problem in Drupal concerning these attributes. From the accessiblity viewpoint, it should be very simple to add a language attribute to every element. But I have to figure out yet how to add a language attribute to a field like the title. (Or the resulting display of this in a nodereference rendering)
There are two language layers here you have to consider: The field language, which simply identifies in which languagepart of the site you want this field to show up, so in case of content translation this is the context language of the container entities, in case of field translation it is the [lang] part of the field.
For instamce, Being Dutch have nodes with partly Dutch and English titles: "Presentatie resultaten onderzoek 'Designed to Last' op 8 oktober 2014".
Trying to convince my governmental organisations to change the titles of their reports to solid Dutch does not work, so I have to deal with this. The result should be

<h1>Presentatie resultaten onderzoek <span lang="en" xml:lang="en">'Designed to Last'</span> op 8 oktober 2014</h1>

I solved it using a jquery on the specific nodes with these kinds of titles, but thats rather an unsatisfying solution.


CASE II : Drupal 7                                                   

So, I figured out how to do this in Drupal 7 with CKEditor.  There is a CKEditor plugin you can install and download
Of course, because why should  life be easy, there are some irritating bugs or features or whatever....

0. Plugin
You can download the plugin from here
https://github.com/fredck/CKEditor-Languages-Plugin

In the example hereunder my module path  is
  /sites/all/modules/contrib/ckeditor
and I've installed the ckeditor itself in
  /sites/all/modules/contrib/ckeditor/ckeditor

1. Now make a folder 'languages' in 
/sites/all/modules/contrib/ckeditor/ckeditor/plugins

2. put plugin.js and icon.png in this folder
/sites/all/modules/contrib/ckeditor/ckeditor/plugins/languages

3. open ckeditor.config.js in the root of your module and add these lines

    config.extraPlugins
= 'languages';
    // The languages you want to support (code:name).
    config.language_list = [ 'de:German''fr:French', 'es:Spanish', 'it:Italian', 'en:English' ];

NB! This is different from the installation instructions on GIThub.

4. Clear your Drupal cache AND clear your browser cache
(the ckeditor does not clear its javascript files on the normal Drupal cache clear)

5. Go to your CKEditor settings and add the languages button to your editor
(In an older version the visual UI did not work, but the manual did. Now this seems ok)


6. Content filters
You'd probably might have to change you content filters to allow for these attributes, but apart from that it should work. I had to add

     p h1 h2 h3 h4 em span [*]

under the extra allowed content in the ckeditor setting for my filtered and full html
(/admin/config/content/ckeditor/edit/Filtered)
For more infor on this see http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules


7. Rejoice in many languages
And yes, ganz lustig,  it works

    And yes, <span dir="ltr" lang="de" xml:lang="de">ganz lustig</span>, it works



Tuesday, February 4, 2014

Make two divs equal height with jquery (in Drupal)

One problem I often face is that I have two divs, a content div and next to it another div with a menu, or links to related content or whatever. And I want both divs, f.i. #content and #rightbar, to be equal height, but they are added loosely to the html bacause the html needs to be responsive.  Sometimes you can get it working with css, but lots of time I get lost.
One solution is to simply compare the two and make them equal height with a javascript/jQuery function.


function equalHeight(one,two) {
   var tallest = 0;
   tallest=one.height();
   if (tallest < two.height()) {
      tallest=two.height();
   }
   one.height(tallest);
   two.height(tallest);

}


Call this function in a document ready like so

(function ($) {
// drupal jquery wrapper
     $(document).ready(function() {
        equalHeight($("#content"),$("#rightbar"));

     });

     function equalHeight(one,two) {
         var tallest 0;
         tallest=one.height();
         if (tallest two.height()) {
         tallest=two.height();
         }
         one.height(tallest);
         two.height(tallest);

         }
// emdof drupal jquery wrapper
}(jQuery));

Monday, February 3, 2014

Lost books of the Bible: The book of Metatheria

There must be a lost biblebook which explains why all marsupials went straight to Australia after Noahs Ark stranded. 'Bye Noah, thanks for saving us!' And none of them decided to stop somewhere halfway in Afghanistan or China.


Well then, except for the opossum and the shrew opossum which went to respectively North and South America, and some lazy marsupials which, crossing Indonesia, decided to take a break and simply stayed there.


And they thus spoke to them, saying:  'Ah, don't worry, we'll cach up later....'.    But that's all explained in this lost Bible book: 1 Metatheria 2:7