diff --git a/docs/extensions/page-templates.md b/docs/extensions/page-templates.md new file mode 100644 index 0000000000000000000000000000000000000000..35f0229e1117a98500e9c71d9e6e4cdbe661cd9f --- /dev/null +++ b/docs/extensions/page-templates.md @@ -0,0 +1,299 @@ +# Page Templates + +<div class="panelMacro"> + +!!! warning{width="16" height="16"} This page has been copied directly from the book. It need updating or deleting. + + +</div> + +CiviCRM uses page template files to display all the pages. This makes it +possible for a person to customize any CiviCRM screen to suit a special +requirement or preference. The HTML for CiviCRM pages is not embedded in +PHP code, instead a template engine (Smarty) sends the correct page to +the web browser. + +You should be familiar with HTML and CSS syntax to be comfortable +editing page templates. Some page templates additionally make use of +JavaScript and an Ajax utility, JQuery. + +## Changing page templates is the wrong choice when ... + +1. it is possible to make the needed changes by updating the + CSS styles. For example, if a requirement is to hide or move some + information or form fields on a screen, a CSS style for that HTML + element can be changed to display: none, or position: absolute + within the CSS file. +2. there is a CiviCRM hook available that can control the page. For + example, there is a hook that can modify the information on the + Contact Summary screen +3. there is no process in place to update the page templates after an + upgrade to a new version of CiviCRM. Page templates are stored in a + separate folder and are not touched during an upgrade, However new + versions of CiviCRM often change which placeholder elements are + available in various templates. Proper source control procedures are + needed to simplify upgrades to new versions. + +## Smarty templates introduction + +CiviCRM uses a page template engine called Smarty. This documentation +is focused on how Smarty is used within the CiviCRM environment. Every +Smarty element is enclosed between braces like these: "{}". All the +other text is going to be displayed directly as HTML in the rendered +page. + +Each page template is stored in a file with the extension *.tpl*. The +PHP code assigns variables for content that needs to be displayed, and +then lets the template engine take care of presenting it. + +The Smarty template engine always does this process : + +1. Load the contents of a *.tpl* file. +2. Scan the *.tpl* file for placeholder elements. +3. Replace each placeholder element with the corresponding + variable value. +4. Send the resulting HTML to the web browser. + +These are the most commonly used Smarty template elements: + +- {$Name}: To display the value of a variable named "Name" +- {$row.Name}: To display the value of the attribute Name in the + object Row +- {foreach from=$rows item=row}...{/foreach}: To loop though all the + items of the Rows array +- {literal} JavaScript code{/literal} to indicate to Smarty the "{}" + aren't smarty elements but JavaScript code, enclose JavaScript + between {literal} +- <span class="Apple-style-span">{ldelim} and {rdelim} are alternative + ways to generate { and }. This is often useful if you have a simple + JavaScript code that needs a lot of values from Smarty + variables </span> +- {include file="CRM/path/to/template.tpl" param1=xxx}: includes the + result of the *template.tpl*. Some included files expect to have + extra param (e.g., *param1*). + +Please read the Smarty documentation for more information. + +**Tip**: To see what variables have been assigned to the template, +enable debug (Administer -> Configure -> Global Settings -> +Debugging) and on any URL, add **&smartyDebug=1**. It opens a new +browser window listing all the variables and values. + +CiviCRM introduces some extra features to Smarty: + +- {ts}Any text{/ts}: It will display the translated text (if you don't + use US English) +- {crmURL + p='civicrm/contact/view' q="reset=1&cid=`$row.source_contact_id`"}. + Generates the proper CiviCRM URL that works both on Joomla! + and Drupal. +- {crmAPI} Allows retrieval and display of extra data that is not + assigned to the template already. Read about the CiviCRM API for + more information. + +## How to find and modify the templates? + +All the templates are under the folder *templates/CRM* in your CiviCRM +installation. Finding which template is used on a given page can be +difficult, but the easiest way to find out the answer is to view the +source of the page from a web browser and search for ".tpl". For +example, for the Contact Summary page, use the web browser to open the +Contact Summary page, then click "View Source" in the browser. You +should find an HTML comment such as:**\ +** + + <!-- .tpl file invoked: CRM/Contact/Page/View/Summary.tpl. Call via form.tpl if we have a form in the page. --> + +You can then view the file at +*templates/CRM/Contact/Page/View/Summary.tpl* to see how the HTML is +generated. If you want to modify the layout; for instance to reorder the +content, do **not** modify directly these files, as all the +modifications will be lost on the next upgrade of CiviCRM. The proper +way is to create a new folder outside of your CiviCRM folder, then +navigate to "Administer -> Configure -> Global settings -> +Directories" in the navigation menu, and set the complete path of the +folder that is going to contain your custom templates in the field +*Custom Templates*. + +## Scenario: The Contact Summary screen needs to be changed + +If you want to alter the Contact Summary page template for Acme +organization, perform these steps: + +1. Create the folder + */var/www/civi.custom/acme/templates/CRM/Contact/Page/View* +2. Update the Custom Template field in the Global Settings directories + to */var/www/civi.custom/acme/templates.* You can use any directory. + We found it easier to put the custom templates under + */var/www/civi.custom/yourorganisation*. +3. copy *templates/Contact/Page/View/Summary.tpl* from your CiviCRM + install to */var/www/civi.custom/acme* + +**Tip**: Say you want to modify the template for a specific profile +form, or a specific event. Instead of copying the Form template to its +default place (*templates/CRM/Profile/Form/Edit.tpl*), you can create a +subfolder with the ID of the profile and put the template file you want +to change in the subfolder (*templates/CRM/Profile/Form/42/Edit.tpl* to +modify only the form for ProfileID 42). + +You might want to modify a template that isn't directly the page you +load, but added later via Ajax. For instance, perhaps you want to change +all the tabs beside the Content Summary (Activities, Groups, etc.). The +easiest way to do this is to install a development oriented plug-in to +your web browser. If using Mozilla Firefox, the Firebug plug-in is +indispensable. Open the Firebug console (or equivalent in your +browser) and click the tab. You will see what URL has been loaded for +the tab (e.g., for the notes tab: +*http://example.org/civicrm/contact/view/note?reset=1&snippet=1&cid=1*). +Open it in a new window or new tab of the web browser, and view the +source. It also contains a comment identifying the template used (*<span +class="comment">CRM/Contact/Page/View/Note.tpl</span>*). + +Keep in mind that when you modify a template, you might have a template +that doesn't work properly anymore after an upgrade of CiviCRM, because +the layout has changed or the name of variables assigned to the template +was modified. In our experience, the easiest is to use a source code +management system (SCM) to keep track of the changes you have made. +Before doing any modification of the template you copied, add it to your +SCM, and obviously also commit the template after having modified it. +That way, you can easily generate a patch of your changes, and see how +to apply them to the latest version of the template. + +## Semantically meaningful HTML attributes + +To make it as easy as possible for you to style any element in the page +(e.g. put a yellow background on all the contacts of the subtype +"members"), or add Ajax (clicking on the status of the activity changes +it to complete), we strive to have a consistent and coherent schema for +class names and ids for the generated HTML. This makes it easier to +isolate the elements you want to alter from a custom style or from +JavaScript: + +- There is a class **crm-entityName** defining the type of the entity + bubbled up as high as possible in the DOM. For instance, each line + on a list of activity has *<tr class="crm-activity ...">* +- There is an id **crm-entityName_entityID** allowing to find the id + of the entity bubbled up. ** e.g., on a list of contacts, the + contact number 42 has a <*tr id="crm-contact_42" ...*> +- Each field or column contains a class identifying it, e.g., + **"crm-activity-subject"** +- Each field or column that contains a value with a fixed set of + possible values (e.g., a Status, a Role, a Contact Type) contains a + class identifying it. It doesn't contain the human readable version + (that can be changed), but the id or a name that can't be modified + by the end-user; such as **class="crm-activity-status-id_42"**. + This is on the top of the class identifying the field name, so the + complete HTML is *<td class="crm-activity-status + crm-activity-status-id_42">Hitchhiked</td>*. + +At the time of the writing, some of the templates don't follow these +conventions. Please update them and submit a bug tracking issue with a +patch if you need to use a template that isn't yet complying. For more +information about submitting a bug or issue, read About the CiviCRM +community. + +## Displaying more content and adding Ajax features + +If your modifications go further than "simple" modifications of the +layout, but need to display more content than the one assigned to the +template by default, or to add Ajax functionality, use the CiviCRM API. +Please read more information about using the CiviCRM API from Ajax to +pursue this approach. + +In most cases, using the CiviCRM APIs should be simple and only takes a +few extra lines of modifications. + +## Appending jQuery or other code to a template + +You can also append jQuery functions, Smarty code, HTML (really +anything) to any template without having to create a customized copy of +the entire file. All you need to do is put your "extra stuff" in a new +file and save it as *template_to_append_to*.extra.tpl. + +**EXAMPLE**: You want to add some jQuery to hide a few of the fields in +the Contact Edit form - Contact.tpl.\ +1. Configure your Custom Templates directory\ +2. Create the directory structure in your custom templates directory +(CRM/Contact/Form)\ +3. Write your jQuery script and save it in a file called +Contact.extra.tpl + +Voila - your jQuery script will be automatically appended to the +standard Contact.tpl template when that form is loaded. + +One heads up … if your file contains Javascript (as it probably will), +you will need to start your "extra" custom file with the Smarty +{literal} tag and the <script> tag. Then use +{/literal}{$variable}{literal} if you need to use any Smarty code or +variables. Finally, end the file with </script>{/literal}. + +For customizations where you just need to add a script, this approach is +preferable to creating a custom copy of the entire template as it should +minimize the need for review and merge of changes during upgrades. + +## Some useful variables and examples + +On each page template, you have extra Smarty variables populated by +CiviCRM. + +**{$config} ** Contains a lot of useful information about your +environment (including the URL, if it's Drupal or Joomla!, etc.) + +**{$session}** Contains information about the user. + +If you want to modify the template only for a logged-in user but leave +it identical for anonymous users, do the following: + + {if $session->get('userID') > 0} Insert your modifications here {/if} + + + +## Modify templates without using jQuery/javascript + +You can insert php code directly into smarty templates, using the {php} +tag. Note that this is deprecated as of Smarty 3. + +<div class="code panel" style="border-width: 1px;"> + +<div class="codeContent panelContent"> + + {php} + CRM_Utils_System::setTitle('Thank You', 'Thank You'); //sets the page title + $form = $this->get_template_vars('form'); //gets the variable 'form' from smarty and puts it in your php scope so you can play with it + $this->assign('form',$form); //assigns $form back to smarty so you can use it in your template file, outside the {php} scope + {/php} + +</div> + +</div> + +You can also do various modifications on elements on the page using +smarty-native or Civi-specific functions: + +<div class="code panel" style="border-width: 1px;"> + +<div class="codeContent panelContent"> + + {* Prefill the input element with the user's email and assign the whole thing to $fieldWithValue. *} + {assign var="fieldWithValue" value=$form.email_confirm.html|crmInsert:value:$email} + + {* Make the field wider *} + {$fieldWithValue|crmInsert:size:40} + + {* Put the result of the include in $modifiedButtons instead of rendering it *} + {include file="CRM/common/formButtons.tpl" location="bottom" assign="modifiedButtons"} + + {* Now change the text of one of the buttons from 'Opt Out' to 'Unsubscribe' *} + {$modifiedButtons|replace:'value="Opt Out"':'value="Unsubscribe"'} + +</div> + +</div> + +You can find more such functions in the smarty documentation. And you +can find other useful Civi-specific functions +[here](https://github.com/civicrm/civicrm-core/tree/4.6/CRM/Core/Smarty/plugins){.external-link}. + +One additional tool you can use is the Word Replacements tool in Civi's +backend. It's available under Administer > Customize Data and Screens +> Word Replacements.