26

Re: Limit the Number of characters entered in the editor

Hi Guys I never usually post but since the amount of time I have spent trying to get all of these to work I will post the solution I have come up with. 

This is using perreault, and garygfx code examples. 

Basically Perreaults code gave me a few issues with IE with multiple forms.  Also his was not dynamic so you could not put it cross site instead had to call specific forms and give names of each.

garygfx had good code but also could not dynamically pick up the forms on a page and process accordingly. 

I have taken both of these and added a few extra lines to dynamically determine the id of the form and also use this information to place the text in the correct location.

Please note that the html and div tags have to be named appropriatly.  Mainly the div tags has to have the same id name plus count, and max read above for more details from perr post.

Also I have not had a chance to fully test but appears to work correctly.  Once I have cleaned it up and mabey added a few extra features I will repost.

If anyone finds an error or issue please let me know and I will correct or try to atleast.

Best of luck.


********************************Script***************************
 

<script language="javascript" type="text/javascript">
            // Notice: The simple theme does not use all options some of them are limited to the advanced theme
             tinyMCE.init({
                mode : "textareas",  
                theme : "advanced", 
                plugins : "iespell",
                        
                theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,removeformat,separator,iespell",
                theme_advanced_buttons2 : "",
                theme_advanced_buttons3 : "" ,
                
                theme_advanced_toolbar_location : "top", 
                theme_advanced_toolbar_align : "center",
                
                handle_event_callback : "myHandleEvent",
                onchange_callback : "myCustomOnChangeHandler",
                oninit : "myCustomOnInit"
    });

var text1_count=0;//init int
var text1_maxchars=3000;// max plain text chars allowed
var text1_undobuffer="";//init string

//init when unit TinyMCE editor is loaded
function myCustomOnInit(){
    tinyMCE_timer1=setTimeout("countchars('Process', tinyMCE.selectedInstance.formTargetElementId ,text1_maxchars,'msgCounter')",1000); //wait a bit to avoid IE error
}

//event when something in TinyMCE changes (which is when an undo level is added. e.g. paste)
function myCustomOnChangeHandler(inst){
    tinyMCE_timer1=setTimeout("countchars('Process', tinyMCE.selectedInstance.formTargetElementId ,text1_maxchars,'msgCounter')",250); //slight delay before counting
}

//event such as key or mouse press
function myHandleEvent(e){
    //window.status = "event:" + e.type;
    if(e.type=="keyup"){
        clearTimeout(tinyMCE_timer1);
        countchars('Process',tinyMCE.selectedInstance.formTargetElementId,text1_maxchars,'msgCounter')
    }
    return true;
}

function getHTML_TinyMCE(txtfield){
    var editor_id=tinyMCE.selectedInstance.formTargetElementId;

    obj=document.getElementById(editor_id + 'Max').innerHTML; 
    if(obj.contentDocument){
        content=obj.contentDocument.body.innerHTML; //FireFox (getContent() messes up cursor position)
    }else{
        content=tinyMCE.getContent(txtfield); //IE
    }
    return content;
}

function stripTags_TinyMCE(txtfield) { //strips html tags leaving plain text
    content=getHTML_TinyMCE(txtfield);
    var re = /(<([^>]+)>)/ig ; //strip all tags
    plaintext = content.replace(re, "");
    return plaintext;
}

function countchars_TinyMCE(txtfield){
    content=stripTags_TinyMCE(txtfield);
    cnt=content.length;
    //alert(cnt);
    return cnt;
}
function countchars(formname,txtfield,maxchars,displayID){
    //editor_id=tinyMCE.selectedInstance.formTargetElementId; // get ID of focused TinyMCE editor
    thefield=eval("document."+formname+"."+txtfield);
    if(isNaN(maxchars)){ //arg could contain a var name rather than a number
        maxchars=eval(maxchars); //convert var to number
    }
    currCount=countchars_TinyMCE(txtfield); // current length of TinyMCE field
    remainCount=maxchars-currCount+1; //fix: allow +1
    tmpvar=txtfield+'_count';   
    eval(tmpvar + '=currCount'); //assign dynamic var to char count
     var editor_id=tinyMCE.selectedInstance.formTargetElementId;
  
            var Show=editor_id + 'Count';
                displayObj=document.getElementById(Show);
    displayObj.innerHTML="You have " + eval(remainCount-1) + " characters remaining"; //-1 to counteract above +1
    if(remainCount<=0){ //typed too much
        if(text1_undobuffer.length > 0){
            tinyMCE_timer2=setTimeout("tinyMCE.setContent(text1_undobuffer)",250); // undo event - replace content with most recent buffer
        };
        displayObj.innerHTML="<B>You have typed the maximum text allowed</B>";
    } else {
        text1_undobuffer=getHTML_TinyMCE(txtfield); //store content in buffer
    }
                
}
</script>

*****************************************************************


****************Page HTML****************************************

<table width="545" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><div id="DescriptionCount">Click inside text area to update current character count.</div><div id="DescriptionMax" style="display:none">3000</div></td>
</tr>
</table>
<table width="545" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>

<textarea name="Description" id="Description" style="width:545px; height:150px"><%=varDescription%></textarea>

</td>
</tr>
</table>

*****************************************************************

PS I am not sure the buffer part is working correctly in IE.  You can get past it by waiting a second and then pasting your text in agian.  It will not go back but keep your over the limit text changes.  If anyone comes up with a quick fix let me know.

PSS Ok one last issue.  Since this is made for a include file it may be placed on a page with forms but without textareas.  in this case IE pops up the script error message were
tinyMCE.selectedInstance.formTargetElementId is null even though it should never even be processing that part.  Any ideas how to fix this issue.  Thanks

-Drew

Last edited by drewber09 (2007-05-17 18:35:29)

27

Re: Limit the Number of characters entered in the editor

Drewber09, thanks for picking up the code and doing some work with it. I've fixed the IE problem. Actually there were a few probs with IE such as the cursor position messing up and the spellchecker not working past the first correction (if you enable the spellchecker). The specific fix is in the getHTML_TinyMCE() function where it handes the IE version of the code. Rather than using the getContent() function which causes the said problems, use this:
content=top.frames[editor_id].document.body.innerHTML; where editor_id would be "mce_editor_0" if you have 1 instance of tinyMCE.

I am getting better results using tinyMCE.selectedInstance.editorId to get the actual ID of TinyMCE itself rather than the textarea's ID.

So here's my new code which works with multiple instances (thanks to drewber09 for pointing me in the right direction), the critical IE fix, a unique buffer for each instance, and a little tidy up.

<HTML>
<HEAD>
<SCRIPT language="javascript" type="text/javascript" src="../jscripts/tiny_mce/tiny_mce.js"></SCRIPT>
<SCRIPT language="javascript" type="text/javascript">
tinyMCE.init({
    mode : "specific_textareas",
    textarea_trigger : "tinyMCE_this",
    theme : "advanced",
    plugins : "",
    theme_advanced_buttons1 : "paste,cut,copy,separator,undo,redo,separator,bold,removeformat,separator,bullist,numlist,outdent,indent,separator,link,separator,code",
    theme_advanced_buttons2 : "",
    theme_advanced_buttons3 : "",
    convert_newlines_to_brs : false,
    handle_event_callback : "myHandleEvent",
    onchange_callback : "myCustomOnChangeHandler",
    oninit : "myCustomOnInit"
});

