Add a jQuery-free vanilla JS implementation of wicket-ajax.js - #1580
Add a jQuery-free vanilla JS implementation of wicket-ajax.js#1580reiern70 wants to merge 3 commits into
Conversation
bb4838c to
41b57d7
Compare
| .add(CSPDirective.STYLE_SRC, | ||
| "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css") | ||
| .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com"); | ||
| getCspSettings().blocking().disabled(); |
There was a problem hiding this comment.
@papegaaij I would appreciate your help here: with strict the new VANILA js is no loaded. I could not figure out why
|
I will do some more testing but this seems to be working. Next steps
|
|
@reiern70 The problem was in the decorator. It did not preserve the nonce. The decorator was not needed at all. I've just pushed a fix on your branch that resolves the engine directly from the session and it works now. |
Many thanks! |
474e847 to
4f7000f
Compare
| coreJs = [ | ||
| '../../wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery-debug.js', | ||
| '../../wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js', | ||
| '../../wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-vanilla.js', |
There was a problem hiding this comment.
Minor nit: How about simply calling it wicket-ajax.js?
|
Love this! |
#1583 Wicket's client-side Ajax/event support (Wicket.Ajax, Wicket.Event, Wicket.DOM, Wicket.Form, Wicket.Head, Wicket.Focus, ...) has always required jQuery. This adds a second, plain-JavaScript implementation exposing the exact same API, so applications that don't want to ship jQuery at all can opt in via: getJavaScriptLibrarySettings().setWicketAjaxReference(WicketAjaxVanillaResourceReference.get()); jQuery stays the default; existing applications are unaffected. Core changes: - wicket-ajax-vanilla.js: full port of wicket-ajax-jquery.js onto native XMLHttpRequest/DOM/event APIs (WicketAjaxVanillaResourceReference.java is its resource reference). - Removed jQuery from every other framework JS file that only used it incidentally (not as its actual implementation choice), so the whole stack can run without jQuery once the vanilla engine is selected: the extensions Ajax components (autocomplete, palette, upload progress bar, ajax download, trap focus), the dev debug bar, native WebSockets support, and FileUploadToResourceField.js - all verified to still work correctly under the default jQuery engine too, and their public extension points/callback signatures are unchanged. - Cleaned up several now-dead legacy-browser fallbacks and deprecated Web APIs encountered along the way (window.escape/unescape, window.event, Attr.specified, IE-only branches). Testing: - Ported the wicket-core QUnit suite (channels/dom/event/form/head/ajax/timer) off jQuery-based test-authoring helpers so the same tests run against either engine; all.html now takes ?vanilla alongside the existing ?<jquery-version>, and the Gruntfile has a matching qunit:vanilla target. - Ran the full suite for real (jQuery 3.7.1, jQuery 4.0.0, vanilla) via a portable Node build + jsdom against a real HTTP server, since no JS runtime was available here otherwise - this caught and fixed several real bugs in the vanilla engine (event "extra data" colliding with native Event.detail, beforeSend's settings.url/data not reflecting the resolved request, unsupported dataType 'json', a DOM.show() default-display mismatch, and scripts in replaced/appended markup never executing). Examples: - wicket-examples can now be started with either engine via a single JVM-wide switch (-Dwicket.examples.use=JQUERY|VANILLA, default JQUERY), applied through AjaxEngineSelector from every example Application's init(), with a startup console banner (mirroring Wicket's own dev-mode warning) confirming which engine is active. - The shared example page header also shows the active engine and lets a visitor switch it for their session only, live, without an application restart - implemented via an IHeaderResponseDecorator rather than mutating the shared JavaScriptLibrarySettings, so concurrent sessions with different choices never interfere with each other. Verified end-to-end with WicketTester (both switch directions render the correct script tags in the correct order, and the toggle link updates the session as expected). Documentation: new user guide section (ajax_11.adoc) explaining both implementations and how to switch; corrected IAjaxCallListener/ajax_5/ajax_6 docs that assumed jqXHR/jqEvent are always jQuery-specific objects.
The engine toggle in WicketExampleHeader was implemented as a header response decorator that substituted the session's wicket-ajax.js reference for the application's configured one. Both that decorator and CSPNonceHeaderResponseDecorator are registered with addPreResourceAggregationDecorator, and CSP registers later (from WebApplication#validateInit, after init()), so it ends up upstream: it stamped the nonce onto the item the selector then threw away, and rendered a fresh JavaScriptHeaderItem with a null nonce in its place. Under script-src 'strict-dynamic' 'nonce-XYZ' the browser blocked that script, so switching to the vanilla engine loaded no wicket-ajax.js at all - which is why the examples had CSP turned off entirely. Resolve the engine at the source instead: give the application a JavaScriptLibrarySettings whose getWicketAjaxReference() returns referenceFor(getEffectiveEngine()) on every call. Nothing is substituted after the fact, so the nonce is applied normally. The instance is shared by all sessions but holds no state - it just forwards to whatever Session#get() resolves to on the calling thread - so concurrent sessions with different choices still do not interfere. Answering at the source also fixes a second defect: because OnDomReadyHeaderItem, OnLoadHeaderItem and OnEventHeaderItem declare a dependency on the configured reference, the aggregator used to pull jQuery back in behind the decorator's back, and a session switched to VANILLA still downloaded jQuery. It no longer does. With that, restore the CSP configuration the examples had before the vanilla engine was added. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4f7000f to
f2953e3
Compare
Thanks. It seems to be working. I need some more testing. If someone else tries it I would be happy to receive feedback. |
| return; | ||
| } | ||
|
|
||
| var isUndef = function (target) { |
There was a problem hiding this comment.
Maybe it worth to use modern let/const syntax? :)
Wicket's client-side Ajax/event support (Wicket.Ajax, Wicket.Event, Wicket.DOM, Wicket.Form, Wicket.Head, Wicket.Focus, ...) has always required jQuery. This adds a second, plain-JavaScript implementation exposing the exact same API, so applications that don't want to ship jQuery at all can opt in via:
jQuery stays the default; existing applications are unaffected.
Core changes:
Testing:
Examples:
Documentation: new user guide section (ajax_11.adoc) explaining both implementations and how to switch; corrected IAjaxCallListener/ajax_5/ajax_6 docs that assumed jqXHR/jqEvent are always jQuery-specific objects.