MediaWiki talk:Gadget-calculator.js
Make it previewable
![]() | This edit request has been answered. Set the |answered= parameter to no to reactivate your request. |
Currently it doesn't work in live preview, reply tool, etc. This should fix it (code).
Line 176: | Line 176: |
// Evaluate the value of an AST at runtime. | // Evaluate the value of an AST at runtime. |
var evaluate = function( ast ) { | var evaluate = function( ast, parserOutput ) { |
if ( ast instanceof Numb ) { | if ( ast instanceof Numb ) { |
return ast.value; | return ast.value; |
} | } |
if ( ast instanceof Ident ) { | if ( ast instanceof Ident ) { |
var elm = |
var elm = parserOutput.querySelector( '#calculator-field-' + ast.value ); |
if ( elm.tagName === 'INPUT' ) { | if ( elm.tagName === 'INPUT' ) { |
if ( elm.type === 'radio' || elm.type === 'checkbox' ) { | if ( elm.type === 'radio' || elm.type === 'checkbox' ) { |
Line 192: | Line 192: |
} | } |
if ( ast instanceof Operator ) { | if ( ast instanceof Operator ) { |
evaledArgs = ast.args.map( |
evaledArgs = ast.args.map( function (arg) { |
return evaluate( arg, parserOutput ); | |
}); | |
if ( mathFuncs.indexOf(ast.op) !== -1 ) { | if ( mathFuncs.indexOf(ast.op) !== -1 ) { |
return Math[ast.op].apply( Math, evaledArgs ); | return Math[ast.op].apply( Math, evaledArgs ); |
Line 276: | Line 278: |
// Start code that does setup and HTML interaction. | // Start code that does setup and HTML interaction. |
var setup = function() { | var setup = function( $content ) { |
var elms = Array.from( |
var elms = Array.from( $content.find( '.calculator-field' ) ); |
if (elms.length > 200) { | if (elms.length > 200) { |
console.log( "Too many calculator widgets on page" ); | console.log( "Too many calculator widgets on page" ); |
Line 346: | Line 348: |
console.log( "Change happened!" ); | console.log( "Change happened!" ); |
inProgressRefresh = {}; | inProgressRefresh = {}; |
// Fall back on body | |
var parserOutput = e.target.closest( '.mw-parser-output, body' ); | |
var itemId = e.target.id.replace( /^calculator-field-/, '' ); | var itemId = e.target.id.replace( /^calculator-field-/, '' ); |
inProgressRefresh[itemId] = true; | inProgressRefresh[itemId] = true; |
for ( var i in backlinks[itemId] ) { | for ( var i in backlinks[itemId] ) { |
refresh( backlinks[itemId][i] ); | refresh( backlinks[itemId][i], parserOutput ); |
} | } |
if ( e.target.type === 'radio' ) { | if ( e.target.type === 'radio' ) { |
// when a radio element gets checked, others get unchecked. | // when a radio element gets checked, others get unchecked. |
var otherElms = |
var otherElms = parserOutput.querySelectorAll( '[name="' + e.target.name + '"]' ); |
for ( var l = 0; l < otherElms.length; l++ ) { | for ( var l = 0; l < otherElms.length; l++ ) { |
if ( otherElms[l].id === e.target.id ) { | if ( otherElms[l].id === e.target.id ) { |
Line 361: | Line 365: |
if ( backlinks[oElmId] ) { | if ( backlinks[oElmId] ) { |
for ( var k in backlinks[oElmId] ) { | for ( var k in backlinks[oElmId] ) { |
refresh( backlinks[oElmId][k] ); | refresh( backlinks[oElmId][k], parserOutput ); |
} | } |
} | } |
Line 369: | Line 373: |
} | } |
var refresh = function (itemId) { | var refresh = function (itemId, parserOutput) { |
if ( !itemList[itemId] || itemList[itemId] instanceof Null ) { | if ( !itemList[itemId] || itemList[itemId] instanceof Null ) { |
// This should not happen. | // This should not happen. |
Line 380: | Line 384: |
} | } |
inProgressRefresh[itemId] = true; | inProgressRefresh[itemId] = true; |
var res = evaluate( itemList[itemId] ); | var res = evaluate( itemList[itemId], parserOutput ); |
var elm = |
var elm = parserOutput.querySelector( "#calculator-field-" + itemId ); |
if ( elm.tagName === 'INPUT' ) { | if ( elm.tagName === 'INPUT' ) { |
elm.value = res; | elm.value = res; |
Line 391: | Line 395: |
} | } |
for ( var i in backlinks[itemId] ) { | for ( var i in backlinks[itemId] ) { |
refresh( backlinks[itemId][i] ); | refresh( backlinks[itemId][i], parserOutput ); |
} | } |
} | } |
|
mw.hook( 'wikipage.content' ).add( setup ); |
} )(); | } )(); |
Nardog (talk) 01:59, 14 September 2024 (UTC) updated 11:34, 14 September 2024 (UTC)
- cc: @Bawolff. – SD0001 (talk) 07:18, 14 September 2024 (UTC)
- Should these sort of changes be made "upstream" during testing? — xaosflux Talk 08:15, 14 September 2024 (UTC)
- I'm unsure that would work properly if the wikipage.content hook was fired multiple times during one page view. Bawolff (talk) 08:51, 14 September 2024 (UTC)
- @Bawolff: For what reason do you suspect it might not? And if it doesn't then it should be fixed. Not being able to preview is unacceptable IMO. I tested my patch and it works in live preview, realtime preview, and reply tool. Nardog (talk) 10:25, 14 September 2024 (UTC)
- Ah, it doesn't work if both live and realtime preview are used, presumably because elements with the same IDs exist. That could be mitigated by scoping queries to the $content fired by the hook and keeping references to the associated elements, requiring a wrapper element, or including a serial number in the IDs that increases on each hook firing. Nardog (talk) 10:34, 14 September 2024 (UTC)
- Another technique is to attach a
--bound
class to the elements that have been processed, and skip them on further runs, c.f. mw:MediaWiki:Gadget-site-tpl-copy.js. – SD0001 (talk) 11:01, 14 September 2024 (UTC)- I'm not sure if that would help because IDs are looked up not only when elements are processed but also on interaction.
- Come to think of it, probably the simplest solution is to scope the query to the nearest
.mw-parser-output
. I'll test it and update the patch. Nardog (talk) 11:12, 14 September 2024 (UTC)- I think the best way to do this would be to have the gadget keep references to the actual elements, instead of just their IDs. Bawolff (talk) 19:34, 15 September 2024 (UTC)
- Another technique is to attach a
- @Izno: What is "the answer" here? Nardog (talk) 09:42, 15 September 2024 (UTC)
- My concern from above didn't really get answered - right now this is a test, and I'd expect that improvements are going to get synced in from the external site, clobbering local improvements. Not a showstopper, just something to consider. — xaosflux Talk 13:31, 15 September 2024 (UTC)
- @Nardog You said
I'll test it and update the patch.
without posting a further update and only now do I see you did actually work on it. You're free to reactivate if you think it's ready again. That was what I based that off. - I do also agree with Xaosflux though. Izno (talk) 16:04, 15 September 2024 (UTC)
![]() | It is requested that an edit be made to the interface page at MediaWiki:Gadget-calculator.js. (edit · history · last · links)
This template must be followed by a complete and specific description of the request, that is, specify what text should be removed and a verbatim copy of the text that should replace it. "Please change X" is not acceptable and will be rejected; the request must be of the form "please change X to Y".
The edit may be made by any interface administrator. Remember to change the |
Can this be resynced with https://mdwiki.org/wiki/MediaWiki:Gadget-calculator.js ? The new version should address User:Nardog's concerns. Bawolff (talk) 06:40, 26 September 2024 (UTC)
NaN
@Bawolff Another issue is that NaN shows up in result cells when one or more inputs are blank. Can we make the result blank in such cases? – SD0001 (talk) 07:54, 26 September 2024 (UTC)
- This can be worked around by setting a default value for all the cells of 0 (or whatever is appropriate), so they don't start off as blank. Alternatively, the calculator template can take a
NaN-text
parameter to adjust the text used for not-a-number (The #if in the template code won't let you set it to empty string, although the js should work if you manually made the html. I guess using something like   should work with the current template). Bawolff (talk) 09:33, 26 September 2024 (UTC)