7

For standard textareas I use this plugin to create a placeholder. How can I extend tinymce so that this works in this way also.

E.g the default value is read from the textarea attribute then cleared when a user focuses on the iframe.

Similar to this for CKEditor: http://alfonsoml.blogspot.com.es/2012/04/placeholder-text-in-ckeditor.html

Community
  • 1
  • 1
John Magnolia
  • 16,769
  • 36
  • 159
  • 270

9 Answers9

12

I refactored Tom Duke's code to work on TinyMCE4 with it's jquery plugin

$('textarea.tinymce').tinymce({
  script_url: _base + '/assets/js/tinymce/tinymce.min.js',
  theme: "modern",
  setup: function(editor) {
    // Set placeholder
    var placeholder = $('#' + editor.id).attr('placeholder');
    if (typeof placeholder !== 'undefined' && placeholder !== false) {
      var is_default = false;
      editor.on('init', function() {
        // get the current content
        var cont = editor.getContent();

        // If its empty and we have a placeholder set the value
        if (cont.length === 0) {
          editor.setContent(placeholder);
          // Get updated content
          cont = placeholder;
        }
        // convert to plain text and compare strings
        is_default = (cont == placeholder);

        // nothing to do
        if (!is_default) {
          return;
        }
      })
      .on('focus', function() {
        // replace the default content on focus if the same as original placeholder
        if (is_default) {
          editor.setContent('');
        }
      })
      .on('blur', function() {
        if (editor.getContent().length === 0) {
          editor.setContent(placeholder);
        }
      });
    }
  }
});
Kamweti
  • 165
  • 1
  • 6
  • I tried the code for the accepted answer first, but this was the code that worked for me. Since the accepted answer is for tinymce 3 and this is for tinymce 4. – james Aug 15 '13 at 12:42
  • 1
    It doesn't work for me. When I type in any content, click somewhere else and click back on the editor, the content disappears. – Atadj Dec 13 '13 at 15:19
  • 1
    This works but it is not really a true HTML5 placeholder. It is just a text filler. I find it crazy that we have to do all this work in order to place in a placeholder. Does anyone know if this can be done simple through the API as a real placeholder? – CodeGodie Dec 13 '13 at 15:33
  • @DiegoCamacho as of now, the API does not offer a way to add placeholders to an edit box – Kamweti Dec 14 '13 at 12:20
  • Updated answer for tinymce4. Amazed after all these years it's still not in the core. – John Magnolia Nov 16 '21 at 11:23
6

I was getting an error if there was no placeholder attribute.

I combined the code from this answer: jQuery hasAttr checking to see if there is an attribute on an element to get the amended code below which deals with that scenario:

setup: function(ed) {

// Set placeholder
var tinymce_placeholder = $('#'+ed.id);
var attr = tinymce_placeholder.attr('placeholder');

// For some browsers, `attr` is undefined; for others,
// `attr` is false.  Check for both.
    if (typeof attr !== 'undefined' && attr !== false) {
        var is_default = false;

        ed.onInit.add(function(ed) {
            // get the current content
            var cont = ed.getContent();

            // If its empty and we have a placeholder set the value
            if(cont.length == 0){
                ed.setContent(tinymce_placeholder.attr("placeholder"));

                // Get updated content
                cont = tinymce_placeholder.attr("placeholder");
            }

            // convert to plain text and compare strings
            is_default = (cont == tinymce_placeholder.attr("placeholder"));

            // nothing to do
            if (!is_default){
                return;
            }
        });

        ed.onMouseDown.add(function(ed,e) {
            // replace the default content on focus if the same as original placeholder
            if (is_default){
                ed.setContent('');
            }
        });
    }
}
Community
  • 1
  • 1
Tom Duke
  • 96
  • 8
  • This works but it is not really a true HTML5 placeholder. It is just a text filler. I find it crazy that we have to do all this work in order to place in a placeholder. Does anyone know if this can be done simple through the API as a real placeholder? – CodeGodie Dec 13 '13 at 15:33
4

The answers above were not working for me, but here's my (for me) working code based on the answers above and using onchange_callback. Hope it helps someone!

onchange_callback : function(ed){
            var tinymce_placeholder = $('#' + ed.id).attr("placeholder");     
            setTimeout(function () {
                var content = ed.getContent().replace(/<p>|<\/p>/g, '');
                if (content == '') {
                    ed.setContent(tinymce_placeholder);
                }
            }, 200);
        },
        setup: function (ed) {
            // Set placeholder
            var tinymce_placeholder = $('#' + ed.id);
            if (tinymce_placeholder.length) {
                ed.onInit.add(function (ed) {
                    var cont = ed.getContent();
                    if (cont.length == 0) {
                        ed.setContent(tinymce_placeholder.attr("placeholder"));
                    }
                });
                ed.onMouseDown.add(function (ed, e) {
                    var content = ed.getContent().replace(/<p>|<\/p>/g, '');
                    if (content == tinymce_placeholder.attr("placeholder")) {
                        ed.setContent('');
                    }
                });
            }
        }
Cyril Mestrom
  • 6,042
  • 4
  • 19
  • 27
  • This works but it is not really a true HTML5 placeholder. It is just a text filler. I find it crazy that we have to do all this work in order to place in a placeholder. Does anyone know if this can be done simple through the API as a real placeholder? – CodeGodie Dec 13 '13 at 15:35
4

Try this code:

