Binding between Developers & ThemersNagailic Sergiu | Nikro
http://nikro.me | http://wearepropeople.com
Content:
http://nikro.me | http://wearepropeople.com
1. Overall theming tips○ Architecture
○ Layout planning
○ Theme installation and setup
2. Working with themes3. Working with modules4. Working with JS, CSS & libraries5. String formatting & Useful functions6. Block building7. JavaScript within Drupal
Overall theming tips
http://nikro.me | http://wearepropeople.com
Architecture:
● What modules to use and where?● What will be hard to render / theme?● What blocks will be dynamic? And how?● Will it be fixed or fluid layout?● What are the Restrictions / Visibility settings / Caching
conditions of the block/region/pane/whatever?
Overall theming tips
http://nikro.me | http://wearepropeople.com
Layout planning:
● On what grid-system is the design based on? (12/16) ● What should be a Theme region?● What should be a Theme zone? (Omega)● How many custom panel layouts do we need? (Oh yeah,
brand them)● What pages will be completely custom?
Overall theming tips
http://nikro.me | http://wearepropeople.com
Theme installation and setup:
● Pick a theme. (Omega / Adaptive / Framework / Mothership)● RTFM of picked theme. (RTFM - read the fucking manual)● Create a sub-theme.● Don't EVER alter the base-theme.● Discuss with the themer when you pick a sub-theme.● Set up your sub-theme.
○ Brand it.○ Define regions and zones.○ Define theme settings.
Overall theming tips
http://nikro.me | http://wearepropeople.com
Final planning:
● Just go through all of pages with a themer near you and define what will be blocks, panels, views, regions, zones, etc.
● Mark those on paper.
Working with themes
http://nikro.me | http://wearepropeople.com
Picking theme:
● It depends on complexity of the project and the themer you're working with:○ Some projects require minimalistic themes for a clean theming process○ Some projects require complex themes○ Some projects require responsive themes○ Some projects are strictly based on a grid-system
● Read the manual and make a correct sub-theme setup.
Structuring a sub-theme:
● Create valid folders in your theme:○ js, css, assets (or images), templates, panels (layouts live here), preprocess and
process (in Omega)● Use one generic script.js or boot.js where all theme-related behaviors will be defined.● Split your template folder in sub-folders for a quicker look-up (views, html-mail, pages,
fields, nodes, modules, regions, sections, etc)
Working with themes
http://nikro.me | http://wearepropeople.com
Working with template.php (in Omega):
● Omega splits all preprocess and process functions in 2 folders:○ preprocess sub-folder○ process sub-folder
● You don't have to have function chaos in template.php, each preprocess and process function "lives" in its own file within those folders.
● Do your best to be more specific at any preprocess or process overrides:○ use theme_preprocess($vars, $hook) to find the right preprocess hooks○ use theme_process($vars, $hook) to find the right process hooks○ use theme devel module to find most specific names
● Don't use hook_form_alter in template.php and other module-specific hooks.● Don't use heavy logic (database queries, http-requests, cache related logic) in template.
php● Template.php, template files, preprocess and process files are mostly for rendering
output and aren't the logic layer.
Working with themes
http://nikro.me | http://wearepropeople.com
Working with template.php (in other themes):
● You can either split your template.php the following ways (if theme doesn't support splitting):
○ Application-specific:
■ contrib.template.inc■ custom.template.inc■ theme.template.inc
○ Usage-specific:
■ preprocess.template.inc■ process.template.inc■ theme.template.inc
● Use include include_once to bind those together, in template.php and put all those files under includes sub-folder in your sub-theme.
Working with themes
http://nikro.me | http://wearepropeople.com
Working with tpl files:
● Folder-structure your tpls (again)● Don't use tpls as a logic layer:
○ don't make queries○ don't use globals○ don't save things○ don't inject JavaScript (no files, not even inline JS)○ don't inject CSS (no files, not even inline CSS)○ don't cache things○ don't do things that you think are wrong to do here
● If you need something new / extra in a tpl, use preprocessing or processing functions and send them to your tpl.
● Always use Drupal friendly functions (will cover those later)● Think twice before you do anything in a tpl.● Don't be shy to leave comments in a tpl (for instance available variables that you send
via preprocess / process functions)
Working with modules
http://nikro.me | http://wearepropeople.com
File structuring:
● Use a separate file for theming functions (includes/mymodule.theme.inc or theme/theme.inc)
● Use a separate folder for: js, css, tpls (templates) files● Try to not use in your module 3rd party libraries (js or php), instead use libraries folder
and libraries module.● Use a separate file for blocks building functions (includes/mymodule.blocks.inc).
In module theming:
● Think a lot when you define hook_theme:○ do you need theme function for this element, or a tpl file○ what will be the required variables passed to function or tpl○ what are the preprocess functions○ consult drupal.org for better overview: http://api.drupal.org/api/drupal/modules%
21system%21system.api.php/function/hook_theme/7● Use right preprocess and process naming:
○ http://api.drupal.org/api/drupal/includes%21theme.inc/function/theme/7● Refine what can be returned in a block as an HTML string, rendered tpl file or a simple
string so you will know what additional theming functions your module can use.
Working with JS, CSSand libraries
http://nikro.me | http://wearepropeople.com
In modules:● If you need to add, in a specific case a JS file, use drupal_add_js:
○ RTFM: http://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_add_js/7○ Inline JS is a bad practice, but sometimes necessary○ Be aware of the group and weight parameters
● If you need to add, in a specific case a CSS file, use drupal_add_css:○ RTFM: http://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_add_css/7○ Inline CSS is a bad practice as well (doh)○ Be aware of the group and weight parameters and media (for responsive
design)● If you need to add, in a specific case a bunch of CSS & JS files, use
drupal_add_library:○ Use hook_library to register a library○ Use drupal_get_library to get library information○ Define libraries if you are sure that someone else might re-use them.○ Define libraries if specified bunch of files work together as a feature.
Working with JS, CSSand libraries
http://nikro.me | http://wearepropeople.com
Form API:● If you want to use a form-specific JS, CSS or library use $form['#attached'] or
$element['#attached']:○ http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#attached○ #attached makes Forms work right when we use Ajax and/or Rebuild forms
● If you want to wrap-up some items in a div or some other html, put them into a container (a FAPI element) and use #attributes.
● Don't use #prefix on one item and #suffix on the other.● For a better theming, put actions buttons in 'actions' (FAPI element)● '#attributes' property must include HTML valid attributes (not any word out of this world)● 'class' (in '#attributes') is an array (just FYI)
String formatting
http://nikro.me | http://wearepropeople.com
String Friendly functions:● t($string, array $args = array(), array $options = array()) - is a helpful function, is
used to run the string through the translation layer, escapes variables because it uses format_string inside.
● st($string, array $args = array(), array $options = array()) - is the same as t() but can be use in a pre-bootstrap phase, is mainly used for installation profiles.
● format_string($string, array $args = array()) - is used to format a string, escape HTML using check_plain or via drupal_placeholders.
● format_plural($count, $singular, $plural, array $args = array(), array $options = array()) - is used to specify the right form of the word in singular and plural case. Uses t()/format_string() inside.
● format_date($timestamp, $type = 'medium', $format = '', $timezone = NULL, $langcode = NULL) - formats a date using a date type format or a custom date format string.
● format_username($account) - format a username.● format_interval($interval, $granularity = 2, $langcode = NULL) - formats a time
interval with the requested granularity.
● Or just go here: http://api.drupal.org/api/drupal/includes%21common.inc/group/format/7
Useful functions
http://nikro.me | http://wearepropeople.com
Other friendly functions:● l($text, $path, array $options = array()) - any time you need to create a link, please,
use this function. It looks up aliases and creates a beautiful link (i.e. node/123 becomes content/my-title)
● theme_image, theme_image_style, theme_image_{other} - use those for outputting images (don't write <img> tags as strings)
● theme_file, theme_file_link, theme_file_icon, etc - use those for outputting files / file links
● theme_links, theme_menu_local_task, theme_{whatever} - check out your autocomplete / intellisense or CTags suggestions and see if there's a theme function for that.
● drupal_html_class($class) - prepares a string for use as a valid class name.● drupal_html_id($id) - prepares a string for use as a valid HTML ID and guarantees
uniqueness.● hide()/show() - are used to set '#printed' to TRUE or FALSE as elements can be
printed only once per a page render.
● Others: just explore common.inc and other modules theming implementations.
Block building
http://nikro.me | http://wearepropeople.com
Blocks are essential to site-building:● We use them as blocks in a theme● We use them as panes in panels● We even use them as blocks that we insert into views regions (header, footer)
Blocks are easy to build / cache:● Basically a block is defined by a function that builds it and outputs an HTML string● It's fairly easy to define block caching when you define a block● We use a empty string that appends and appends and appends piece-by-piece strings
that in return results into one huge HTML string (not bad)● But even better, we have to use theme_{whatever} functions inside of that block, so
block will be less responsible for theming and more responsible for the logic (better)● Don't use one-two long-line HTML strings, they are hard to read.● Consider creating blocks with arguments (when blocks are different depending on
$user, $node, $other)
Blocks with Panels' contexts
http://nikro.me | http://wearepropeople.com
Blocks with Panels' contexts
http://nikro.me | http://wearepropeople.com
Working with JS
http://nikro.me | http://wearepropeople.com
Get to know Drupal.js - it's awesome:● Drupal.t() function, pretty much as the PHP t() function, passes the front-end string
through the translation layer.● Drupal.theme() function, works similar way to PHP theme() function, themes something
on the front-end side.○ http://engineeredweb.com/blog/11/5/javascript-theme-functions-drupal/
● Drupal.formatPlural() function, works similar way to PHP format_plural() function.● Drupal.formatString() function, works similar way to PHP format_string() function.● Drupal.checkPlain() function, works similar way to PHP check_plain() function.
Use Drupal.settings to store / get module settings:● You can check / reuse other modules settings (if the are present)● You can send different values / settings from your module (backend) to the JavaScript
(frontend) via drupal_add_js by using settings as the parameter● You can use Drupal.settings.myModule as a global site-wide storage for your
JavaScript values.
Working with JS
http://nikro.me | http://wearepropeople.com
Use Drupal.views and other Drupal.{otherModules}:● You can use Drupal.views and Drupal.settings.views to make magical things with
views.○ In example binding two views:
http://nikro.me/articles/professional/drupal-views-ajax
● You can use Drupal.ajax - to create Drupal-like Ajax calls.● Etc.
Use Drupal.myModule for your module API:● If you have custom functionality that you use in your Drupal.behaviors.myBehavior or
in Drupal.settings.myModule, put those into Drupal.myModule.● If you have custom functionality that can be reused by any other module or behavior,
also consider using Drupal.myModule.
Working with JS
http://nikro.me | http://wearepropeople.com
Use Drupal.behaviors.myModule:● attach(context, settings):
○ use context when you filter content, not $('.someClass') but $('.someClass', context).
○ use settings as a short version of Drupal.settings.○ understand when behaviors are attached and what context represents.
● detach(context, settings):○ use context when you filter content, not $('.someClass') but $('.someClass',
context).○ use settings as a short version of Drupal.settings.○ understand when behaviors are detached and what context represents.
● Clean-up after yourself, don't allow behaviors to be attached twice or more times.● If you don't use Drupal.ajax but you use jQuery.ajax or modify DOM via JavaScript,
consider applying Drupal.attachBehaviors to newly created DOM elements.
Project Demo& Code Demo
http://nikro.me | http://wearepropeople.com
Thanks.
http://nikro.me | http://wearepropeople.com
Questions?
http://nikro.me | http://wearepropeople.com
http://nikro.me | http://wearepropeople.com
Web: http://nikro.me/Twitter: nikro_md