Adding button to header of Gutenberg editor in Wordpress through plugin - wordpress

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/

Related

Suggestions on how to extend WordPress shortcode Edit button without losing its functionality

I'd like to extend the WordPress shortcode Edit button and have my own functionality onClick and at the same time don't lose/overwrite the one the WordPress has.
Here is the code I have right now (which works) but this overwrites the WordPress onClick which doesn't work any more and obviously I don't want to have that.
editor.addButton( 'wp_view_edit', {
tooltip : 'Edit',
icon : 'dashicon dashicons-edit',
onclick : function() {
// here goes my code for custom functionality
}
} );
And here is the original code from WP found in /wp-incldes/js/tinymcs/plugins/wp-view/plugins.js
editor.addButton( 'wp_view_edit', {
tooltip: 'Edit|button', // '|button' is not displayed, only used for context
icon: 'dashicon dashicons-edit',
onclick: function() {
var node = editor.selection.getNode();
if ( isView( node ) ) {
wp.mce.views.edit( editor, node );
}
}
} );

woocommerce how show loading icon when click add to cart button

I want to show a spinner icon while the 'Add To Cart' button is processing.
I'm using this code:
jQuery('a.add_to_cart_button').click(function(){
jQuery(this).append('<img src="/spinner.gif" width="20px" height="20px"/>')});
It works well after user clicks the 'Add to Cart' button, but I want to remove this icon after successful execution.
It's no need to use your own loader or spinner icon because WooCommerce itself provides its own loader in front end. Here is the flow to use the code of loader.
As soon as add to cart button is clicked. Add this line in your click function, it adds loader in a particular section
block( $( 'div.summary.entry-summary' ) );
Now when the product is successfully added to cart and your ajax response is success add this line to remove the loader. It removes the loader from that section.
unblock( $( 'div.summary.entry-summary' ) );
This code blocks and unblocks a particular section, if you want you can increase its scope by specifying the element you want.
These are the functions responsible for applying and removing the loader.
var is_blocked = function( $node ) {
return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
};
var block = function( $node ) {
if ( ! is_blocked( $node ) ) {
$node.addClass( 'processing' ).block( {
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
} );
}
};
var unblock = function( $node ) {
$node.removeClass( 'processing' ).unblock();
};

WooCommerce Product Gallery: Swap Featured Image with Selected Thumbnail

Woocommerce displays the product gallery on a lightbox or new tab by default. I would like to display the product gallery on the box where the product image is displayed. I tried WooCommerce Dynamic Gallery but the LITE version doesn't allow me to display all the product gallery images on each product. Also, it displays the image on the product description.
Can anyone suggest me a wordpress plugin or coding that can display the product gallery dynamically ? Thanks a lot.
It's possible with some straightforward jquery (see below). You'll also need to override the default lightbox that WooCommerce includes for the gallery.
I believe that it's possible to disable it from the admin under WC -> Settings -> Products -> Display. But you can also remove the styles and scripts directly.
I haven't tested this code on a fresh install of WooCommerce--this is some modified code from a site with a heavily customized product gallery that includes video support.
You'll need to include this in your theme's functons.php file, etc. etc.
add_action( 'wp_enqueue_scripts', 'wc_remove_lightboxes', 99 );
/**
* Remove WooCommerce default prettyphoto lightbox
*/
function wc_remove_lightboxes() {
// Styles
wp_dequeue_style( 'woocommerce_prettyPhoto_css' );
// Scripts
wp_dequeue_script( 'prettyPhoto' );
wp_dequeue_script( 'prettyPhoto-init' );
wp_dequeue_script( 'fancybox' );
wp_dequeue_script( 'enable-lightbox' );
}
/* Customize Product Gallery */
/**
* Click on thumbnail to view image for single product page gallery. Includes
* responsive image support using 'srcset' attribute introduced in WP 4.4
* #link https://make.wordpress.org/core/2015/11/10/responsive-images-in-wordpress-4-4/
*/
add_action( 'wp_footer', 'wc_gallery_override' );
function wc_gallery_override()
{
// Only include if we're on a single product page.
if (is_product()) {
?>
<script type="text/javascript">
( function( $ ) {
// Override default behavior
$('.woocommerce-main-image').on('click', function( event ) {
event.preventDefault();
});
// Find the individual thumbnail images
var thumblink = $( '.thumbnails .zoom' );
// Add our active class to the first thumb which will already be displayed
//on page load.
thumblink.first().addClass('active');
thumblink.on( 'click', function( event ) {
// Override default behavior on click.
event.preventDefault();
// We'll generate all our attributes for the new main
// image from the thumbnail.
var thumb = $(this).find('img');
// The new main image url is formed from the thumbnail src by removing
// the dimensions appended to the file name.
var photo_fullsize = thumb.attr('src').replace('-300x300','');
// srcset attributes are associated with thumbnail img. We'll need to also change them.
var photo_srcset = thumb.attr('srcset');
// Retrieve alt attribute for use in main image.
var alt = thumb.attr('alt');
// If the selected thumb already has the .active class do nothing.
if ($(this).hasClass('active')) {
return false;
} else {
// Remove .active class from previously selected thumb.
thumblink.removeClass('active');
// Add .active class to new thumb.
$(this).addClass('active');
// Fadeout main image and replace various attributes with those defined above. Once the image is loaded we'll make it visible.
$('.woocommerce-main-image img').css( 'opacity', '0' ).attr('src', photo_fullsize).attr('srcset', photo_srcset).attr('alt', alt).load(function() {
$(this).animate({ opacity: 1 });
});
return false;
}
});
} )( jQuery );
</script>
<?php
}
}

