1

I need a manual code to my functions php to extend the visual editor from removing tabs when pasting code blocks.

I tried this code, found at this site, but it does not work as I want. If I got:

add_filter('tiny_mce_before_init', 'tiny_mce_before_init');
function tiny_mce_before_init($init) {
    $init['setup'] = "function(ed) {
        ed.onBeforeSetContent.add(function(ed, o) {
            if ( o.content.indexOf('<pre') != -1) {
                o.content = o.content.replace(/<pre[^>]*>[\\s\\S]+?<\\/pre>/g, function(a) {
                    return a.replace(/(\\r\\n|\\n)/g, '<br />');
                });
            }
        });
    }";
    return $init;
}

and paste into Visual, I got this:

add_filter('tiny_mce_before_init', 'tiny_mce_before_init');
function tiny_mce_before_init($init) {
$init['setup'] = "function(ed) {
ed.onBeforeSetContent.add(function(ed, o) {
if ( o.content.indexOf('<pre') != -1) {
o.content = o.content.replace(/<pre[^>]*>[\\s\\S]+?<\\/pre>/g, function(a) {
return a.replace(/(\\r\\n|\\n)/g, '<br />');
});
}
});
}";
return $init;
}

I do understand that the TinyMCE settings does not intend to work with preserving tabs, as "it takes up space"...

I need a manual paste & go solution, not links to installing plugins that handles a lot of other stuff. Switching between the editors are not allowed to change anything either. Is it possible?

Thanks for reading and helping!

1

My answer is, there is no solution within the TinyMCE and Wordpress conversation for this. But There are diffrent approaches to work with coding material.

I Shared this on an other discussion, but it might be a better context within your question.

This solution has been working for me many years, and I love it. This approach uses a "middle-hand" to serve correct pre-content and characters between the editors and wpautop() issues. It also handles the entity char problems switching between editors.

Just paste into functions.php

How to use: Create default pre-formatted textblock in the editor, like using the dropdown in the toolbar. Then inside the editor just Click on it -as you would do with images. A area appears to paste or edit, send it back. Just click on the pre block again to edit.

It seems heavy, but its light. No modals API or whatever. But jQuery must be in "global scope" as it talks with tinyMCE API. The dollarsign $ can NOT be in use and the jQuery text clutter the code down. Its mostly the creation of HTML elements that takes space.

How it works: Pretty simple, Without "touching" it -TinyMCE dont mess with it. Its worth trying out!

/**
 * PRE Handler
 * Solves <pre> handle in Wordpress tinyMCE editor
 * TAB support
 * TAB support to TEXT editor
 * Simple cleanup with Undo
 * Push cleanup (experimental)
 * Moves empty code chunks to beginning
**/


function entex_tiny_mce_before_init(){
    add_filter('tiny_mce_before_init', function($mceInit){
        $mceInit['setup'] = 'ua_TinyMCE_setup_callback';
        return $mceInit;
    });
    add_action('before_wp_tiny_mce', 'entex_TinyMCE_javascript');
}
add_action('after_setup_theme', 'entex_tiny_mce_before_init');


