I would like to add a custom button to the wysiwyg editor in Advanced custom fields. I have not found any good solution on how to do it.
What I want is a button that wraps the selected text in <span class="someclass"></span> so that I can style this as I want.
How do I do this?
What you will need to do is tie into your TinyMCE editor buttons. This will add a format dropdown to your WYSIWYG editor for the class. You can then select your text and choose the class from the dropdown. Use text view to check to see if it worked.
/*
* Callback function to filter the MCE settings
*/
// Callback function to insert 'styleselect' into the $buttons array
function my_mce_buttons_2($buttons) {
array_unshift($buttons, 'styleselect');
return $buttons;
}
// Register our callback to the appropriate filter
add_filter('mce_buttons_2', 'my_mce_buttons_2');
function my_mce_before_init_insert_formats($init_array) {
// Define the style_formats array
$style_formats = array(
// Each array child is a format with it's own settings
array(
'title' => 'Some Class',
'inline' => 'span',
'classes' => 'someclass'
),
);
// Insert the array, JSON ENCODED, into 'style_formats'
$init_array['style_formats'] = json_encode($style_formats);
return $init_array;
}
// Attach callback to 'tiny_mce_before_init'
add_filter('tiny_mce_before_init', 'my_mce_before_init_insert_formats');
Related
Problem: I'm looking to expand our WordPress theme(s)/websites to make it easier for our communications team to create posts and pages by adding in Bootstrap rows and columns.
My idea is to create A custom Field type with a selection to add in rows and columns to fit our themes pages.
Has anyone done something like this? We are using Divi Builder but that is a bit complicated for average users and we are not in arush to create a whole new theme for our 30+ websites.
Or would I need to create a custom plugin for that? I'd rather not use a third party plugin for security reasons
So are you wanting output bootstrap markup in your default wordpress editor to make rows and columns etc?
Short answer is no, the wysiwyg editor is only really built for paragraphs, headings, quotes, horizontal rules, lists, images, inline formatting etc...
In order integrate bootstraps block layout markup would require some extra level of builder addon. Elementor definitely could do the job with some super customisation, even ACF flexible content would do it, and i think even WP Gutenberg can do this natively... but would require customisation to use bootstrap markup.
But if you wanted to attempt and utilise the standard wordpress editor (not Gutenberg editor) using the element dropdown (paragraph, headings etc by default).
You could try this, however I recommend loading the same front end bootstrap css into the wysiwyg editor so you can instantly see changes.
Please note this method below is risky as the user would need to understand how bootstraps row/column structure should be formatted. The probability of html markup going wrong is highly likely. Hence using an actual block element builder (like Elementor or ACF) would be a safer choice.
Anyway, see below example of how to customise standard wordpress wysiwyg editor dropdown for wrapping html tags around content.
First load the same front end bootstrap css into the wysiwyg editor...
// editor stylesheet (containing the front end css for the post content)
add_editor_style('dist/css/editor.css');
Now lets add the styleselect dropdown to our wysiwyg editor...
// add the style select dropdown to our wysiwyg editor
add_filter('mce_buttons_2', 'formatting_dropdown');
/**
* #link https://developer.wordpress.org/reference/hooks/mce_buttons_2
* #param $buttons
* #return mixed
*/
function formatting_dropdown($buttons) {
// global post object
global $post;
// if no post return param
if(!$post) return $buttons;
// switch case for post types or type to run this on (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// reveal the hidden “Styles” dropdown in the advanced toolbar
array_unshift($buttons,'styleselect');
return $buttons;
default;
return $buttons;
}
}
And then add your bootstrap formatting settings using this filter below...
// init filter for handling the style select options
add_filter('tiny_mce_before_init', 'formatting_dropdown_options');
/**
* #link https://developer.wordpress.org/reference/hooks/tiny_mce_before_init/
* #param $mceInit
* #return mixed
*/
function formatting_dropdown_options($mceInit) {
// global post
global $post;
// if no post return param
if(!$post) return $mceInit;
// switch case for post type (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// new style array
$style_formats = [
[
'title' => 'row',
'block' => 'div',
'classes' => 'row'
],
[
'title' => 'col',
'block' => 'div',
'classes' => 'col'
]
];
// bs5 breakpoints
$breakpoints = ['xs','sm','md','lg','xl','xxl'];
// bs5 column grid
$grid = 12;
// add bs5 column classes to $style_formats array
foreach ($breakpoints as $breakpoint) {
foreach (range(1, $grid) as $column) {
$style_formats[] = [
'title' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column,
'block' => 'div',
'classes' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column
]
}
}
// override style format with new style formats
$mceInit['style_formats'] = json_encode($style_formats);
// init array
return $mceInit;
break;
default;
// init array
return $mceInit;
}
}
I'm forcing a block template for the editor view of a specific custom post type using basically this example as a guide:
https://developer.wordpress.org/block-editor/reference-guides/block-api/block-templates/#locking
function myplugin_register_template() {
$post_type_object = get_post_type_object( 'post' );
$post_type_object->template = array(
array( 'core/paragraph', array(
'placeholder' => 'Add Description...',
) ),
);
$post_type_object->template_lock = 'all';
}
add_action( 'init', 'myplugin_register_template' );
I was able to set multiple input fields and change their default attributes like their placeholder or content.
What I would love is the ability to add a label in the editor above the input field.
The only solution I could find was creating a static block with static text.
Awful.
I would need to create a block for each label.
I would love a way to set its content from the placeholder or content attribute from the above template definition code but, for the life of me, I can't find any documentation on how to go about it.
so the questions are:
is there an easier way to set a static label above each field in a template that I'm missing?
is there a way to implement a label block that takes a content attribute from there?
Yes, using a 3 step approach you can add an extra attribute/s and insert custom content to existing blocks without creating a new block. After the additional attribute is added, you can then set the default value in your custom post template which is then displayed in the Editor, eg:
Step 1: Use Register Block Type Filter to assign a new label attribute to the existing "core/paragraph" block:
plugin.js:
function addLabelAttribute(settings, name) {
if (name !== 'core/paragraph') {
return settings;
}
return lodash.assign({}, settings, {
attributes: lodash.assign({}, settings.attributes, {
label: {
type: 'string',
default: ""
}
})
});
}
wp.hooks.addFilter(
'blocks.registerBlockType',
'core/paragraph',
addLabelAttribute
);
Part 2: Create a Higher Order Component to insert the <label>...<\label> into <BlockEdit> only if a label is set. The value of the label attribute is destructured from the props:
plugin.js
const { createHigherOrderComponent } = wp.compose;
const { useBlockProps } = wp.blockEditor;
const withLabelOutput = createHigherOrderComponent((BlockEdit) => {
return (props) => {
const blockProps = useBlockProps();
const { attributes: { label } } = props;
if (label) {
// Add the custom label within a wrapped <BlockEdit>
return (
<div {...blockProps}>
<label>{label}</label>
<BlockEdit {...props} />
</div>
);
}
// No label set, return default <BlockEdit>
return (<BlockEdit {...props} />)
};
}, 'withLabelOutput');
wp.hooks.addFilter(
'editor.BlockEdit',
'core/paragraph',
withLabelOutput
);
Ref: Block Editor Handbook > Block Filters
Part 3: Set a default value for the new label attribute within the template of the required post/custom post type:
plugin.php:
function myplugin_register_template(){
// N.B. Use a custom post type unless you want this to apply to all posts
$post_type_object = get_post_type_object('post');
$post_type_object->template = array(
array(
'core/paragraph',
array(
'placeholder' => 'Add Description...',
'label' => 'My Custom Label'
)
)
);
$post_type_object->template_lock = 'all';
}
add_action('init', 'myplugin_register_template');
(Optional) Add a your own custom editor style for the <label>, and enqueue it for the editor only, eg:
.wp-block-paragraph label{
font-weight: bold;
border-bottom: 1px solid grey;
padding-bottom: 0.5em;
display:block;
width:100%;
}
All the code example given above can be combined into a plugin, which creates a label in the Editor like:
goal : I want to place a text after the submit button using hook_form_alter.
Below is my code but if I use the weight key in the array then its postion does move in the form but not below the submit/save button. What can I do for it to go below the save button ?
$xdmp_twoshow="text";
$form['previewxdmp'] = array(
'#type'=>'markup',
'#markup'=>$xdmp_toshow,
'#weight' => 35,
);
Each element can have a #prefix and #suffix property which will place text/HTML immediately after the rendered output. With that in mind you can simply attach a suffix to the existing submit button like so:
$form['submit']['#suffix'] = '<p>Some text to place after the submit button</p>';
Obviously the location of the submit button within the $form array might be slightly different depending on the form you're altering.
I did it as follows:
/**
* Implements hook_form_FROM_ID_alter()
*/
function mymodule_form_mycontenttype_node_form_alter(&$form, &$form_state, $form_id) {
$form['actions']['submit']['#suffix'] = '<p>' . t('Some text to place after the submit button.') . '</p>';
}
Submit buttons are usually placed in $form['actions'] which has the default weight of 100. You can either set the weight of the $form['actions'] as you like, or give other elements a weight greater than 100 to place them after the submit button.
Example 1:
All elements with #weight greater than 34 will be placed after the submit button (and any other action buttons).
$form['actions']['#weight'] = 34;
Example 2:
Only the given element will be placed after the submit button.
$form['previewxdmp'] = array(
'#type' => 'markup',
'#markup' => $xdmp_toshow,
'#weight' => 101,
);
I want to add a custom button to drupal create form so if the user clicked on it instead of submit button, the workflow state of the created object change to another state(not the default first state)
any suggestion?
To modify the default forms generated by drupal you have to add a form_alter hook to your module. You can do it by defining a function like modulename_form_alter assuming the name of your module is modulename. The drupal system passed the form array and the form_state array which you can use to override the default behavior. In your case, the complete function would look something like this.
function modulename_form_alter(&$form, $form_state, $form_id) {
if($form_id == 'what you want') {
$form['buttons']['another_button'] = array(
'#type' => 'submit',
'#value' => 'Add to another state',
'#submit' => array('modulename_custom_form_submit')
);
}
}
function modulename_custom_form_submit($form, &$form_state) {
if($form_state['values']['another_button'] == 'Add to another state') {
//Do your thing
}
}
After you made the necessary modifications, you can simply submit to the default submit action of the creation form.
on click of button i want hi message to be displayed using javascript in drupal.I have made a .js file and know that to incude that i must use drupal_add_js(drupal_get_path('module', 'document') .'/click.js'); but the problem is to create button i used $form['click'] = array(
'#type' => 'button',
'#attributes' => array('onclick' =>drupal_add_js(drupal_get_path('module', 'document') . '/cancel.js')),
'#value' => t('click'),
);
I want that hi message which i have included in js file to be shown when button is clicked.
Please help
Hi thanx for your concern..........
here is the way i proceeded in .module file
function document_form(&$node) {
$form['click'] = array(
'#type' => 'button',
'#attributes' => array('onclick' =>message()),
'#value' => t('click'),
);
}
function document_form_alter(&$form, &$form_state, $form_id) {
drupal_add_js(drupal_get_path('module', 'document').'/cancel.js', 'module');
$settings['click'] = array(
'nid' => $form['nid']['#value'],
'cid' => $form['cid']['#value'],
'uid' => $form['uid']['#value'],
'pid' => $form['pid']['#value'],
);
drupal_add_js($settings, 'setting');
}
and my .js file code is as follows:
function message()
{
alert("This alert box was called");
}
<body>
</body>
but still onclick of button i m not getting the message "This alert box was called"
Kindly help where the problem is coming now.......
Thanx in advance....
in wait of your response
The form alter won't add the JS file in the way you are wanting.
In the function you create the form you can use drupal_add_js, outside of the creation of the form array.
Then you can use the onclick to call the function in your JS file.
A better way to do this is to use drupal behaviours to add an click listner to the button (see example here).
Looks like simplest solution would be, as you actually don't need the button to go to submit and other form stuff.
add a link to the text
style the the link as button using css .mybuttons{}
hook the js on the id. $(#mybutton1).alert..