Add a placeholder text for the tinyMCE inline editor:

    $scope.ContentOptions = {
    setup: function(editor) {

        editor.on('init', function () {
            // Default classes of tinyMCE are a bit weird
            // I add my own class on init
            // this also sets the empty class on the editor on init
            tinymce.DOM.addClass( editor.bodyElement, 'content-editor' );
        });

        // You CAN do it on 'change' event, but tinyMCE sets debouncing on that event
        // so for a tiny moment you would see the placeholder text and the text you you typed in the editor
        // the selectionchange event happens a lot more and with no debouncing, so in some situations
        // you might have to go back to the change event instead.
         editor.on('selectionchange', function () {
             if ( editor.getContent() === "" ) {
                 tinymce.DOM.addClass( editor.bodyElement, 'empty' );
             } else {
                 tinymce.DOM.removeClass( editor.bodyElement, 'empty' );
             }
         });
   }} 

The HTML part in the view

<div data-placeholder="Content..." id="post-content-editor" ui-tinymce="ContentOptions" ng-model="newPostContentModel"></div>

and Finally the CSS to create the placeholder text (it gets it from data-placeholder="Content..." but you could do it directly in css

    .content-editorr:before {
        display: none;
}
.content-editor.empty:before {
        display: block;
        position: absolute;
        content: attr(data-placeholder);
}

I found it on github:

https://github.com/angular-ui/ui-tinymce/issues/197

I tried many placeholder solutions for tinymce and found this solution very usefull as it meets all the requirement of placeholder. I think it is the best solution,

Gaurav
  • 872
  • 12
  • 28
2

For tinymce 4 I had problems with the events where ed.onInit was not defined. tinymce 4 uses ed.on('event' , callback) instead. Here is my implementation. I also used focus instead of mousedown as the event to listen for when clearing the editor because mousdown wasn't working for some reason.

setup :  function(ed) {

        // Set placeholder
        var tinymce_placeholder = $('#'+ed.id);
        var attr = tinymce_placeholder.attr('placeholder');

        // For some browsers, `attr` is undefined; for others,
        // `attr` is false.  Check for both.
        if (typeof attr !== 'undefined' && attr !== false) {
            var is_default = false;

            ed.on('init' , function(ed) {
                // get the current content
                var cont = ed.target.getContent();

                // If its empty and we have a placeholder set the value
                if(cont.length == 0){
                    ed.target.setContent(tinymce_placeholder.attr("placeholder"));

                    // Get updated content
                    cont = tinymce_placeholder.attr("placeholder");
                }

                // convert to plain text and compare strings
                is_default = (cont == tinymce_placeholder.attr("placeholder"));

                // nothing to do
                if (!is_default){
                    return;
                }
            });

            ed.on('focus', function(ed,e) {
                // replace the default content on focus if the same as original placeholder
                if (is_default){
                    ed.target.setContent('');
                }
            });
        }
    }

hope this helps for anyone who had problems with the other answers

Joe Fitzgibbons
  • 331
  • 3
  • 8
  • This works but it is not really a true HTML5 placeholder. It is just a text filler. I find it crazy that we have to do all this work in order to place in a placeholder. Does anyone know if this can be done simple through the API as a real placeholder? – CodeGodie Dec 13 '13 at 15:33
2

I found another method that doesn't ever mess with the content of the textarea. I like this so that I don't have to have special conditions that prevent a user from submitting content that is just the placeholder. The write-up is found here, but I added the onclick method so that the label is clickable-- without this the user has to click either below the <label> or to the side of it. This works great with TinyMCE 4.

style

.tinyMCEPlaceholder {
    top: 45px;
    left: 9px;
    z-index: 1;
    color: #bbbbbb;
    position: absolute;
    cursor:text;
}

html

<div id="holder">
    <label for="tinymce" onclick="tinymce.execCommand('mceFocus',false,'area_id');">Type your article</label>
    <textarea id="comments" id="area_id" class="tinymce" name="comments" cols="40" rows="10"></textarea>
</div>

<!-- or -->

<div id="holder">
    <label for="tinymce" onclick="tinymce.get('area_id').fire('focus',{},false);">Type your article</label>
    <textarea id="comments" id="area_id" class="tinymce" name="comments" cols="40" rows="10"></textarea>
</div>

TinyMCE Setup

 // setup
    setup : function(ed) {
        /* toggle all labels that have the attr 'tinymce' */
        ed.on('init', function() {
            if(ed.getContent() != '') {
                $('label[for="tinymce"]').hide();
            }

            $(ed.getDoc()).contents().find('body').focus(function(){
                $('label[for="tinymce"]').hide();
            });

            $(ed.getDoc()).contents().find('body').blur(function(){
                if(ed.getContent() == '') {
                    $('label[for="tinymce"]').show();
                }
            });
        });
    },
AddieD
  • 138
  • 7
1

This plugin for TinyMCE seems to be a solution:

https://github.com/mohan/tinymce-placeholder

Hope it helps!

Darío Pm
  • 139
  • 1
  • 9
1

Gaurav's solution works OK, but needs a few changes. I used this modification to make it nearly perfect:

editor.on("init", function(){
    tinymce.DOM.addClass( editor.bodyElement, 'content-editor' );
    if ( editor.getContent() === "" ) {
        tinymce.DOM.addClass( editor.bodyElement, 'empty' );
        var pseudoBeforeHeight = window.getComputedStyle(editor.bodyElement, ':before').height;
        tinymce.DOM.setStyles( editor.bodyElement, { 'height': pseudoBeforeHeight } );
    }
});
liebezeit
  • 31
  • 2
  • 3
0

I added placehold easily by adding data-mce-placeholder attribute on textarea element.
data-mce-placeholder is referred of body::before text css in iframe of editor

<textarea
  ng-model="textContent",
  ng-change="save()",
  style="height: 360px; max-height: 50vh; border: none !important",
  ui-tinymce="tinymceOptions"
  data-mce-placeholder="Input your text here"
></textarea>
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Owen Ma
  • 1
  • 3