Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(790)

Unified Diff: appengine/config_service/ui/bower_components/polymer/lib/utils/flattened-nodes-observer.html

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: appengine/config_service/ui/bower_components/polymer/lib/utils/flattened-nodes-observer.html
diff --git a/appengine/config_service/ui/bower_components/polymer/lib/utils/flattened-nodes-observer.html b/appengine/config_service/ui/bower_components/polymer/lib/utils/flattened-nodes-observer.html
new file mode 100644
index 0000000000000000000000000000000000000000..66ad7795f70e32b58e8d8edd02888dcc6a1d888a
--- /dev/null
+++ b/appengine/config_service/ui/bower_components/polymer/lib/utils/flattened-nodes-observer.html
@@ -0,0 +1,242 @@
+<!--
+@license
+Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<link rel="import" href="../utils/boot.html">
+<link rel="import" href="../utils/array-splice.html">
+<link rel="import" href="../utils/async.html">
+<script>
+(function() {
+ 'use strict';
+
+ function isSlot(node) {
+ return (node.localName === 'slot');
+ }
+
+ /**
+ * Class that listens for changes (additions or removals) to
+ * "flattened nodes" on a given `node`. The list of flattened nodes consists
+ * of a node's children and, for any children that are `<slot>` elements,
+ * the expanded flattened list of `assignedNodes`.
+ * For example, if the observed node has children `<a></a><slot></slot><b></b>`
+ * and the `<slot>` has one `<div>` assigned to it, then the flattened
+ * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
+ * `<slot>` elements assigned to it, these are flattened as well.
+ *
+ * The provided `callback` is called whenever any change to this list
+ * of flattened nodes occurs, where an addition or removal of a node is
+ * considered a change. The `callback` is called with one argument, an object
+ * containing an array of any `addedNodes` and `removedNodes`.
+ *
+ * Note: the callback is called asynchronous to any changes
+ * at a microtask checkpoint. This is because observation is performed using
+ * `MutationObserver` and the `<slot>` element's `slotchange` event which
+ * are asynchronous.
+ *
+ * @memberof Polymer
+ * @param {Node} target Node on which to listen for changes.
+ * @param {Function} callback Function called when there are additions
+ * or removals from the target's list of flattened nodes.
+ * @summary Class that listens for changes (additions or removals) to
+ * "flattened nodes" on a given `node`.
+ */
+ class FlattenedNodesObserver {
+
+ /**
+ * Returns the list of flattened nodes for the given `node`.
+ * This list consists of a node's children and, for any children
+ * that are `<slot>` elements, the expanded flattened list of `assignedNodes`.
+ * For example, if the observed node has children `<a></a><slot></slot><b></b>`
+ * and the `<slot>` has one `<div>` assigned to it, then the flattened
+ * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
+ * `<slot>` elements assigned to it, these are flattened as well.
+ *
+ * @param {Node} node The node for which to return the list of flattened nodes.
+ * @return {Array} The list of flattened nodes for the given `node`.
+ */
+ static getFlattenedNodes(node) {
+ if (isSlot(node)) {
+ return node.assignedNodes({flatten: true});
+ } else {
+ return Array.from(node.childNodes).map(node => {
+ if (isSlot(node)) {
+ return node.assignedNodes({flatten: true});
+ } else {
+ return [node];
+ }
+ }).reduce((a, b) => a.concat(b), []);
+ }
+ }
+
+ constructor(target, callback) {
+ /** @type {MutationObserver} */
+ this._shadyChildrenObserver = null;
+ /** @type {MutationObserver} */
+ this._nativeChildrenObserver = null;
+ this._connected = false;
+ this._target = target;
+ this.callback = callback;
+ this._effectiveNodes = [];
+ this._observer = null;
+ this._scheduled = false;
+ this._boundSchedule = () => {
+ this._schedule();
+ }
+ this.connect();
+ this._schedule();
+ }
+
+ /**
+ * Activates an observer. This method is automatically called when
+ * a `FlattenedNodesObserver` is created. It should only be called to
+ * re-activate an observer that has been deactivated via the `disconnect` method.
+ */
+ connect() {
+ if (isSlot(this._target)) {
+ this._listenSlots([this._target]);
+ } else {
+ this._listenSlots(this._target.children);
+ if (window.ShadyDOM) {
+ this._shadyChildrenObserver =
+ ShadyDOM.observeChildren(this._target, (mutations) => {
+ this._processMutations(mutations);
+ });
+ } else {
+ this._nativeChildrenObserver =
+ new MutationObserver((mutations) => {
+ this._processMutations(mutations);
+ });
+ this._nativeChildrenObserver.observe(this._target, {childList: true});
+ }
+ }
+ this._connected = true;
+ }
+
+ /**
+ * Deactivates the flattened nodes observer. After calling this method
+ * the observer callback will not be called when changes to flattened nodes
+ * occur. The `connect` method may be subsequently called to reactivate
+ * the observer.
+ */
+ disconnect() {
+ if (isSlot(this._target)) {
+ this._unlistenSlots([this._target]);
+ } else {
+ this._unlistenSlots(this._target.children);
+ if (window.ShadyDOM && this._shadyChildrenObserver) {
+ ShadyDOM.unobserveChildren(this._shadyChildrenObserver);
+ this._shadyChildrenObserver = null;
+ } else if (this._nativeChildrenObserver) {
+ this._nativeChildrenObserver.disconnect();
+ this._nativeChildrenObserver = null;
+ }
+ }
+ this._connected = false;
+ }
+
+ _schedule() {
+ if (!this._scheduled) {
+ this._scheduled = true;
+ Polymer.Async.microTask.run(() => this.flush());
+ }
+ }
+
+ _processMutations(mutations) {
+ this._processSlotMutations(mutations);
+ this.flush();
+ }
+
+ _processSlotMutations(mutations) {
+ if (mutations) {
+ for (let i=0; i < mutations.length; i++) {
+ let mutation = mutations[i];
+ if (mutation.addedNodes) {
+ this._listenSlots(mutation.addedNodes);
+ }
+ if (mutation.removedNodes) {
+ this._unlistenSlots(mutation.removedNodes);
+ }
+ }
+ }
+ }
+
+ /**
+ * Flushes the observer causing any pending changes to be immediately
+ * delivered the observer callback. By default these changes are delivered
+ * asynchronously at the next microtask checkpoint.
+ *
+ * @return {boolean} Returns true if any pending changes caused the observer
+ * callback to run.
+ */
+ flush() {
+ if (!this._connected) {
+ return;
+ }
+ if (window.ShadyDOM) {
+ ShadyDOM.flush();
+ }
+ if (this._nativeChildrenObserver) {
+ this._processSlotMutations(this._nativeChildrenObserver.takeRecords());
+ } else if (this.shadyChildrenObserver) {
+ this._processSlotMutations(this._shadyChildrenObserver.takeRecords());
+ }
+ this._scheduled = false;
+ let info = {
+ target: this._target,
+ addedNodes: [],
+ removedNodes: []
+ };
+ let newNodes = this.constructor.getFlattenedNodes(this._target);
+ let splices = Polymer.ArraySplice.calculateSplices(newNodes,
+ this._effectiveNodes);
+ // process removals
+ for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
+ for (let j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) {
+ info.removedNodes.push(n);
+ }
+ }
+ // process adds
+ for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
+ for (let j=s.index; j < s.index + s.addedCount; j++) {
+ info.addedNodes.push(newNodes[j]);
+ }
+ }
+ // update cache
+ this._effectiveNodes = newNodes;
+ let didFlush = false;
+ if (info.addedNodes.length || info.removedNodes.length) {
+ didFlush = true;
+ this.callback.call(this._target, info);
+ }
+ return didFlush;
+ }
+
+ _listenSlots(nodeList) {
+ for (let i=0; i < nodeList.length; i++) {
+ let n = nodeList[i];
+ if (isSlot(n)) {
+ n.addEventListener('slotchange', this._boundSchedule);
+ }
+ }
+ }
+
+ _unlistenSlots(nodeList) {
+ for (let i=0; i < nodeList.length; i++) {
+ let n = nodeList[i];
+ if (isSlot(n)) {
+ n.removeEventListener('slotchange', this._boundSchedule);
+ }
+ }
+ }
+
+ }
+
+ Polymer.FlattenedNodesObserver = FlattenedNodesObserver;
+
+})();
+</script>

Powered by Google App Engine
This is Rietveld 408576698