Change Wordpress logo click redirection

I would like to change the logo redirection when clicked. Right now when you click on the logo, the user is redirected to the homepage but I want it to redirect to another site. How do I do this?
I agree with Stu Mileham. Another way to implement what you are asking for would be to use JavaScript / jQuery.
Save the following code to a .js file (eg. pageRedirect.js, let's say placed in a js folder inside your theme's root folder):
(function($) {
$(document).ready(function() {
$('#pageLogo').on( "click", function(event) {
event.preventDefault();
window.location.assign("http://www.google.com/");
});
});
})(jQuery);
To make the previous code work, you would have to select somehow the page logo via jQuery.
On the previous code this is achived via $('#pageLogo') since I have made the assumption that your logo has an id with the value pageLogo.
Of course, to enable your theme to use this pageRedirect.js file, you have to enqueue it by placing the following code to your theme's functions.php file:
/**
* Enqueue pageRedirect script.
*/
function pageRedirect_scripts() {
wp_enqueue_script( 'page-redirect-js', get_template_directory_uri() . '/js/pageRedirect.js', array('jquery'), '20150528', true );
}
add_action( 'wp_enqueue_scripts', 'pageRedirect_scripts' );
Code Explanation:
//-jQuery selects html element with id='pageLogo'
//-when it is clicked, it calls a function in which it passes the event
$('#pageLogo').on( "click", function(event) {
//prevents page from redirecting to homepage
event.preventDefault();
//redirects to your desired webpage
window.location.assign("http://www.google.com/");
});
If you don't have the option to change the link from admin then you will have to edit your theme's header.php file (most likely, depends on how the theme is built though).
Many themes have a tag similar to the following:
<img src="logo.jpg">
You would need to change this to:
<img src="logo.jpg">
I've added the target tag to open the site in a new window, this is my personal preference when re-directing to a different site but it's optional.
Your theme files might look very different to this, it's impossible to know for sure without seeing some code, but this should give you an idea.
Also be aware that your changes could be overwritten by a theme update. This can be avoided by creating a child theme.
https://codex.wordpress.org/Child_Themes
Depends on your theme
Some theme creators gives you the possibility to change the link from admin
Some theme creators just believe that clicking the logo you need to go on homepage - so you need to edit the theme
Depending upon the theme you are using, you can try one of the following options.
Explore the admin options and see if the theme provides a direct way to change the link on the logo.
If not found in admin options, try looking for the code in header.php. Do an inspect element on your logo and see the html code surrounding the logo file, If the code is directly present in header.php, your task is simple. Just change the code to update the URL, instead of reading it from home_url(). Something like <a href="<?php echo home_url();?>"> will need to be replaced with <a href="https://www.example.com">
The other option to look for is get_custom_logo. Some themes get the logo code from this function. You can apply a filter to change the home_url just before this method is called in your theme and then remove filter afterwards. Or else you can copy the code from wordpress and update it with a differently named function say get_custom_link_logo in functions.php then where'ver your theme is using get_custom_logo you can use get_custom_link_logo instead of that.
function get_custom_link_logo ( $blog_id = 0 ) {
$html = "";
$switched_blog = false;
if ( is_multisite() && ! empty( $blog_id ) && (int) $blog_id !== get_current_blog_id() ) {
switch_to_blog( $blog_id );
$switched_blog = true;
}
$custom_logo_id = get_theme_mod( 'custom_logo' );
// We have a logo. Logo is go.
if ( $custom_logo_id ) {
$custom_logo_attr = array(
'class' => 'custom-logo',
'itemprop' => 'logo',
);
/*
* If the logo alt attribute is empty, get the site title and explicitly
* pass it to the attributes used by wp_get_attachment_image().
*/
$image_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
if ( empty( $image_alt ) ) {
$custom_logo_attr['alt'] = get_bloginfo( 'name', 'display' );
}
/*
* If the alt attribute is not empty, there's no need to explicitly pass
* it because wp_get_attachment_image() already adds the alt attribute.
*/
$html = sprintf( '%2$s',
esc_url( "https://www.example.com" ),
wp_get_attachment_image( $custom_logo_id, 'full', false, $custom_logo_attr )
);
}
// If no logo is set but we're in the Customizer, leave a placeholder (needed for the live preview).
elseif ( is_customize_preview() ) {
$html = sprintf( '<img class="custom-logo"/>',
esc_url( "https://www.example.com" )
);
}
if ( $switched_blog ) {
restore_current_blog();
}
/**
* Filters the custom logo output.
*
* #since 4.5.0
* #since 4.6.0 Added the `$blog_id` parameter.
*
* #param string $html Custom logo HTML output.
* #param int $blog_id ID of the blog to get the custom logo for.
*/
return apply_filters( 'get_custom_logo', $html, $blog_id ); }
This might not cover all the use cases, but you get the idea. Depending upon the theme you'll have a similar solution for your case. The important thing to figure out which case you fall under will be to identify the code where html for your logo is getting added. header.php is a good starting point.
Use this javascript in the header or footer of your theme:
<script>
document.getElementsByClassName("site-logo")[0].getElementsByTagName('a')[0].href="https://www.test.com";
</script>
i am assuming that site-logo is the class name of your LOGO.

