How to change WP Gutenberg's category components panel? - wordpress

In Gutenberg Editor, I try to modify the categories panel (the one on the right where I choose the categories my post will be placed into).
One should not be able to add a post to a category if that category has child-categories. As the categories are static, it'll be ok to use the category-id.
My idea was to use the enqueue_block_editor_assets and add some javascript to disable the checkbox via the ID of the element.
This does not work, the element could not be found :-(
This is my unfunctional code so far:
functions.php:
function gutenberg_enqueue()
{
wp_enqueue_script(
'gutenberg-additions-script',
get_stylesheet_directory_uri().'/gutenberg-additions.js',
array(), true, true
);
}
add_action('enqueue_block_editor_assets', 'gutenberg_enqueue', 999);
(I use get_stylesheet_directory_uri(), because I am in a child theme)
gutenberg-additions.js:
window.onload = function () {
var cat1 = document.getElementById('editor-post-taxonomies-hierarchical-term-1');
if (cat1 != null) {
cat1.disabled = true;
}

Welcome to Stackoverflow. There is an example about that in the gutenberg github directory. It is written in the old es5 syntax, but should easily be transferrable to esnext. It uses the editor.PostTaxonomyType filter to edit the taxonomies component.
var el = wp.element.createElement;
function customizeProductTypeSelector( OriginalComponent ) {
return function( props ) {
if ( props.slug === 'product-type' ) {
return el(
'div',
{},
'Product Type Selector'
);
} else {
return el(
OriginalComponent,
props
);
}
}
};
wp.hooks.addFilter(
'editor.PostTaxonomyType',
'my-custom-plugin',
customizeProductTypeSelector
);
If you need more information, also read the comments on this github issue.

Related

Gutenberg PluginDocumentSettingPanel retrieve post name

I am trying to add language switch links in my WordPress gutenberg so that I can switch to the corresponding language edit page easily.
I follow this step: https://developer.wordpress.org/block-editor/developers/slotfills/plugin-document-setting-panel/.
The "Language Switcher" section appears successfully, but I don't know how I can add the edit links.
My ideas are:
To get the edit link, we need to know the post_id.
The post names are consistent among the whole websites, say, a post is in language1.example.com/post1, then it has language2.example.com/post1, language3.example.com/post1, and so on...
So, I need to get the post name first, then get the post id for the other languages, and then save them into a list of links.
However, I am stuck with step 3, I don't know how to get the post name properly...
Below is my code:
import { registerPlugin } from '#wordpress/plugins';
import { PluginDocumentSettingPanel } from '#wordpress/edit-post';
const { select } = wp.data;
const title = select("core/editor").getEditedPostAttribute( 'title' );
const languageSwitcher = () => (
<PluginDocumentSettingPanel
name="custom-panel"
title="Language Switcher"
className="custom-panel"
>
<a>English {title}</a>
<a>简体中文</a>
<a>繁體中文</a>
</PluginDocumentSettingPanel>
);
registerPlugin( 'language-switcher', {
render: languageSwitcher,
icon: 'translation',
} );
Now, select("core/editor").getEditedPostAttribute( 'title' ) returns undefined...
I really appreciate your help! Thank you!
Have you tried adding wp-data to your wp_enqueue_script.
Ex:
wp_enqueue_script(
'your-doc',
plugins_url( 'build/yourDoc.js', __DIR__ ),
[ 'wp-i18n', 'wp-edit-post', 'wp-element', 'wp-data' ],
'0.0.1',
true
);

How to rename submenu in toolbar in Wordpress?

I have two plugins installed, which has generated two "Events" submenu in my toolbar. I would like to rename one of them to be able to make a difference.
I have found this topic:
how to rename plugin title
With this I can achieve to rename BOTH "Events" to any other title:
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Event' :
$translated_text = __( '3rd party Events', 'Event' );
break;
}
return $translated_text;
}
add_filter( 'gettext', 'my_text_strings', 20, 3 );
The problem with this is that it renames both of my Event menu and I only want to rename the first.
With this code I can target the admin menu to get the complete tree in the source code and get the plugin's unique name, but this only gets me admin menu, not the toolbar.
add_action( 'admin_menu', 'myRenamedPlugin' );
function myRenamedPlugin() {
global $menu;
$searchPlugin = "pgl_wp_files"; // Use the unique plugin name
$replaceName = "New Name for Plugin";
$menuItem = "";
foreach($menu as $key => $item){
if ( $item[2] === $searchPlugin ){
$menuItem = $key;
}
}
$menu[$menuItem][0] = $replaceName; // Position 0 stores the menu title
}
There is another topic discussing the question here, but this also renames ALL with the same name.
How do I target the exact menu item (not just the ones with matching name) in the Toolbar to rename?
I've looked at the code and there isn't any filters that I can see. So you basically will need to do a hack.
Option 1
Get at the node you want to change (by id). Remove that node, then change the title and add it back
add_action('wp_before_admin_bar_render', function () {
global $wp_admin_bar;
// Get the node
$node = $wp_admin_bar->get_node('some-event-id');
// Remove the node
$wp_admin_bar->remove_node('some-event-id');
// Change the node title
$node->title = 'Events #2';
// Add the node back to the menu
$wp_admin_bar->add_menu($node);
}, 9999999, 0);
Option 2
Capture the output buffer of the admin menu, do some string or regex find and replace, then output the buffer
add_action('wp_before_admin_bar_render', function () {
ob_start();
add_action('wp_after_admin_bar_render', function () {
$buffer = ob_get_clean();
// do some find/replace
echo $buffer;
}, 1, 0);
}, 9999999, 0);
There are pros/cons to each, and neither would be perfect. But as far as I can tell, that is your best shot.

