Search code examples
tinymce-4

What code will force a reselection in TinyMCE 4.6?


I'm having a problem with TinyMCE 4.6. I've implemented a custom button that bumps the font size of selected text:

ed.addButton('finc', {
           image: '/tinymce/plugins/zackel/button_images/big.png',
           title: '+ font size',
           id : 'finc',
           onclick:function(editor,url) {
             console.log("************ In finc: ", ed);

             var delta;
             var currentFontSize = new Number($(ed.selection.getNode()).css('font-size').replace('px',''));
             console.log("************ finc: currentFontSize = " + currentFontSize);


             var node = ed.selection.getNode();  // <======= LINE 565
             var nodeName = node.nodeName;  // for example 'DIV ' or 'P'
              console.log("************ finc: node is ", node, "nodeName = " + nodeName);

             if (currentFontSize >= 24) {
                 delta = 2;
             }
             else {
                 delta = 1;
             }

             currentFontSize =  currentFontSize + delta;
              console.log("************ finc: New font size = " + currentFontSize);
             ed.formatter.register('incfont', {
                 inline : 'span',
                 styles : {'font-size' : currentFontSize + 'px'}
              });
              ed.formatter.apply('incfont');
              console.log("********** finc: posting to val box  " +  currentFontSize);
              $("div#px_val button").text(currentFontSize + 'px');  // show value in value box
           }
        });

If the text is initially in a P the button works fine but puts the text into a span inside the P when it's done. If I then just hit the button again it fails because the node it brings back on line 565 is still the P, which still has the original font size. So if he initial font size is 16, it goes to 17 but then every bump after that stays at 17. If I deselect the text after bumping it and reselect it, line 565 gets the span and the bumps work every time.

How can I force a reselection from my code, so 565 finds the span the second time instead of the P, without me deselecting and reselecting the text?

Thanks


Solution

  • It seems to me that I understand you problem, but i believe that the text re-selection should not happen every time you apply the formatting - just only in the case TinyMCE is adding the new SPAN.

    Here is my proposal:

    var delta;
    var currentFontSize = new Number($(ed.selection.getNode()).css('font-size').replace('px',''));
    var node = ed.selection.getNode();
    var nodeName = node.nodeName;  // for example 'DIV ' or 'P'
    if (currentFontSize >= 24) {
        delta = 2;
    }
    else {
        delta = 1;
    }
    currentFontSize =  currentFontSize + delta;
    ed.formatter.register('incfont', {
        inline : 'span',
        styles : {'font-size' : currentFontSize + 'px'}
    });
    
    var cnt = ed.selection.getContent({format : 'html'});
    var lenBefore = $(cnt).length;
    
    ed.formatter.apply('incfont');
    
    var cnt = ed.selection.getContent({format : 'html'});
    var lenAfter = $(cnt).length;
    
    if(lenAfter > lenBefore) {
        var newText = ed.selection.selectedRange.startContainer;
        var rng = ed.dom.createRng();
        rng.setStart(newText, 0);
        rng.setEnd(newText, newText.nodeValue.length);
        ed.selection.setRng(rng);
        ed.nodeChanged();
    }
    

    Explanation:

    when you apply the formatter for the first time, TinyMCE is adding the SPAN and you will find the new selection inside the ed.selection.selectedRange.startContainer node of type text. This is the same as the first child node of type text of the newly inserted SPAN. For subsequent actions, there shall be no need to do any re-selection.

    Moreover, IMHO i feel somehow unusual to change the font size in mouse click, i would prefer a standard plugin button which works only with a already existing text selection (but this is up to you):

    enter image description here

    Of course, the main question of the re-selection is solved, and the plugin will work repeatedly with subsequent mouse clicks also by using a plugin button.

    Just in case, as said before, you may also check at the very top if there is any content:

    var hasContent = ed.selection.getContent({format : 'text'}.length > 0);
    if(!hasContent) return;
    

    So i believe the whole stuff should do the job but anyway, i feel there is still room for some improvements, for example if you need also to reduce the font size, and thus you will also need to delete the already existing - but no longer necessary - SPAN which contain the formatting.