How to add a button to a custom post type in Wordpress?

I have a "Products" custom post type. Normally, this custom post type have an "Add New" button. I want to add another button call "Update from Provider".
Currently, I have modify the Wordpress code (in "wordpress\wp-admin\includes\class-wp-list-table.php") to add that button. In this case, when I update Wordpress, my modified code will be deleted. Therefore, I need to move that button to my plug-in code.
In this case, please help me how to move that button to my plug-in code.
Well, if you opened the core file you saw that there's no action in it where we can hook.
Only a couple of filters. We can use the following:
add_filter( 'views_edit-movies', 'so_13813805_add_button_to_views' );
function so_13813805_add_button_to_views( $views )
{
$views['my-button'] = '<button id="update-from-provider" type="button" title="Update from Provider" style="margin:5px">Update from Provider</button>';
return $views;
}
It produces this:
To put it in an approximate position from where you'd like, use the following:
add_action( 'admin_head-edit.php', 'so_13813805_move_custom_button' );
function so_13813805_move_custom_button( )
{
global $current_screen;
// Not our post type, exit earlier
if( 'movies' != $current_screen->post_type )
return;
?>
<script type="text/javascript">
jQuery(document).ready( function($)
{
$('#update-from-provider').prependTo('span.displaying-num');
});
</script>
<?php
}
Which results in this:

Resources