function entex_TinyMCE_javascript() {

    echo '<script type="text/javascript">'."\n";
    ?>

    var ua_tinyMCE_invoked = 0;

    function ua_TinyMCE_setup_callback(ed){

        if(ua_tinyMCE_invoked) return;
        ua_tinyMCE_invoked = 1;

        ed.on('init', function(e) {
            jQuery(ed.getBody()).on('click', 'pre', function() {
                ua_TinyMCE_edit_pre(ed, this);
                return false;
            });
        });
    }

    function ua_TinyMCE_helper_cleanBeginnings(str, find, replace){
        return str.replace(new RegExp(find, 'g'), replace);
    }

    function ua_TinyMCE_edit_pre(ed, obj) {
        var jQueryE = jQuery(obj); 
        var jQueryB = jQuery(ed.getBody());
        var content = jQuery('<textarea/>').html(jQueryE.html()).text();
        content = content.replace(/(<br>)/g, '');
        /* add whatever stuff to manipulate here */
        //content = content.replace(/   /g, '\t');
        var data = content;


        var jQueryL = jQuery('<div />').css({
            'position': 'fixed',
            'box-sizing': 'border-box',
            'background-color': 'rgba(255, 255, 255, 0.85',
            'border': '3px solid #ccc',
            'padding': '10px',
            'z-index': '9992',
            'height': 'auto',
            'width': '80%',
            'left': '50%',
            'margin-left': '-40%',
            'top': '5%'
        });

        var jQueryT = jQuery('<textarea />').keydown(function(e){

            if ( e.which != 9 ) return;
            var start = this.selectionStart;
            var end = this.selectionEnd;
            this.value = this.value.substr( 0, start ) + "\t" + this.value.substr( end );
            this.selectionStart = this.selectionEnd = start + 1;
            e.preventDefault();
            return false;

        }).attr('wrap', 'soft').css({
            'height': '98%',
            'width': '88%',
            'min-height': '300px',
            'tab-size': '3',
            'font-family': 'courier new',
            'box-sizing': 'border-box'
        });

        jQuery('#wpcontent').css('position', 'relative').append(jQueryL);
        jQueryL.append(jQueryT);
        jQueryL.append(
            jQuery('<div />').css({
                'width': '10%',
                'height': '100%',
                'position': 'absolute',
                'top': '0px',
                'right': '10px',
                'padding-top': '10px',
                'box-sizing': 'border-box'
            }).append(
                jQuery('<a />').attr('title', 'Send to element').click(function(){

                    var encodedStr = jQueryT.val().replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
                        return '&#'+i.charCodeAt(0)+';';
                    });

                    jQueryE.html(encodedStr);
                    ed.focus();
                    jQueryL.remove();
                    return false;

                }).text('Send').addClass('button button-primary').css({
                    'display': 'block',
                    'width': '100%',
                    'margin-bottom': '5px',
                    'text-align': 'center',
                    'box-sizing': 'border-box'
                }), 

                jQuery('<a />').attr('title', 'Cleanup').click(function(){

                    var data = jQueryT.val();
                    var original = data;
                    data = data.replace(/(\r\n|\n|\r)/gm, "\r\n");
                    var workspace = data.replace(/(\r\n|\n|\r)/gm, '');

                    if(/^\s/.test(workspace)) {
                        var search_string = workspace.replace(/^\s+|\s+$/g, '');
                        if(search_string){
                            var firstChar = search_string[0];
                            var remove = workspace.substr(0, workspace.indexOf(firstChar));
                            remove = "\r\n" + remove;
                            data = ua_TinyMCE_helper_cleanBeginnings(data, remove, "\r\n");
                        }
                        data = data.replace(/   /g, "\t");
                        data = data.replace(/^\s+|\s+$/g, '');
                    } else {
                        data = data.replace(/^\s+|\s+$/g, '');
                    }
                    if(data != original){
                        jQueryT.data('original', original);
                        if(!jQuery('#ua-TinyMCE-btt-undo').get(0)){
                        jQuery(this).after(
                            jQuery('<a />').attr('title', 'Undo').click(function(){
                                jQueryT.val(jQueryT.data('original'));
                                jQuery(this).remove();
                                return false;

                            }).text('Undo').addClass('button').css({
                                'display': 'block',
                                'width': '100%',
                                'margin-bottom': '5px',
                                'text-align': 'center',
                                'box-sizing': 'border-box'
                            }).attr('id', 'ua-TinyMCE-btt-undo')
                        );
                        }
                    }
                    data = data.replace(/   /g, "\t");
                    jQueryT.val(data);
                    return false;

                }).text('Cleanup').addClass('button').css({
                    'display': 'block',
                    'width': '100%',
                    'margin-bottom': '5px',
                    'text-align': 'center',
                    'box-sizing': 'border-box'
                }),

                jQuery('<a />').attr('title', 'Close').click(function(){

                    ed.focus();
                    jQueryL.remove();
                    return false;

                }).text('Close').addClass('button').css({
                    'display': 'block',
                    'width': '100%',
                    'margin-bottom': '5px',
                    'text-align': 'center',
                    'box-sizing': 'border-box'
                }),

                jQuery('<a />').attr('title', 'Remove all data').click(function(){

                    jQueryT.val('').focus();
                    return false;

                }).text('Delete').addClass('button').css({
                    'display': 'block',
                    'width': '100%',
                    'margin-bottom': '0px',
                    'position': 'absolute',
                    'bottom': '10px',
                    'background-color': '#D54E21',
                    'color': '#fff',
                    'text-align': 'center',
                    'box-sizing': 'border-box'
                })
            )
        );
        jQueryT.val(content).focus();
        return false;
    }

    // WP EDITOR
    jQuery(document).ready(function($){
        if($('textarea#content').get(0)){
            $('textarea#content').on('keydown', function(e){
                if ( e.which != 9 ) return;
                var start = this.selectionStart;
                var end = this.selectionEnd;
                this.value = this.value.substr( 0, start ) + "\t" + this.value.substr( end );
                this.selectionStart = this.selectionEnd = start + 1;
                e.preventDefault();
                return false;
            }).css('tab-size', '3');
        }
    });

    <?php
    echo '</script>'."\n";
}

This approach is not a hack or a corny preg match solution. It produces the same converastions as default API.

The PUSH cleanup works if you paste a code from a PHP class or whatever and the chunk or cutted out function you wanna present, has a lot of space or tabs "before". It calculates the space that occurs on the first existing line.

Makes this:

                    if(search_string){
                        var firstChar = search_string[0];
                        var remove = workspace.substr(0, workspace.indexOf(firstChar));
                        remove = "\r\n" + remove;
                        data = ua_TinyMCE_helper_cleanBeginnings(data, remove, "\r\n");
                    }

Into This:

if(search_string){
    var firstChar = search_string[0];
    var remove = workspace.substr(0, workspace.indexOf(firstChar));
    remove = "\r\n" + remove;
    data = ua_TinyMCE_helper_cleanBeginnings(data, remove, "\r\n");
}

Note, This is quite RAW, it can be customized very easy if you know jQuery. This function also add TAB support to the Text editor.

Tips: You should give your admin CSS tab-size: 3 to all your pre/ editor/ code-elements to match and sync the "visual" aspect.

Please use it, comment, And I will try to guide any improvements.

  • Works perfectly for my needs, best approach ever. Thanks! – cavameta Oct 16 '17 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.