Adding button to header of Gutenberg editor in Wordpress through plugin

I am developing a plugin for wordpress and I want to add the button to the header of gutenberg editor just like the one added by Elementor plugin "Edit with Elementor"
Can anyone guide me what should i do to achieve this... Thanks in Advance
I've checked Guternberg source code on header toolbar and unfortunately right now there's only not a beautiful solution possible. You can have 'custom' buttons but they are only done through calling registerPlugin with PluginSidebar component which creates sidebar and button appears on right side for pinned\starred sidebars (like Yoast SEO does).
Elementor does it this way: it subscribes to wp.data store changes and whenever something happens it injects it's button if it's not yet injected. Just because React rerenders DOM it may eventually wipe button out, so subscribing to changes is important so if it wipes out custom button js code just reinjects it.
Below is simplified ES5 code to inject a custom link\button or really any custom HTML into it (just as Elementor does).
// custom-link-in-toolbar.js
// wrapped into IIFE - to leave global space clean.
( function( window, wp ){
// just to keep it cleaner - we refer to our link by id for speed of lookup on DOM.
var link_id = 'Your_Super_Custom_Link';
// prepare our custom link's html.
var link_html = '<a id="' + link_id + '" class="components-button" href="#" >Custom Link</a>';
// check if gutenberg's editor root element is present.
var editorEl = document.getElementById( 'editor' );
if( !editorEl ){ // do nothing if there's no gutenberg root element on page.
return;
}
var unsubscribe = wp.data.subscribe( function () {
setTimeout( function () {
if ( !document.getElementById( link_id ) ) {
var toolbalEl = editorEl.querySelector( '.edit-post-header__toolbar' );
if( toolbalEl instanceof HTMLElement ){
toolbalEl.insertAdjacentHTML( 'beforeend', link_html );
}
}
}, 1 )
} );
// unsubscribe is a function - it's not used right now
// but in case you'll need to stop this link from being reappeared at any point you can just call unsubscribe();
} )( window, wp )
So create a js file in your theme or plugin and then link it this way:
add_action( 'enqueue_block_editor_assets', 'custom_link_injection_to_gutenberg_toolbar' );
function custom_link_injection_to_gutenberg_toolbar(){
// Here you can also check several conditions,
// for example if you want to add this link only on CPT you can
$screen= get_current_screen();
// and then
if ( 'cpt-name' === $screen->post_type ){
wp_enqueue_script( 'custom-link-in-toolbar', get_template_directory_uri() . '/assets/js/custom-link-in-toolbar.js', array(), '1.0', true );
}
}
Again this solution isn't perfect because we just inject our custom HTML into DOM which is managed by Gutenberg(React) but at this point it seems like the only way to achieve it, may be in future we'll have something like filters or hooks which will allow us to inject our custom components being rendered in toolbar but not yet.
Still Elementor does it this way. you can check it's code at
https://github.com/elementor/elementor/blob/master/assets/dev/js/admin/gutenberg.js
Now there is a slot for the Main dashboard button you can use that one
import { registerPlugin } from '#wordpress/plugins';
import {
__experimentalFullscreenModeClose as FullscreenModeClose,
__experimentalMainDashboardButton as MainDashboardButton,
} from '#wordpress/edit-post';
import { close,image } from '#wordpress/icons';
const MainDashboardButtonIconTest = () => (
<MainDashboardButton>
<FullscreenModeClose icon={ close } href="http://wordpress.org" />
<Button variant="primary" icon={image}>
My Button
</Button>
</MainDashboardButton>
);
registerPlugin( 'main-dashboard-button-icon-test', {
render: MainDashboardButtonIconTest,
} );
ref: https://developer.wordpress.org/block-editor/reference-guides/slotfills/main-dashboard-button/

