GUAC-1378: Use <meta> tags instead of a special <guac-patch> root element.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/f57a4f80 Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/f57a4f80 Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/f57a4f80 Branch: refs/heads/master Commit: f57a4f80db8ddd4c89514acdc990306337da0a6b Parents: 9c11363 Author: Michael Jumper <[email protected]> Authored: Thu Feb 18 17:13:47 2016 -0800 Committer: Michael Jumper <[email protected]> Committed: Thu Feb 18 17:13:47 2016 -0800 ---------------------------------------------------------------------- .../index/config/templateRequestDecorator.js | 243 ++++++++++++++++--- 1 file changed, 214 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/f57a4f80/guacamole/src/main/webapp/app/index/config/templateRequestDecorator.js ---------------------------------------------------------------------- diff --git a/guacamole/src/main/webapp/app/index/config/templateRequestDecorator.js b/guacamole/src/main/webapp/app/index/config/templateRequestDecorator.js index cb848c3..51e2361 100644 --- a/guacamole/src/main/webapp/app/index/config/templateRequestDecorator.js +++ b/guacamole/src/main/webapp/app/index/config/templateRequestDecorator.js @@ -32,18 +32,194 @@ angular.module('index').config(['$provide', function($provide) { var $q = $injector.get('$q'); /** - * Array of the root elements of all patches which should be applied to - * the HTML of retrieved templates. + * Array of the raw HTML of all patches which should be applied to the + * HTML of retrieved templates. * - * @type Element[] + * @type String[] */ var patches = [ - $('<guac-patch before="a"><p>HELLO BEFORE</p></guac-patch>')[0], - $('<guac-patch after="a"><p>HELLO AFTER</p></guac-patch>')[0], - $('<guac-patch replace="div.protocol"><div class="protocol">:-)</div></guac-patch>')[0] + '<meta name="before" content="a"><p>HELLO BEFORE</p>', + '<meta name="after" content="a"><p>HELLO AFTER</p>', + '<meta name="replace" content="div.protocol"><div class="protocol">:-)</div>' ]; /** + * Represents a single HTML patching operation which will be applied + * to the raw HTML of a template. The name of the patching operation + * MUST be one of the valid names defined within + * PatchOperation.Operations. + * + * @contructor + * @param {String} name + * The name of the patching operation that will be applied. Valid + * names are defined within PatchOperation.Operations. + * + * @param {String} selector + * The CSS selector which determines which elements within a + * template will be affected by the patch operation. + */ + var PatchOperation = function PatchOperation(name, selector) { + + /** + * Applies this patch operation to the template defined by the + * given root element, which must be a single element wrapped by + * JQuery. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template to which + * this patch operation should be applied. + * + * @param {Element[]} elements + * The elements which should be applied by the patch + * operation. For example, if the patch operation is inserting + * elements, these are the elements that will be inserted. + */ + this.apply = function apply(root, elements) { + PatchOperation.Operations[name](root, selector, elements); + }; + + }; + + /** + * Mapping of all valid patch operation names to their corresponding + * implementations. Each implementation accepts the same three + * parameters: the root element of the template being patched, the CSS + * selector determining which elements within the template are patched, + * and an array of elements which make up the body of the patch. + * + * @type Object.<String, Function> + */ + PatchOperation.Operations = { + + /** + * Inserts the given elements before the elements matched by the + * provided CSS selector. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'before' : function before(root, selector, elements) { + root.find(selector).before(elements); + }, + + /** + * Inserts the given elements after the elements matched by the + * provided CSS selector. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'after' : function after(root, selector, elements) { + root.find(selector).after(elements); + }, + + /** + * Replaces the elements matched by the provided CSS selector with + * the given elements. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'replace' : function replace(root, selector, elements) { + root.find(selector).replaceWith(elements); + }, + + /** + * Inserts the given elements within the elements matched by the + * provided CSS selector, before any existing children. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'before-children' : function beforeChildren(root, selector, elements) { + root.find(selector).prepend(elements); + }, + + /** + * Inserts the given elements within the elements matched by the + * provided CSS selector, after any existing children. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'after-children' : function afterChildren(root, selector, elements) { + root.find(selector).append(elements); + }, + + /** + * Inserts the given elements within the elements matched by the + * provided CSS selector, replacing any existing children. + * + * @param {Element[]} root + * The JQuery-wrapped root element of the template being + * patched. + * + * @param {String} selector + * The CSS selector which determines where this patch operation + * should be applied within the template defined by root. + * + * @param {Element[]} elements + * The contents of the patch which should be applied to the + * template defined by root at the locations selected by the + * given CSS selector. + */ + 'replace-children' : function replaceChildren(root, selector, elements) { + root.find(selector).empty().append(elements); + } + + }; + + /** * Invokes $templateRequest() with all arguments exactly as provided, * applying all HTML patches from any installed Guacamole extensions * to the HTML of the requested template. @@ -65,29 +241,38 @@ angular.module('index').config(['$provide', function($provide) { // Apply all defined patches angular.forEach(patches, function applyPatch(patch) { - // Ignore any patches which are malformed - if (patch.tagName !== 'GUAC-PATCH') - return; - - // Insert after any elements which match the "after" - // selector (if defined) - var after = patch.getAttribute('after'); - if (after) - root.find(after).after(patch.innerHTML); - - // Insert before any elements which match the "before" - // selector (if defined) - var before = patch.getAttribute('before'); - if (before) - root.find(before).before(patch.innerHTML); - - // Replace any elements which match the "replace" selector - // (if defined) - var replace = patch.getAttribute('replace'); - if (replace) - root.find(replace).html(patch.innerHTML); - - // Ignore all other attributes + var elements = $(patch); + + // Filter out and parse all applicable meta tags + var operations = []; + elements = elements.filter(function filterMetaTags(index, element) { + + // Leave non-meta tags untouched + if (element.tagName !== 'META') + return true; + + // Only meta tags having a valid "name" attribute need + // to be filtered + var name = element.getAttribute('name'); + if (!name || !(name in PatchOperation.Operations)) + return true; + + // The "content" attribute must be present for any + // valid "name" meta tag + var content = element.getAttribute('content'); + if (!content) + return true; + + // Filter out and parse meta tag + operations.push(new PatchOperation(name, content)); + return false; + + }); + + // Apply each operation implied by the meta tags + angular.forEach(operations, function applyOperation(operation) { + operation.apply(root, elements); + }); });
