Index: trunk/phase3/RELEASE-NOTES-1.19 |
— | — | @@ -281,6 +281,8 @@ |
282 | 282 | * (bug 12262) Indents and lists are now aligned |
283 | 283 | * (bug 34972) An error occurred while changing your watchlist settings for |
284 | 284 | [[Special:WhatLinksHere/Example]] |
| 285 | +* (bug 35294) jquery.byteLimit shouldn't set element specific variables outside |
| 286 | + the "return this.each" loop. |
285 | 287 | |
286 | 288 | === API changes in 1.19 === |
287 | 289 | * Made action=edit less likely to return "unknownerror", by returning the actual error |
Index: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js |
— | — | @@ -202,4 +202,51 @@ |
203 | 203 | expected: 'User:Sample' |
204 | 204 | }); |
205 | 205 | |
206 | | -}( jQuery ) ); |
\ No newline at end of file |
| 206 | + test( 'Confirm properties and attributes set', function () { |
| 207 | + var $el, $elA, $elB; |
| 208 | + |
| 209 | + expect(5); |
| 210 | + |
| 211 | + $el = $( '<input>' ) |
| 212 | + .attr( 'type', 'text' ) |
| 213 | + .prop( 'maxLength', '7' ) |
| 214 | + .appendTo( '#qunit-fixture' ) |
| 215 | + .byteLimit(); |
| 216 | + |
| 217 | + strictEqual( $el.prop( 'maxLength' ), 7, 'Pre-set maxLength property unchanged' ); |
| 218 | + |
| 219 | + $el = $( '<input>' ) |
| 220 | + .attr( 'type', 'text' ) |
| 221 | + .prop( 'maxLength', '7' ) |
| 222 | + .appendTo( '#qunit-fixture' ) |
| 223 | + .byteLimit( 12 ); |
| 224 | + |
| 225 | + strictEqual( $el.prop( 'maxLength' ), 12, 'maxLength property updated if value was passed to $.fn.byteLimit' ); |
| 226 | + |
| 227 | + $elA = $( '<input>' ) |
| 228 | + .addClass( 'mw-test-byteLimit-foo' ) |
| 229 | + .attr( 'type', 'text' ) |
| 230 | + .prop( 'maxLength', '7' ) |
| 231 | + .appendTo( '#qunit-fixture' ); |
| 232 | + |
| 233 | + $elB = $( '<input>' ) |
| 234 | + .addClass( 'mw-test-byteLimit-foo' ) |
| 235 | + .attr( 'type', 'text' ) |
| 236 | + .prop( 'maxLength', '12' ) |
| 237 | + .appendTo( '#qunit-fixture' ); |
| 238 | + |
| 239 | + $el = $( '.mw-test-byteLimit-foo' ); |
| 240 | + |
| 241 | + strictEqual( $el.length, 2, 'Verify that there are no other elements clashing with this test suite' ); |
| 242 | + |
| 243 | + $el.byteLimit(); |
| 244 | + |
| 245 | + // Before bug 35294 was fixed, both $elA and $elB had maxLength set to 7, |
| 246 | + // because $.fn.byteLimit sets: |
| 247 | + // `limit = limitArg || this.prop( 'maxLength' ); this.prop( 'maxLength', limit )` |
| 248 | + // and did so outside the each() loop. |
| 249 | + strictEqual( $elA.prop( 'maxLength' ), 7, 'maxLength was not incorrectly set on #1 when calling byteLimit on multiple elements (bug 35294)' ); |
| 250 | + strictEqual( $elB.prop( 'maxLength' ), 12, 'maxLength was not incorrectly set on #2 when calling byteLimit on multiple elements (bug 35294)' ); |
| 251 | + }); |
| 252 | + |
| 253 | +}( jQuery ) ); |
Index: trunk/phase3/resources/jquery/jquery.byteLimit.js |
— | — | @@ -1,9 +1,10 @@ |
2 | 2 | /** |
3 | | - * jQuery byteLimit |
| 3 | + * jQuery byteLimit plugin |
4 | 4 | * |
5 | | - * @author Jan Paul Posma |
| 5 | + * @author Jan Paul Posma, 2011 |
| 6 | + * @author Timo Tijhof, 2011-2012 |
6 | 7 | */ |
7 | | -( function( $ ) { |
| 8 | +( function ( $, undefined ) { |
8 | 9 | |
9 | 10 | /** |
10 | 11 | * Enforces a byte limit to a textbox, so that UTF-8 entries are counted as well, when, for example, |
— | — | @@ -16,12 +17,12 @@ |
17 | 18 | * or both. Order of arguments is important! |
18 | 19 | * |
19 | 20 | * @context {jQuery} Instance of jQuery for one or more input elements |
20 | | - * @param limit {Number} (optional) Limit to enforce, fallsback to maxLength-attribute, |
| 21 | + * @param limit {Number} [optional] Limit to enforce, fallsback to maxLength-attribute, |
21 | 22 | * called with fetched value as argument. |
22 | | - * @param fn {Function} (optional) Function to call on the input string before assessing the length |
| 23 | + * @param fn {Function} [optional] Function to call on the input string before assessing the length |
23 | 24 | * @return {jQuery} The context |
24 | 25 | */ |
25 | | - $.fn.byteLimit = function( limit, fn ) { |
| 26 | + $.fn.byteLimit = function ( limit, fn ) { |
26 | 27 | // If the first argument is the function, |
27 | 28 | // set fn to the first argument's value and ignore the second argument. |
28 | 29 | if ( $.isFunction( limit ) ) { |
— | — | @@ -29,59 +30,67 @@ |
30 | 31 | limit = undefined; |
31 | 32 | } |
32 | 33 | |
33 | | - // Default limit to current attribute value |
34 | | - if ( limit === undefined ) { |
35 | | - limit = this.prop( 'maxLength' ); |
36 | | - } |
| 34 | + // The following is specific to each element in the collection |
| 35 | + return this.each( function ( i, el ) { |
| 36 | + var $el, elLimit; |
37 | 37 | |
38 | | - // Update/set attribute value, but only if there is no callback set. |
39 | | - // If there's a callback set, it's possible that the limit being enforced |
40 | | - // is too low (ie. if the callback would return "Foo" for "User:Foo"). |
41 | | - // Usually this isn't a problem since browsers ignore maxLength when setting |
42 | | - // the value property through JavaScript, but Safari 4 violates that rule, so |
43 | | - // we have to remove or not set the property if we have a callback. |
44 | | - if ( fn == undefined ) { |
45 | | - this.prop( 'maxLength', limit ); |
46 | | - } else { |
47 | | - this.removeProp( 'maxLength' ); |
48 | | - } |
| 38 | + $el = $( el ); |
49 | 39 | |
50 | | - // Nothing passed and/or empty attribute, return without binding an event. |
51 | | - if ( limit === undefined ) { |
52 | | - return this; |
53 | | - } |
54 | | - |
55 | | - // Save function for reference |
56 | | - this.data( 'byteLimit-callback', fn ); |
57 | | - |
58 | | - // We've got something, go for it: |
59 | | - return this.keypress( function( e ) { |
60 | | - // First check to see if this is actually a character key |
61 | | - // being pressed. |
62 | | - // Based on key-event info from http://unixpapa.com/js/key.html |
63 | | - // jQuery should also normalize e.which to be consistent cross-browser, |
64 | | - // however the same check is still needed regardless of jQuery. |
65 | | - |
66 | | - // Note: At the moment, for some older opera versions (~< 10.5) |
67 | | - // some special keys won't be recognized (aka left arrow key). |
68 | | - // Backspace will be, so not big issue. |
69 | | - |
70 | | - if ( e.which === 0 || e.charCode === 0 || e.which === 8 || |
71 | | - e.ctrlKey || e.altKey || e.metaKey ) |
72 | | - { |
73 | | - return true; //a special key (backspace, etc) so don't interfere. |
| 40 | + // Default limit to current attribute value |
| 41 | + // Can't re-use 'limit' variable because it's in the higher scope |
| 42 | + // that affects the next each() iteration as well. |
| 43 | + elLimit = limit === undefined ? $el.prop( 'maxLength' ) : limit; |
| 44 | + |
| 45 | + // Update/set attribute value, but only if there is no callback set. |
| 46 | + // If there's a callback set, it's possible that the limit being enforced |
| 47 | + // is too low (ie. if the callback would return "Foo" for "User:Foo"). |
| 48 | + // Usually this isn't a problem since browsers ignore maxLength when setting |
| 49 | + // the value property through JavaScript, but Safari 4 violates that rule, so |
| 50 | + // we have to remove or not set the property if we have a callback. |
| 51 | + if ( fn === undefined ) { |
| 52 | + $el.prop( 'maxLength', elLimit ); |
| 53 | + } else { |
| 54 | + $el.removeProp( 'maxLength' ); |
74 | 55 | } |
75 | | - |
76 | | - var val = fn !== undefined ? fn( $( this ).val() ): $( this ).val(), |
77 | | - len = $.byteLength( val ), |
| 56 | + |
| 57 | + // Nothing passed and/or empty attribute, return without binding an event. |
| 58 | + if ( elLimit === undefined ) { |
| 59 | + return; |
| 60 | + } |
| 61 | + |
| 62 | + // Save function for reference |
| 63 | + $el.data( 'byteLimit-callback', fn ); |
| 64 | + |
| 65 | + // We've got something, go for it: |
| 66 | + $el.keypress( function ( e ) { |
| 67 | + var val, len, charLen; |
| 68 | + // First check to see if this is actually a character key |
| 69 | + // being pressed. |
| 70 | + // Based on key-event info from http://unixpapa.com/js/key.html |
| 71 | + // jQuery should also normalize e.which to be consistent cross-browser, |
| 72 | + // however the same check is still needed regardless of jQuery. |
| 73 | + |
| 74 | + // Note: At the moment, for some older opera versions (~< 10.5) |
| 75 | + // some special keys won't be recognized (aka left arrow key). |
| 76 | + // Backspace will be, so not big issue. |
| 77 | + |
| 78 | + if ( e.which === 0 || e.charCode === 0 || e.which === 8 || |
| 79 | + e.ctrlKey || e.altKey || e.metaKey ) |
| 80 | + { |
| 81 | + // A special key (backspace, etc) so don't interfere |
| 82 | + return true; |
| 83 | + } |
| 84 | + |
| 85 | + val = fn !== undefined ? fn( $( this ).val() ): $( this ).val(); |
| 86 | + len = $.byteLength( val ); |
78 | 87 | // Note that keypress returns a character code point, not a keycode. |
79 | 88 | // However, this may not be super reliable depending on how keys come in... |
80 | 89 | charLen = $.byteLength( String.fromCharCode( e.which ) ); |
81 | | - |
82 | | - if ( ( len + charLen ) > limit ) { |
83 | | - e.preventDefault(); |
84 | | - } |
| 90 | + |
| 91 | + if ( ( len + charLen ) > elLimit ) { |
| 92 | + e.preventDefault(); |
| 93 | + } |
| 94 | + }); |
85 | 95 | }); |
86 | 96 | }; |
87 | | - |
88 | | -} )( jQuery ); |
| 97 | +}( jQuery ) ); |