Last active
April 30, 2021 21:32
-
-
Save rahulsprajapati/066f61e97f934ff82dc6f77bc89bf522 to your computer and use it in GitHub Desktop.
Custom Shortcode UI Functionality: TinyMce And Repeater
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Accordion ShortCode. | |
* | |
* @param array $accordion_attrs Accordion ShortCode attribute. | |
* | |
* @return string | |
*/ | |
function accordion_register_shortcode( $accordion_attrs ) { | |
// Attributes defined for repeater section. | |
$accordion_default_attrs = array( | |
'question' => '', | |
'answer' => '', | |
); | |
$repeater_field_count = get_repeater_shortcode_attr_count( $accordion_attrs, $accordion_default_attrs ); | |
if ( $repeater_field_count <= 0 ) { | |
return ''; | |
} | |
$content = '<div class="layout__block">'; | |
for ( $i = 0; $i < $repeater_field_count; $i ++ ) { | |
if ( empty( $accordion_attrs[ 'question-' . $i ] ) || empty( $accordion_attrs[ 'answer-' . $i ] ) ) { | |
continue; | |
} | |
$content .= '<div class="accordion">'; | |
$content .= '<div class="js-accordionTrigger">'; | |
$content .= sprintf( '<div class="accordion__title">%s</div>', esc_html( $accordion_attrs[ 'question-' . $i ] ) ); | |
$content .= '</div>'; | |
$content .= sprintf( '<div>%s</div>', wp_kses_post( rawurldecode( $accordion_attrs[ 'answer-' . $i ] ) ) ); | |
$content .= '</div>'; | |
} | |
$content .= '</div>'; | |
return $content; | |
} | |
add_shortcode( 'accordion', 'accordion_register_shortcode' ); | |
/** | |
* Register Accordion ShortCode UI. | |
*/ | |
function accordion_register_shortcode_ui() { | |
// Register ShortCode ui for Accordion. | |
shortcode_ui_register_for_shortcode( 'accordion', | |
array( | |
'label' => esc_html__( 'Add Accordion', 'festival' ), | |
'listItemImage' => 'dashicons-list-view', | |
'post_type' => array( 'page', 'post' ), | |
'attrs' => array( | |
array( | |
'label' => esc_html__( 'Question', 'festival' ), | |
'attr' => 'question-0', | |
'type' => 'text', | |
), | |
array( | |
'label' => esc_html__( 'Answer', 'festival' ), | |
'attr' => 'answer-0', | |
'type' => 'textarea', | |
'encode' => true, | |
'meta' => array( | |
'data-wysiwyg' => 'true', | |
), | |
), | |
), | |
) | |
); | |
} | |
add_action( 'register_shortcode_ui', 'accordion_register_shortcode_ui' ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Style for Shortcode UI content editor with tinymce. | |
*/ | |
.shortcode-ui-model-open .field-block .mce-tinymce { | |
border: 1px solid #ddd; | |
} | |
.shortcode-ui-model-open .mce-panel.mce-menu, .shortcode-ui-model-open .mce-tooltip, .shortcode-ui-model-open .mce-inline-toolbar-grp, .shortcode-ui-model-open .ui-autocomplete.wplink-autocomplete, .shortcode-ui-model-open #wp-link-wrap { | |
z-index: 160001 !important; | |
} | |
.shortcode-ui-repeater-section { | |
border: 1px solid; | |
padding: 10px; | |
margin-bottom: 10px; | |
} | |
.repeater-new-section-container { | |
padding: 15px 0; | |
} | |
.repeater-new-section-button { | |
padding: 10px; | |
cursor: pointer; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Script for shortcode UI customization. | |
* Add tinyMCE and repeater Field. | |
*/ | |
(function( $, wp ) { | |
'use strict'; | |
// Shorcodes for which to enable tinyMCE on inner content field. | |
var supportedShortcodeTagsForWysiwyg = [ 'accordion' ]; | |
var supportedShortcodeTagsForRepeater = [ 'accordion' ]; | |
window.CustomShortcodeUI = { | |
// Function to load TinyMCE Editor to selector. | |
loadEditor: function( shortcode, selectorId ) { | |
var selector = '.shortcode-ui-edit-' + shortcode.get('shortcode_tag') + ' #' + selectorId; | |
var _that = this; | |
if( 'undefined' === typeof selectorId ) { | |
selector = '.shortcode-ui-edit-' + shortcode.get('shortcode_tag') + ' textarea[data-wysiwyg]'; | |
} | |
if ( $( selector ).length > 1 ) { | |
$( selector ).each( function() { | |
selectorId = $( this ).attr( 'id' ); | |
_that.initTinyMce( selector, selectorId ); | |
} ); | |
} else { | |
selectorId = $( selector ).attr( 'id' ); | |
_that.initTinyMce( selector, selectorId ); | |
} | |
return true; | |
}, | |
initTinyMce: function( selector, selectorId ) { | |
var editor = tinymce.get(selectorId); | |
// Check if editor is already initialized, destroy before re-init. | |
if ( editor ) { | |
editor.destroy(); | |
} | |
// Initialize tinymce editor to selector textarea. | |
tinyMCE.init({ | |
selector: selector, | |
id: selectorId, | |
content_css: tinyMCEPreInit.mceInit.content.content_css, | |
menubar: false, | |
relative_urls: true, | |
height: 200, | |
toolbar: 'formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,wp_more', | |
plugins: [ 'lists', 'paste', 'wordpress', 'wplink' ], | |
init_instance_callback: function( editor ) { | |
editor.on( 'change', function() { | |
var $target = $( editor.targetElm ); | |
$target.val( editor.getContent( { format: 'raw' } ) ); | |
$target.val( tinymce.html.Entities.decode( $target.val().trim() ) ); | |
$target.trigger( 'input' ); | |
}); | |
} | |
}); | |
}, | |
// Function to unload TinyMCE Editor to selector. | |
unloadEditor: function( shortcode ) { | |
var selectorId, | |
selector = '.shortcode-ui-edit-' + shortcode.get('shortcode_tag') + ' textarea[data-wysiwyg]'; | |
if ( $( selector ).length > 1 ) { | |
$( selector ).each( function() { | |
selectorId = $( this ).attr( 'id' ); | |
var editor = tinymce.get(selectorId); | |
if ( editor ) { | |
editor.destroy(); | |
} | |
} ); | |
} else { | |
selectorId = $( selector ).attr('id'); | |
var editor = tinymce.get(selectorId); | |
if ( editor ) { | |
editor.destroy(); | |
} | |
} | |
}, | |
addRepeaterSupport: function ( shortcode ) { | |
var shortcodeTag = shortcode.get('shortcode_tag'); | |
var selector = '.shortcode-ui-edit-' + shortcodeTag; | |
var shortcodeContainer = $( selector ).parent( '.edit-shortcode-form' ); | |
if ( supportedShortcodeTagsForWysiwyg.indexOf( shortcodeTag ) >= 0 ) { | |
this.unloadEditor( shortcode ); | |
} | |
$( shortcodeContainer ).addClass( 'shortcode-ui-repeater-container' ); | |
$( selector ).addClass('shortcode-ui-repeater-section'); | |
var addNewFieldButton = $( '<button/>', { | |
class: 'repeater-new-section-button', | |
text: 'Add New Section', | |
type: 'button' | |
} ); | |
var addNewFieldContainer = $( '<div/>', { | |
class: 'repeater-new-section-container', | |
} ); | |
var repeaterFieldsContainer = $( '<div/>', { | |
class: 'repeater-fields-container' | |
} ); | |
$( selector ).appendTo( repeaterFieldsContainer ); | |
$( shortcodeContainer ).append( repeaterFieldsContainer ); | |
$( addNewFieldContainer ).append( addNewFieldButton ); | |
$( shortcodeContainer ).append( addNewFieldContainer ); | |
if ( supportedShortcodeTagsForWysiwyg.indexOf( shortcodeTag ) >= 0 ) { | |
this.loadEditor( shortcode ); | |
} | |
this.addNewSection( shortcode, repeaterFieldsContainer ); | |
}, | |
addNewSection: function( shortcode, repeaterFieldsContainer ) { | |
var EditShortcodeForm = sui.views.EditShortcodeForm; | |
var shortcodeAttrs = $.extend( true, {}, shortcode.get( 'attrs' ) ); | |
var shortcodeAttrsCount = shortcodeAttrs.length; | |
var shortcodeView = new EditShortcodeForm({ model: shortcode }); | |
var updatedCid = ''; | |
var increment = 1; | |
var _this = this; | |
var shortcodeRepeaterAttrs = shortcode.get('attributes_backup'); | |
var shortcodeRepeaterAttrsLength = Object.keys( shortcodeRepeaterAttrs ).length; | |
var editExistingRepeaterShortcode = ( shortcodeRepeaterAttrsLength > 0 ); | |
var wysiwygEditors = []; | |
shortcode.set( 'attributes_backup', {} ); | |
if( editExistingRepeaterShortcode ) { | |
var extraAttrsIndex = {}; | |
$.each( shortcodeRepeaterAttrs, function ( key ) { | |
var splitKeys = key.split('-'); | |
var index = parseInt( splitKeys.pop() ); | |
extraAttrsIndex[ index ] = index; | |
}); | |
var existingRepeaterSectionCount = Object.keys( extraAttrsIndex ).length; | |
for ( var i = 1; i <= existingRepeaterSectionCount; i++ ) { | |
var newSectionContainer = $( | |
'<div/>', | |
{ class: 'edit-shortcode-form-fields shortcode-ui-repeater-section shortcode-ui-edit-' + shortcode.get('shortcode_tag') } | |
); | |
shortcodeAttrs.each( function ( attr, index ) { | |
var newAttrs = $.extend( true, {}, attr ); | |
var type = newAttrs.get('type'); | |
var newAttr = newAttrs.get('attr'); | |
var metaData = newAttrs.get( 'meta' ); | |
var newAttrValue; | |
if ( ! shortcodeUIFieldData[type] ) { | |
return; | |
} | |
newAttr = newAttr.substring( 0, newAttr.length - 2 ); | |
newAttr = newAttr + '-' + increment; | |
newAttrs.set('attr', newAttr); | |
if ( 'undefined' !== typeof shortcodeRepeaterAttrs[newAttr] ) { | |
newAttrValue = shortcodeRepeaterAttrs[newAttr]; | |
if (newAttrs && newAttrs.get('encode')) { | |
newAttrValue = decodeURIComponent(newAttrValue); | |
newAttrValue = newAttrValue.replace("%", "%"); | |
} | |
newAttrs.set('value', newAttrValue); | |
} | |
updatedCid = 'c' + ( parseInt( newAttrs.cid.substring(1) ) + ( shortcodeAttrsCount * increment ) ); | |
newAttrs.set('id', 'shortcode-ui-' + newAttrs.get('attr') + '-' + updatedCid); | |
newAttrs.cid = updatedCid; | |
shortcode.attributes.attrs.models.push( newAttrs ); | |
var viewObjName = shortcodeUIFieldData[type].view; | |
var tmplName = shortcodeUIFieldData[type].template; | |
var view = new sui.views[viewObjName]({model: newAttrs}); | |
view.template = wp.media.template(tmplName); | |
view.shortcode = shortcodeView.model; | |
shortcodeView.views.add( '.edit-shortcode-form-fields', view ); | |
view.render(); | |
if( 'undefined' !== typeof metaData['data-wysiwyg'] ) { | |
wysiwygEditors.push( newAttrs.get('id') ); | |
} | |
$(newSectionContainer).append( view.el ); | |
} ); | |
$( repeaterFieldsContainer ).append( newSectionContainer ); | |
shortcode._previousAttributes = shortcode.attributes; | |
shortcode.attributes.attrs.length = shortcode.attributes.attrs.length + shortcodeAttrsCount; | |
increment++; | |
} | |
} | |
if( wysiwygEditors.length > 0 ) { | |
$.each( wysiwygEditors, function ( index, value ) { | |
_this.loadEditor( shortcode, value ); | |
}); | |
} | |
wysiwygEditors = []; | |
$( '.repeater-new-section-button' ).on( 'click', function( e ) { | |
// TODO: Add in one function. | |
var newSectionContainer = $( | |
'<div/>', | |
{ class: 'edit-shortcode-form-fields shortcode-ui-repeater-section shortcode-ui-edit-' + shortcode.get('shortcode_tag') } | |
); | |
shortcodeAttrs.each( function ( attr, index ) { | |
var newAttrs = $.extend( true, {}, attr ); | |
var type = newAttrs.get('type'); | |
var newAttr = newAttrs.get('attr'); | |
var metaData = newAttrs.get( 'meta' ); | |
newAttr = newAttr.substring( 0, newAttr.length - 2 ); | |
newAttrs.set('attr', newAttr + '-' + increment); | |
newAttrs.set('value', ''); | |
updatedCid = 'c' + ( parseInt( newAttrs.cid.substring(1) ) + shortcodeAttrsCount ); | |
newAttrs.set('id', 'shortcode-ui-' + newAttrs.get('attr') + '-' + updatedCid); | |
newAttrs.cid = updatedCid; | |
if ( ! shortcodeUIFieldData[type] ) { | |
return; | |
} | |
var viewObjName = shortcodeUIFieldData[type].view; | |
var tmplName = shortcodeUIFieldData[type].template; | |
var view = new sui.views[viewObjName]({model: newAttrs}); | |
view.template = wp.media.template(tmplName); | |
view.shortcode = shortcodeView.model; | |
shortcodeView.views.add( '.edit-shortcode-form-fields', view ); | |
view.render(); | |
if( 'undefined' !== typeof metaData['data-wysiwyg'] ) { | |
wysiwygEditors.push( newAttrs.get('id') ); | |
} | |
$(newSectionContainer).append( view.el ); | |
shortcode.attributes.attrs.models.push( newAttrs ); | |
}); | |
$( repeaterFieldsContainer ).append( newSectionContainer ); | |
if( wysiwygEditors.length > 0 ) { | |
$.each( wysiwygEditors, function ( index, value ) { | |
_this.loadEditor( shortcode, value ); | |
}); | |
} | |
increment++; | |
}); | |
} | |
}; | |
// Shortcode ui plugin render_edit shortcode action. | |
wp.shortcake.hooks.addAction( 'shortcode-ui.render_edit', function( shortcode ) { | |
// Need to handle css based on this class. Default model-open class is not working properly when we use attachement in shortcode-ui. | |
$( 'body' ).addClass('shortcode-ui-model-open'); | |
if ( supportedShortcodeTagsForRepeater.indexOf( shortcode.get( 'shortcode_tag' ) ) >= 0 ) { | |
CustomShortcodeUI.addRepeaterSupport( shortcode ); | |
} else if ( supportedShortcodeTagsForWysiwyg.indexOf( shortcode.get( 'shortcode_tag' ) ) >= 0 ) { | |
CustomShortcodeUI.loadEditor( shortcode ); | |
} | |
} ); | |
// Shortcode ui plugin render_new shortcode action. | |
wp.shortcake.hooks.addAction( 'shortcode-ui.render_new', function( shortcode ) { | |
// Need to handle css based on this class. Default model-open class is not working properly when we use attachement in shortcode-ui. | |
$( 'body' ).addClass('shortcode-ui-model-open'); | |
if ( supportedShortcodeTagsForRepeater.indexOf( shortcode.get( 'shortcode_tag' ) ) >= 0 ) { | |
CustomShortcodeUI.addRepeaterSupport( shortcode ); | |
} else if ( supportedShortcodeTagsForWysiwyg.indexOf( shortcode.get( 'shortcode_tag' ) ) >= 0 ) { | |
CustomShortcodeUI.loadEditor( shortcode ); | |
} | |
} ); | |
// Shortcode ui plugin render_destroy shortcode action. | |
wp.shortcake.hooks.addAction( 'shortcode-ui.render_destroy', function( shortcode ) { | |
// Need to handle css based on this class. Default model-open class is not working properly when we use attachement in shortcode-ui. | |
$( 'body' ).removeClass('shortcode-ui-model-open'); | |
if ( supportedShortcodeTagsForWysiwyg.indexOf( shortcode.get( 'shortcode_tag' ) ) >= 0 ) { | |
CustomShortcodeUI.unloadEditor( shortcode ); | |
} | |
} ); | |
})( jQuery, window.wp ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Admin Enqueue Scripts. | |
*/ | |
function custom_admin_enqueue_scripts() { | |
// Admin Custom style. | |
wp_enqueue_style( 'custom-admin-style', get_template_directory_uri() . 'css/admin-style.css' ); | |
} | |
add_action( 'admin_enqueue_scripts', 'custom_admin_enqueue_scripts' ); | |
/** | |
* Shortcode UI customization. | |
*/ | |
function custom_shortcode_ui_scripts() { | |
// Shortcode ui customization script. | |
wp_enqueue_script( 'custom-shortcode-ui', get_template_directory_uri() . 'js/custom-shortcode-ui.js', array( 'shortcode-ui' ), '1.0.0', true ); | |
} | |
add_action( 'enqueue_shortcode_ui', 'custom_shortcode_ui_scripts' ); | |
/** | |
* Get repeater section count for shortcode attributes. | |
* | |
* @param array $attrs Shortcode Attributes. | |
* @param array $defined_attrs Shortcode Defined Attributes. | |
* | |
* @return int | |
*/ | |
function get_repeater_shortcode_attr_count( $attrs, $defined_attrs ) { | |
$repeater_attrs_indexes = []; | |
foreach ( $attrs as $key => $value ) { | |
$index = substr( $key, 0, strrpos( $key, '-' ) ); | |
if ( array_key_exists( $index, $defined_attrs ) ) { | |
$index = substr( $key, strrpos( $key, '-' ) + 1 ); | |
$repeater_attrs_indexes[ $index ] = true; | |
} | |
} | |
return count( $repeater_attrs_indexes ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For repeater shortcode ui we need to expose EditShortcodeForm View for reuse markup.
ref: wp-shortcake/shortcake#773