var text1_maxchars=250;// max plain text chars allowed
var mce_editor_0_undobuffer="";//init string (first tinyMCE instance)
var mce_editor_1_undobuffer="";//init string (second tinyMCE instance, etc)

//init when unit TinyMCE editor is loaded
function myCustomOnInit(){
    tinyMCE_timer1=setTimeout("countchars('form1',tinyMCE.selectedInstance.editorId,text1_maxchars,'msgCounter')",1000); //wait a bit to avoid IE error
}

//event when something in TinyMCE changes (which is when an undo level is added. e.g. paste)
function myCustomOnChangeHandler(inst){
    tinyMCE_timer1=setTimeout("countchars('form1',tinyMCE.selectedInstance.editorId,text1_maxchars,'msgCounter')",250); //slight delay before counting
}

//event such as key or mouse press
function myHandleEvent(e){
    if(e.type=="keyup"){
        clearTimeout(tinyMCE_timer1);
        countchars('form1',tinyMCE.selectedInstance.editorId,text1_maxchars,'msgCounter')
    }
    return true;
}

function getHTML_TinyMCE(editor_id){ //gets HTML from currently selected instance
    obj=document.getElementById(editor_id);
    if(obj.contentDocument){
        content=obj.contentDocument.body.innerHTML; //FireFox (getContent() messes up cursor position)
    }else{
        content=top.frames[editor_id].document.body.innerHTML; //IE - avoid getContent() due to spellchecker and cursor issues
    }
    return content;
}

function stripTags_TinyMCE(editor_id) { //strips html tags leaving plain text
    content=getHTML_TinyMCE(editor_id);
    var re = /(<([^>]+)>)/ig ; //strip all tags
    plaintext = content.replace(re, "");
    return plaintext;
}

function countchars_TinyMCE(editor_id){
    content=stripTags_TinyMCE(editor_id);
    cnt=content.length;
    return cnt;
}
function countchars(formname,editor_id,maxchars,displayID){
    if(isNaN(maxchars)){ //arg could contain a var name rather than a number
        maxchars=eval(maxchars); //convert var to number
    }
    currCount=countchars_TinyMCE(editor_id); // current length of TinyMCE field
    remainCount=maxchars-currCount+1; //fix: allow +1
    tmpvar=editor_id+'_count';   
    eval(tmpvar + '=currCount'); //assign dynamic var to char count
    displayObj=document.getElementById(displayID);
    displayObj.innerHTML="You have " + eval(remainCount-1) + " characters remaining"; //-1 to counteract above +1
    if(remainCount<=0){ //typed too much
        thisBuffer=eval(editor_id+'_undobuffer');
        if(thisBuffer.length > 0){
            tinyMCE_timer2=setTimeout("tinyMCE.setContent(thisBuffer)",250); // undo event - replace content with most recent buffer
        };
        displayObj.innerHTML="<B>You have typed the maximum text allowed</B>";
    } else {
        eval(editor_id+'_undobuffer=getHTML_TinyMCE(editor_id)'); //store content in buffer
    }
}
</SCRIPT>
</HEAD>

<BODY>
<FORM name="form1" id="form1" method="post" action="" onSubmit="tinyMCE.triggerSave()">
    <TEXTAREA id="text1" name="text1" rows="12" cols="80" style="width: 600px" tinyMCE_this="true">
        <H2>Test Header</H2><P>This is my huose where I liive.</P><UL><LI>First bullet point</LI><LI>Second bullet point</LI></UL><br>
    </TEXTAREA><BR>
<SPAN id="msgCounter">Maximum of <SCRIPT language="javascript">document.write(text1_maxchars);</SCRIPT> characters allowed</SPAN><br><br>
    <TEXTAREA id="text2" name="text2" rows="6" cols="80" style="width: 600px" tinyMCE_this="true">
        Some other text.<br>
    </TEXTAREA><BR>
    <INPUT type="submit" name="save" value="Submit" />
    <INPUT type="reset" name="reset" value="Reset" />
</FORM>
</BODY>
</HTML>

28

Re: Limit the Number of characters entered in the editor

Thanks garygfx,


I will look at this and get back to you.  Also note that when using the stripTags_TinyMCE may cause problems if you are loading to database.  As you are not counting the html code added behind the text, Even though this will be added to the database.  Usually it will not cause problems but say you have a varchar(2000) and you are setting your max to 2000 characters.  it is possible that you will try to push more the the 2000 characters and get a fault if you dont have any server side checks going.  I basically just changed it to

                function stripTags_TinyMCE(txtfield) { //strips html tags leaving plain text
                                content=getHTML_TinyMCE(txtfield);
                                //var re = /(<([^>]+)>)/ig ; //strip all tags
                                //plaintext = content.replace(re, "");
                                plaintext = content;
                                return plaintext;
                }

And it corrected the issue.  I am not currently running server side checking yet so figured this would be a quick fix.

Awsome code though thanks for posting agian.  I will try to get this working and see if I find anything.

-Drew

29

Re: Limit the Number of characters entered in the editor

Hi Drew,

My angle on stripping html tags before doing the char count was more of a end-user issue. If users added a link, made something bold, or even created a new paragraph and saw that 7 to 100 characters were eaten up without them actually typing any more text then they'd wonder what's going on. Most of the public don't understand html so they'd question the madness of the char count going down so quickly.

Of course, if your website is for more savvy users then sure, they'd probably realise the counter includes the invisible html elements.

My database character limit is set much higher than what the web form allows to take into account special characters (  etc) and tags. Obviously it's up to the developer (or manager!) to decide how to impliment it and every website will be different, but your point is valid and I'm pleased you've changed the code to get it working the way you want it to.

At one point I was considering making it more user friendly and showing a word count rather than a character count. i.e. you'd set a 100 word limit in the form but allow 2000 chars in your database to take into account an average of 6 chars per word and html tags. It would mean some users hitting the 100 word limit with just 500 characters while some would be over 1000 if they user longer words and have lots of links.

Best wishes,
Gary.

30

Re: Limit the Number of characters entered in the editor

Hello Gary,

Definitely understand the need to strip the html for that purpose, and makes perfect since.  My post was more to inform others if that it could cause issues if they didnt set max characters correctly.

The IE issue was resolved and I commend you on finding that solution.  It has solved pretty much all issues I had with the system and even made it a little better as we could have general calls to different tinymce setups.  If anyone was having this issue with the code i posted you can switch the top

    mode : "specific_textareas",
    textarea_trigger : "tinyMCE_this",

    Just put tinyMCE_this="true" in the textarea to signal tinymce to pick it up.


The only issue that I could not resolve with the updated code you posted was the display of two textarea counters.  it will update according to the one you are selected but if you post the display twice the second will not update.

Not sure if there is an easy solution to this.  The code I posted does solve this but in a time consuming way as you must put id specific names in the code above each textarea to show correctly.

I will be trying to come up with general code that will update and display both counters.  If you have any ideas please post them.

Thanks for the help in this,

