Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php |
— | — | @@ -17,10 +17,12 @@ |
18 | 18 | 'articlefeedbackv5-cta1-edit-linktext' => 'Edit this page', |
19 | 19 | |
20 | 20 | // error messages |
| 21 | + 'articlefeedbackv5-error' => 'An error has occured. Please try again later.', |
21 | 22 | 'articlefeedbackv5-error-email' => 'That email address is not valid', |
22 | 23 | 'articlefeedbackv5-error-validation' => 'Validation error', |
23 | 24 | 'articlefeedbackv5-error-unknown' => 'Unknown error', |
24 | 25 | 'articlefeedbackv5-error-submit' => 'Form submission error.', |
| 26 | + 'articlefeedbackv5-error-nofeedback' => 'Please enter your feedback.', |
25 | 27 | |
26 | 28 | // Article Feedback special page. |
27 | 29 | 'articlefeedbackv5-form-optionid' => 'Option $1', |
— | — | @@ -143,7 +145,6 @@ |
144 | 146 | 'articlefeedbackv5-bucket5-wellwritten-tooltip-4' => 'Good clarity', |
145 | 147 | 'articlefeedbackv5-bucket5-wellwritten-tooltip-5' => 'Exceptional clarity', |
146 | 148 | /* Messages shared by all displays */ |
147 | | - 'articlefeedbackv5-error' => 'An error has occured. Please try again later.', |
148 | 149 | 'articlefeedbackv5-shared-on-feedback' => 'Your comment will be shared on this $1.', |
149 | 150 | 'articlefeedbackv5-shared-on-feedback-linktext' => 'feedback page', |
150 | 151 | 'articlefeedbackv5-help-tooltip-title' => 'What\'s this?', |
— | — | @@ -304,6 +305,8 @@ |
305 | 306 | This message is used in JavaScript by module 'jquery.articleFeedback'. |
306 | 307 | $1 is an integer, and the rating count.", |
307 | 308 | /* Messages shared by all displays */ |
| 309 | + 'articlefeedbackv5-error' => 'This error message will be displayed in a grey box replacing the form if there was an unrecoverable error.', |
| 310 | + 'articlefeedbackv5-error-nofeedback' => 'This error message will be displayed above the form (but below the title) if the user has attempted to submit a blank form.', |
308 | 311 | 'articlefeedbackv5-shared-on-feedback' => 'This is the top line of the small text that goes beside the submit button and lets the user know that their comment will be posted on the feedback page. $1 will hold the link to the feedback page.', |
309 | 312 | 'articlefeedbackv5-shared-on-feedback-linktext' => 'The text for the feedback page link (see "articlefeedbackv5-shared-on-feedback")', |
310 | 313 | 'articlefeedbackv5-help-tooltip-title' => 'The title for the help tooltip', |
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.css |
— | — | @@ -870,4 +870,10 @@ |
871 | 871 | /*** Bucket 5 ***/ |
872 | 872 | #articleFeedbackv5-bucket5 .articleFeedbackv5-submit { |
873 | 873 | float: right; |
874 | | -} |
\ No newline at end of file |
| 874 | +} |
| 875 | + |
| 876 | +/*** Top error ***/ |
| 877 | +.articleFeedbackv5-top-error { |
| 878 | + color: #8b0000; |
| 879 | + margin-bottom: 5px; |
| 880 | +} |
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js |
— | — | @@ -176,9 +176,7 @@ |
177 | 177 | <h3><html:msg key="help-tooltip-title" /></h3><span class="articleFeedbackv5-tooltip-close">X</span>\ |
178 | 178 | <div class="clear"></div>\ |
179 | 179 | <p><html:msg key="help-tooltip-info" /></p>\ |
180 | | - <p><a target="_blank" href="' + |
181 | | -mw.msg( 'articlefeedbackv5-help-tooltip-linkurl' ) |
182 | | -+ '"><html:msg key="help-tooltip-linktext" /> >></a></p>\ |
| 180 | + <p><a target="_blank" class="articleFeedbackv5-tooltip-link"><html:msg key="help-tooltip-linktext" /> >></a></p>\ |
183 | 181 | </div>\ |
184 | 182 | <div class="tooltip-bottom"></div>\ |
185 | 183 | </div>\ |
— | — | @@ -223,6 +221,7 @@ |
224 | 222 | */ |
225 | 223 | block: '\ |
226 | 224 | <form>\ |
| 225 | + <div class="articleFeedbackv5-top-error"></div>\ |
227 | 226 | <div class="form-row articleFeedbackv5-bucket1-toggle">\ |
228 | 227 | <p class="instructions-left"><html:msg key="bucket1-question-toggle" /></p>\ |
229 | 228 | <div class="buttons">\ |
— | — | @@ -402,7 +401,11 @@ |
403 | 402 | getFormData: function () { |
404 | 403 | var data = {}; |
405 | 404 | var $check = $.articleFeedbackv5.find( '.articleFeedbackv5-bucket1-toggle input[checked]' ); |
406 | | - data.found = $check.val() == 'yes' ? 1 : 0; |
| 405 | + if ( $check.val() == 'yes' ) { |
| 406 | + data.found = 1; |
| 407 | + } else if ( $check.val() == 'no' ) { |
| 408 | + data.found = 0; |
| 409 | + } |
407 | 410 | data.comment = $.articleFeedbackv5.find( '.articleFeedbackv5-comment textarea' ).val(); |
408 | 411 | var def_msg_yes = mw.msg( 'articlefeedbackv5-bucket1-question-comment-yes' ); |
409 | 412 | var def_msg_no = mw.msg( 'articlefeedbackv5-bucket1-question-comment-no' ); |
— | — | @@ -413,21 +416,24 @@ |
414 | 417 | }, |
415 | 418 | |
416 | 419 | // }}} |
417 | | - // {{{ markFormError |
| 420 | + // {{{ localValidation |
418 | 421 | |
419 | 422 | /** |
420 | | - * Marks any errors on the form |
| 423 | + * Performs any local validation |
421 | 424 | * |
422 | | - * @param object error errors, indexed by field name |
| 425 | + * @param object formdata the form data |
| 426 | + * @return mixed if ok, false; otherwise, an object as { 'field name' : 'message' } |
423 | 427 | */ |
424 | | - markFormError: function ( error ) { |
425 | | - if ( '_api' in error ) { |
426 | | - $.articleFeedbackv5.markShowstopperError( error._api.info ); |
427 | | - } else { |
428 | | - alert( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
429 | | - mw.log( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
| 428 | + localValidation: function ( formdata ) { |
| 429 | + var error = {}; |
| 430 | + var ok = true; |
| 431 | + if ( ( !( 'comment' in formdata ) || formdata.comment == '' ) |
| 432 | + && !( 'found' in formdata ) ) { |
| 433 | + $.articleFeedbackv5.enableSubmission( false ); |
| 434 | + error.nofeedback = mw.msg( 'articlefeedbackv5-error-nofeedback' ); |
| 435 | + ok = false; |
430 | 436 | } |
431 | | - console.log( error ); |
| 437 | + return ok ? false : error; |
432 | 438 | } |
433 | 439 | |
434 | 440 | // }}} |
— | — | @@ -467,6 +473,7 @@ |
468 | 474 | */ |
469 | 475 | block: '\ |
470 | 476 | <form>\ |
| 477 | + <div class="articleFeedbackv5-top-error"></div>\ |
471 | 478 | <div>\ |
472 | 479 | <div class="articleFeedbackv5-tags">\ |
473 | 480 | <ul></ul>\ |
— | — | @@ -711,21 +718,23 @@ |
712 | 719 | }, |
713 | 720 | |
714 | 721 | // }}} |
715 | | - // {{{ markFormError |
| 722 | + // {{{ localValidation |
716 | 723 | |
717 | 724 | /** |
718 | | - * Marks any errors on the form |
| 725 | + * Performs any local validation |
719 | 726 | * |
720 | | - * @param object error errors, indexed by field name |
| 727 | + * @param object formdata the form data |
| 728 | + * @return mixed if ok, false; otherwise, an object as { 'field name' : 'message' } |
721 | 729 | */ |
722 | | - markFormError: function ( error ) { |
723 | | - if ( '_api' in error ) { |
724 | | - $.articleFeedbackv5.markShowstopperError( error._api.info ); |
725 | | - } else { |
726 | | - alert( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
727 | | - mw.log( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
| 730 | + localValidation: function ( formdata ) { |
| 731 | + var error = {}; |
| 732 | + var ok = true; |
| 733 | + if ( !( 'comment' in formdata ) || formdata.comment == '' ) { |
| 734 | + $.articleFeedbackv5.enableSubmission( false ); |
| 735 | + error.nofeedback = mw.msg( 'articlefeedbackv5-error-nofeedback' ); |
| 736 | + ok = false; |
728 | 737 | } |
729 | | - console.log( error ); |
| 738 | + return ok ? false : error; |
730 | 739 | } |
731 | 740 | |
732 | 741 | // }}} |
— | — | @@ -752,6 +761,7 @@ |
753 | 762 | */ |
754 | 763 | block: '\ |
755 | 764 | <form>\ |
| 765 | + <div class="articleFeedbackv5-top-error"></div>\ |
756 | 766 | <div>\ |
757 | 767 | <p class="instructions-left"><html:msg key="bucket3-rating-question" /></p>\ |
758 | 768 | <div class="articleFeedbackv5-rating articleFeedbackv5-rating-new">\ |
— | — | @@ -997,21 +1007,24 @@ |
998 | 1008 | }, |
999 | 1009 | |
1000 | 1010 | // }}} |
1001 | | - // {{{ markFormError |
| 1011 | + // {{{ localValidation |
1002 | 1012 | |
1003 | 1013 | /** |
1004 | | - * Marks any errors on the form |
| 1014 | + * Performs any local validation |
1005 | 1015 | * |
1006 | | - * @param object error errors, indexed by field name |
| 1016 | + * @param object formdata the form data |
| 1017 | + * @return mixed if ok, false; otherwise, an object as { 'field name' : 'message' } |
1007 | 1018 | */ |
1008 | | - markFormError: function ( error ) { |
1009 | | - if ( '_api' in error ) { |
1010 | | - $.articleFeedbackv5.markShowstopperError( error._api.info ); |
1011 | | - } else { |
1012 | | - alert( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
1013 | | - mw.log( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
| 1019 | + localValidation: function ( formdata ) { |
| 1020 | + var error = {}; |
| 1021 | + var ok = true; |
| 1022 | + if ( ( !( 'comment' in formdata ) || formdata.comment == '' ) |
| 1023 | + && ( !( 'rating' in formdata ) || formdata.rating < 1 ) ) { |
| 1024 | + $.articleFeedbackv5.enableSubmission( false ); |
| 1025 | + error.nofeedback = mw.msg( 'articlefeedbackv5-error-nofeedback' ); |
| 1026 | + ok = false; |
1014 | 1027 | } |
1015 | | - console.log( error ); |
| 1028 | + return ok ? false : error; |
1016 | 1029 | } |
1017 | 1030 | |
1018 | 1031 | // }}} |
— | — | @@ -1653,6 +1666,9 @@ |
1654 | 1667 | $.articleFeedbackv5.find( '.articleFeedbackv5-expertise input:checked' ).each( function () { |
1655 | 1668 | data['expertise-' + $( this ).val()] = 1; |
1656 | 1669 | } ); |
| 1670 | + if ( $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove input:checked' ).length > 0 ) { |
| 1671 | + data.email = $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove-email' ).val(); |
| 1672 | + } |
1657 | 1673 | return data; |
1658 | 1674 | }, |
1659 | 1675 | |
— | — | @@ -1669,8 +1685,7 @@ |
1670 | 1686 | var error = {}; |
1671 | 1687 | var ok = true; |
1672 | 1688 | if ( $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove input:checked' ).length > 0 ) { |
1673 | | - var mail = $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove-email' ).val(); |
1674 | | - if ( !mw.util.validateEmail( mail ) ) { |
| 1689 | + if ( 'email' in formdata && !mw.util.validateEmail( formdata.email ) ) { |
1675 | 1690 | error.helpimprove_email = mw.msg( 'articlefeedbackv5-error-email' ); |
1676 | 1691 | ok = false; |
1677 | 1692 | } |
— | — | @@ -1679,30 +1694,19 @@ |
1680 | 1695 | }, |
1681 | 1696 | |
1682 | 1697 | // }}} |
1683 | | - // {{{ markFormError |
| 1698 | + // {{{ markFormErrors |
1684 | 1699 | |
1685 | 1700 | /** |
1686 | 1701 | * Marks any errors on the form |
1687 | 1702 | * |
1688 | | - * @param object error errors, indexed by field name |
| 1703 | + * @param object errors errors, indexed by field name |
1689 | 1704 | */ |
1690 | | - markFormError: function ( error ) { |
1691 | | - if ( '_api' in error ) { |
1692 | | - if ($.articleFeedbackv5.debug) { |
1693 | | - $.articleFeedbackv5.find( '.articleFeedbackv5-error-message' ) |
1694 | | - .html( error._api.info.replace( "\n", '<br />' ) ); |
1695 | | - } |
1696 | | - $.articleFeedbackv5.find( '.articleFeedbackv5-error' ).show(); |
1697 | | - } else { |
1698 | | - if ( 'helpimprove_email' in error ) { |
1699 | | - $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove-email' ) |
1700 | | - .addClass( 'invalid' ) |
1701 | | - .removeClass( 'valid' ); |
1702 | | - } |
1703 | | - alert( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
1704 | | - mw.log( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
| 1705 | + markFormErrors: function ( errors ) { |
| 1706 | + if ( 'helpimprove_email' in errors ) { |
| 1707 | + $.articleFeedbackv5.find( '.articleFeedbackv5-helpimprove-email' ) |
| 1708 | + .addClass( 'invalid' ) |
| 1709 | + .removeClass( 'valid' ); |
1705 | 1710 | } |
1706 | | - console.log( error ); |
1707 | 1711 | }, |
1708 | 1712 | |
1709 | 1713 | // }}} |
— | — | @@ -2049,9 +2053,11 @@ |
2050 | 2054 | |
2051 | 2055 | // Set up the tooltip for the panel version |
2052 | 2056 | $wrapper.find( '.articleFeedbackv5-title-wrap' ).append( $.articleFeedbackv5.templates.helpToolTip ); |
| 2057 | + $wrapper.find( '.articleFeedbackv5-tooltip-link' ) |
| 2058 | + .attr( 'href', mw.msg( 'articlefeedbackv5-help-tooltip-linkurl' ) ); |
2053 | 2059 | $wrapper.find( '.articleFeedbackv5-tooltip' ).hide(); |
2054 | 2060 | |
2055 | | - if( $.articleFeedbackv5.bucketId == 5 ) { |
| 2061 | + if ( $.articleFeedbackv5.bucketId == 5 ) { |
2056 | 2062 | $wrapper.find( '.articleFeedbackv5-tooltip-trigger' ).hide(); |
2057 | 2063 | } else { |
2058 | 2064 | $wrapper.find( '.articleFeedbackv5-tooltip-trigger' ).click( function () { |
— | — | @@ -2096,6 +2102,8 @@ |
2097 | 2103 | // Set up the tooltip for the dialoag |
2098 | 2104 | $titlebar.append( $.articleFeedbackv5.templates.helpToolTip ); |
2099 | 2105 | $titlebar.find( '.articleFeedbackv5-tooltip' ).hide(); |
| 2106 | + $titlebar.find( '.articleFeedbackv5-tooltip-link' ) |
| 2107 | + .attr( 'href', mw.msg( 'articlefeedbackv5-help-tooltip-linkurl' ) ); |
2100 | 2108 | $titlebar.find( '.articleFeedbackv5-tooltip-trigger' ).click( function ( e ) { |
2101 | 2109 | $( e.target ).next( '.articleFeedbackv5-tooltip' ).toggle(); |
2102 | 2110 | } ); |
— | — | @@ -2139,13 +2147,9 @@ |
2140 | 2148 | |
2141 | 2149 | // Perform any local validation |
2142 | 2150 | if ( 'localValidation' in bucket ) { |
2143 | | - var error = bucket.localValidation( formdata ); |
2144 | | - if ( error ) { |
2145 | | - if ( 'markFormError' in bucket ) { |
2146 | | - bucket.markFormError( error ); |
2147 | | - } else { |
2148 | | - alert( error.join( "\n" ) ); |
2149 | | - } |
| 2151 | + var errors = bucket.localValidation( formdata ); |
| 2152 | + if ( errors ) { |
| 2153 | + $.articleFeedbackv5.markFormErrors( errors ); |
2150 | 2154 | return; |
2151 | 2155 | } |
2152 | 2156 | } |
— | — | @@ -2190,19 +2194,15 @@ |
2191 | 2195 | if ( 'error' in data ) { |
2192 | 2196 | msg = data.error; |
2193 | 2197 | } else { |
2194 | | - msg = mw.msg( 'articlefeedbackv5-error-unknown' ); |
| 2198 | + msg = { info: mw.msg( 'articlefeedbackv5-error-unknown' ) }; |
2195 | 2199 | } |
2196 | | - if ( 'markFormError' in bucket ) { |
2197 | | - bucket.markFormError( { _api : msg } ); |
2198 | | - } else { |
2199 | | - alert( mw.msg( 'articlefeedbackv5-error-submit' ) ); |
2200 | | - } |
| 2200 | + $.articleFeedbackv5.markFormErrors( { _api : msg } ); |
2201 | 2201 | $.articleFeedbackv5.unlockForm(); |
2202 | 2202 | } |
2203 | 2203 | }, |
2204 | 2204 | 'error': function () { |
2205 | | - mw.log( mw.msg( 'articlefeedbackv5-error-submit' ) ); |
2206 | | - alert( mw.msg( 'articlefeedbackv5-error-submit' ) ); |
| 2205 | + var err = { _api: { info: mw.msg( 'articlefeedbackv5-error-submit' ) } }; |
| 2206 | + $.articleFeedbackv5.markFormErrors( err ); |
2207 | 2207 | $.articleFeedbackv5.unlockForm(); |
2208 | 2208 | } |
2209 | 2209 | } ); |
— | — | @@ -2293,6 +2293,48 @@ |
2294 | 2294 | }; |
2295 | 2295 | |
2296 | 2296 | // }}} |
| 2297 | + // {{{ markTopError |
| 2298 | + |
| 2299 | + /** |
| 2300 | + * Marks an error at the top of the form |
| 2301 | + * |
| 2302 | + * @param msg string the error message |
| 2303 | + */ |
| 2304 | + $.articleFeedbackv5.markTopError = function ( msg ) { |
| 2305 | + $.articleFeedbackv5.find( '.articleFeedbackv5-top-error' ).html( msg ); |
| 2306 | + }; |
| 2307 | + |
| 2308 | + // }}} |
| 2309 | + // {{{ markFormErrors |
| 2310 | + |
| 2311 | + /** |
| 2312 | + * Marks any errors on the form |
| 2313 | + * |
| 2314 | + * @param object errors errors, indexed by field name |
| 2315 | + */ |
| 2316 | + $.articleFeedbackv5.markFormErrors = function ( errors ) { |
| 2317 | + if ( '_api' in errors ) { |
| 2318 | + if ( $.articleFeedbackv5.debug ) { |
| 2319 | + $.articleFeedbackv5.markTopError( errors._api.info ); |
| 2320 | + } else { |
| 2321 | + mw.log( mw.msg( 'articlefeedbackv5-error-submit' ) ); |
| 2322 | + } |
| 2323 | + mw.log( mw.msg( errors._api.info ) ); |
| 2324 | + } else { |
| 2325 | + mw.log( mw.msg( 'articlefeedbackv5-error-validation' ) ); |
| 2326 | + if ( 'nofeedback' in errors ) { |
| 2327 | + $.articleFeedbackv5.markTopError( mw.msg( 'articlefeedbackv5-error-nofeedback' ) ); |
| 2328 | + } |
| 2329 | + } |
| 2330 | + if ( $.articleFeedbackv5.debug ) { |
| 2331 | + console.log( errors ); |
| 2332 | + } |
| 2333 | + if ( 'markFormErrors' in $.articleFeedbackv5.currentBucket() ) { |
| 2334 | + $.articleFeedbackv5.currentBucket().markFormErrors( errors ); |
| 2335 | + } |
| 2336 | + }; |
| 2337 | + |
| 2338 | + // }}} |
2297 | 2339 | // {{{ lockForm |
2298 | 2340 | |
2299 | 2341 | /** |
— | — | @@ -2331,7 +2373,6 @@ |
2332 | 2374 | */ |
2333 | 2375 | $.articleFeedbackv5.addToRemovalQueue = function ( $el ) { |
2334 | 2376 | $.articleFeedbackv5.$toRemove = $.articleFeedbackv5.$toRemove.add( $el ); |
2335 | | - console.log( $.articleFeedbackv5.$toRemove ); |
2336 | 2377 | }; |
2337 | 2378 | |
2338 | 2379 | // }}} |
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php |
— | — | @@ -45,6 +45,7 @@ |
46 | 46 | 'messages' => array( |
47 | 47 | 'articlefeedbackv5-error-email', |
48 | 48 | 'articlefeedbackv5-error-validation', |
| 49 | + 'articlefeedbackv5-error-nofeedback', |
49 | 50 | 'articlefeedbackv5-error-unknown', |
50 | 51 | 'articlefeedbackv5-error-submit', |
51 | 52 | 'articlefeedbackv5-cta1-thanks', |