I would like to automatically add a class to a standard Gutenberg gallery block named 'custom-class' so I don't have to add this manually every time I create a new gallery.
Is this possible via a hook in functions.php?
My attempt doesn't work...
function add_custom_class_to_gallery_block($settings)
{
if (isset($settings['blockSettings']['core/gallery']['attributes']['className'])) {
$settings['blockSettings']['core/gallery']['attributes']['className'] .= ' custom-class';
} else {
$settings['blockSettings']['core/gallery']['attributes']['className'] = 'custom-class';
}
return $settings;
}
add_filter('block_editor_settings', 'add_custom_class_to_gallery_block');
A filter can be applied to a target a specific Gutenberg block with render_block_{$this->name} where the first parameter is the $block_content string (HTML markup). Without affecting the Editor classes or validation of the markup saved, a simple string replacement can be used on the $block_content string to add the class before WP_Block->render() is called, eg:
<?php
function add_custom_class_to_gallery_block($block_content)
{
// Simple string replacement
$block_content = str_replace('wp-block-gallery', 'wp-block-gallery custom-class', $block_content);
// Returns altered $block_content to be rendered
return $block_content;
}
// Add filter only to 'core/gallery' block
add_filter('render_block_core/gallery', 'add_custom_class_to_gallery_block');
Related
I could add extra functionality to a dataobject if I extend it with a dataextension. For example I've got an Item which gets extended from a module with stock keeping functionality. Let's say the Item also gets's extended form a few other modules.
After the extension with the stock keeping functionality, I'd like to display the availability of the item in the frontend, for example with a green/red dot. How can I get this dot's markup inside my template for the detail page(ItemPage.ss) and the include (Item.ss) for the overview page of items without overwriting the whole template. Just adding this one part, like the way I extend a function on my base class?
That could be a way to add extra markup to the original template.
Inside dataobject or global dataobject extension
public function ExtraTemplateHTML($position) {
$html = null;
foreach($this->owner->extend('updateExtraTemplateHTML') as $positionBlocks) {
if(isset($positionBlocks[$position])) {
foreach($positionBlocks[$position] as $htmlBlock) {
$html .= $htmlBlock->getValue();
}
}
}
return $html;
}
Inside the specific dataobject extension
public function updateExtraTemplateHTML($htmlBlocks) {
$viewer = new SSViewer(__CLASS__);
$html = $viewer->process($this->owner);
$htmlBlocks['bottom'][] = $html;
$topHtml = HTMLText::create();
$topHtml->setValue(123);
$htmlBlocks['top'][] = $topHtml;
return $htmlBlocks;
}
Original Template
$ExtraTemplateHTML(top)
...
...
$ExtraTemplateHTML(bottom)
Extension Template
Than just write a new template for your extension with the content you would like to add.
You cannot partially change a template, you can only substitute the template with another. So, keeping this in mind you should keep modular architecture with many logical includes.
Another possible way to extend existing content is using DOM and javascript. But you should think about side effects. For example if you add extra textual content then it won't be visible by crawlers and will effect your SEO. But for decorative enhancements, like adding extra coloured dot, this approach will work.
I am trying to replace the title of the user profile page, which is the username, with other fields that were added later. Trying to show the full name as the title of the page.
I edited page.tpl.php $title with following code but it doesn't work.
if(arg(0)=="user")
{
$title=$field_user_last_name;
}
Install the RealName module and go to /admin/config/people/realname to change the pattern used for the user's name.
I'm using Profile2 to add the first and last name field and the following pattern:
[user:profile-person:field_first_name] [user:profile-person:field_last_name]
But you can probably add the fields at /admin/config/people/accounts/fields without using Profile2 aswell.
A cleaner way to do this:
function mymodule_page_alter() {
global $user;
if(drupal_get_title() === $user->name) {
drupal_set_title('New value');
}
}
You can accomplish this functionality nicely using the Entity API module's metadata wrapper and hook_user_view(). Add a dependency to Entity API in your module's .info file and then the code could look something like the following (assuming you want to set the title to the user's full name and you have fields called field_first_name and field_last_name):
/**
* Implements hook_user_view().
*/
function MYMODULE_user_view($account, $view_mode, $langcode) {
// Set the page title of the user profile page to the user's full name.
$wrapper = entity_metadata_wrapper('user', $account);
$first_name = $wrapper->field_first_name->value();
$last_name = $wrapper->field_last_name->value();
if ($first_name && $last_name) {
drupal_set_title($first_name . ' ' . $last_name);
}
}
I got solution!!!
I added following code on preprocess_page function on my template.php
if(isset($variables['page']['content']['system_main']['field_name'])){
$title=$variables['page']['content']['system_main']['field_name']['#object']->field_name['und'][0]['value'];
drupal_set_title($title);
}
i want to using the taxonomy page template according to the content type? namely, the tag under content type "story" using a tpl.php, and the tag under the content page, using another tpl.php file. how should i do?thank you.
In template.php of your theme:
/**
* Override or insert variables into the page templates.
*
* #param $vars
* An array of variables to pass to the theme template.
*/
function YOURTHEMENAME_preprocess_page(&$vars) {
// ...
$node = $vars['node'];
if ($node && ($node->type=='story')) {
foreach ($node->taxonomy as $term) {
if ($term->name == 'SOMETAG1') {
$vars['template_files'][] = 'page-sometag1';
break;
}
else if ($term->name == 'SOMETAG2') {
$vars['template_files'][] = 'page-sometag2';
break;
}
}
}
// ...
}
Replace uppercase with your values. page-sometag1.tpl.php and page-sometag2.tpl.php files should be in your theme folder.
The ThemeKey module might do this.
(Not sure it can work with both content-type and taxonomy term in the same condition ; but I've seen it used a couple of times to change templates / themes bases on some conditions)
Similar to the question posting form on SO, Drupal adds a draggable expander to the bottom of textareas created through the form api. How can I disable this in a nice manner?
The draggable expander gets added via the behavior defined in 'misc/textearea.js'. From that you can see that it applies to textareas having a class 'resizable'. You can prevent the output of this class if you set the '#resizable' property on a textareas FAPI definition to FALSE (it defaults to TRUE if not explicitly set).
So for your own forms, you can just declare the textareas accordingly. For other forms, youD need to adjust them via hook_form_alter().
A new module called Disable Resizable Textarea was release now.
This is a simple module that add ability to override the default #resizable property of textarea fields. By default, all textareas are resizable. This module allows you to disable this feature on each field.
It is very easy to set up. Just edit the desired field and you will see an "Disable #resizable property of this textarea" option. You can also disable resizable from its summary, if the field is of type "Long text with summary".
body textarea {
resize: none;
}
The simplest, would be to remove the file /misc/textarea.js.
The harder, but probably nicer way is to fix this in either your theme, or in a tiny module.
In your theme, you have two options again:
use a preprocess to remove the textarea.js from the list of javascript files.
use a theme override (yourtheme_textarea) to remove the class resizable-textarea from the rendered HTML. Some information on that in the forums
The option in a module, would be to run a hook_form_alter() to grab any form and run that trough a processor:
/**
* Implementation of hook_form_alter().
*
* Before Drupal 7, there is no way to easily identify form fields that are
* input format enabled. As a workaround, we assign a form #after_build
* processing callback that is executed on all forms after they have been
* completely built, so form elements are in their effective order
* and position already.
*
* #see wysiwyg_process_form()
*/ /**
* Implementation of hook_form_alter().
*
* Before Drupal 7, there is no way to easily identify form fields that are
* input format enabled. As a workaround, we assign a form #after_build
* processing callback that is executed on all forms after they have been
* completely built, so form elements are in their effective order
* and position already.
*
* #see wysiwyg_process_form()
*/
function wysiwyg_form_alter(&$form, &$form_state) {
$form['#after_build'][] = 'wysiwyg_process_form';
// Teaser splitter is unconditionally removed and NOT supported.
if (isset($form['body_field'])) {
unset($form['body_field']['teaser_js']);
}
}
function wysiwyg_process_form(&$form) {
// Iterate over element children; resetting array keys to access last index.
if ($children = array_values(element_children($form))) {
foreach ($children as $index => $item) {
$element = &$form[$item];
// filter_form() always uses the key 'format'. We need a type-agnostic
// match to prevent false positives. Also, there must have been at least
// one element on this level.
if (($item === 'format' || $item === 'signature_format') && $index > 0) {
// Make sure we either match a input format selector or input format
// guidelines (displayed if user has access to one input format only).
if ((isset($element['#type']) && $element['#type'] == 'fieldset') || isset($element['format']['guidelines'])) {
// The element before this element is the target form field.
$field = &$form[$children[$index - 1]];
$extra_class = '';
if (!empty($field['#resizable'])) {
$extra_class = ' wysiwyg-resizable-1';
drupal_add_js('misc/textarea.js');
}
// If we loaded at least one editor, then the 'none' editor will
// handle resizable textareas instead of core.
if (isset($loaded) && !empty($field['#resizable'])) {
$field['#resizable'] = FALSE;
}
}
// If this element is 'format', do not recurse further.
continue;
}
// Recurse into children.
wysiwyg_process_form($element);
}
}
return $form;
}
These examples are from WYSIWYG module, and slightly altered.
In your theme is far simple, but requires a theme that you can override. The module is both performance-wise worse, and a lot more complex. However, it will work on any theme.
There are to ways how to remove resizable textarea in Drupal (7).
1th Place this simple snipped into your theme template.php. Don't forget to rename THEMENAME to your theme name.
/**
* Override of theme('textarea').
* Deprecate misc/textarea.js in favor of using the 'resize' CSS3 property.
*/
function THEMENAME_textarea($variables) {
$element = $variables ['element'];
element_set_attributes($element, array('id', 'name', 'cols', 'rows'));
_form_set_class($element, array('form-textarea'));
$wrapper_attributes = array(
'class' => array('form-textarea-wrapper'),
);
$output = '<div' . drupal_attributes($wrapper_attributes) . '>';
$output .= '<textarea' . drupal_attributes($element ['#attributes']) . '>' . check_plain($element ['#value']) . '</textarea>';
$output .= '</div>';
return $output;
}
2nd Other way is to use another module called Disable resizable textarea.
More info and source.
I want to override the theming of only one (custom) menu. I can do this with phptemplate_menu_tree() but - of course - it overrides the rendering of all menus.
I've tried returning FALSE (an obvious technique IMO) if the menu is not the specific one I want to override - but this doesn't cause the overridden theme function to be called.
My only alternative (when the menu is anything other than the specific one) is to call the overridden function from within phptemplate_menu_tree() - but this seems to defeat the whole point of the override system, since the default rendering function will be hard-coded therein.
I hope the explanation is clear, and any help is greatly appreciated - tks.
UPDATE
For the sake of future reference, I'll explain how I solved this.
First off, the menu rendering starts with this function in menu.module:
function menu_block($op = 'list', $delta = 0) {
$menus = menu_get_menus();
// The Navigation menu is handled by the user module.
unset($menus['navigation']);
if ($op == 'list') {
$blocks = array();
foreach ($menus as $name => $title) {
// Default "Navigation" block is handled by user.module.
$blocks[$name]['info'] = check_plain($title);
// Menu blocks can't be cached because each menu item can have
// a custom access callback. menu.inc manages its own caching.
$blocks[$name]['cache'] = BLOCK_NO_CACHE;
}
return $blocks;
}
else if ($op == 'view') {
$data['subject'] = check_plain($menus[$delta]);
$data['content'] = menu_tree($delta);
return $data;
}
}
If you only want to override how individual item (links) are rendered then you can use the theme system (there are loads of references on how do this) - but if you want complete control on how the entire menu tree is rendered (for example, wrapping the output in nested DIVs so it can be centred on the page) then there is no way to override menu_block().
Therefore, I removed the menu I wanted to render differently from the administer blocks page (site building->blocks) and rendered the menu directly in my page.tpl.php using code something like this: (angle brackets removed)
$m = menu_tree_page_data('my-menu-id');
$o = "DIV";
foreach($m as $k => $v){
$o .= "SPAN {$v['link']['title']} /SPAN";
}
$o .= "/DIV";
echo $o;
I hope this helps.
I've had mixed success doing template.php menu overrides to force CSS classes and ids or HTML into the output.
You could make use of Block Theme when enabling the menu as a block, but I've never tried it.
http://drupal.org/project/blocktheme
If you want to tackle the template way, here are the zen menu override funcitons...
function zen_menu_item_link($link) {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}
// If an item is a LOCAL TASK, render it as a tab
if ($link['type'] & MENU_IS_LOCAL_TASK) {
$link['title'] = '<span class="tab">' . check_plain($link['title']) . '</span>';
$link['localized_options']['html'] = TRUE;
}
return l($link['title'], $link['href'], $link['localized_options']);
}
function zen_menu_local_tasks() {
$output = '';
if ($primary = menu_primary_local_tasks()) {
$output .= '<ul class="tabs primary clear-block">' . $primary . '</ul>';
}
if ($secondary = menu_secondary_local_tasks()) {
$output .= '<ul class="tabs secondary clear-block">' . $secondary . '</ul>';
}
return $output;
}
You could use sections module, or look at how it switches theme for certain menu-items.
what I did was register a new theme function in my template.php called primary_links (because I wanted to only customize this menu in certain way) created the function mytheme_primary_links() in my template.php refreshed the cache so Drupal would add my theme function to the system then changed theme function on primary_links from links to my custom theme function primary_links - this allows me to customize only this 1 menu - could you do this and hook into where ever to change the theme function being called for your links?
Chris