-Drew

31

Re: Limit the Number of characters entered in the editor

Hai all,
I am using more TinyNCE at one page how can i get the content of the particular editor and how can i limit the charecter as 3000 for every editor. any one can help me

32

Re: Limit the Number of characters entered in the editor

Hi Deiva,

The way you get multiple forms working on the same page is that you specifically give them and the div tags showing the counter their own id name.  I will give you an example of my code for the tinymce as well as the code i use for multiple forms. 

The only issue that still exists is that you can not include the tinymce code on a page without a textarea using the tinymce.  Otherwise IE will throw and error.  I basically just use logic to comment out the code or not include it whenever it is a regular page and add it in when I know there is a text area.

This is the Code I have in TinyMCE include.

<script language="javascript" type="text/javascript">
        <!--
            // Notice: The simple theme does not use all options some of them are limited to the advanced theme
             tinyMCE.init({
    mode : "textareas", 
                plugins : "iespell",
                        
                theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,removeformat,separator,iespell",
                theme_advanced_buttons2 : "",
                theme_advanced_buttons3 : "" ,
                
                theme_advanced_toolbar_location : "top", 
                theme_advanced_toolbar_align : "center",
    
                handle_event_callback : "myHandleEvent",
                onchange_callback : "myCustomOnChangeHandler",
                oninit : "myCustomOnInit"

    });

                var text1_count=0;//init int
                var text1_maxchars=7000;// max plain text chars allowed
                var mce_editor_0_undobuffer="";//init string (first tinyMCE instance)
    var mce_editor_1_undobuffer="";//init string (second tinyMCE instance, etc)

                    function myCustomOnInit(){
                                    tinyMCE_timer1=setTimeout("countchars('Process',text1_maxchars,'msgCounter')",1000); //wait a bit to avoid IE error
                    }
                    
                    
                    //event when something in TinyMCE changes (which is when an undo level is added. e.g. paste)
                    function myCustomOnChangeHandler(inst){
                                    tinyMCE_timer1=setTimeout("countchars('Process',text1_maxchars,'msgCounter')",250); //slight delay before counting
                    }
                    
                    //event such as key or mouse press
                    function myHandleEvent(e){
                                    if(e.type=="keyup"){
                                                    clearTimeout(tinyMCE_timer1);
                                                    countchars('Process',text1_maxchars,'msgCounter')
                                    }
                                    return true;
                    }
                    
                    function countchars(formname,maxchars,displayID){
                                            
                                            editor_id = tinyMCE.selectedInstance.editorId;
                                            
                                            if(isNaN(maxchars)){ //arg could contain a var name rather than a number
                                                            maxchars=eval(maxchars); //convert var to number
                                            }
                                            thefield=eval("document."+formname+"."+tinyMCE.selectedInstance.formTargetElementId);                
                                            
                                            //To get Current Count.///////////////////////////////////////////////////////////////////////////////////////////////////////////
                                            obj=document.getElementById(editor_id);
                                            if(obj.contentDocument){
                                                            content=obj.contentDocument.body.innerHTML //FireFox (getContent() messes up cursor position)
                                            }else{
                                                            content=top.frames[editor_id].document.body.innerHTML //IE - avoid getContent() due to spellchecker and cursor issues
                                            }
                                            currCount=content.length;
                                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            remainCount=maxchars-currCount+1; //fix: allow +1
                                            tmpvar=tinyMCE.selectedInstance.formTargetElementId+'_count';   
                                            eval(tmpvar + '=currCount'); //assign dynamic var to char count
                                        
                                        
                                            displayObj=document.getElementById(tinyMCE.selectedInstance.formTargetElementId + 'Count');
                                            displayObj.innerHTML=eval(remainCount-1) + " characters left"; //-1 to counteract above +1
                                            
                                            
                                            //Checks and Corrects Adding To much//////////////////////////////////////////////////////////////////////////////////////////////
                                            if(remainCount<=0){ //typed too much
                                                            thisBuffer=eval(editor_id+'_undobuffer')
                                                            if(thisBuffer.length > 0){
                                                                            tinyMCE_timer2=setTimeout("tinyMCE.setContent(thisBuffer)",250) // undo event - replace content with most recent buffer
                                                            }
                                                            displayObj.innerHTML="<B>You have typed the maximum text allowed</B>";
                                            } else {
                                                            eval(editor_id+'_undobuffer=content'); //store content in buffer
                                            }
                                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            

                    }
                -->
                </script>

Now on the page I have a table with a div tag to show the counter as well as the textarea.

Here is two examples.

                            <%' ***************************************************************************************** %>
                                    <textarea name="Expected_Impact" id="Expected_Impact" style="width:545px; height:100px"><%=varExpected_Impact%></textarea>
                            <%' ***************************************************************************************** %>
                            <table width="545" border="0" cellspacing="0" cellpadding="0">
                                <tr>
                                    <td><div id="Expected_ImpactCount"></div><div id="Expected_ImpactMax" style="display:none">3000</div></td>
                                </tr>
                            </table>

As you can see I have specific ID names for both the textarea as well as the div tag so that it is associated only with this form.

The next form on the same page.

                                <%' ***************************************************************************************** %>
                                        <textarea name="Expected_Purpose" id="Expected_Purpose" style="width:545px; height:100px"><%=varExpected_Purpose%></textarea>
                                <%' ***************************************************************************************** %>
                                <table width="545" border="0" cellspacing="0" cellpadding="0">
                                    <tr>
                                        <td><div id="Expected_PurposeCount"></div><div id="Expected_PurposeMax" style="display:none">3000</div></td>
                                    </tr>
                                </table>

Please let me know if you still have issues.  This implementation will work for 1- infinate number of textareas as long as the format is the same. 

I have still not figured out to have a include that incompases an intire site without commenting out the include on pages without a textarea.  And if anyone has done this using this code or something similar please let me know.

Thanks.

-Drew

PS one thing to note is that the Max Div does not function or do anything at this time.  The Max count is in the actual tinymce functions.  The Count Div does infact need to be used as it is what displays the current count.

Last edited by drewber09 (2007-06-28 12:56:21)

33

Re: Limit the Number of characters entered in the editor

Hai Drew,

Ok Thanks for kind Help
And one more help,
If i can add another one editor what are all the changes i can do? Please explain

34

Re: Limit the Number of characters entered in the editor

Hello,

Thanks for the great work on counting the number of characters.
But, it's counting the HTML tags also.  How can I use the same code but to count ONLY the actual content without the HTML tags.

Thanks in advance.

Sorry, found the answer:

Replace: content = obj.contentDocument.body.innerHTML;
By: content = tinyMCE.selectedInstance.getBody().textContent;

Last edited by Teebo (2007-08-01 10:49:57)

35

Re: Limit the Number of characters entered in the editor

Hi,
    Great tool!  I love the way it works, but I'm having a bit of a problem in IE with it.  In Firefox, everything works great, but when I load it up in IE, the counter never appears and I get the following error in the status bar:

Error: Object doesn't support this property or method.

My javascript debugger has pointed out the following line as the problem:

content=top.frames[editor_id].document.body.innerHTML //IE - avoid getContent() due to spellchecker and cursor issues