In wordpress to mark required fields in Add New Post page

in WP 4.2 opening Add New Post page and without editing any fields, clicking on "Publish" button page is submitted and reopened, but no any of fields are marked with red background color as required.
How to make it? Seems, that is original behauvior of this page.
I want it to work like editor of categories, when in similar situation field name is marked with red background color as required.
Also I added several fields to New Post page using register_post_type function and I aslo want to marked with red background color as required. Which is the best way for this?
Thanks!
You can call your jquery validation by your self using below code,
Add this code in theme's functions.php and custom.js in your theme js folder
add_action( 'admin_print_scripts-post-new.php', 'custom_admin_script', 11 );
add_action( 'admin_print_scripts-post.php', 'custom_admin_script', 11 );
function custom_admin_script() {
global $post_type;
// Post type = "post" or "page" you can load script wheater it is post or page , if page then change 'post' to 'page' in below condition
if( 'post' == $post_type )
wp_enqueue_script( 'custom-admin-script', get_stylesheet_directory_uri() . '/js/custom.js' );
}
custom.js
jQuery(document).ready(function ($) {
if ($("#post").length > 0) {
var frm = true;
$("#publish").click(function () {
var title = $("#title").val();
var excerpt = $("#excerpt").val();
// your custom field variable goes here
if (jQuery.trim(title) == "" || jQuery.trim(excerpt) == "") {
frm = false;
}
if (frm == false) {
$("#publish").prop('disabled', true);
} else {
$("#publish").prop('disabled', false);
}
});
}
});

TinyMCE - Custom plugin makes visual editor blank in wordpress

I am trying to add TinyMCE custom plugin in wordpress that change the direction of selected text by using <bdo>. I register the plugin in wordpress:
/*Register Custom TinyMCE plugin*/
add_filter('mce_external_plugins', 'my_tinymce_plugins');
function my_tinymce_plugins() {
$plugins_array = array(
'tiny' => 'tiny.js' //Plugin directory is same as theme's funtion.php
);
return $plugins_array;
}
But it hide visual editor completely & also make text editor, un-editable. What is wrong?
I think you're overwriting all the other plugins, rather than just adding yours. Try
function my_tinymce_plugins($plugin_array) {
$plugin_array['tiny'] = 'tiny.js';
return $plugin_array;
}
instead. You may need to prepend get_stylesheet_directory_uri() to tiny.js to ensure the URL is correct.
Edit
Further to your comment, here's some code I used a few years ago to add a button. I can't say for certain best practices haven't changed, but it worked for me:
add_action('init', 'immo_add_column_button');
function immo_add_column_button() {
if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') ) {
return;
}
if ( get_user_option('rich_editing') == 'true') {
add_filter('mce_external_plugins', 'immo_add_column_tinymce_plugin');
add_filter('mce_buttons', 'immo_register_addcolumn_button');
}
}
function immo_register_addcolumn_button($buttons) {
array_push($buttons, "|", "addcol");
return $buttons;
}
function immo_add_column_tinymce_plugin($plugin_array) {
$plugin_array['addcol'] = get_bloginfo('stylesheet_directory').'/js/immo_column_button.js';
return $plugin_array;
}
add_filter( 'tiny_mce_version', 'immo_refresh_mce');
function immo_refresh_mce($ver) {
// Force refresh of TinyMCE cache by updating the version number
$ver += 3;
return $ver;
}

Resources