Updated Branches: refs/heads/master 71c8e8402 -> 43237280a
WICKET-5142 Generating invalid JavaScript for ajax update Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/43237280 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/43237280 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/43237280 Branch: refs/heads/master Commit: 43237280ae58c4094508aa11cdb295f8a8fdcb4e Parents: 71c8e84 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Mon Apr 22 13:46:54 2013 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Mon Apr 22 13:46:54 2013 +0200 ---------------------------------------------------------------------- .../wicket/ajax/res/js/wicket-ajax-jquery.js | 99 +++++++++++---- wicket-core/src/test/js/ajax.js | 23 ++++ wicket-core/src/test/js/all.html | 1 + .../js/data/ajax/twoEvaluationsWithIdentifier.xml | 18 +++ 4 files changed, 115 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/43237280/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js ---------------------------------------------------------------------- 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 4db6061..4ebf4ed 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 @@ -1044,53 +1044,100 @@ // used to match evaluation scripts which manually call FunctionsExecuter's notify() when ready var scriptWithIdentifierR = new RegExp("^\\(function\\(\\)\\{([a-zA-Z_]\\w*)\\|((.|\\n)*)?\\}\\)\\(\\);$"); - context.steps.push(function (notify) { - // get the javascript body - var text; + /** + * 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\\(\\)\\{.*?}\\)\\(\\);)"); - try { - text = node.firstChild.nodeValue; - } catch (e) { - // TODO remove this fallback in 6.11.0+ - text = jQuery(node).text(); + /** + * Removes all empty items from an Array of String's + * @param original The array is empty string elements + * @returns {Array[String]} An array that has no empty elements + */ + // Needed because String.split(scriptSplitterR) returns something like ["", "script1", "", "script2", ""] + var cleanArray = function (original) { + var result = []; + for(var i = 0; i < original.length; i++){ + if (original[i]) { + result.push(original[i]); + } } + return result; + }; - // unescape it if necessary - var encoding = node.getAttribute("encoding"); - if (encoding) { - text = Wicket.Head.Contributor.decode(encoding, text); - } + // get the javascript body + var text; - // 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 - var res = text.match(scriptWithIdentifierR); + try { + text = node.firstChild.nodeValue; + } catch (e) { + // TODO remove this fallback in 6.11.0+ + text = jQuery(node).text(); + } - if (res !== null) { + // unescape it if necessary + var encoding = node.getAttribute("encoding"); + if (encoding) { + text = Wicket.Head.Contributor.decode(encoding, text); + } + + // aliases to improve performance + var steps = context.steps; + var log = Wicket.Log; + + var evaluateWithManualNotify = function (parameters, body) { + return function(notify) { var f = jQuery.noop; - text = "f = function(" + res[1] + ") {" + res[2] + "};"; + var toExecute = "f = function(" + parameters + ") {" + body + "};"; try { // do the evaluation - eval(text); + eval(toExecute); f(notify); } catch (exception) { - Wicket.Log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: " + exception + ", text: " + text); + log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: " + exception + ", text: " + text); } + }; + }; - } else { + var evaluate = function (script) { + return function(notify) { // just evaluate the javascript try { // do the evaluation - eval(text); + eval(script); } catch (exception) { - Wicket.Log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: " + exception + ", text: " + text); + log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: " + exception + ", text: " + text); } // continue to next step notify(); + }; + }; + + // 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 = cleanArray(text.split(scriptSplitterR)); + + 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)); + } }, // Adds a closure that processes a header contribution http://git-wip-us.apache.org/repos/asf/wicket/blob/43237280/wicket-core/src/test/js/ajax.js ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/js/ajax.js b/wicket-core/src/test/js/ajax.js index 2086d73..0117f1b 100644 --- a/wicket-core/src/test/js/ajax.js +++ b/wicket-core/src/test/js/ajax.js @@ -109,6 +109,29 @@ jQuery(document).ready(function() { execute(attrs); }); + /** + * Executes the second part of 'something|functionBody' by passing 'notify' function as parameter. + * There are two functions with passed 'notify' function which leads to splitting the text in + * <(priority-)evaluate> elements to eval one function at a time to be able to call notify manually. + */ + asyncTest('processEvaluation*s* with identifier|code.', function () { + + expect(7); + + var attrs = { + u: 'data/ajax/twoEvaluationsWithIdentifier.xml', + c: 'twoEvaluationsWithIdentifier', + counter: 0, + coh: [ + function(attrs) { + start(); + equal(attrs.counter, 3, "The counter is incremented in both evaluations with and without manual notifying"); + } + ] + }; + execute(attrs); + }); + asyncTest('processComponent, normal case.', function () { expect(2); http://git-wip-us.apache.org/repos/asf/wicket/blob/43237280/wicket-core/src/test/js/all.html ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/js/all.html b/wicket-core/src/test/js/all.html index a6f4d52..aa27ad1 100644 --- a/wicket-core/src/test/js/all.html +++ b/wicket-core/src/test/js/all.html @@ -46,6 +46,7 @@ <div id="evaluationId"></div> <div id="priorityEvaluationId"></div> <div id="evaluationIdentifierAndCodeId"></div> + <div id="twoEvaluationsWithIdentifier"></div> <div id="componentToReplace">old body</div> http://git-wip-us.apache.org/repos/asf/wicket/blob/43237280/wicket-core/src/test/js/data/ajax/twoEvaluationsWithIdentifier.xml ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/js/data/ajax/twoEvaluationsWithIdentifier.xml b/wicket-core/src/test/js/data/ajax/twoEvaluationsWithIdentifier.xml new file mode 100644 index 0000000..12706d9 --- /dev/null +++ b/wicket-core/src/test/js/data/ajax/twoEvaluationsWithIdentifier.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<ajax-response><evaluate>(function(){notify|context.attrs.counter++; ok(true, 'Evaluation1 with identifier must be executed!'); equal(typeof(notify), 'function', 'The passed identifier1 must be a function'); notify();})();(function(){context.attrs.counter++;ok(true, 'Evaluation2 without identifier must be executed!');})();(function(){notify|context.attrs.counter++;ok(true, 'Evaluation3 with identifier must be executed!'); equal(typeof(notify), 'function', 'The passed identifier3 must be a function'); notify();})();</evaluate></ajax-response> \ No newline at end of file
