Created
September 25, 2019 07:54
-
-
Save svenmeier/bd4375ab26e330617a834e1d53d86556 to your computer and use it in GitHub Desktop.
Wicket Ajax suspension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 70dd69d..bb952bc 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 | |
@@ -933,16 +933,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 +940,54 @@ | |
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 | |
+ // start with no suspension | |
+ Wicket.Ajax._suspended = 0; | |
+ Wicket.Ajax.suspend = function() { | |
+ // keep track of suspensions | |
+ Wicket.Ajax._suspended++; | |
+ | |
+ var released = false; | |
+ | |
+ return function() { | |
+ // relase only once | |
+ if (released == false) { | |
+ released = true; | |
+ | |
+ // keep track of suspensions | |
+ Wicket.Ajax._suspended--; | |
+ | |
+ if (Wicket.Ajax._suspended == 0) { | |
+ // last suspension released | |
+ notify(); | |
+ } | |
+ } | |
+ } | |
+ }; | |
+ | |
+ // evaluate the javascript | |
try { | |
// do the evaluation in global scope | |
window.eval(script); | |
} catch (exception) { | |
log.error("Ajax.Call.processEvaluation: Exception evaluating javascript: %s", text, exception); | |
} | |
- // continue to next step | |
- return FunctionsExecuter.DONE; | |
+ | |
+ if (Wicket.Ajax._suspended) { | |
+ // suspended | |
+ return FunctionsExecuter.ASYNC; | |
+ } else { | |
+ // no suspension | |
+ Wicket.Ajax._suspended = undefined; | |
+ Wicket.Ajax.suspend = undefined; | |
+ | |
+ // continue to next step | |
+ return FunctionsExecuter.DONE; | |
+ } | |
}; | |
}; | |
- | |
- // 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-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java | |
index da126a2..e7a2a52 100644 | |
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java | |
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java | |
@@ -64,15 +64,22 @@ | |
void addChildren(MarkupContainer parent, Class<?> childCriteria); | |
/** | |
- * Adds javascript that will be evaluated on the client side after components are replaced | |
- * | |
- * <p>If the javascript needs to do something asynchronously (i.e. needs to use window.setTimeout(), for example | |
- * to do animations) then the following special syntax may be used: <code>someFunctionName|myJsLogic(someFunctionName);</code>. | |
- * Wicket will transform it to: <code>function(someFunctionName){myJsLogic(someFunctionName);}</code> and your code | |
- * is responsible to execute <em>someFunctionName()</em> when the asynchronous task is finished. Once <em>someFunctionName</em> | |
- * is executed the next appended script will be executed. <strong>Important</strong>: it is highly recommended to | |
- * execute your code in try/finally to make sure <em>someFunctionName</em> is executed even an error happens in | |
- * your code, otherwise all following scripts wont be executed.</p> | |
+ * Adds JavaScript that will be evaluated on the client side after components are replaced | |
+ * <p> | |
+ * If the JavaScript needs to do something asynchronously (i.e. needs to use window.setTimeout(), for example to do animations) | |
+ * then the global method <code>Wicket.Ajax.suspend()</code> may be used, e.g.: | |
+ * <pre> | |
+ * target.prependJavaScript("jQuery('#id').fadeOut(1000, Wicket.Ajax.suspend());"); | |
+ * target.appendJavaScript("jQuery('#id').hide().fadeIn(1000, Wicket.Ajax.suspend());"); | |
+ * </pre> | |
+ * <code>suspend()</code> returns a JavaScript function which your code is responsible to invoke when the | |
+ * asynchronous task has finished (in the example above done automatically by jQuery fading methods). | |
+ * Once this is done the next appended script will be executed. | |
+ * <p> | |
+ * <strong>Important</strong>: it is highly recommended to execute your code in try/finally to | |
+ * make sure the suspension is released even an error happens in your code, otherwise all | |
+ * following scripts wont be executed. | |
+ * </p> | |
* | |
* @param javascript | |
*/ | |
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..ea078c7 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 | |
@@ -21,7 +21,12 @@ | |
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> | |
+counter 3: <span wicket:id="c3"></span> | |
+<br/> | |
+<br/> | |
+<a href="#" wicket:id="c1-link">counter1++ and shake</a>   | |
+<a href="#" wicket:id="c2-link">counter2++ and highlight</a>   | |
+<a href="#" wicket:id="c3-link">counter3++ and fade</a> | |
</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..4b48677 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,40 +36,7 @@ | |
{ | |
private int counter1 = 0; | |
private int counter2 = 0; | |
- | |
- /** | |
- * @return Value of counter1 | |
- */ | |
- public int getCounter1() | |
- { | |
- return counter1; | |
- } | |
- | |
- /** | |
- * @param counter1 | |
- * New value for counter1 | |
- */ | |
- public void setCounter1(int counter1) | |
- { | |
- this.counter1 = counter1; | |
- } | |
- | |
- /** | |
- * @return Value for counter2 | |
- */ | |
- public int getCounter2() | |
- { | |
- return counter2; | |
- } | |
- | |
- /** | |
- * @param counter2 | |
- * New value for counter2 | |
- */ | |
- public void setCounter2(int counter2) | |
- { | |
- this.counter2 = counter2; | |
- } | |
+ private int counter3 = 0; | |
/** | |
* Constructor | |
@@ -84,6 +51,10 @@ | |
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 | |
@@ -91,8 +62,7 @@ | |
{ | |
counter1++; | |
target.add(c1); | |
- target.appendJavaScript(String.format("jQuery('#%s').effect('shake');", | |
- c1.getMarkupId())); | |
+ target.appendJavaScript(String.format("jQuery('#%s').effect('shake');", c1.getMarkupId())); | |
} | |
@Override | |
@@ -112,8 +82,29 @@ | |
counter2++; | |
targetOptional.ifPresent(target -> { | |
target.add(c2); | |
- target.appendJavaScript(String.format("jQuery('#%s').effect('highlight');", | |
- c2.getMarkupId())); | |
+ target.appendJavaScript(String.format("jQuery('#%s').effect('highlight');", c2.getMarkupId())); | |
+ }); | |
+ } | |
+ | |
+ @Override | |
+ protected void updateAjaxAttributes(AjaxRequestAttributes attributes) | |
+ { | |
+ attributes.setChannel(new AjaxChannel("effects", Type.DROP)); | |
+ | |
+ 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(1000, Wicket.Ajax.suspend());",c3.getMarkupId())); | |
+ target.add(c3); | |
+ target.appendJavaScript(String.format("jQuery('#%s').hide().fadeIn(1000, Wicket.Ajax.suspend());", c3.getMarkupId())); | |
}); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment