This is an automated email from the ASF dual-hosted git repository. svenmeier pushed a commit to branch WICKET-6703-replace-eval-with-domEval in repository https://gitbox.apache.org/repos/asf/wicket.git
commit e1bc21b957baedd059a0c257b2eee159a2092ca7 Author: Sven Meier <svenme...@apache.org> AuthorDate: Thu Oct 24 14:53:08 2019 +0200 WICKET-6703 Ajax suspension via suspendCall() instead of pipe | syntax --- .../wicket/ajax/res/js/wicket-ajax-jquery.js | 110 +++++++++++---------- .../wicket/examples/ajax/builtin/EffectsPage.html | 29 ++++-- .../wicket/examples/ajax/builtin/EffectsPage.java | 46 ++++++++- 3 files changed, 123 insertions(+), 62 deletions(-) diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js index dd856cf..018fc4b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js @@ -350,6 +350,32 @@ */ Wicket.Ajax.Call = Wicket.Class.create(); + Wicket.Ajax._currentSuspension = undefined; + + /** + * Suspend the currently evaluated Ajax call, fails if no Ajax call is currently + * evaluated. + */ + Wicket.Ajax.suspendCall = function () { + var suspension = Wicket.Ajax._currentSuspension; + + if (suspension === undefined) { + Wicket.Log.error("Can't suspend: no Ajax call in process"); + return; + } + + // suspend + suspension.suspend(); + + return function () { + // release only once + if (suspension !== null) { + suspension.release(); + suspension = null; + } + } + }; + Wicket.Ajax.Call.prototype = { initialize: jQuery.noop, @@ -933,16 +959,6 @@ */ processEvaluation: function (context, node) { - // used to match evaluation scripts which manually call FunctionsExecuter's notify() when ready - var scriptWithIdentifierR = new RegExp("\\(function\\(\\)\\{([a-zA-Z_]\\w*)\\|((.|\\n)*)?\\}\\)\\(\\);$"); - - /** - * A regex used to split the text in (priority-)evaluate elements in the Ajax response - * when there are scripts which require manual call of 'FunctionExecutor#notify()' - * @type {RegExp} - */ - var scriptSplitterR = new RegExp("\\(function\\(\\)\\{[\\s\\S]*?}\\)\\(\\);", 'gi'); - // get the javascript body var text = Wicket.DOM.text(node); @@ -950,61 +966,47 @@ var steps = context.steps; var log = Wicket.Log; - var evaluateWithManualNotify = function (parameters, body) { - return function(notify) { - var toExecute = "(function(" + parameters + ") {" + body + "})"; - - try { - // do the evaluation in global scope - var f = window.eval(toExecute); - f(notify); - } catch (exception) { - log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: %s", text, exception); - } - return FunctionsExecuter.ASYNC; - }; - }; - var evaluate = function (script) { return function(notify) { - // just evaluate the javascript + + var suspension = { + suspended: 0, + + suspend: function() { + suspension.suspended++; + }, + + release: function() { + suspension.suspended--; + if (suspension.suspended == 0) { + notify(); + } + } + }; + try { + Wicket.Ajax._currentSuspension = suspension; + // do the evaluation in global scope window.eval(script); } catch (exception) { log.error("Ajax.Call.processEvaluation: Exception evaluating javascript: %s", text, exception); + } finally { + Wicket.Ajax.currentSuspension = undefined; } + // continue to next step - return FunctionsExecuter.DONE; + if (suspension.suspended === 0) { + // execution finished without suspension, just continue to next step + return FunctionsExecuter.DONE; + } else { + // suspended, signal asynchronous execution of next step + return FunctionsExecuter.ASYNC; + } }; }; - - // test if the javascript is in form of identifier|code - // if it is, we allow for letting the javascript decide when the rest of processing will continue - // by invoking identifier();. This allows usage of some asynchronous/deferred logic before the next script - // See WICKET-5039 - if (scriptWithIdentifierR.test(text)) { - var scripts = []; - var scr; - while ( (scr = scriptSplitterR.exec(text) ) !== null ) { - scripts.push(scr[0]); - } - - for (var s = 0; s < scripts.length; s++) { - var script = scripts[s]; - if (script) { - var scriptWithIdentifier = script.match(scriptWithIdentifierR); - if (scriptWithIdentifier) { - steps.push(evaluateWithManualNotify(scriptWithIdentifier[1], scriptWithIdentifier[2])); - } - else { - steps.push(evaluate(script)); - } - } - } - } else { - steps.push(evaluate(text)); - } + + steps.push(evaluate(text)); }, // Adds a closure that processes a header contribution diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.html index 241c86e..d875cea 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.html +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.html @@ -15,13 +15,28 @@ } </style> <div class="container"> -counter 1:<span wicket:id="c1"></span> -<br/> -<br/> -counter 2: <span wicket:id="c2"></span> -<br/> -<br/> -<a href="#" wicket:id="c1-link">counter1++ and shake</a>  <a href="#" wicket:id="c2-link">counter2++ and highlight</a> + <div> + <p> + counter 1:<span wicket:id="c1"></span> + </p> + <p> + counter 2: <span wicket:id="c2"></span> + </p> + <p> + counter 3: <span wicket:id="c3"></span> + </p> + </div> + <div> + <p> + <a href="#" wicket:id="c1-link">counter1++ and shake</a> + </p> + <p> + <a href="#" wicket:id="c2-link">counter2++ and highlight</a> + </p> + <p> + <a href="#" wicket:id="c3-link">counter3++, fade-out and fade-in</a> + </p> + </div> </div> </wicket:extend> </html> \ No newline at end of file diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.java index e286584..b0749ff 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.java @@ -36,6 +36,7 @@ public class EffectsPage extends BasePage { private int counter1 = 0; private int counter2 = 0; + private int counter3 = 0; /** * @return Value of counter1 @@ -71,6 +72,24 @@ public class EffectsPage extends BasePage this.counter2 = counter2; } + + /** + * @return Value for counter3 + */ + public int getCounter3() + { + return counter3; + } + + /** + * @param counter3 + * New value for counter3 + */ + public void setCounter3(int counter3) + { + this.counter3 = counter3; + } + /** * Constructor */ @@ -84,6 +103,10 @@ public class EffectsPage extends BasePage c2.setOutputMarkupId(true); add(c2); + final Label c3 = new Label("c3", new PropertyModel<>(this, "counter3")); + c3.setOutputMarkupId(true); + add(c3); + add(new AjaxLink<Void>("c1-link") { @Override @@ -125,13 +148,34 @@ public class EffectsPage extends BasePage super.updateAjaxAttributes(attributes); } }); + + add(new AjaxFallbackLink<Void>("c3-link") + { + @Override + public void onClick(Optional<AjaxRequestTarget> targetOptional) + { + counter3++; + targetOptional.ifPresent(target -> { + target.prependJavaScript((String.format("jQuery('#%s').fadeOut(500, Wicket.Ajax.suspendCall());", c3.getMarkupId()))); + target.add(c3); + target.appendJavaScript((String.format("jQuery('#%s').hide().fadeIn(500);", c3.getMarkupId()))); + }); + } + + @Override + protected void updateAjaxAttributes(AjaxRequestAttributes attributes) + { + attributes.setChannel(new AjaxChannel("effects", Type.DROP)); + + super.updateAjaxAttributes(attributes); + } + }); } @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); - response.render(OnDomReadyHeaderItem.forScript("jQuery.noConflict();")); }