function countchars(formname,maxchars,displayID){

            editor_id = tinyMCE.selectedInstance.editorId;

            

            if(isNaN(maxchars)){ //arg could contain a var name rather than a number

                maxchars=eval(maxchars); //convert var to number

            }

            thefield=eval("document."+formname+"."+tinyMCE.selectedInstance.formTargetElementId);

            

            //To get Current Count.///////////////////////////////////////////////////////////////////////////////////////////////////////////

            obj=document.getElementById(editor_id);

            if(obj.contentDocument){

                content=obj.contentDocument.body.innerHTML //FireFox (getContent() messes up cursor position)

            }else{

                content=top.frames[editor_id].document.body.innerHTML //IE - avoid getContent() due to spellchecker and cursor issues

            }

            currCount=content.length;

I'm not an expert javascript programmer, but this code seems ok to me.   Any ideas? I'd greatly appreciate any help here.

36

Re: Limit the Number of characters entered in the editor

Hi,
Thanks a lot for that great infopool you provide us.

My question is so : how can i limit the lines in my textarea ?
In fact I want to generate a pdf file after input, but the text should fit in its textbox.

If anybody had an idea about the direction I should take, I'll be really greatfull.

Mat.

Last edited by mat (2007-11-09 15:35:54)

37

Re: Limit the Number of characters entered in the editor

Hi,

mat wrote:

My question is so : how can i limit the lines in my textarea ?
In fact I want to generate a pdf file after input, but the text should fit in its textbox.

In my case, i want to generate a RTF file and I want to have only 1 page.
This script block new entered characters entered in editor when number of chars is equal of limit.
It's another variant of perreault code.

EDIT : 18:10 = Correct a mistake.
Script code :

tinyMCE.init({
        mode : "textareas",
        theme : "advanced",
        theme_advanced_buttons1 : "mybutton,bold,italic,underline,strikethrough,separator,"
        +"undo,redo,separator,bullist,numlist,outdent,indent,separator,cleanup",
        theme_advanced_buttons2 : "",
        theme_advanced_buttons3 : "",
        onchange_callback : "CheckSize", 
        handle_event_callback : "CheckSize" 
    });
    
    //Number of maximum caracters
      var max=1750;
      var boolCorrect = true;
      var periodeActiv = 10;
      var periodeEnCours = 10;
            
    function CheckSize() {
        
        var editor_id = tinyMCE.selectedInstance.formTargetElementId; 
        var Show=editor_id + 'Count';
        var x=tinyMCE.getContent();
        var response = 'Nombre de caracteres restant : ';

        //Extract HTML code.
        /*var re = /(<([^>]+)>)/ig ; //strip all tags
        var strTextWhoutHTML = "";
        strTextWhoutHTML = x.replace(re, "");*/
        
        //Activate fonction each 10 period (because strong function)
        if(periodeEnCours >= periodeActiv){
            periodeEnCours = 0;
            ///////////////////////////////
            //Row number counting
            //Computing number of line when the text is export in
            //a RTF format. I want to know when i enter some text
            //if i have more than 1 page in export format.
            var nbCarParligne = 50; //Number of char in a line
            var nbCarParTab = 7;    //Number of char in a tab
            var nbLigneMax = 42;    //Maximum number of line in editor
            var nbLigne = 1;        //1 pour la ligne de départ
            var strAffichage = "Nombre de ligne(s) estimée(s) : ";
            
            var boolOuvertureBalise = false;
            var nomBaliseCourante = "";
            var boolFiltreNBSP = false;
            var textCaracSpe = "";
            var nbCarSpe = 0;
            
            var boolBalisePOuverte = false;
            var textBetweenP = "";
            var nbCarTextBetweenP = 0;
            var boolBaliseDIVOuverte = false;
            var textBetweenDIV = "";
            var nbCarTextBetweenDIV = 0;
            var boolBaliseLIOuverte = false;
            var textBetweenLI = "";
            var nbCarTextBetweenLI = 0;
            
            var textWithoutTag = "";
            var nbCarTextWthoutTag = 0; 
            
            //For each char in String.
            for(i=0; i<x.length; i++){
                ///////////////////////
                //Finding HTML Tags 
                ///////////////////////
                if(x.charAt(i) == ">"){
                    boolOuvertureBalise = false;
                    nomBaliseCourante = nomBaliseCourante + x.charAt(i);
                }        
                if(x.charAt(i) == "<"){
                    boolOuvertureBalise = true;
                }
                if(boolOuvertureBalise == true){
                    nomBaliseCourante = nomBaliseCourante + x.charAt(i);
                }
                ////////////////////////////////////
                //Works for each tags.
                ////////////////////////////////////
                //--Open P tag
                if(boolOuvertureBalise == false && nomBaliseCourante == "<p>"){
                    boolBalisePOuverte = true;
                    nomBaliseCourante = "";
                //--Close P tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "</p>"){
                    boolBalisePOuverte = false;
                    nomBaliseCourante = "";
                    
                //--Open DIV tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "<div>"){
                    boolBaliseDIVOuverte = true;
                    nomBaliseCourante = "";
                //--Close DIV tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "</div>"){
                    boolBaliseDIVOuverte = false;
                    nomBaliseCourante = "";
                
                //--Open LI tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "<li>"){
                    boolBaliseLIOuverte = true;
                    nomBaliseCourante = "";
                //--Close LI tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "</li>"){
                    boolBaliseLIOuverte = false;
                    nomBaliseCourante = "";
                    
                //--Close BR tag
                }else if(boolOuvertureBalise == false && nomBaliseCourante == "<br />"){
                    nomBaliseCourante = "";
                    nbLigne = nbLigne + 1;
                    //Reset of all var, it's a new line.
                    textBetweenP = "";
                    nbCarTextBetweenP = 0;
                    textBetweenDIV = "";
                    nbCarTextBetweenDIV = 0;
                    textBetweenLI = "";
                    nbCarTextBetweenLI = 0;
                    textWithoutTag = "";
                    nbCarTextWthoutTag = 0;
                    
                //Else do nothing fo other tags
                }else if(boolOuvertureBalise == false){
                    //Clear current tag name.
                    nomBaliseCourante = "";
                }
                ///////////////////////////////////
                //Storing text for each tag
                ///////////////////////////////////
                //For P tag
                if(boolBalisePOuverte == true && boolOuvertureBalise == false && x.charAt(i)!=">"){
                    //Storing and count char between P tag
                    if(boolFiltreNBSP == false && x.charAt(i)!="&"){
                        textBetweenP = textBetweenP + x.charAt(i);
                        nbCarTextBetweenP = nbCarTextBetweenP + 1;
                    //Filter special HTML char
                    }else{
                        boolFiltreNBSP = true
                        //If we are at the end of special char
                        if(x.charAt(i) == ";"){
                            boolFiltreNBSP = false
                            //Replacing special char by 1 char
                            textBetweenP = textBetweenP + '?';
                            //Counting 1 more char
                            nbCarTextBetweenP = nbCarTextBetweenP + 1;
                        }
                    }
                //For LI tag
                }else if(boolBaliseLIOuverte == true && boolOuvertureBalise == false && x.charAt(i)!=">"
                        || boolBaliseLIOuverte == true && boolOuvertureBalise == false && x.charAt(i)!=">" && boolBaliseDIVOuverte == true){
                    //Storing and count char between P tag
                    if(boolFiltreNBSP == false && x.charAt(i)!="&"){
                        textBetweenLI = textBetweenLI + x.charAt(i);
                        nbCarTextBetweenLI = nbCarTextBetweenLI + 1;
                    //Filter special HTML char
                    }else{
                        boolFiltreNBSP = true
                        //If we are at the end of special char
                        if(x.charAt(i) == ";"){
                            boolFiltreNBSP = false
                            //Replacing special char by 1 char
                            textBetweenLI = textBetweenLI + '?';
                            //Counting 1 more char
                            nbCarTextBetweenLI = nbCarTextBetweenLI + 1;
                        }
                    }
                //For DIV tag
                }else if(boolBaliseDIVOuverte == true && boolOuvertureBalise == false && x.charAt(i)!=">"){
                    //Storing and count char between P tag
                    if(boolFiltreNBSP == false && x.charAt(i)!="&"){
                        textBetweenDIV = textBetweenDIV + x.charAt(i);
                        nbCarTextBetweenDIV = nbCarTextBetweenDIV + 1;
                    //Filter special HTML char
                    }else{
                        boolFiltreNBSP = true
                        //If we are at the end of special char
                        if(x.charAt(i) == ";"){
                            boolFiltreNBSP = false
                            //Replacing special char by 1 char
                            textBetweenDIV = textBetweenDIV + '?';
                            //Counting 1 more char
                            nbCarTextBetweenDIV = nbCarTextBetweenDIV + 1;
                        }
                    }
                //For text without tag
                }else if(boolOuvertureBalise == false && boolBaliseLIOuverte == false && boolBaliseDIVOuverte == false
                        && boolBalisePOuverte == false && x.charAt(i)!=">"){
                    //Storing and count char without tag
                    if(boolFiltreNBSP == false && x.charAt(i)!="&"){
                        textWithoutTag = textWithoutTag + x.charAt(i);
                        nbCarTextWthoutTag = nbCarTextWthoutTag + 1;
                    //Filter special HTML char
                    }else{
                        boolFiltreNBSP = true
                        //If we are at the end of special char
                        if(x.charAt(i) == ";"){
                            boolFiltreNBSP = false
                            //Replacing special char by 1 char
                            textWithoutTag = textWithoutTag + '?';
                            //Counting 1 more char
                            nbCarTextWthoutTag = nbCarTextWthoutTag + 1;
                        }
                    }
                }
                ////////////////////////////////////////
                //Counting number of line for each tag
                if(boolBalisePOuverte == false && textBetweenP != "" && nbCarTextBetweenP != 0){
                    nbLigne = nbLigne + Math.floor(nbCarTextBetweenP/nbCarParligne) + 2;
                    textBetweenP = "";
                    nbCarTextBetweenP = 0;
                }else if(boolBaliseDIVOuverte == false && textBetweenDIV != "" && nbCarTextBetweenDIV != 0){
                    nbLigne = nbLigne + Math.floor(nbCarTextBetweenDIV/nbCarParligne) + 2;
                    textBetweenDIV = "";
                    nbCarTextBetweenDIV = 0;
                }else if(boolBaliseLIOuverte == false && textBetweenLI != "" && nbCarTextBetweenLI != 0){
                    nbLigne = nbLigne + Math.floor((nbCarTextBetweenLI + nbCarParTab)/nbCarParligne);
                    textBetweenLI = "";
                    nbCarTextBetweenLI = 0;
                }
                //Add number of text without tag
                if(nbCarTextWthoutTag != 0 && textWithoutTag != "" && i == (x.length-1)    ){
                    nbLigne = nbLigne + Math.floor(nbCarTextWthoutTag/nbCarParligne);
                }
            }
            //Show number of line
            if(nbLigne <= nbLigneMax-10){
                strAffichage = strAffichage + '<font style="color:green">'+nbLigne+'</font> / '+nbLigneMax;
            }else if(nbLigne <= nbLigneMax-5){
                strAffichage = strAffichage + '<font style="color:orange">'+nbLigne+'</font> / '+nbLigneMax;
            }else{
                strAffichage = strAffichage + '<font style="color:red">'+nbLigne+'</font> / '+nbLigneMax;
            }
            document.getElementById(editor_id+'Line').innerHTML = strAffichage;
            //END Row number counting
            //////////////////////////
        }else{
            //Counting 1 more period
            periodeEnCours = periodeEnCours + 1;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////
        //Check text length to correct
        if (x.length>max && boolCorrect) {
            x=x.substring(0, max-16);
            tinyMCE.setContent(x);
            boolCorrect = false; 
        };
        //Show number of char in textarea
        if (x.length<=max-100){
            boolCorrect = true;
            response = response + '<font style="color:green">'+(max-x.length)+'</font>';
        }else if(x.length<=max-10){
            boolCorrect = true;
            response = response + '<font style="color:orange">'+(max-x.length)+'</font>';
        }else if(x.length<=max){
            boolCorrect = true;
            response = response + '<font style="color:red">'+(max-x.length)+'</font>';
        }else{
            response = response + '<font style="color:red; font-weight:bold;">'+(max-x.length)+'</font>';
        }
        document.getElementById(Show).innerHTML=response+ ' / '+max;
        //To view source code in textarea with Tiny_MCE
        //document.getElementById(editor_id+'View').innerHTML='<xmp>'+x+'</xmp>';
        return true;
    }

Body code :

<div style="float:left;clear:right">
                  <textarea name="presentation" cols="50" rows="35" id="presentation">
                    <div style="text-align: justify"><%=ficheRefBean.getItemValue("presentation") %></div>
                  </textarea>
              </div>
              <div id="presentationCount"></div>
              <div id="presentationLine"></div> 
        <div id="presentationMax" style="display:none">1750</div>
              <div id="presentationView"></div>

I'm not an expert javascript programmer, so I'm sorry if I didn't respect programming rules.
I give french name for each var...sorry smile... but it's understandable.
It's a solution, not the only one and certainly not the best... it's a way.

Best regards,
Greg

Last edited by [FR]Greg (2007-11-26 18:24:58)

38

Re: Limit the Number of characters entered in the editor

OK... So I collected together a lot of the code that was written in here. I've tailored it to my situation, but made it very extensible (any number of editors). I haven't tested it exhaustively and it is a simple feature set. In particular, it does the following:

- Written specifically against version 3.0

- Is written to be considerably less brittle / more robust than some of the previous code and relies on more standard methods in tinyMCE to do the work.

- Will validate ALL editors against a specific maximum length.

- Saves an "undo" buffer of the content in each editor as it checks the length.

- Maximum length is absolute (includes all characters). This is appropriate for doing protections against database limitations so that the user doesn't try to submit too many characters. As it has already been pointed out, you must still absolutely provide server-side protections to verify that too much data wasn't submitted anyhow.

- Provides an alert to the user that they exceeded the maximum limit for that text area.

- Removes the new / extraneous text which put it over the limit (replacing the contents with the saved undo buffer).

- Moves the user's cursor back to where they would have been before the extra info was put in. For typing this is usually one character, but could be more... and in the case of a paste could be quite a bit.


It is also worth noting the following limitations:

- This only has one absolute limit for all text areas. It would be trivial and very personal (depending on JavaScript libraries and HTML structure of web application) to chose to store that value per editor in a hidden form field or some such as previous people have on this forum.

- This code only uses an alert to communicate with the user and it prevents the user from putting more content in the textarea than would otherwise fit. Changing that is fairly straightforward and, again, would be a trivial and personal choice to change that behavior as others have on this forum.

- I have a very simply use of TinyMCE so it is ENTIRELY possible that this doesn't work in some variety of common scenarios that I just don't need to worry about. I have tested this as happy in FF 2.0, IE7, and IE6.

- IE6 doesn't seem to deal with the bookmarking stuff well... but it doesn't complain.


var tinyMceBuffers    = new Object();
var tinyMceCharCounts = new Object();

// Event fired when something in TinyMCE changes such as when an undo
// level is added like after a copy/paste.
function tinyMceOnChange(inst){ tinyMceCheckContentLength(inst.id,4000); }

// Event fired for any normal UI event such as a key or mouse press.
function tinyMceEventHandler(e){
    switch (e.type) {
        case 'keyup': tinyMceOnChange(tinyMCE.activeEditor); break;
    }
    return true;
}

// Strips all html tags from a given string, leaving only plain text
function stripHtmlTags(strContent) { return strContent.replace(/(<([^>]+)>)/ig, ""); }

function tinyMceCheckContentLength(strEditorId, intMaxLength) {
    var editorInstance   = tinyMCE.get(strEditorId);
    if (editorInstance   == null || editorInstance   == undefined) { alert('NO EDITOR'); }

    var contentContainer = editorInstance.getBody();
    if (contentContainer == null || contentContainer == undefined) { alert('NO CONTENT CONTAINER'); }

    var strContent       = contentContainer.innerHTML;
    var intContentLength = strContent.length;
    var intCharCount     = stripHtmlTags(strContent).length;

    if (intContentLength <= intMaxLength) {
        // The user has not passed the maximum amount of content in the editor...

        // Save away the current contents in case they have typed too much and we have to
        // revert back to this state.
        tinyMceBuffers   [strEditorId] = strContent;
        tinyMceCharCounts[strEditorId] = intCharCount;

    } else {
        // The user has put more than the maximum amount of content in the editor...
        // We must now revert back to the last good contents that we had for the editor,
        // or else whatever fits if we never had anything saved from there.
        var bm = editorInstance.selection.getBookmark(); // Stores a bookmark of the current selection
        editorInstance.setContent((tinyMceBuffers[strEditorId]) ? tinyMceBuffers[strEditorId] : strContent.substring(0, intMaxLength - 10));
        var intDelta = intCharCount - tinyMceCharCounts[strEditorId];
        if (bm['start'] && bm['start'] > intDelta) {
            bm['start'] -= intDelta;
            bm['end']   =  bm['start'];
        }
        editorInstance.selection.moveToBookmark(bm); // Restore the selection bookmark

        alert('You have exceeded the maximum size for this text and we have undone your last change.');
    }
}


tinyMCE.init({
    theme   : "custom",
    skin    : "o2k7",
    mode    : "textareas",
    plugins : "contextmenu,emotions,fullscreen,inlinepopups,nonbreaking,paste,safari",

    onchange_callback     : "tinyMceOnChange",
    handle_event_callback : "tinyMceEventHandler"
});

39

Re: Limit the Number of characters entered in the editor

Hey, I've got the solution of the problem. We can now check the character limit from the client side as well.
Here, the problem was that, the TinyMCE editor is loaded in an iFrame and that's why we couldn't get it's control on the client side. Following is the snippet (pseudo code) to do so.

        var txtNotes;
        if (browser = "IE") //if IE
            txtNotes = document.getElementById("mce_editor_0").contentWindow.document.body;
        else // If Mozilla
            txtNotes = document.getElementById("mce_editor_0").contentDocument.body;
       
        if (String(txtNotes.innerHTML).length > 4000)
        {
            alert("Notes must be 4000 characters or less");
        }

Here, the id "mce_editor_0", is the id of the iFrame being loaded. Each instance of the editor on a single page would increase the suffix sequence by 1. i.e. If my page has 2 instances of the editor. the second would have the id = "mce_editor_1".
I guess, this'll help.

40

Re: Limit the Number of characters entered in the editor

user_m wrote:

Hi,
I need to limit the number of characters entered . I've tried to set the maxlength of the text area but does not help. Any suggestions ??

Hey, I've got the solution of the problem. We can now check the character limit from the client side as well.
Here, the problem was that, the TinyMCE editor is loaded in an iFrame and that's why we couldn't get it's control on the client side. Following is the snippet (pseudo code) to do so.

        var txtNotes;
        if (browser = "IE") //if IE
            txtNotes = document.getElementById("mce_editor_0").contentWindow.document.body;
        else // If Mozilla
            txtNotes = document.getElementById("mce_editor_0").contentDocument.body;
       
        if (String(txtNotes.innerHTML).length > 4000)
        {
            alert("Notes must be 4000 characters or less");
        }

Here, the id "mce_editor_0", is the id of the iFrame being loaded. Each instance of the editor on a single page would increase the suffix sequence by 1. i.e. If my page has 2 instances of the editor. the second would have the id = "mce_editor_1".
I guess, this'll help.

41

Re: Limit the Number of characters entered in the editor

has anyone got a sample of this with 2 editors? I have tried all the codes here, mixed and matched them and cant get none of them working without errors. running version 3.1.1

all errors show up in IE and googles chrome browsers (well not really show up as an error but the script isnt working)

IE 8 beta

and google chrome beta

Last edited by dude (2008-09-10 18:31:14)

42

Re: Limit the Number of characters entered in the editor

Hello TinyMCE forum reader,

One more way to solve it.

Hello, I edit this code
Please understand that by special Char Like: ö   it will be replace AFTER Saving with HTML Code ö
so in this example you can write 5 char that will not be save. Mathematic Explication :

ö = 1 char
ö = 6 char

but 1 char will anyway used. so  6-1 = 5char imprecise input autorised.



<HTML>
    <HEAD>
        <!--
        * Firm        : http://www.fiveinfo.ch
        * Author    : Stéphane Lauper
        * Email        : slauper at gmail dot com
        * Date        : 10.October.2008
        *
        * Objective : with InternetExplorer (endUser wish)
        * MaxLength solution for the TinyMCE Editor with target to write in Database
        * without HTML formatting loss and without Database field size Overflow.
        -->
        <!-- Directory to the TinyMCE Editor Engine -->
        <SCRIPT language="javascript" type="text/javascript" src="jscripts/tiny_mce/tiny_mce.js"></SCRIPT>
        <!-- Intern JavaScript Code -->
        <SCRIPT type="text/javascript">
            function myMaxLength(){
                // variable declaration; You must change this value for your use.
                /*
                !! ATTENTION !!
                in purpose to not lose the HTML balise in the 'TinyMCE Editor' (like: <p></p>)
                this value will be used to save the visible char AND the HTML balise
                that mean :
                    var mytext = '<p>123</p>';
                    alert(mytext.length);
                    //10
                */
                return CantWriteMoreThan = 10; //Maxlength
                /*
                Post Scriptum:
                You can use the 'replace' function (thanks to lorenzocampanis at users.sourceforge.net)if you want to count ONLY visible char
                that mean :
                    var mytext = '<p>123</p>';
                    alert(mytext.length.replace(/<\/?[^>]+(>|$)/g, ""));
                    //3
                */
            };
           
            function the_HTML_id_Of_My_TextArea(){
                //variable declaration; You must change this value for your use
                return 'Desc';
            };

            tinyMCE.init(
                {
                    mode : "exact",
                    elements : "Desc",
                    theme : "advanced",
                    theme_advanced_buttons1 : "fontselect,fontsizeselect,bold,italic,underline,separator,justifyleft,justifycenter,justifyright, justifyfull,separator,hr,code,removeformat,separator,bullist,numlist,separator,undo,redo",
                    theme_advanced_buttons2 : "",
                    theme_advanced_buttons3 : "",
                    theme_advanced_toolbar_location : "top",
                    theme_advanced_toolbar_align : "left",
                    setup : function(ed) {
                        ed.onKeyDown.add(
                            function(ed, e) {
                                //variable declaration; No change needed.
                                var CantWriteMoreThan = myMaxLength_2056();/* if you want to change the 'Max number of char allowed' you can change this value in a unique location. See the above myMaxLength() function. */
                                var Authorized_theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent();    //is the 'undo-text'
                                var theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent(); //Content of the TextArea
                                var theTextAreaContentLength = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent().length; //Length of the Content of the TextArea
                                //alert('OnKeyDown Event : '+ CantWriteMoreThan);
                                //alert('OnKeyDown Event : '+ theTextAreaContent);
                                //alert('OnKeyDown Event : '+ theTextAreaContentLength);
                                if (theTextAreaContentLength <= CantWriteMoreThan){
                                    //Set 'HTML hidden input' with the value got from the 'TinyMCE Editor'.
                                    document.getElementById('UndoText').value = Authorized_theTextAreaContent;
                                }//endif
                                if(theTextAreaContentLength > CantWriteMoreThan){
                                    //Set the 'TinyMCE Editor' Editor with the value got from the 'HTML hidden input'.
                                    tinyMCE.get(the_HTML_id_Of_My_TextArea()).setContent(document.getElementById('UndoText').value);
                                }//end if
                            }//end function(ed,e)
                        );//end ed.onKeyDown.add
                       
                        ed.onChange.add(function(ed, e) {
                                //variable declaration; No change needed.
                                var CantWriteMoreThan = myMaxLength_2056();/* if you want to change the 'Max number of char allowed' you can change this value in a unique location. See the above myMaxLength() function. */
                                var Authorized_theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent();    //is the 'undo-text'
                                var theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent(); //Content of the TextArea
                                var theTextAreaContentLength = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent().length; //Length of the Content of the TextArea
                                //alert('OnChange Event : '+ CantWriteMoreThan);
                                //alert('OnChange Event : '+ theTextAreaContent);
                                //alert('OnChange Event : '+ theTextAreaContentLength);
                                if (theTextAreaContentLength <= CantWriteMoreThan){
                                    //Set 'HTML hidden input' with the value got from the 'TinyMCE Editor'.
                                    document.getElementById('UndoText').value = Authorized_theTextAreaContent;
                                }//endif
                                if(theTextAreaContentLength > CantWriteMoreThan){
                                    //Set the 'TinyMCE Editor' Editor with the value got from the 'HTML hidden input'.
                                    tinyMCE.get(the_HTML_id_Of_My_TextArea()).setContent(document.getElementById('UndoText').value);
                                }//end if
                            }//end function(ed,e)
                        );//end ed.onChange.add
                       
                        ed.onKeyUp.add(function(ed, e) {
                                //variable declaration; No change needed.
                                var CantWriteMoreThan = myMaxLength_2056();/* if you want to change the 'Max number of char allowed' you can change this value in a unique location. See the above myMaxLength() function. */
                                var Authorized_theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent();    //is the 'undo-text'
                                var theTextAreaContent = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent(); //Content of the TextArea
                                var theTextAreaContentLength = tinyMCE.get(the_HTML_id_Of_My_TextArea()).getContent().length; //Length of the Content of the TextArea
                                //alert('OnKeyUp Event : '+ CantWriteMoreThan);
                                //alert('OnKeyUp Event : '+ theTextAreaContent);
                                //alert('OnKeyUp Event : '+ theTextAreaContentLength);
                                if (theTextAreaContentLength <= CantWriteMoreThan){
                                    //Set 'HTML hidden input' with the value got from the 'TinyMCE Editor'.
                                    document.getElementById('UndoText').value = Authorized_theTextAreaContent;
                                }//endif
                                if(theTextAreaContentLength > CantWriteMoreThan){
                                    //Set the 'TinyMCE Editor' Editor with the value got from the 'HTML hidden input'.
                                    tinyMCE.get(the_HTML_id_Of_My_TextArea()).setContent(document.getElementById('UndoText').value);
                                }//end if
                            }//end function(ed,e)
                        );//end ed.onKeyUp.add
                   }//end setup : function(ed)
                }
            ); //end tinyMCE.init
        </SCRIPT>
    </HEAD>

    <BODY>
        <FORM name="form1" method="post" action="">

            <!-- Do not delete this hidden input element. It is the 'undo' of the MaxLength -->
            <input type="hidden" name="UndoText"/>
            <!-- Do not delete this hidden input element. It is the 'undo' of the MaxLength -->

            <!-- Do not delete this element. This is My_TextArea -->
            <textarea rows="15" id="Desc" tabindex="30" style="width: 600px" >12</textarea>
            <!-- Do not delete this element. This is My_TextArea -->
        </FORM>
    </BODY>
</HTML>

Last edited by slauper (2009-05-04 11:30:34)

43

Re: Limit the Number of characters entered in the editor

Hi all,

I've tested all these script with TinyMCE last version(3.2.1.1), and it doesn't work. (Perhaps my fault, but I've tried to debbug/modify without sucess...)
Could someone help me? Or give me a link to download an old version, that could work with these scripts? Because I dind't found any archive on the website...

Many tanks!
CC

44

Re: Limit the Number of characters entered in the editor

Jungers42's compilation of the code in this tread worked very well for me. I modified it a little and added/changed the following to allow for a specific setting for each editor.

I added a variable declaration at the top to hold my array of settings:

    var tinyMceBuffers    = new Object();
    var tinyMceCharCounts = new Object();
    
    var tinyMCEArray; // Added this part! Will hold my array of settings.

I changed his custom tinyMceOnChange event:

    // Event fired when something in TinyMCE changes such as when an undo
    // level is added like after a copy/paste.
    function tinyMceOnChange(inst){ 

        //tinyMceCheckContentLength(inst.id,60); // Edit out the old code.

        // Added the following to parse through the array and extract the setting.
        if (tinyMCEArray[0].indexOf(inst.id) != -1) {
            var index = tinyMCEArray[0].indexOf(inst.id);
            tinyMceCheckContentLength(inst.id, tinyMCEArray[1][index]);
        }

    }

My editor elements are named "teaser" and "headline". So in the tinyMCE.init function:

tinyMCE.init({
    mode : "exact",
    elements : "teaser,headline",
    ...

...and also in the tinyMCE.init function, I added the following:

tinyMCE.init({
    ...
    // Added this setup function.
    setup : function() {
        tinyMCEArray = [['headline', 'teaser'],[60, 120]]; // Setup a matrix here. The headline editor to allow no more than 60, and the teaser no more than 120 characters.
    },

    onchange_callback     : "tinyMceOnChange",
    handle_event_callback : "tinyMceEventHandler"

I'm very new to tinyMCE, so if there is a better way, please share. This worked for me, so I went with it.

Thanks everyone here that contributed! It saved me a lot of work figuring things out on my own.

45

Re: Limit the Number of characters entered in the editor

Dear All,

The last script from Beaudoin works like a charm in Firefox. It does not work in IE though. It throws a script error telling that
"Object doesn't support this property or method." and point to this line of script.

Beaudoin wrote:
        // Added the following to parse through the array and extract the setting.
        if (tinyMCEArray[0].indexOf(inst.id) != -1) {
            var index = tinyMCEArray[0].indexOf(inst.id);
            tinyMceCheckContentLength(inst.id, tinyMCEArray[1][index]);
        }
    }

I am not very good with javascript, and have tried changing it a little bit, but without luck. Can somebody please tell me how to make this wonderful script work in IE?

Added later:
I think I found the fix for the script above:

function tinyMceOnChange(inst){ 
        var IEArray = tinyMCEArray[0];
        var index = IEArray.indexOf(inst.id);
        if (index != -1) { //IE does not like to have the array.indexOf being called directly.
        tinyMceCheckContentLength(inst.id, tinyMCEArray[1][index]);
        }
}

The code will work on IE 7 and Firefox. I have not tried any other IE version, but looking at the script it should be 'regular' enough to work on any other browser.

Thank you for the great scripts.

Sincerely,
Ahau.

Last edited by hs (2009-02-13 17:25:36)

46

Re: Limit the Number of characters entered in the editor

Hi everyone!

This code here:

Jungers42 wrote:
(...)
function tinyMceCheckContentLength(strEditorId, intMaxLength)
(...)

works all great and fine, but I do have a problem with the onchange event and the focus in IE 6 (and maybe 7).
When I press the bold button (or italics or whatever) before doing anything else and then type some text, I can type on as much as I want, tinyMceCheckContentLength() will never be triggered.
I tried placing all kinds of variations of this.focus() or tinyMCE.execCommand('mceFocus',false,strEditorId) all over my code, but nothing works. Actually, tinyMceOnChange() only gets called when pressing the bold button, but then never again though I can type on. I can see, that pressing a button on the editor button bar takes away the focus from the content area of the editor, but how do I put it back, and where do I place that piece of coding?

I tried:

function tinyMceOnChange(inst){
    tinyMceCheckContentLength(inst.id,document.getElementById(inst.id).getAttribute('maxchar'));
    inst.focus();  <-------------------------------------------
}

And I tried:

function tinyMceCheckContentLength(strEditorId, intMaxLength) {
    (...)
    if (contentContainer == null || contentContainer == undefined) { alert('NO CONTENT CONTAINER'); }
    tinyMCE.execCommand('mceFocus',false,strEditorId);  <-------------------------------------------
   (...)
    if (intContentLength <= intMaxLength) {
       (...)
        tinyMCE.execCommand('mceFocus',false,strEditorId);  <-------------------------------------------
    } else {
       (...)
        editorInstance.selection.moveToBookmark(bm); // Restore the selection bookmark
        tinyMCE.execCommand('mceFocus',false,strEditorId);  <-------------------------------------------

        alert('You have exceeded the maximum size for this text and we have undone your last change.');
    }
}

None of the above worked.

Thank you already so much!


Bye bye
Rána

47

Re: Limit the Number of characters entered in the editor

The only script I managed to get working in FF, IE7 and IE6 with my version of this editor to work in Joomla, is based on that of perreault:

function CheckSize() {

var Limit=20;
var Show='introtextCount';
var x=tinyMCE.get('introtext').getContent();

if (x.length>Limit) {
x=x.substring(0, Limit-10);
tinyMCE.setContent(x);
alert('You have reached the maximum size for this field');
};
document.getElementById(Show).innerHTML=Limit-x.length;
return true;
}

tinyMCE.init({
    onchange_callback     : "CheckSize",
    handle_event_callback : "CheckSize"
});

<div id="introtextCount" ></div>
<textarea id="introtext" name="introtext" mce_editable="true" class="mceEditor">asdvsdfve</textarea>

but unfortunately, it also triggers the popup when using a second editor. Even thou I specifically make it check the editor with id 'introtext'.

How do I get the restrictions to only kick in with one specific editor?

48

Re: Limit the Number of characters entered in the editor

carsten888 wrote:

How do I get the restrictions to only kick in with one specific editor?

You'll need a second init for it. Example 04: Multiple inits. I'd suggest you initialize "introtext" with "mode:exact".

Greetings from Germany,

Felix Riesterer.
(-> about me and this forum <-)

49

Re: Limit the Number of characters entered in the editor

Hi,

I'm new to tinyMCE & PHP, but I have to support a website using both.  The designer I'm working with has to convert the data in a large excel file into a webpage.  TinyMCE is used on the CMS side of the website for page creation.  While she is able to copy the HTML she has come up with into the HTML pane & see it when she clicks 'Update', saving the newly created page seems to truncate what she's entered.  The only tinyMCE editor that seems to retain everything had 2690 HTML characters copied into the HTML pane.

I've been searching for where this truncation happens, with no luck thus far.  The content in each tinyMCE editor goes to a separate text type field in a SQL database, & text fields allow up to 2GB of storage, so I imagine that the databse is *not* doing the truncating.  I can't seem to find anything in the PHP indicating a truncation, but I've contacted the dev house find out if that is hidden somewhere in the code.

The only other thing I can think of is that a tinyMCE editor has a character max allowable in each instance.  Is there a default character max on what a tinyMCE editor can accept (before what it has stored is sent off to the database)?  If so, what is that max & where is it set?  If it is settable, where can I increase the max?  Is there an absolute max?

Thanks for any help in advance...

- O8

50

Re: Limit the Number of characters entered in the editor

TinyMCE does not, and won't ever set a limit to the amount of characters entered into the editor. Two simple reasons:

1.) JavaScript applications can get manipulated on-the-fly
2.) If somebody turns off JavaScript in his/her browser then all restrictions from TinyMCE are gone.

So:
Only server-side sanitization is truly efficient.

If your submitted data gets truncated on its way to the server then check the following things:

1.) Method of submission (POST/GET)
2.) Server settings with regard to amount of received data (different settings for POST and GET?)
3.) Store the received data in an extra debug file and compare it with saved DB contents.

Greetings from Germany,

Felix Riesterer.
(-> about me and this forum <-)