jquery.byteLimit fixes:
[mediawiki.git] / resources / jquery / jquery.byteLimit.js
blobe45aa632d24c6e36df91ec33bdd4ff2b6bb74f48
1 /**
2  * jQuery byteLimit
3  */
4 ( function( $ ) {
6         /**
7          * Enforces a byte limit to a textbox, so that UTF-8 entries are not arbitrarily truncated.
8          */
9         $.fn.byteLimit = function( limit ) {
11                 // Default to current attribute value
12                 if ( limit == null ) {
13                         limit = this.attr( 'maxLength' );
15                 // If passed, update/set attribute value instead
16                 } else {
17                         this.attr( 'maxLength', limit );
18                 }
20                 // Nothing passed and/or empty attribute, return this for further chaining.
21                 if ( limit == null ) {
22                         return this;
23                 }
25                 // We've got something, go for it:
26                 return this.keypress( function( e ) {
27                         // First check to see if this is actually a character key
28                         // being pressed.
29                         // Based on key-event info from http://unixpapa.com/js/key.html
30                         // jQuery should also normalize e.which to be consistent cross-browser,
31                         // however the same check is still needed regardless of jQuery.
32         
33                         // Note: At the moment, for some older opera versions (~< 10.5)
34                         // some special keys won't be recognized (aka left arrow key).
35                         // Backspace will be, so not big issue.
36         
37                         if ( e.which === 0 || e.charCode === 0 || e.which === 8 ||
38                                 e.ctrlKey || e.altKey || e.metaKey )
39                         {
40                                 return true; //a special key (backspace, etc) so don't interfere.
41                         }
42         
43                         // This basically figures out how many bytes a UTF-16 string (which is what js sees)
44                         // will take in UTF-8 by replacing a 2 byte character with 2 *'s, etc, and counting that.
45                         // Note, surrogate (\uD800-\uDFFF) characters are counted as 2 bytes, since there's two of them
46                         // and the actual character takes 4 bytes in UTF-8 (2*2=4). Might not work perfectly in
47                         // edge cases such as illegal sequences, but that should never happen.
48         
49                         var len = this.value
50                                 .replace( /[\u0080-\u07FF\uD800-\uDFFF]/g, '**' )
51                                 .replace( /[\u0800-\uD7FF\uE000-\uFFFF]/g, '***' )
52                                 .length;
54                         // limit-3 as this doesn't count the character about to be inserted.
55                         if ( len > ( limit-3 ) ) {
56                                 e.preventDefault();
57                         }
58                 });
59         };
61 } )( jQuery );