| Index: chrome/browser/resources/md_history/app.crisper.js
|
| diff --git a/chrome/browser/resources/md_history/app.crisper.js b/chrome/browser/resources/md_history/app.crisper.js
|
| index 3e75862e14094e32974a703a7d4959977c019372..d0f753b089bacd0c235ac3ac8bc9a1b322fd6887 100644
|
| --- a/chrome/browser/resources/md_history/app.crisper.js
|
| +++ b/chrome/browser/resources/md_history/app.crisper.js
|
| @@ -2,24 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @fileoverview PromiseResolver is a helper class that allows creating a
|
| - * Promise that will be fulfilled (resolved or rejected) some time later.
|
| - *
|
| - * Example:
|
| - * var resolver = new PromiseResolver();
|
| - * resolver.promise.then(function(result) {
|
| - * console.log('resolved with', result);
|
| - * });
|
| - * ...
|
| - * ...
|
| - * resolver.resolve({hello: 'world'});
|
| - */
|
| -
|
| -/**
|
| - * @constructor @struct
|
| - * @template T
|
| - */
|
| +
|
| function PromiseResolver() {
|
| /** @private {function(T=): void} */
|
| this.resolve_;
|
| @@ -51,11 +34,6 @@ PromiseResolver.prototype = {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * The global object.
|
| - * @type {!Object}
|
| - * @const
|
| - */
|
| var global = this;
|
|
|
| /** @typedef {{eventName: string, uid: number}} */
|
| @@ -65,26 +43,12 @@ var WebUIListener;
|
| var cr = cr || function() {
|
| 'use strict';
|
|
|
| - /**
|
| - * Builds an object structure for the provided namespace path,
|
| - * ensuring that names that already exist are not overwritten. For
|
| - * example:
|
| - * "a.b.c" -> a = {};a.b={};a.b.c={};
|
| - * @param {string} name Name of the object that this file defines.
|
| - * @param {*=} opt_object The object to expose at the end of the path.
|
| - * @param {Object=} opt_objectToExportTo The object to add the path to;
|
| - * default is {@code global}.
|
| - * @return {!Object} The last object exported (i.e. exportPath('cr.ui')
|
| - * returns a reference to the ui property of window.cr).
|
| - * @private
|
| - */
|
| function exportPath(name, opt_object, opt_objectToExportTo) {
|
| var parts = name.split('.');
|
| var cur = opt_objectToExportTo || global;
|
|
|
| for (var part; parts.length && (part = parts.shift());) {
|
| if (!parts.length && opt_object !== undefined) {
|
| - // last part and we have an object; use it
|
| cur[part] = opt_object;
|
| } else if (part in cur) {
|
| cur = cur[part];
|
| @@ -95,13 +59,6 @@ var cr = cr || function() {
|
| return cur;
|
| }
|
|
|
| - /**
|
| - * Fires a property change event on the target.
|
| - * @param {EventTarget} target The target to dispatch the event on.
|
| - * @param {string} propertyName The name of the property that changed.
|
| - * @param {*} newValue The new value for the property.
|
| - * @param {*} oldValue The old value for the property.
|
| - */
|
| function dispatchPropertyChange(target, propertyName, newValue, oldValue) {
|
| var e = new Event(propertyName + 'Change');
|
| e.propertyName = propertyName;
|
| @@ -110,50 +67,18 @@ var cr = cr || function() {
|
| target.dispatchEvent(e);
|
| }
|
|
|
| - /**
|
| - * Converts a camelCase javascript property name to a hyphenated-lower-case
|
| - * attribute name.
|
| - * @param {string} jsName The javascript camelCase property name.
|
| - * @return {string} The equivalent hyphenated-lower-case attribute name.
|
| - */
|
| function getAttributeName(jsName) {
|
| return jsName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
| }
|
|
|
| - /**
|
| - * The kind of property to define in {@code defineProperty}.
|
| - * @enum {string}
|
| - * @const
|
| - */
|
| var PropertyKind = {
|
| - /**
|
| - * Plain old JS property where the backing data is stored as a "private"
|
| - * field on the object.
|
| - * Use for properties of any type. Type will not be checked.
|
| - */
|
| JS: 'js',
|
|
|
| - /**
|
| - * The property backing data is stored as an attribute on an element.
|
| - * Use only for properties of type {string}.
|
| - */
|
| ATTR: 'attr',
|
|
|
| - /**
|
| - * The property backing data is stored as an attribute on an element. If the
|
| - * element has the attribute then the value is true.
|
| - * Use only for properties of type {boolean}.
|
| - */
|
| BOOL_ATTR: 'boolAttr'
|
| };
|
|
|
| - /**
|
| - * Helper function for defineProperty that returns the getter to use for the
|
| - * property.
|
| - * @param {string} name The name of the property.
|
| - * @param {PropertyKind} kind The kind of the property.
|
| - * @return {function():*} The getter for the property.
|
| - */
|
| function getGetter(name, kind) {
|
| switch (kind) {
|
| case PropertyKind.JS:
|
| @@ -173,22 +98,9 @@ var cr = cr || function() {
|
| };
|
| }
|
|
|
| - // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
|
| - // the browser/unit tests to preprocess this file through grit.
|
| throw 'not reached';
|
| }
|
|
|
| - /**
|
| - * Helper function for defineProperty that returns the setter of the right
|
| - * kind.
|
| - * @param {string} name The name of the property we are defining the setter
|
| - * for.
|
| - * @param {PropertyKind} kind The kind of property we are getting the
|
| - * setter for.
|
| - * @param {function(*, *):void=} opt_setHook A function to run after the
|
| - * property is set, but before the propertyChange event is fired.
|
| - * @return {function(*):void} The function to use as a setter.
|
| - */
|
| function getSetter(name, kind, opt_setHook) {
|
| switch (kind) {
|
| case PropertyKind.JS:
|
| @@ -234,20 +146,9 @@ var cr = cr || function() {
|
| };
|
| }
|
|
|
| - // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
|
| - // the browser/unit tests to preprocess this file through grit.
|
| throw 'not reached';
|
| }
|
|
|
| - /**
|
| - * Defines a property on an object. When the setter changes the value a
|
| - * property change event with the type {@code name + 'Change'} is fired.
|
| - * @param {!Object} obj The object to define the property for.
|
| - * @param {string} name The name of the property.
|
| - * @param {PropertyKind=} opt_kind What kind of underlying storage to use.
|
| - * @param {function(*, *):void=} opt_setHook A function to run after the
|
| - * property is set, but before the propertyChange event is fired.
|
| - */
|
| function defineProperty(obj, name, opt_kind, opt_setHook) {
|
| if (typeof obj == 'function')
|
| obj = obj.prototype;
|
| @@ -261,40 +162,18 @@ var cr = cr || function() {
|
| obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));
|
| }
|
|
|
| - /**
|
| - * Counter for use with createUid
|
| - */
|
| var uidCounter = 1;
|
|
|
| - /**
|
| - * @return {number} A new unique ID.
|
| - */
|
| function createUid() {
|
| return uidCounter++;
|
| }
|
|
|
| - /**
|
| - * Returns a unique ID for the item. This mutates the item so it needs to be
|
| - * an object
|
| - * @param {!Object} item The item to get the unique ID for.
|
| - * @return {number} The unique ID for the item.
|
| - */
|
| function getUid(item) {
|
| if (item.hasOwnProperty('uid'))
|
| return item.uid;
|
| return item.uid = createUid();
|
| }
|
|
|
| - /**
|
| - * Dispatches a simple event on an event target.
|
| - * @param {!EventTarget} target The event target to dispatch the event on.
|
| - * @param {string} type The type of the event.
|
| - * @param {boolean=} opt_bubbles Whether the event bubbles or not.
|
| - * @param {boolean=} opt_cancelable Whether the default action of the event
|
| - * can be prevented. Default is true.
|
| - * @return {boolean} If any of the listeners called {@code preventDefault}
|
| - * during the dispatch this will return false.
|
| - */
|
| function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {
|
| var e = new Event(type, {
|
| bubbles: opt_bubbles,
|
| @@ -303,32 +182,10 @@ var cr = cr || function() {
|
| return target.dispatchEvent(e);
|
| }
|
|
|
| - /**
|
| - * Calls |fun| and adds all the fields of the returned object to the object
|
| - * named by |name|. For example, cr.define('cr.ui', function() {
|
| - * function List() {
|
| - * ...
|
| - * }
|
| - * function ListItem() {
|
| - * ...
|
| - * }
|
| - * return {
|
| - * List: List,
|
| - * ListItem: ListItem,
|
| - * };
|
| - * });
|
| - * defines the functions cr.ui.List and cr.ui.ListItem.
|
| - * @param {string} name The name of the object that we are adding fields to.
|
| - * @param {!Function} fun The function that will return an object containing
|
| - * the names and values of the new fields.
|
| - */
|
| function define(name, fun) {
|
| var obj = exportPath(name);
|
| var exports = fun();
|
| for (var propertyName in exports) {
|
| - // Maybe we should check the prototype chain here? The current usage
|
| - // pattern is always using an object literal so we only care about own
|
| - // properties.
|
| var propertyDescriptor = Object.getOwnPropertyDescriptor(exports,
|
| propertyName);
|
| if (propertyDescriptor)
|
| @@ -336,26 +193,12 @@ var cr = cr || function() {
|
| }
|
| }
|
|
|
| - /**
|
| - * Adds a {@code getInstance} static method that always return the same
|
| - * instance object.
|
| - * @param {!Function} ctor The constructor for the class to add the static
|
| - * method to.
|
| - */
|
| function addSingletonGetter(ctor) {
|
| ctor.getInstance = function() {
|
| return ctor.instance_ || (ctor.instance_ = new ctor());
|
| };
|
| }
|
|
|
| - /**
|
| - * Forwards public APIs to private implementations.
|
| - * @param {Function} ctor Constructor that have private implementations in its
|
| - * prototype.
|
| - * @param {Array<string>} methods List of public method names that have their
|
| - * underscored counterparts in constructor's prototype.
|
| - * @param {string=} opt_target Selector for target node.
|
| - */
|
| function makePublic(ctor, methods, opt_target) {
|
| methods.forEach(function(method) {
|
| ctor[method] = function() {
|
| @@ -366,28 +209,8 @@ var cr = cr || function() {
|
| });
|
| }
|
|
|
| - /**
|
| - * The mapping used by the sendWithPromise mechanism to tie the Promise
|
| - * returned to callers with the corresponding WebUI response. The mapping is
|
| - * from ID to the PromiseResolver helper; the ID is generated by
|
| - * sendWithPromise and is unique across all invocations of said method.
|
| - * @type {!Object<!PromiseResolver>}
|
| - */
|
| var chromeSendResolverMap = {};
|
|
|
| - /**
|
| - * The named method the WebUI handler calls directly in response to a
|
| - * chrome.send call that expects a response. The handler requires no knowledge
|
| - * of the specific name of this method, as the name is passed to the handler
|
| - * as the first argument in the arguments list of chrome.send. The handler
|
| - * must pass the ID, also sent via the chrome.send arguments list, as the
|
| - * first argument of the JS invocation; additionally, the handler may
|
| - * supply any number of other arguments that will be included in the response.
|
| - * @param {string} id The unique ID identifying the Promise this response is
|
| - * tied to.
|
| - * @param {boolean} isSuccess Whether the request was successful.
|
| - * @param {*} response The response as sent from C++.
|
| - */
|
| function webUIResponse(id, isSuccess, response) {
|
| var resolver = chromeSendResolverMap[id];
|
| delete chromeSendResolverMap[id];
|
| @@ -398,14 +221,6 @@ var cr = cr || function() {
|
| resolver.reject(response);
|
| }
|
|
|
| - /**
|
| - * A variation of chrome.send, suitable for messages that expect a single
|
| - * response from C++.
|
| - * @param {string} methodName The name of the WebUI handler API.
|
| - * @param {...*} var_args Varibale number of arguments to be forwarded to the
|
| - * C++ call.
|
| - * @return {!Promise}
|
| - */
|
| function sendWithPromise(methodName, var_args) {
|
| var args = Array.prototype.slice.call(arguments, 1);
|
| var promiseResolver = new PromiseResolver();
|
| @@ -415,28 +230,11 @@ var cr = cr || function() {
|
| return promiseResolver.promise;
|
| }
|
|
|
| - /**
|
| - * A map of maps associating event names with listeners. The 2nd level map
|
| - * associates a listener ID with the callback function, such that individual
|
| - * listeners can be removed from an event without affecting other listeners of
|
| - * the same event.
|
| - * @type {!Object<!Object<!Function>>}
|
| - */
|
| var webUIListenerMap = {};
|
|
|
| - /**
|
| - * The named method the WebUI handler calls directly when an event occurs.
|
| - * The WebUI handler must supply the name of the event as the first argument
|
| - * of the JS invocation; additionally, the handler may supply any number of
|
| - * other arguments that will be forwarded to the listener callbacks.
|
| - * @param {string} event The name of the event that has occurred.
|
| - * @param {...*} var_args Additional arguments passed from C++.
|
| - */
|
| function webUIListenerCallback(event, var_args) {
|
| var eventListenersMap = webUIListenerMap[event];
|
| if (!eventListenersMap) {
|
| - // C++ event sent for an event that has no listeners.
|
| - // TODO(dpapad): Should a warning be displayed here?
|
| return;
|
| }
|
|
|
| @@ -446,14 +244,6 @@ var cr = cr || function() {
|
| }
|
| }
|
|
|
| - /**
|
| - * Registers a listener for an event fired from WebUI handlers. Any number of
|
| - * listeners may register for a single event.
|
| - * @param {string} eventName The event to listen to.
|
| - * @param {!Function} callback The callback run when the event is fired.
|
| - * @return {!WebUIListener} An object to be used for removing a listener via
|
| - * cr.removeWebUIListener. Should be treated as read-only.
|
| - */
|
| function addWebUIListener(eventName, callback) {
|
| webUIListenerMap[eventName] = webUIListenerMap[eventName] || {};
|
| var uid = createUid();
|
| @@ -461,13 +251,6 @@ var cr = cr || function() {
|
| return {eventName: eventName, uid: uid};
|
| }
|
|
|
| - /**
|
| - * Removes a listener. Does nothing if the specified listener is not found.
|
| - * @param {!WebUIListener} listener The listener to be removed (as returned by
|
| - * addWebUIListener).
|
| - * @return {boolean} Whether the given listener was found and actually
|
| - * removed.
|
| - */
|
| function removeWebUIListener(listener) {
|
| var listenerExists = webUIListenerMap[listener.eventName] &&
|
| webUIListenerMap[listener.eventName][listener.uid];
|
| @@ -490,7 +273,6 @@ var cr = cr || function() {
|
| makePublic: makePublic,
|
| PropertyKind: PropertyKind,
|
|
|
| - // C++ <-> JS communication related methods.
|
| addWebUIListener: addWebUIListener,
|
| removeWebUIListener: removeWebUIListener,
|
| sendWithPromise: sendWithPromise,
|
| @@ -538,14 +320,6 @@ var cr = cr || function() {
|
|
|
| cr.define('cr.ui', function() {
|
|
|
| - /**
|
| - * Decorates elements as an instance of a class.
|
| - * @param {string|!Element} source The way to find the element(s) to decorate.
|
| - * If this is a string then {@code querySeletorAll} is used to find the
|
| - * elements to decorate.
|
| - * @param {!Function} constr The constructor to decorate with. The constr
|
| - * needs to have a {@code decorate} function.
|
| - */
|
| function decorate(source, constr) {
|
| var elements;
|
| if (typeof source == 'string')
|
| @@ -559,11 +333,7 @@ cr.define('cr.ui', function() {
|
| }
|
| }
|
|
|
| - /**
|
| - * Helper function for creating new element for define.
|
| - */
|
| function createElementHelper(tagName, opt_bag) {
|
| - // Allow passing in ownerDocument to create in a different document.
|
| var doc;
|
| if (opt_bag && opt_bag.ownerDocument)
|
| doc = opt_bag.ownerDocument;
|
| @@ -572,28 +342,6 @@ cr.define('cr.ui', function() {
|
| return doc.createElement(tagName);
|
| }
|
|
|
| - /**
|
| - * Creates the constructor for a UI element class.
|
| - *
|
| - * Usage:
|
| - * <pre>
|
| - * var List = cr.ui.define('list');
|
| - * List.prototype = {
|
| - * __proto__: HTMLUListElement.prototype,
|
| - * decorate: function() {
|
| - * ...
|
| - * },
|
| - * ...
|
| - * };
|
| - * </pre>
|
| - *
|
| - * @param {string|Function} tagNameOrFunction The tagName or
|
| - * function to use for newly created elements. If this is a function it
|
| - * needs to return a new element when called.
|
| - * @return {function(Object=):Element} The constructor function which takes
|
| - * an optional property bag. The function also has a static
|
| - * {@code decorate} method added to it.
|
| - */
|
| function define(tagNameOrFunction) {
|
| var createFunction, tagName;
|
| if (typeof tagNameOrFunction == 'function') {
|
| @@ -604,14 +352,6 @@ cr.define('cr.ui', function() {
|
| tagName = tagNameOrFunction;
|
| }
|
|
|
| - /**
|
| - * Creates a new UI element constructor.
|
| - * @param {Object=} opt_propertyBag Optional bag of properties to set on the
|
| - * object after created. The property {@code ownerDocument} is special
|
| - * cased and it allows you to create the element in a different
|
| - * document than the default.
|
| - * @constructor
|
| - */
|
| function f(opt_propertyBag) {
|
| var el = createFunction(tagName, opt_propertyBag);
|
| f.decorate(el);
|
| @@ -621,10 +361,6 @@ cr.define('cr.ui', function() {
|
| return el;
|
| }
|
|
|
| - /**
|
| - * Decorates an element as a UI element class.
|
| - * @param {!Element} el The element to decorate.
|
| - */
|
| f.decorate = function(el) {
|
| el.__proto__ = f.prototype;
|
| el.decorate();
|
| @@ -633,18 +369,7 @@ cr.define('cr.ui', function() {
|
| return f;
|
| }
|
|
|
| - /**
|
| - * Input elements do not grow and shrink with their content. This is a simple
|
| - * (and not very efficient) way of handling shrinking to content with support
|
| - * for min width and limited by the width of the parent element.
|
| - * @param {!HTMLElement} el The element to limit the width for.
|
| - * @param {!HTMLElement} parentEl The parent element that should limit the
|
| - * size.
|
| - * @param {number} min The minimum width.
|
| - * @param {number=} opt_scale Optional scale factor to apply to the width.
|
| - */
|
| function limitInputWidth(el, parentEl, min, opt_scale) {
|
| - // Needs a size larger than borders
|
| el.style.width = '10px';
|
| var doc = el.ownerDocument;
|
| var win = doc.defaultView;
|
| @@ -652,20 +377,16 @@ cr.define('cr.ui', function() {
|
| var parentComputedStyle = win.getComputedStyle(parentEl);
|
| var rtl = computedStyle.direction == 'rtl';
|
|
|
| - // To get the max width we get the width of the treeItem minus the position
|
| - // of the input.
|
| var inputRect = el.getBoundingClientRect(); // box-sizing
|
| var parentRect = parentEl.getBoundingClientRect();
|
| var startPos = rtl ? parentRect.right - inputRect.right :
|
| inputRect.left - parentRect.left;
|
|
|
| - // Add up border and padding of the input.
|
| var inner = parseInt(computedStyle.borderLeftWidth, 10) +
|
| parseInt(computedStyle.paddingLeft, 10) +
|
| parseInt(computedStyle.paddingRight, 10) +
|
| parseInt(computedStyle.borderRightWidth, 10);
|
|
|
| - // We also need to subtract the padding of parent to prevent it to overflow.
|
| var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) :
|
| parseInt(parentComputedStyle.paddingRight, 10);
|
|
|
| @@ -691,24 +412,12 @@ cr.define('cr.ui', function() {
|
| limit();
|
| }
|
|
|
| - /**
|
| - * Takes a number and spits out a value CSS will be happy with. To avoid
|
| - * subpixel layout issues, the value is rounded to the nearest integral value.
|
| - * @param {number} pixels The number of pixels.
|
| - * @return {string} e.g. '16px'.
|
| - */
|
| function toCssPx(pixels) {
|
| if (!window.isFinite(pixels))
|
| console.error('Pixel value is not a number: ' + pixels);
|
| return Math.round(pixels) + 'px';
|
| }
|
|
|
| - /**
|
| - * Users complain they occasionaly use doubleclicks instead of clicks
|
| - * (http://crbug.com/140364). To fix it we freeze click handling for
|
| - * the doubleclick time interval.
|
| - * @param {MouseEvent} e Initial click event.
|
| - */
|
| function swallowDoubleClick(e) {
|
| var doc = e.target.ownerDocument;
|
| var counter = Math.min(1, e.detail);
|
| @@ -719,17 +428,12 @@ cr.define('cr.ui', function() {
|
| function onclick(e) {
|
| if (e.detail > counter) {
|
| counter = e.detail;
|
| - // Swallow the click since it's a click inside the doubleclick timeout.
|
| swallow(e);
|
| } else {
|
| - // Stop tracking clicks and let regular handling.
|
| doc.removeEventListener('dblclick', swallow, true);
|
| doc.removeEventListener('click', onclick, true);
|
| }
|
| }
|
| - // The following 'click' event (if e.type == 'mouseup') mustn't be taken
|
| - // into account (it mustn't stop tracking clicks). Start event listening
|
| - // after zero timeout.
|
| setTimeout(function() {
|
| doc.addEventListener('click', onclick, true);
|
| doc.addEventListener('dblclick', swallow, true);
|
| @@ -748,27 +452,9 @@ cr.define('cr.ui', function() {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @fileoverview A command is an abstraction of an action a user can do in the
|
| - * UI.
|
| - *
|
| - * When the focus changes in the document for each command a canExecute event
|
| - * is dispatched on the active element. By listening to this event you can
|
| - * enable and disable the command by setting the event.canExecute property.
|
| - *
|
| - * When a command is executed a command event is dispatched on the active
|
| - * element. Note that you should stop the propagation after you have handled the
|
| - * command if there might be other command listeners higher up in the DOM tree.
|
| - */
|
|
|
| cr.define('cr.ui', function() {
|
|
|
| - /**
|
| - * This is used to identify keyboard shortcuts.
|
| - * @param {string} shortcut The text used to describe the keys for this
|
| - * keyboard shortcut.
|
| - * @constructor
|
| - */
|
| function KeyboardShortcut(shortcut) {
|
| var mods = {};
|
| var ident = '';
|
| @@ -793,14 +479,8 @@ cr.define('cr.ui', function() {
|
| }
|
|
|
| KeyboardShortcut.prototype = {
|
| - /**
|
| - * Whether the keyboard shortcut object matches a keyboard event.
|
| - * @param {!Event} e The keyboard event object.
|
| - * @return {boolean} Whether we found a match or not.
|
| - */
|
| matchesEvent: function(e) {
|
| if (e.key == this.ident_) {
|
| - // All keyboard modifiers needs to match.
|
| var mods = this.mods_;
|
| return ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].every(function(k) {
|
| return e[k] == !!mods[k];
|
| @@ -810,19 +490,11 @@ cr.define('cr.ui', function() {
|
| }
|
| };
|
|
|
| - /**
|
| - * Creates a new command element.
|
| - * @constructor
|
| - * @extends {HTMLElement}
|
| - */
|
| var Command = cr.ui.define('command');
|
|
|
| Command.prototype = {
|
| __proto__: HTMLElement.prototype,
|
|
|
| - /**
|
| - * Initializes the command.
|
| - */
|
| decorate: function() {
|
| CommandManager.init(assert(this.ownerDocument));
|
|
|
| @@ -830,12 +502,6 @@ cr.define('cr.ui', function() {
|
| this.shortcut = this.getAttribute('shortcut');
|
| },
|
|
|
| - /**
|
| - * Executes the command by dispatching a command event on the given element.
|
| - * If |element| isn't given, the active element is used instead.
|
| - * If the command is {@code disabled} this does nothing.
|
| - * @param {HTMLElement=} opt_element Optional element to dispatch event on.
|
| - */
|
| execute: function(opt_element) {
|
| if (this.disabled)
|
| return;
|
| @@ -848,32 +514,11 @@ cr.define('cr.ui', function() {
|
| }
|
| },
|
|
|
| - /**
|
| - * Call this when there have been changes that might change whether the
|
| - * command can be executed or not.
|
| - * @param {Node=} opt_node Node for which to actuate command state.
|
| - */
|
| canExecuteChange: function(opt_node) {
|
| dispatchCanExecuteEvent(this,
|
| opt_node || this.ownerDocument.activeElement);
|
| },
|
|
|
| - /**
|
| - * The keyboard shortcut that triggers the command. This is a string
|
| - * consisting of a key (as reported by WebKit in keydown) as
|
| - * well as optional key modifiers joinded with a '|'.
|
| - *
|
| - * Multiple keyboard shortcuts can be provided by separating them by
|
| - * whitespace.
|
| - *
|
| - * For example:
|
| - * "F1"
|
| - * "Backspace|Meta" for Apple command backspace.
|
| - * "a|Ctrl" for Control A
|
| - * "Delete Backspace|Meta" for Delete and Command Backspace
|
| - *
|
| - * @type {string}
|
| - */
|
| shortcut_: '',
|
| get shortcut() {
|
| return this.shortcut_;
|
| @@ -885,18 +530,12 @@ cr.define('cr.ui', function() {
|
| return new KeyboardShortcut(shortcut);
|
| });
|
|
|
| - // Set this after the keyboardShortcuts_ since that might throw.
|
| this.shortcut_ = shortcut;
|
| cr.dispatchPropertyChange(this, 'shortcut', this.shortcut_,
|
| oldShortcut);
|
| }
|
| },
|
|
|
| - /**
|
| - * Whether the event object matches the shortcut for this command.
|
| - * @param {!Event} e The key event object.
|
| - * @return {boolean} Whether it matched or not.
|
| - */
|
| matchesEvent: function(e) {
|
| if (!this.keyboardShortcuts_)
|
| return false;
|
| @@ -907,68 +546,29 @@ cr.define('cr.ui', function() {
|
| },
|
| };
|
|
|
| - /**
|
| - * The label of the command.
|
| - */
|
| cr.defineProperty(Command, 'label', cr.PropertyKind.ATTR);
|
|
|
| - /**
|
| - * Whether the command is disabled or not.
|
| - */
|
| cr.defineProperty(Command, 'disabled', cr.PropertyKind.BOOL_ATTR);
|
|
|
| - /**
|
| - * Whether the command is hidden or not.
|
| - */
|
| cr.defineProperty(Command, 'hidden', cr.PropertyKind.BOOL_ATTR);
|
|
|
| - /**
|
| - * Whether the command is checked or not.
|
| - */
|
| cr.defineProperty(Command, 'checked', cr.PropertyKind.BOOL_ATTR);
|
|
|
| - /**
|
| - * The flag that prevents the shortcut text from being displayed on menu.
|
| - *
|
| - * If false, the keyboard shortcut text (eg. "Ctrl+X" for the cut command)
|
| - * is displayed in menu when the command is assosiated with a menu item.
|
| - * Otherwise, no text is displayed.
|
| - */
|
| cr.defineProperty(Command, 'hideShortcutText', cr.PropertyKind.BOOL_ATTR);
|
|
|
| - /**
|
| - * Dispatches a canExecute event on the target.
|
| - * @param {!cr.ui.Command} command The command that we are testing for.
|
| - * @param {EventTarget} target The target element to dispatch the event on.
|
| - */
|
| function dispatchCanExecuteEvent(command, target) {
|
| var e = new CanExecuteEvent(command);
|
| target.dispatchEvent(e);
|
| command.disabled = !e.canExecute;
|
| }
|
|
|
| - /**
|
| - * The command managers for different documents.
|
| - */
|
| var commandManagers = {};
|
|
|
| - /**
|
| - * Keeps track of the focused element and updates the commands when the focus
|
| - * changes.
|
| - * @param {!Document} doc The document that we are managing the commands for.
|
| - * @constructor
|
| - */
|
| function CommandManager(doc) {
|
| doc.addEventListener('focus', this.handleFocus_.bind(this), true);
|
| - // Make sure we add the listener to the bubbling phase so that elements can
|
| - // prevent the command.
|
| doc.addEventListener('keydown', this.handleKeyDown_.bind(this), false);
|
| }
|
|
|
| - /**
|
| - * Initializes a command manager for the document as needed.
|
| - * @param {!Document} doc The document to manage the commands for.
|
| - */
|
| CommandManager.init = function(doc) {
|
| var uid = cr.getUid(doc);
|
| if (!(uid in commandManagers)) {
|
| @@ -978,17 +578,9 @@ cr.define('cr.ui', function() {
|
|
|
| CommandManager.prototype = {
|
|
|
| - /**
|
| - * Handles focus changes on the document.
|
| - * @param {Event} e The focus event object.
|
| - * @private
|
| - * @suppress {checkTypes}
|
| - * TODO(vitalyp): remove the suppression.
|
| - */
|
| handleFocus_: function(e) {
|
| var target = e.target;
|
|
|
| - // Ignore focus on a menu button or command item.
|
| if (target.menu || target.command)
|
| return;
|
|
|
| @@ -1000,10 +592,6 @@ cr.define('cr.ui', function() {
|
| });
|
| },
|
|
|
| - /**
|
| - * Handles the keydown event and routes it to the right command.
|
| - * @param {!Event} e The keydown event.
|
| - */
|
| handleKeyDown_: function(e) {
|
| var target = e.target;
|
| var commands = Array.prototype.slice.call(
|
| @@ -1011,14 +599,10 @@ cr.define('cr.ui', function() {
|
|
|
| for (var i = 0, command; command = commands[i]; i++) {
|
| if (command.matchesEvent(e)) {
|
| - // When invoking a command via a shortcut, we have to manually check
|
| - // if it can be executed, since focus might not have been changed
|
| - // what would have updated the command's state.
|
| command.canExecuteChange();
|
|
|
| if (!command.disabled) {
|
| e.preventDefault();
|
| - // We do not want any other element to handle this.
|
| e.stopPropagation();
|
| command.execute();
|
| return;
|
| @@ -1028,13 +612,6 @@ cr.define('cr.ui', function() {
|
| }
|
| };
|
|
|
| - /**
|
| - * The event type used for canExecute events.
|
| - * @param {!cr.ui.Command} command The command that we are evaluating.
|
| - * @extends {Event}
|
| - * @constructor
|
| - * @class
|
| - */
|
| function CanExecuteEvent(command) {
|
| var e = new Event('canExecute', {bubbles: true, cancelable: true});
|
| e.__proto__ = CanExecuteEvent.prototype;
|
| @@ -1045,18 +622,8 @@ cr.define('cr.ui', function() {
|
| CanExecuteEvent.prototype = {
|
| __proto__: Event.prototype,
|
|
|
| - /**
|
| - * The current command
|
| - * @type {cr.ui.Command}
|
| - */
|
| command: null,
|
|
|
| - /**
|
| - * Whether the target can execute the command. Setting this also stops the
|
| - * propagation and prevents the default. Callers can tell if an event has
|
| - * been handled via |this.defaultPrevented|.
|
| - * @type {boolean}
|
| - */
|
| canExecute_: false,
|
| get canExecute() {
|
| return this.canExecute_;
|
| @@ -1068,7 +635,6 @@ cr.define('cr.ui', function() {
|
| }
|
| };
|
|
|
| - // Export
|
| return {
|
| Command: Command,
|
| CanExecuteEvent: CanExecuteEvent
|
| @@ -1078,9 +644,6 @@ Polymer({
|
| is: 'app-drawer',
|
|
|
| properties: {
|
| - /**
|
| - * The opened state of the drawer.
|
| - */
|
| opened: {
|
| type: Boolean,
|
| value: false,
|
| @@ -1088,28 +651,17 @@ Polymer({
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * The drawer does not have a scrim and cannot be swiped close.
|
| - */
|
| persistent: {
|
| type: Boolean,
|
| value: false,
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * The alignment of the drawer on the screen ('left', 'right', 'start' or 'end').
|
| - * 'start' computes to left and 'end' to right in LTR layout and vice versa in RTL
|
| - * layout.
|
| - */
|
| align: {
|
| type: String,
|
| value: 'left'
|
| },
|
|
|
| - /**
|
| - * The computed, read-only position of the drawer on the screen ('left' or 'right').
|
| - */
|
| position: {
|
| type: String,
|
| readOnly: true,
|
| @@ -1117,18 +669,12 @@ Polymer({
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * Create an area at the edge of the screen to swipe open the drawer.
|
| - */
|
| swipeOpen: {
|
| type: Boolean,
|
| value: false,
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * Trap keyboard focus when the drawer is opened and not persistent.
|
| - */
|
| noFocusTrap: {
|
| type: Boolean,
|
| value: false
|
| @@ -1153,17 +699,12 @@ Polymer({
|
| _lastTabStop: null,
|
|
|
| ready: function() {
|
| - // Set the scroll direction so you can vertically scroll inside the drawer.
|
| this.setScrollDirection('y');
|
|
|
| - // Only transition the drawer after its first render (e.g. app-drawer-layout
|
| - // may need to set the initial opened state which should not be transitioned).
|
| this._setTransitionDuration('0s');
|
| },
|
|
|
| attached: function() {
|
| - // Only transition the drawer after its first render (e.g. app-drawer-layout
|
| - // may need to set the initial opened state which should not be transitioned).
|
| Polymer.RenderStatus.afterNextRender(this, function() {
|
| this._setTransitionDuration('');
|
| this._boundEscKeydownHandler = this._escKeydownHandler.bind(this);
|
| @@ -1179,43 +720,22 @@ Polymer({
|
| document.removeEventListener('keydown', this._boundEscKeydownHandler);
|
| },
|
|
|
| - /**
|
| - * Opens the drawer.
|
| - */
|
| open: function() {
|
| this.opened = true;
|
| },
|
|
|
| - /**
|
| - * Closes the drawer.
|
| - */
|
| close: function() {
|
| this.opened = false;
|
| },
|
|
|
| - /**
|
| - * Toggles the drawer open and close.
|
| - */
|
| toggle: function() {
|
| this.opened = !this.opened;
|
| },
|
|
|
| - /**
|
| - * Gets the width of the drawer.
|
| - *
|
| - * @return {number} The width of the drawer in pixels.
|
| - */
|
| getWidth: function() {
|
| return this.$.contentContainer.offsetWidth;
|
| },
|
|
|
| - /**
|
| - * Resets the layout. If you changed the size of app-header via CSS
|
| - * you can notify the changes by either firing the `iron-resize` event
|
| - * or calling `resetLayout` directly.
|
| - *
|
| - * @method resetLayout
|
| - */
|
| resetLayout: function() {
|
| this.debounce('_resetLayout', function() {
|
| this.fire('app-drawer-reset-layout');
|
| @@ -1241,7 +761,6 @@ Polymer({
|
| _escKeydownHandler: function(event) {
|
| var ESC_KEYCODE = 27;
|
| if (event.keyCode === ESC_KEYCODE) {
|
| - // Prevent any side effects if app-drawer closes.
|
| event.preventDefault();
|
| this.close();
|
| }
|
| @@ -1252,7 +771,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // Disable user selection on desktop.
|
| event.preventDefault();
|
|
|
| switch (event.detail.state) {
|
| @@ -1271,7 +789,6 @@ Polymer({
|
| _trackStart: function(event) {
|
| this._drawerState = this._DRAWER_STATE.TRACKING;
|
|
|
| - // Disable transitions since style attributes will reflect user track events.
|
| this._setTransitionDuration('0s');
|
| this.style.visibility = 'visible';
|
|
|
| @@ -1288,8 +805,6 @@ Polymer({
|
| _trackMove: function(event) {
|
| this._translateDrawer(event.detail.dx + this._translateOffset);
|
|
|
| - // Use Date.now() since event.timeStamp is inconsistent across browsers (e.g. most
|
| - // browsers use milliseconds but FF 44 uses microseconds).
|
| this._trackDetails.push({
|
| dx: event.detail.dx,
|
| timeStamp: Date.now()
|
| @@ -1304,7 +819,6 @@ Polymer({
|
| (x <= 0 || x >= drawerWidth);
|
|
|
| if (!isInEndState) {
|
| - // No longer need the track events after this method returns - allow them to be GC'd.
|
| var trackDetails = this._trackDetails;
|
| this._trackDetails = null;
|
|
|
| @@ -1314,8 +828,6 @@ Polymer({
|
| }
|
| }
|
|
|
| - // If the drawer is not flinging, toggle the opened state based on the position of
|
| - // the drawer.
|
| var halfWidth = drawerWidth / 2;
|
| if (event.detail.dx < -halfWidth) {
|
| this.opened = this.position === 'right';
|
| @@ -1323,7 +835,6 @@ Polymer({
|
| this.opened = this.position === 'left';
|
| }
|
|
|
| - // Trigger app-drawer-transitioned now since there will be no transitionend event.
|
| if (isInEndState) {
|
| this._resetDrawerState();
|
| }
|
| @@ -1334,7 +845,6 @@ Polymer({
|
| },
|
|
|
| _calculateVelocity: function(event, trackDetails) {
|
| - // Find the oldest track event that is within 100ms using binary search.
|
| var now = Date.now();
|
| var timeLowerBound = now - 100;
|
| var trackDetail;
|
| @@ -1342,7 +852,6 @@ Polymer({
|
| var max = trackDetails.length - 1;
|
|
|
| while (min <= max) {
|
| - // Floor of average of min and max.
|
| var mid = (min + max) >> 1;
|
| var d = trackDetails[mid];
|
| if (d.timeStamp >= timeLowerBound) {
|
| @@ -1364,7 +873,6 @@ Polymer({
|
| _flingDrawer: function(event, trackDetails) {
|
| var velocity = this._calculateVelocity(event, trackDetails);
|
|
|
| - // Do not fling if velocity is not above a threshold.
|
| if (Math.abs(velocity) < this._MIN_FLING_THRESHOLD) {
|
| return;
|
| }
|
| @@ -1386,7 +894,6 @@ Polymer({
|
| dx = -x;
|
| }
|
|
|
| - // Enforce a minimum transition velocity to make the drawer feel snappy.
|
| if (isVelocityPositive) {
|
| velocity = Math.max(velocity, this._MIN_TRANSITION_VELOCITY);
|
| this.opened = this.position === 'left';
|
| @@ -1395,8 +902,6 @@ Polymer({
|
| this.opened = this.position === 'right';
|
| }
|
|
|
| - // Calculate the amount of time needed to finish the transition based on the
|
| - // initial slope of the timing function.
|
| this._setTransitionDuration((this._FLING_INITIAL_SLOPE * dx / velocity) + 'ms');
|
| this._setTransitionTimingFunction(this._FLING_TIMING_FUNCTION);
|
|
|
| @@ -1404,13 +909,9 @@ Polymer({
|
| },
|
|
|
| _transitionend: function(event) {
|
| - // contentContainer will transition on opened state changed, and scrim will
|
| - // transition on persistent state changed when opened - these are the
|
| - // transitions we are interested in.
|
| var target = Polymer.dom(event).rootTarget;
|
| if (target === this.$.contentContainer || target === this.$.scrim) {
|
|
|
| - // If the drawer was flinging, we need to reset the style attributes.
|
| if (this._drawerState === this._DRAWER_STATE.FLINGING) {
|
| this._setTransitionDuration('');
|
| this._setTransitionTimingFunction('');
|
| @@ -1469,7 +970,6 @@ Polymer({
|
| document.body.style.overflow = '';
|
| }
|
|
|
| - // Don't fire the event on initial load.
|
| if (oldState !== this._DRAWER_STATE.INIT) {
|
| this.fire('app-drawer-transitioned');
|
| }
|
| @@ -1481,8 +981,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // NOTE: Unless we use /deep/ (which we shouldn't since it's deprecated), this will
|
| - // not select focusable elements inside shadow roots.
|
| var focusableElementsSelector = [
|
| 'a[href]:not([tabindex="-1"])',
|
| 'area[href]:not([tabindex="-1"])',
|
| @@ -1500,14 +998,10 @@ Polymer({
|
| this._firstTabStop = focusableElements[0];
|
| this._lastTabStop = focusableElements[focusableElements.length - 1];
|
| } else {
|
| - // Reset saved tab stops when there are no focusable elements in the drawer.
|
| this._firstTabStop = null;
|
| this._lastTabStop = null;
|
| }
|
|
|
| - // Focus on app-drawer if it has non-zero tabindex. Otherwise, focus the first focusable
|
| - // element in the drawer, if it exists. Use the tabindex attribute since the this.tabIndex
|
| - // property in IE/Edge returns 0 (instead of -1) when the attribute is not set.
|
| var tabindex = this.getAttribute('tabindex');
|
| if (tabindex && parseInt(tabindex, 10) > -1) {
|
| this.focus();
|
| @@ -1554,17 +1048,7 @@ Polymer({
|
| FLINGING: 5
|
| }
|
|
|
| - /**
|
| - * Fired when the layout of app-drawer has changed.
|
| - *
|
| - * @event app-drawer-reset-layout
|
| - */
|
|
|
| - /**
|
| - * Fired when app-drawer has finished transitioning.
|
| - *
|
| - * @event app-drawer-transitioned
|
| - */
|
| });
|
| (function() {
|
| 'use strict';
|
| @@ -1572,9 +1056,6 @@ Polymer({
|
| Polymer({
|
| is: 'iron-location',
|
| properties: {
|
| - /**
|
| - * The pathname component of the URL.
|
| - */
|
| path: {
|
| type: String,
|
| notify: true,
|
| @@ -1582,9 +1063,6 @@ Polymer({
|
| return window.decodeURIComponent(window.location.pathname);
|
| }
|
| },
|
| - /**
|
| - * The query string portion of the URL.
|
| - */
|
| query: {
|
| type: String,
|
| notify: true,
|
| @@ -1592,9 +1070,6 @@ Polymer({
|
| return window.decodeURIComponent(window.location.search.slice(1));
|
| }
|
| },
|
| - /**
|
| - * The hash component of the URL.
|
| - */
|
| hash: {
|
| type: String,
|
| notify: true,
|
| @@ -1602,42 +1077,16 @@ Polymer({
|
| return window.decodeURIComponent(window.location.hash.slice(1));
|
| }
|
| },
|
| - /**
|
| - * If the user was on a URL for less than `dwellTime` milliseconds, it
|
| - * won't be added to the browser's history, but instead will be replaced
|
| - * by the next entry.
|
| - *
|
| - * This is to prevent large numbers of entries from clogging up the user's
|
| - * browser history. Disable by setting to a negative number.
|
| - */
|
| dwellTime: {
|
| type: Number,
|
| value: 2000
|
| },
|
|
|
| - /**
|
| - * A regexp that defines the set of URLs that should be considered part
|
| - * of this web app.
|
| - *
|
| - * Clicking on a link that matches this regex won't result in a full page
|
| - * navigation, but will instead just update the URL state in place.
|
| - *
|
| - * This regexp is given everything after the origin in an absolute
|
| - * URL. So to match just URLs that start with /search/ do:
|
| - * url-space-regex="^/search/"
|
| - *
|
| - * @type {string|RegExp}
|
| - */
|
| urlSpaceRegex: {
|
| type: String,
|
| value: ''
|
| },
|
|
|
| - /**
|
| - * urlSpaceRegex, but coerced into a regexp.
|
| - *
|
| - * @type {RegExp}
|
| - */
|
| _urlSpaceRegExp: {
|
| computed: '_makeRegExp(urlSpaceRegex)'
|
| },
|
| @@ -1662,8 +1111,6 @@ Polymer({
|
| this.listen(window, 'location-changed', '_urlChanged');
|
| this.listen(window, 'popstate', '_urlChanged');
|
| this.listen(/** @type {!HTMLBodyElement} */(document.body), 'click', '_globalOnClick');
|
| - // Give a 200ms grace period to make initial redirects without any
|
| - // additions to the user's history.
|
| this._lastChangedAt = window.performance.now() - (this.dwellTime - 200);
|
|
|
| this._initialized = true;
|
| @@ -1680,11 +1127,6 @@ Polymer({
|
| this.hash = window.decodeURIComponent(window.location.hash.substring(1));
|
| },
|
| _urlChanged: function() {
|
| - // We want to extract all info out of the updated URL before we
|
| - // try to write anything back into it.
|
| - //
|
| - // i.e. without _dontUpdateUrl we'd overwrite the new path with the old
|
| - // one when we set this.hash. Likewise for query.
|
| this._dontUpdateUrl = true;
|
| this._hashChanged();
|
| this.path = window.decodeURIComponent(window.location.pathname);
|
| @@ -1717,11 +1159,9 @@ Polymer({
|
| window.location.search.substring(1)) &&
|
| this.hash === window.decodeURIComponent(
|
| window.location.hash.substring(1))) {
|
| - // Nothing to do, the current URL is a representation of our properties.
|
| return;
|
| }
|
| var newUrl = this._getUrl();
|
| - // Need to use a full URL in case the containing page has a base URI.
|
| var fullNewUrl = new URL(
|
| newUrl, window.location.protocol + '//' + window.location.host).href;
|
| var now = window.performance.now();
|
| @@ -1735,16 +1175,7 @@ Polymer({
|
| }
|
| this.fire('location-changed', {}, {node: window});
|
| },
|
| - /**
|
| - * A necessary evil so that links work as expected. Does its best to
|
| - * bail out early if possible.
|
| - *
|
| - * @param {MouseEvent} event .
|
| - */
|
| _globalOnClick: function(event) {
|
| - // If another event handler has stopped this event then there's nothing
|
| - // for us to do. This can happen e.g. when there are multiple
|
| - // iron-location elements in a page.
|
| if (event.defaultPrevented) {
|
| return;
|
| }
|
| @@ -1753,29 +1184,16 @@ Polymer({
|
| return;
|
| }
|
| event.preventDefault();
|
| - // If the navigation is to the current page we shouldn't add a history
|
| - // entry or fire a change event.
|
| if (href === window.location.href) {
|
| return;
|
| }
|
| window.history.pushState({}, '', href);
|
| this.fire('location-changed', {}, {node: window});
|
| },
|
| - /**
|
| - * Returns the absolute URL of the link (if any) that this click event
|
| - * is clicking on, if we can and should override the resulting full
|
| - * page navigation. Returns null otherwise.
|
| - *
|
| - * @param {MouseEvent} event .
|
| - * @return {string?} .
|
| - */
|
| _getSameOriginLinkHref: function(event) {
|
| - // We only care about left-clicks.
|
| if (event.button !== 0) {
|
| return null;
|
| }
|
| - // We don't want modified clicks, where the intent is to open the page
|
| - // in a new tab.
|
| if (event.metaKey || event.ctrlKey) {
|
| return null;
|
| }
|
| @@ -1789,16 +1207,13 @@ Polymer({
|
| }
|
| }
|
|
|
| - // If there's no link there's nothing to do.
|
| if (!anchor) {
|
| return null;
|
| }
|
|
|
| - // Target blank is a new tab, don't intercept.
|
| if (anchor.target === '_blank') {
|
| return null;
|
| }
|
| - // If the link is for an existing parent frame, don't intercept.
|
| if ((anchor.target === '_top' ||
|
| anchor.target === '_parent') &&
|
| window.top !== window) {
|
| @@ -1807,8 +1222,6 @@ Polymer({
|
|
|
| var href = anchor.href;
|
|
|
| - // It only makes sense for us to intercept same-origin navigations.
|
| - // pushState/replaceState don't work with cross-origin links.
|
| var url;
|
| if (document.baseURI != null) {
|
| url = new URL(href, /** @type {string} */(document.baseURI));
|
| @@ -1818,7 +1231,6 @@ Polymer({
|
|
|
| var origin;
|
|
|
| - // IE Polyfill
|
| if (window.location.origin) {
|
| origin = window.location.origin;
|
| } else {
|
| @@ -1834,12 +1246,10 @@ Polymer({
|
| }
|
| var normalizedHref = url.pathname + url.search + url.hash;
|
|
|
| - // If we've been configured not to handle this url... don't handle it!
|
| if (this._urlSpaceRegExp &&
|
| !this._urlSpaceRegExp.test(normalizedHref)) {
|
| return null;
|
| }
|
| - // Need to use a full URL in case the containing page has a base URI.
|
| var fullNormalizedHref = new URL(
|
| normalizedHref, window.location.href).href;
|
| return fullNormalizedHref;
|
| @@ -1907,8 +1317,6 @@ Polymer({
|
| _decodeParams: function(paramString) {
|
| var params = {};
|
|
|
| - // Work around a bug in decodeURIComponent where + is not
|
| - // converted to spaces:
|
| paramString = (paramString || '').replace(/\+/g, '%20');
|
|
|
| var paramList = paramString.split('&');
|
| @@ -1924,46 +1332,18 @@ Polymer({
|
| });
|
| 'use strict';
|
|
|
| - /**
|
| - * Provides bidirectional mapping between `path` and `queryParams` and a
|
| - * app-route compatible `route` object.
|
| - *
|
| - * For more information, see the docs for `app-route-converter`.
|
| - *
|
| - * @polymerBehavior
|
| - */
|
| Polymer.AppRouteConverterBehavior = {
|
| properties: {
|
| - /**
|
| - * A model representing the deserialized path through the route tree, as
|
| - * well as the current queryParams.
|
| - *
|
| - * A route object is the kernel of the routing system. It is intended to
|
| - * be fed into consuming elements such as `app-route`.
|
| - *
|
| - * @type {?Object}
|
| - */
|
| route: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * A set of key/value pairs that are universally accessible to branches of
|
| - * the route tree.
|
| - *
|
| - * @type {?Object}
|
| - */
|
| queryParams: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The serialized path through the route tree. This corresponds to the
|
| - * `window.location.pathname` value, and will update to reflect changes
|
| - * to that value.
|
| - */
|
| path: {
|
| type: String,
|
| notify: true,
|
| @@ -1981,9 +1361,6 @@ Polymer({
|
| this.linkPaths('queryParams', 'route.__queryParams');
|
| },
|
|
|
| - /**
|
| - * Handler called when the path or queryParams change.
|
| - */
|
| _locationChanged: function() {
|
| if (this.route &&
|
| this.route.path === this.path &&
|
| @@ -1997,9 +1374,6 @@ Polymer({
|
| };
|
| },
|
|
|
| - /**
|
| - * Handler called when the route prefix and route path change.
|
| - */
|
| _routeChanged: function() {
|
| if (!this.route) {
|
| return;
|
| @@ -2008,12 +1382,6 @@ Polymer({
|
| this.path = this.route.prefix + this.route.path;
|
| },
|
|
|
| - /**
|
| - * Handler called when the route queryParams change.
|
| - *
|
| - * @param {Object} queryParams A set of key/value pairs that are
|
| - * universally accessible to branches of the route tree.
|
| - */
|
| _routeQueryParamsChanged: function(queryParams) {
|
| if (!this.route) {
|
| return;
|
| @@ -2027,82 +1395,37 @@ Polymer({
|
| is: 'app-location',
|
|
|
| properties: {
|
| - /**
|
| - * A model representing the deserialized path through the route tree, as
|
| - * well as the current queryParams.
|
| - */
|
| route: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * In many scenarios, it is convenient to treat the `hash` as a stand-in
|
| - * alternative to the `path`. For example, if deploying an app to a static
|
| - * web server (e.g., Github Pages) - where one does not have control over
|
| - * server-side routing - it is usually a better experience to use the hash
|
| - * to represent paths through one's app.
|
| - *
|
| - * When this property is set to true, the `hash` will be used in place of
|
| -
|
| - * the `path` for generating a `route`.
|
| - */
|
| useHashAsPath: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * A regexp that defines the set of URLs that should be considered part
|
| - * of this web app.
|
| - *
|
| - * Clicking on a link that matches this regex won't result in a full page
|
| - * navigation, but will instead just update the URL state in place.
|
| - *
|
| - * This regexp is given everything after the origin in an absolute
|
| - * URL. So to match just URLs that start with /search/ do:
|
| - * url-space-regex="^/search/"
|
| - *
|
| - * @type {string|RegExp}
|
| - */
|
| urlSpaceRegex: {
|
| type: String,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * A set of key/value pairs that are universally accessible to branches
|
| - * of the route tree.
|
| - */
|
| __queryParams: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * The pathname component of the current URL.
|
| - */
|
| __path: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The query string portion of the current URL.
|
| - */
|
| __query: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The hash portion of the current URL.
|
| - */
|
| __hash: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The route path, which will be either the hash or the path, depending
|
| - * on useHashAsPath.
|
| - */
|
| path: {
|
| type: String,
|
| observer: '__onPathChanged'
|
| @@ -2137,39 +1460,21 @@ Polymer({
|
| is: 'app-route',
|
|
|
| properties: {
|
| - /**
|
| - * The URL component managed by this element.
|
| - */
|
| route: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The pattern of slash-separated segments to match `path` against.
|
| - *
|
| - * For example the pattern "/foo" will match "/foo" or "/foo/bar"
|
| - * but not "/foobar".
|
| - *
|
| - * Path segments like `/:named` are mapped to properties on the `data` object.
|
| - */
|
| pattern: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The parameterized values that are extracted from the route as
|
| - * described by `pattern`.
|
| - */
|
| data: {
|
| type: Object,
|
| value: function() {return {};},
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * @type {?Object}
|
| - */
|
| queryParams: {
|
| type: Object,
|
| value: function() {
|
| @@ -2178,9 +1483,6 @@ Polymer({
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The part of `path` NOT consumed by `pattern`.
|
| - */
|
| tail: {
|
| type: Object,
|
| value: function() {return {path: null, prefix: null, __queryParams: null};},
|
| @@ -2197,9 +1499,6 @@ Polymer({
|
| type: Boolean,
|
| value: false
|
| },
|
| - /**
|
| - * @type {?string}
|
| - */
|
| _matched: {
|
| type: String,
|
| value: ''
|
| @@ -2220,10 +1519,6 @@ Polymer({
|
| this.linkPaths('tail.__queryParams', 'route.__queryParams');
|
| },
|
|
|
| - /**
|
| - * Deal with the query params object being assigned to wholesale.
|
| - * @export
|
| - */
|
| __routeQueryParamsChanged: function(queryParams) {
|
| if (queryParams && this.tail) {
|
| this.set('tail.__queryParams', queryParams);
|
| @@ -2232,8 +1527,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // Copy queryParams and track whether there are any differences compared
|
| - // to the existing query params.
|
| var copyOfQueryParams = {};
|
| var anythingChanged = false;
|
| for (var key in queryParams) {
|
| @@ -2244,7 +1537,6 @@ Polymer({
|
| anythingChanged = true;
|
| }
|
| }
|
| - // Need to check whether any keys were deleted
|
| for (var key in this.queryParams) {
|
| if (anythingChanged || !(key in queryParams)) {
|
| anythingChanged = true;
|
| @@ -2261,18 +1553,12 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * @export
|
| - */
|
| __tailQueryParamsChanged: function(queryParams) {
|
| if (queryParams && this.route) {
|
| this.set('route.__queryParams', queryParams);
|
| }
|
| },
|
|
|
| - /**
|
| - * @export
|
| - */
|
| __queryParamsChanged: function(changes) {
|
| if (!this.active || this._queryParamsUpdating) {
|
| return;
|
| @@ -2284,13 +1570,8 @@ Polymer({
|
| __resetProperties: function() {
|
| this._setActive(false);
|
| this._matched = null;
|
| - //this.tail = { path: null, prefix: null, queryParams: null };
|
| - //this.data = {};
|
| },
|
|
|
| - /**
|
| - * @export
|
| - */
|
| __tryToMatch: function() {
|
| if (!this.route) {
|
| return;
|
| @@ -2319,7 +1600,6 @@ Polymer({
|
| }
|
| var pathPiece = remainingPieces.shift();
|
|
|
| - // We don't match this path.
|
| if (!pathPiece && pathPiece !== '') {
|
| this.__resetProperties();
|
| return;
|
| @@ -2336,15 +1616,12 @@ Polymer({
|
|
|
| this._matched = matched.join('/');
|
|
|
| - // Properties that must be updated atomically.
|
| var propertyUpdates = {};
|
|
|
| - //this.active
|
| if (!this.active) {
|
| propertyUpdates.active = true;
|
| }
|
|
|
| - // this.tail
|
| var tailPrefix = this.route.prefix + this._matched;
|
| var tailPath = remainingPieces.join('/');
|
| if (remainingPieces.length > 0) {
|
| @@ -2360,7 +1637,6 @@ Polymer({
|
| };
|
| }
|
|
|
| - // this.data
|
| propertyUpdates.data = namedMatches;
|
| this._dataInUrl = {};
|
| for (var key in namedMatches) {
|
| @@ -2370,9 +1646,6 @@ Polymer({
|
| this.__setMulti(propertyUpdates);
|
| },
|
|
|
| - /**
|
| - * @export
|
| - */
|
| __tailPathChanged: function() {
|
| if (!this.active) {
|
| return;
|
| @@ -2388,9 +1661,6 @@ Polymer({
|
| this.set('route.path', newPath);
|
| },
|
|
|
| - /**
|
| - * @export
|
| - */
|
| __updatePathOnDataChange: function() {
|
| if (!this.route || !this.active) {
|
| return;
|
| @@ -2429,17 +1699,6 @@ Polymer({
|
| },
|
|
|
| __setMulti: function(setObj) {
|
| - // HACK(rictic): skirting around 1.0's lack of a setMulti by poking at
|
| - // internal data structures. I would not advise that you copy this
|
| - // example.
|
| - //
|
| - // In the future this will be a feature of Polymer itself.
|
| - // See: https://github.com/Polymer/polymer/issues/3640
|
| - //
|
| - // Hacking around with private methods like this is juggling footguns,
|
| - // and is likely to have unexpected and unsupported rough edges.
|
| - //
|
| - // Be ye so warned.
|
| for (var property in setObj) {
|
| this._propertySetter(property, setObj[property]);
|
| }
|
| @@ -2456,9 +1715,6 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The Boolean return value of the media query.
|
| - */
|
| queryMatches: {
|
| type: Boolean,
|
| value: false,
|
| @@ -2466,35 +1722,22 @@ Polymer({
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The CSS media query to evaluate.
|
| - */
|
| query: {
|
| type: String,
|
| observer: 'queryChanged'
|
| },
|
|
|
| - /**
|
| - * If true, the query attribute is assumed to be a complete media query
|
| - * string rather than a single media feature.
|
| - */
|
| full: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * @type {function(MediaQueryList)}
|
| - */
|
| _boundMQHandler: {
|
| value: function() {
|
| return this.queryHandler.bind(this);
|
| }
|
| },
|
|
|
| - /**
|
| - * @type {MediaQueryList}
|
| - */
|
| _mq: {
|
| value: null
|
| }
|
| @@ -2541,38 +1784,13 @@ Polymer({
|
| }
|
|
|
| });
|
| -/**
|
| - * `IronResizableBehavior` is a behavior that can be used in Polymer elements to
|
| - * coordinate the flow of resize events between "resizers" (elements that control the
|
| - * size or hidden state of their children) and "resizables" (elements that need to be
|
| - * notified when they are resized or un-hidden by their parents in order to take
|
| - * action on their new measurements).
|
| - *
|
| - * Elements that perform measurement should add the `IronResizableBehavior` behavior to
|
| - * their element definition and listen for the `iron-resize` event on themselves.
|
| - * This event will be fired when they become showing after having been hidden,
|
| - * when they are resized explicitly by another resizable, or when the window has been
|
| - * resized.
|
| - *
|
| - * Note, the `iron-resize` event is non-bubbling.
|
| - *
|
| - * @polymerBehavior Polymer.IronResizableBehavior
|
| - * @demo demo/index.html
|
| - **/
|
| Polymer.IronResizableBehavior = {
|
| properties: {
|
| - /**
|
| - * The closest ancestor element that implements `IronResizableBehavior`.
|
| - */
|
| _parentResizable: {
|
| type: Object,
|
| observer: '_parentResizableChanged'
|
| },
|
|
|
| - /**
|
| - * True if this element is currently notifying its descedant elements of
|
| - * resize.
|
| - */
|
| _notifyingDescendant: {
|
| type: Boolean,
|
| value: false
|
| @@ -2584,8 +1802,6 @@ Polymer({
|
| },
|
|
|
| created: function() {
|
| - // We don't really need property effects on these, and also we want them
|
| - // to be created before the `_parentResizable` observer fires:
|
| this._interestedResizables = [];
|
| this._boundNotifyResize = this.notifyResize.bind(this);
|
| },
|
| @@ -2613,10 +1829,6 @@ Polymer({
|
| this._parentResizable = null;
|
| },
|
|
|
| - /**
|
| - * Can be called to manually notify a resizable and its descendant
|
| - * resizables of a resize change.
|
| - */
|
| notifyResize: function() {
|
| if (!this.isAttached) {
|
| return;
|
| @@ -2631,18 +1843,10 @@ Polymer({
|
| this._fireResize();
|
| },
|
|
|
| - /**
|
| - * Used to assign the closest resizable ancestor to this resizable
|
| - * if the ancestor detects a request for notifications.
|
| - */
|
| assignParentResizable: function(parentResizable) {
|
| this._parentResizable = parentResizable;
|
| },
|
|
|
| - /**
|
| - * Used to remove a resizable descendant from the list of descendants
|
| - * that should be notified of a resize change.
|
| - */
|
| stopResizeNotificationsFor: function(target) {
|
| var index = this._interestedResizables.indexOf(target);
|
|
|
| @@ -2652,15 +1856,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * This method can be overridden to filter nested elements that should or
|
| - * should not be notified by the current element. Return true if an element
|
| - * should be notified, or false if it should not be notified.
|
| - *
|
| - * @param {HTMLElement} element A candidate descendant element that
|
| - * implements `IronResizableBehavior`.
|
| - * @return {boolean} True if the `element` should be notified of resize.
|
| - */
|
| resizerShouldNotify: function(element) { return true; },
|
|
|
| _onDescendantIronResize: function(event) {
|
| @@ -2669,9 +1864,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // NOTE(cdata): In ShadowDOM, event retargetting makes echoing of the
|
| - // otherwise non-bubbling event "just work." We do it manually here for
|
| - // the case where Polymer is not using shadow roots for whatever reason:
|
| if (!Polymer.Settings.useShadow) {
|
| this._fireResize();
|
| }
|
| @@ -2709,9 +1901,6 @@ Polymer({
|
| },
|
|
|
| _notifyDescendant: function(descendant) {
|
| - // NOTE(cdata): In IE10, attached is fired on children first, so it's
|
| - // important not to notify them if the parent is not attached yet (or
|
| - // else they will get redundantly notified when the parent attaches).
|
| if (!this.isAttached) {
|
| return;
|
| }
|
| @@ -2721,10 +1910,6 @@ Polymer({
|
| this._notifyingDescendant = false;
|
| }
|
| };
|
| -/**
|
| - * @param {!Function} selectCallback
|
| - * @constructor
|
| - */
|
| Polymer.IronSelection = function(selectCallback) {
|
| this.selection = [];
|
| this.selectCallback = selectCallback;
|
| @@ -2732,24 +1917,10 @@ Polymer({
|
|
|
| Polymer.IronSelection.prototype = {
|
|
|
| - /**
|
| - * Retrieves the selected item(s).
|
| - *
|
| - * @method get
|
| - * @returns Returns the selected item(s). If the multi property is true,
|
| - * `get` will return an array, otherwise it will return
|
| - * the selected item or undefined if there is no selection.
|
| - */
|
| get: function() {
|
| return this.multi ? this.selection.slice() : this.selection[0];
|
| },
|
|
|
| - /**
|
| - * Clears all the selection except the ones indicated.
|
| - *
|
| - * @method clear
|
| - * @param {Array} excludes items to be excluded.
|
| - */
|
| clear: function(excludes) {
|
| this.selection.slice().forEach(function(item) {
|
| if (!excludes || excludes.indexOf(item) < 0) {
|
| @@ -2758,28 +1929,13 @@ Polymer({
|
| }, this);
|
| },
|
|
|
| - /**
|
| - * Indicates if a given item is selected.
|
| - *
|
| - * @method isSelected
|
| - * @param {*} item The item whose selection state should be checked.
|
| - * @returns Returns true if `item` is selected.
|
| - */
|
| isSelected: function(item) {
|
| return this.selection.indexOf(item) >= 0;
|
| },
|
|
|
| - /**
|
| - * Sets the selection state for a given item to either selected or deselected.
|
| - *
|
| - * @method setItemSelected
|
| - * @param {*} item The item to select.
|
| - * @param {boolean} isSelected True for selected, false for deselected.
|
| - */
|
| setItemSelected: function(item, isSelected) {
|
| if (item != null) {
|
| if (isSelected !== this.isSelected(item)) {
|
| - // proceed to update selection only if requested state differs from current
|
| if (isSelected) {
|
| this.selection.push(item);
|
| } else {
|
| @@ -2795,14 +1951,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Sets the selection state for a given item. If the `multi` property
|
| - * is true, then the selected state of `item` will be toggled; otherwise
|
| - * the `item` will be selected.
|
| - *
|
| - * @method select
|
| - * @param {*} item The item to select.
|
| - */
|
| select: function(item) {
|
| if (this.multi) {
|
| this.toggle(item);
|
| @@ -2812,12 +1960,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Toggles the selection state for `item`.
|
| - *
|
| - * @method toggle
|
| - * @param {*} item The item to toggle.
|
| - */
|
| toggle: function(item) {
|
| this.setItemSelected(item, !this.isSelected(item));
|
| }
|
| @@ -2826,116 +1968,51 @@ Polymer({
|
| /** @polymerBehavior */
|
| Polymer.IronSelectableBehavior = {
|
|
|
| - /**
|
| - * Fired when iron-selector is activated (selected or deselected).
|
| - * It is fired before the selected items are changed.
|
| - * Cancel the event to abort selection.
|
| - *
|
| - * @event iron-activate
|
| - */
|
| -
|
| - /**
|
| - * Fired when an item is selected
|
| - *
|
| - * @event iron-select
|
| - */
|
| -
|
| - /**
|
| - * Fired when an item is deselected
|
| - *
|
| - * @event iron-deselect
|
| - */
|
| -
|
| - /**
|
| - * Fired when the list of selectable items changes (e.g., items are
|
| - * added or removed). The detail of the event is a mutation record that
|
| - * describes what changed.
|
| - *
|
| - * @event iron-items-changed
|
| - */
|
| +
|
| +
|
| +
|
|
|
| properties: {
|
|
|
| - /**
|
| - * If you want to use an attribute value or property of an element for
|
| - * `selected` instead of the index, set this to the name of the attribute
|
| - * or property. Hyphenated values are converted to camel case when used to
|
| - * look up the property of a selectable element. Camel cased values are
|
| - * *not* converted to hyphenated values for attribute lookup. It's
|
| - * recommended that you provide the hyphenated form of the name so that
|
| - * selection works in both cases. (Use `attr-or-property-name` instead of
|
| - * `attrOrPropertyName`.)
|
| - */
|
| attrForSelected: {
|
| type: String,
|
| value: null
|
| },
|
|
|
| - /**
|
| - * Gets or sets the selected element. The default is to use the index of the item.
|
| - * @type {string|number}
|
| - */
|
| selected: {
|
| type: String,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * Returns the currently selected item.
|
| - *
|
| - * @type {?Object}
|
| - */
|
| selectedItem: {
|
| type: Object,
|
| readOnly: true,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The event that fires from items when they are selected. Selectable
|
| - * will listen for this event from items and update the selection state.
|
| - * Set to empty string to listen to no events.
|
| - */
|
| activateEvent: {
|
| type: String,
|
| value: 'tap',
|
| observer: '_activateEventChanged'
|
| },
|
|
|
| - /**
|
| - * This is a CSS selector string. If this is set, only items that match the CSS selector
|
| - * are selectable.
|
| - */
|
| selectable: String,
|
|
|
| - /**
|
| - * The class to set on elements when selected.
|
| - */
|
| selectedClass: {
|
| type: String,
|
| value: 'iron-selected'
|
| },
|
|
|
| - /**
|
| - * The attribute to set on elements when selected.
|
| - */
|
| selectedAttribute: {
|
| type: String,
|
| value: null
|
| },
|
|
|
| - /**
|
| - * Default fallback if the selection based on selected with `attrForSelected`
|
| - * is not found.
|
| - */
|
| fallbackSelection: {
|
| type: String,
|
| value: null
|
| },
|
|
|
| - /**
|
| - * The list of items from which a selection can be made.
|
| - */
|
| items: {
|
| type: Array,
|
| readOnly: true,
|
| @@ -2945,12 +2022,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * The set of excluded elements where the key is the `localName`
|
| - * of the element that will be ignored from the item list.
|
| - *
|
| - * @default {template: 1}
|
| - */
|
| _excludedLocalNames: {
|
| type: Object,
|
| value: function() {
|
| @@ -2988,69 +2059,29 @@ Polymer({
|
| this._removeListener(this.activateEvent);
|
| },
|
|
|
| - /**
|
| - * Returns the index of the given item.
|
| - *
|
| - * @method indexOf
|
| - * @param {Object} item
|
| - * @returns Returns the index of the item
|
| - */
|
| indexOf: function(item) {
|
| return this.items.indexOf(item);
|
| },
|
|
|
| - /**
|
| - * Selects the given value.
|
| - *
|
| - * @method select
|
| - * @param {string|number} value the value to select.
|
| - */
|
| select: function(value) {
|
| this.selected = value;
|
| },
|
|
|
| - /**
|
| - * Selects the previous item.
|
| - *
|
| - * @method selectPrevious
|
| - */
|
| selectPrevious: function() {
|
| var length = this.items.length;
|
| var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length;
|
| this.selected = this._indexToValue(index);
|
| },
|
|
|
| - /**
|
| - * Selects the next item.
|
| - *
|
| - * @method selectNext
|
| - */
|
| selectNext: function() {
|
| var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length;
|
| this.selected = this._indexToValue(index);
|
| },
|
|
|
| - /**
|
| - * Selects the item at the given index.
|
| - *
|
| - * @method selectIndex
|
| - */
|
| selectIndex: function(index) {
|
| this.select(this._indexToValue(index));
|
| },
|
|
|
| - /**
|
| - * Force a synchronous update of the `items` property.
|
| - *
|
| - * NOTE: Consider listening for the `iron-items-changed` event to respond to
|
| - * updates to the set of selectable items after updates to the DOM list and
|
| - * selection state have been made.
|
| - *
|
| - * WARNING: If you are using this method, you should probably consider an
|
| - * alternate approach. Synchronously querying for items is potentially
|
| - * slow for many use cases. The `items` property will update asynchronously
|
| - * on its own to reflect selectable items in the DOM.
|
| - */
|
| forceSynchronousItemUpdate: function() {
|
| this._updateItems();
|
| },
|
| @@ -3096,8 +2127,6 @@ Polymer({
|
|
|
| _selectSelected: function(selected) {
|
| this._selection.select(this._valueToItem(this.selected));
|
| - // Check for items, since this array is populated only when attached
|
| - // Since Number(0) is falsy, explicitly check for undefined
|
| if (this.fallbackSelection && this.items.length && (this._selection.get() === undefined)) {
|
| this.selected = this.fallbackSelection;
|
| }
|
| @@ -3154,7 +2183,6 @@ Polymer({
|
| this._setSelectedItem(this._selection.get());
|
| },
|
|
|
| - // observe items change under the given node.
|
| _observeItems: function(node) {
|
| return Polymer.dom(node).observeNodes(function(mutation) {
|
| this._updateItems();
|
| @@ -3163,8 +2191,6 @@ Polymer({
|
| this._updateSelected();
|
| }
|
|
|
| - // Let other interested parties know about the change so that
|
| - // we don't have to recreate mutation observers everywhere.
|
| this.fire('iron-items-changed', mutation, {
|
| bubbles: false,
|
| cancelable: false
|
| @@ -3205,10 +2231,6 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - // as the selected page is the only one visible, activateEvent
|
| - // is both non-sensical and problematic; e.g. in cases where a user
|
| - // handler attempts to change the page and the activateEvent
|
| - // handler immediately changes it back
|
| activateEvent: {
|
| type: String,
|
| value: null
|
| @@ -3227,12 +2249,6 @@ Polymer({
|
| (function() {
|
| 'use strict';
|
|
|
| - /**
|
| - * Chrome uses an older version of DOM Level 3 Keyboard Events
|
| - *
|
| - * Most keys are labeled as text, but some are Unicode codepoints.
|
| - * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set
|
| - */
|
| var KEY_IDENTIFIER = {
|
| 'U+0008': 'backspace',
|
| 'U+0009': 'tab',
|
| @@ -3241,13 +2257,6 @@ Polymer({
|
| 'U+007F': 'del'
|
| };
|
|
|
| - /**
|
| - * Special table for KeyboardEvent.keyCode.
|
| - * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better
|
| - * than that.
|
| - *
|
| - * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode
|
| - */
|
| var KEY_CODE = {
|
| 8: 'backspace',
|
| 9: 'tab',
|
| @@ -3266,11 +2275,6 @@ Polymer({
|
| 106: '*'
|
| };
|
|
|
| - /**
|
| - * MODIFIER_KEYS maps the short name for modifier keys used in a key
|
| - * combo string to the property name that references those same keys
|
| - * in a KeyboardEvent instance.
|
| - */
|
| var MODIFIER_KEYS = {
|
| 'shift': 'shiftKey',
|
| 'ctrl': 'ctrlKey',
|
| @@ -3278,44 +2282,16 @@ Polymer({
|
| 'meta': 'metaKey'
|
| };
|
|
|
| - /**
|
| - * KeyboardEvent.key is mostly represented by printable character made by
|
| - * the keyboard, with unprintable keys labeled nicely.
|
| - *
|
| - * However, on OS X, Alt+char can make a Unicode character that follows an
|
| - * Apple-specific mapping. In this case, we fall back to .keyCode.
|
| - */
|
| var KEY_CHAR = /[a-z0-9*]/;
|
|
|
| - /**
|
| - * Matches a keyIdentifier string.
|
| - */
|
| var IDENT_CHAR = /U\+/;
|
|
|
| - /**
|
| - * Matches arrow keys in Gecko 27.0+
|
| - */
|
| var ARROW_KEY = /^arrow/;
|
|
|
| - /**
|
| - * Matches space keys everywhere (notably including IE10's exceptional name
|
| - * `spacebar`).
|
| - */
|
| var SPACE_KEY = /^space(bar)?/;
|
|
|
| - /**
|
| - * Matches ESC key.
|
| - *
|
| - * Value from: http://w3c.github.io/uievents-key/#key-Escape
|
| - */
|
| var ESC_KEY = /^escape$/;
|
|
|
| - /**
|
| - * Transforms the key.
|
| - * @param {string} key The KeyBoardEvent.key
|
| - * @param {Boolean} [noSpecialChars] Limits the transformation to
|
| - * alpha-numeric characters.
|
| - */
|
| function transformKey(key, noSpecialChars) {
|
| var validKey = '';
|
| if (key) {
|
| @@ -3331,7 +2307,6 @@ Polymer({
|
| } else if (ARROW_KEY.test(lKey)) {
|
| validKey = lKey.replace('arrow', '');
|
| } else if (lKey == 'multiply') {
|
| - // numpad '*' can map to Multiply on IE/Windows
|
| validKey = '*';
|
| } else {
|
| validKey = lKey;
|
| @@ -3359,17 +2334,12 @@ Polymer({
|
| var validKey = '';
|
| if (Number(keyCode)) {
|
| if (keyCode >= 65 && keyCode <= 90) {
|
| - // ascii a-z
|
| - // lowercase is 32 offset from uppercase
|
| validKey = String.fromCharCode(32 + keyCode);
|
| } else if (keyCode >= 112 && keyCode <= 123) {
|
| - // function keys f1-f12
|
| validKey = 'f' + (keyCode - 112);
|
| } else if (keyCode >= 48 && keyCode <= 57) {
|
| - // top 0-9 keys
|
| validKey = String(keyCode - 48);
|
| } else if (keyCode >= 96 && keyCode <= 105) {
|
| - // num pad 0-9
|
| validKey = String(keyCode - 96);
|
| } else {
|
| validKey = KEY_CODE[keyCode];
|
| @@ -3378,19 +2348,7 @@ Polymer({
|
| return validKey;
|
| }
|
|
|
| - /**
|
| - * Calculates the normalized key for a KeyboardEvent.
|
| - * @param {KeyboardEvent} keyEvent
|
| - * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key
|
| - * transformation to alpha-numeric chars. This is useful with key
|
| - * combinations like shift + 2, which on FF for MacOS produces
|
| - * keyEvent.key = @
|
| - * To get 2 returned, set noSpecialChars = true
|
| - * To get @ returned, set noSpecialChars = false
|
| - */
|
| function normalizedKeyForEvent(keyEvent, noSpecialChars) {
|
| - // Fall back from .key, to .keyIdentifier, to .keyCode, and then to
|
| - // .detail.key to support artificial keyboard events.
|
| return transformKey(keyEvent.key, noSpecialChars) ||
|
| transformKeyIdentifier(keyEvent.keyIdentifier) ||
|
| transformKeyCode(keyEvent.keyCode) ||
|
| @@ -3398,7 +2356,6 @@ Polymer({
|
| }
|
|
|
| function keyComboMatchesEvent(keyCombo, event) {
|
| - // For combos with modifiers we support only alpha-numeric keys
|
| var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers);
|
| return keyEvent === keyCombo.key &&
|
| (!keyCombo.hasModifiers || (
|
| @@ -3442,49 +2399,8 @@ Polymer({
|
| });
|
| }
|
|
|
| - /**
|
| - * `Polymer.IronA11yKeysBehavior` provides a normalized interface for processing
|
| - * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding).
|
| - * The element takes care of browser differences with respect to Keyboard events
|
| - * and uses an expressive syntax to filter key presses.
|
| - *
|
| - * Use the `keyBindings` prototype property to express what combination of keys
|
| - * will trigger the callback. A key binding has the format
|
| - * `"KEY+MODIFIER:EVENT": "callback"` (`"KEY": "callback"` or
|
| - * `"KEY:EVENT": "callback"` are valid as well). Some examples:
|
| - *
|
| - * keyBindings: {
|
| - * 'space': '_onKeydown', // same as 'space:keydown'
|
| - * 'shift+tab': '_onKeydown',
|
| - * 'enter:keypress': '_onKeypress',
|
| - * 'esc:keyup': '_onKeyup'
|
| - * }
|
| - *
|
| - * The callback will receive with an event containing the following information in `event.detail`:
|
| - *
|
| - * _onKeydown: function(event) {
|
| - * console.log(event.detail.combo); // KEY+MODIFIER, e.g. "shift+tab"
|
| - * console.log(event.detail.key); // KEY only, e.g. "tab"
|
| - * console.log(event.detail.event); // EVENT, e.g. "keydown"
|
| - * console.log(event.detail.keyboardEvent); // the original KeyboardEvent
|
| - * }
|
| - *
|
| - * Use the `keyEventTarget` attribute to set up event handlers on a specific
|
| - * node.
|
| - *
|
| - * See the [demo source code](https://github.com/PolymerElements/iron-a11y-keys-behavior/blob/master/demo/x-key-aware.html)
|
| - * for an example.
|
| - *
|
| - * @demo demo/index.html
|
| - * @polymerBehavior
|
| - */
|
| Polymer.IronA11yKeysBehavior = {
|
| properties: {
|
| - /**
|
| - * The EventTarget that will be firing relevant KeyboardEvents. Set it to
|
| - * `null` to disable the listeners.
|
| - * @type {?EventTarget}
|
| - */
|
| keyEventTarget: {
|
| type: Object,
|
| value: function() {
|
| @@ -3492,10 +2408,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * If true, this property will cause the implementing element to
|
| - * automatically stop propagation on any handled KeyboardEvents.
|
| - */
|
| stopKeyboardEventPropagation: {
|
| type: Boolean,
|
| value: false
|
| @@ -3508,8 +2420,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - // We use this due to a limitation in IE10 where instances will have
|
| - // own properties of everything on the "prototype".
|
| _imperativeKeyBindings: {
|
| type: Object,
|
| value: function() {
|
| @@ -3523,11 +2433,6 @@ Polymer({
|
| ],
|
|
|
|
|
| - /**
|
| - * To be used to express what combination of keys will trigger the relative
|
| - * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}`
|
| - * @type {Object}
|
| - */
|
| keyBindings: {},
|
|
|
| registered: function() {
|
| @@ -3542,33 +2447,18 @@ Polymer({
|
| this._unlistenKeyEventListeners();
|
| },
|
|
|
| - /**
|
| - * Can be used to imperatively add a key binding to the implementing
|
| - * element. This is the imperative equivalent of declaring a keybinding
|
| - * in the `keyBindings` prototype property.
|
| - */
|
| addOwnKeyBinding: function(eventString, handlerName) {
|
| this._imperativeKeyBindings[eventString] = handlerName;
|
| this._prepKeyBindings();
|
| this._resetKeyEventListeners();
|
| },
|
|
|
| - /**
|
| - * When called, will remove all imperatively-added key bindings.
|
| - */
|
| removeOwnKeyBindings: function() {
|
| this._imperativeKeyBindings = {};
|
| this._prepKeyBindings();
|
| this._resetKeyEventListeners();
|
| },
|
|
|
| - /**
|
| - * Returns true if a keyboard event matches `eventString`.
|
| - *
|
| - * @param {KeyboardEvent} event
|
| - * @param {string} eventString
|
| - * @return {boolean}
|
| - */
|
| keyboardEventMatchesKeys: function(event, eventString) {
|
| var keyCombos = parseEventString(eventString);
|
| for (var i = 0; i < keyCombos.length; ++i) {
|
| @@ -3604,7 +2494,6 @@ Polymer({
|
| this._addKeyBinding(eventString, this._imperativeKeyBindings[eventString]);
|
| }
|
|
|
| - // Give precedence to combos with modifiers to be checked first.
|
| for (var eventName in this._keyBindings) {
|
| this._keyBindings[eventName].sort(function (kb1, kb2) {
|
| var b1 = kb1[0].hasModifiers;
|
| @@ -3655,7 +2544,6 @@ Polymer({
|
| var boundKeyHandler;
|
|
|
| while (this._boundKeyHandlers.length) {
|
| - // My kingdom for block-scope binding and destructuring assignment..
|
| keyHandlerTuple = this._boundKeyHandlers.pop();
|
| keyEventTarget = keyHandlerTuple[0];
|
| eventName = keyHandlerTuple[1];
|
| @@ -3670,7 +2558,6 @@ Polymer({
|
| event.stopPropagation();
|
| }
|
|
|
| - // if event has been already prevented, don't do anything
|
| if (event.defaultPrevented) {
|
| return;
|
| }
|
| @@ -3680,7 +2567,6 @@ Polymer({
|
| var handlerName = keyBindings[i][1];
|
| if (keyComboMatchesEvent(keyCombo, event)) {
|
| this._triggerKeyHandler(keyCombo, handlerName, event);
|
| - // exit the loop if eventDefault was prevented
|
| if (event.defaultPrevented) {
|
| return;
|
| }
|
| @@ -3702,17 +2588,10 @@ Polymer({
|
| }
|
| };
|
| })();
|
| -/**
|
| - * @demo demo/index.html
|
| - * @polymerBehavior
|
| - */
|
| Polymer.IronControlState = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * If true, the element currently has focus.
|
| - */
|
| focused: {
|
| type: Boolean,
|
| value: false,
|
| @@ -3721,9 +2600,6 @@ Polymer({
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * If true, the user cannot interact with this element.
|
| - */
|
| disabled: {
|
| type: Boolean,
|
| value: false,
|
| @@ -3755,11 +2631,6 @@ Polymer({
|
| },
|
|
|
| _focusBlurHandler: function(event) {
|
| - // NOTE(cdata): if we are in ShadowDOM land, `event.target` will
|
| - // eventually become `this` due to retargeting; if we are not in
|
| - // ShadowDOM land, `event.target` will eventually become `this` due
|
| - // to the second conditional which fires a synthetic event (that is also
|
| - // handled). In either case, we can disregard `event.path`.
|
|
|
| if (event.target === this) {
|
| this._setFocused(event.type === 'focus');
|
| @@ -3789,24 +2660,16 @@ Polymer({
|
| },
|
|
|
| _changedControlState: function() {
|
| - // _controlStateChanged is abstract, follow-on behaviors may implement it
|
| if (this._controlStateChanged) {
|
| this._controlStateChanged();
|
| }
|
| }
|
|
|
| };
|
| -/**
|
| - * @demo demo/index.html
|
| - * @polymerBehavior Polymer.IronButtonState
|
| - */
|
| Polymer.IronButtonStateImpl = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * If true, the user is currently holding down the button.
|
| - */
|
| pressed: {
|
| type: Boolean,
|
| readOnly: true,
|
| @@ -3815,19 +2678,12 @@ Polymer({
|
| observer: '_pressedChanged'
|
| },
|
|
|
| - /**
|
| - * If true, the button toggles the active state with each tap or press
|
| - * of the spacebar.
|
| - */
|
| toggles: {
|
| type: Boolean,
|
| value: false,
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * If true, the button is a toggle and is currently in the active state.
|
| - */
|
| active: {
|
| type: Boolean,
|
| value: false,
|
| @@ -3835,30 +2691,17 @@ Polymer({
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * True if the element is currently being pressed by a "pointer," which
|
| - * is loosely defined as mouse or touch input (but specifically excluding
|
| - * keyboard input).
|
| - */
|
| pointerDown: {
|
| type: Boolean,
|
| readOnly: true,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * True if the input device that caused the element to receive focus
|
| - * was a keyboard.
|
| - */
|
| receivedFocusFromKeyboard: {
|
| type: Boolean,
|
| readOnly: true
|
| },
|
|
|
| - /**
|
| - * The aria attribute to be set if the button is a toggle and in the
|
| - * active state.
|
| - */
|
| ariaActiveAttribute: {
|
| type: String,
|
| value: 'aria-pressed',
|
| @@ -3887,7 +2730,6 @@ Polymer({
|
|
|
| _tapHandler: function() {
|
| if (this.toggles) {
|
| - // a tap is needed to toggle the active state
|
| this._userActivate(!this.active);
|
| } else {
|
| this.active = false;
|
| @@ -3898,8 +2740,6 @@ Polymer({
|
| this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);
|
| },
|
|
|
| - // to emulate native checkbox, (de-)activations from a user interaction fire
|
| - // 'change' events
|
| _userActivate: function(active) {
|
| if (this.active !== active) {
|
| this.active = active;
|
| @@ -3918,15 +2758,10 @@ Polymer({
|
| this._setPressed(false);
|
| },
|
|
|
| - /**
|
| - * @param {!KeyboardEvent} event .
|
| - */
|
| _spaceKeyDownHandler: function(event) {
|
| var keyboardEvent = event.detail.keyboardEvent;
|
| var target = Polymer.dom(keyboardEvent).localTarget;
|
|
|
| - // Ignore the event if this is coming from a focused light child, since that
|
| - // element will deal with it.
|
| if (this.isLightDescendant(/** @type {Node} */(target)))
|
| return;
|
|
|
| @@ -3935,15 +2770,10 @@ Polymer({
|
| this._setPressed(true);
|
| },
|
|
|
| - /**
|
| - * @param {!KeyboardEvent} event .
|
| - */
|
| _spaceKeyUpHandler: function(event) {
|
| var keyboardEvent = event.detail.keyboardEvent;
|
| var target = Polymer.dom(keyboardEvent).localTarget;
|
|
|
| - // Ignore the event if this is coming from a focused light child, since that
|
| - // element will deal with it.
|
| if (this.isLightDescendant(/** @type {Node} */(target)))
|
| return;
|
|
|
| @@ -3953,15 +2783,12 @@ Polymer({
|
| this._setPressed(false);
|
| },
|
|
|
| - // trigger click asynchronously, the asynchrony is useful to allow one
|
| - // event handler to unwind before triggering another event
|
| _asyncClick: function() {
|
| this.async(function() {
|
| this.click();
|
| }, 1);
|
| },
|
|
|
| - // any of these changes are considered a change to button state
|
|
|
| _pressedChanged: function(pressed) {
|
| this._changedButtonState();
|
| @@ -3991,7 +2818,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - // provide hook for follow-on behaviors to react to button-state
|
|
|
| _changedButtonState: function() {
|
| if (this._buttonStateChanged) {
|
| @@ -4019,10 +2845,6 @@ Polymer({
|
| window.performance.now.bind(window.performance) : Date.now
|
| };
|
|
|
| - /**
|
| - * @param {HTMLElement} element
|
| - * @constructor
|
| - */
|
| function ElementMetrics(element) {
|
| this.element = element;
|
| this.width = this.boundingRect.width;
|
| @@ -4046,10 +2868,6 @@ Polymer({
|
| }
|
| };
|
|
|
| - /**
|
| - * @param {HTMLElement} element
|
| - * @constructor
|
| - */
|
| function Ripple(element) {
|
| this.element = element;
|
| this.color = window.getComputedStyle(element).color;
|
| @@ -4143,8 +2961,6 @@ Polymer({
|
| },
|
|
|
| get outerOpacity() {
|
| - // Linear increase in background opacity, capped at the opacity
|
| - // of the wavefront (waveOpacity).
|
| var outerOpacity = this.mouseUpElapsedSeconds * 0.3;
|
| var waveOpacity = this.opacity;
|
|
|
| @@ -4223,8 +3039,6 @@ Polymer({
|
| dy = this.yNow - (this.containerMetrics.height / 2);
|
|
|
|
|
| - // 2d transform for safari because of border-radius and overflow:hidden clipping bug.
|
| - // https://bugs.webkit.org/show_bug.cgi?id=98538
|
| this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)';
|
| this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + 'px, 0)';
|
| this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
|
| @@ -4300,62 +3114,26 @@ Polymer({
|
| ],
|
|
|
| properties: {
|
| - /**
|
| - * The initial opacity set on the wave.
|
| - *
|
| - * @attribute initialOpacity
|
| - * @type number
|
| - * @default 0.25
|
| - */
|
| initialOpacity: {
|
| type: Number,
|
| value: 0.25
|
| },
|
|
|
| - /**
|
| - * How fast (opacity per second) the wave fades out.
|
| - *
|
| - * @attribute opacityDecayVelocity
|
| - * @type number
|
| - * @default 0.8
|
| - */
|
| opacityDecayVelocity: {
|
| type: Number,
|
| value: 0.8
|
| },
|
|
|
| - /**
|
| - * If true, ripples will exhibit a gravitational pull towards
|
| - * the center of their container as they fade away.
|
| - *
|
| - * @attribute recenters
|
| - * @type boolean
|
| - * @default false
|
| - */
|
| recenters: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, ripples will center inside its container
|
| - *
|
| - * @attribute recenters
|
| - * @type boolean
|
| - * @default false
|
| - */
|
| center: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * A list of the visual ripples.
|
| - *
|
| - * @attribute ripples
|
| - * @type Array
|
| - * @default []
|
| - */
|
| ripples: {
|
| type: Array,
|
| value: function() {
|
| @@ -4363,10 +3141,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * True when there are visible ripples animating within the
|
| - * element.
|
| - */
|
| animating: {
|
| type: Boolean,
|
| readOnly: true,
|
| @@ -4374,22 +3148,12 @@ Polymer({
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, the ripple will remain in the "down" state until `holdDown`
|
| - * is set to false again.
|
| - */
|
| holdDown: {
|
| type: Boolean,
|
| value: false,
|
| observer: '_holdDownChanged'
|
| },
|
|
|
| - /**
|
| - * If true, the ripple will not generate a ripple effect
|
| - * via pointer interaction.
|
| - * Calling ripple's imperative api like `simulatedRipple` will
|
| - * still generate the ripple effect.
|
| - */
|
| noink: {
|
| type: Boolean,
|
| value: false
|
| @@ -4418,9 +3182,6 @@ Polymer({
|
| },
|
|
|
| attached: function() {
|
| - // Set up a11yKeysBehavior to listen to key events on the target,
|
| - // so that space and enter activate the ripple even if the target doesn't
|
| - // handle key events. The key handlers deal with `noink` themselves.
|
| if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE
|
| this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host;
|
| } else {
|
| @@ -4450,28 +3211,17 @@ Polymer({
|
| simulatedRipple: function() {
|
| this.downAction(null);
|
|
|
| - // Please see polymer/polymer#1305
|
| this.async(function() {
|
| this.upAction();
|
| }, 1);
|
| },
|
|
|
| - /**
|
| - * Provokes a ripple down effect via a UI event,
|
| - * respecting the `noink` property.
|
| - * @param {Event=} event
|
| - */
|
| uiDownAction: function(event) {
|
| if (!this.noink) {
|
| this.downAction(event);
|
| }
|
| },
|
|
|
| - /**
|
| - * Provokes a ripple down effect via a UI event,
|
| - * *not* respecting the `noink` property.
|
| - * @param {Event=} event
|
| - */
|
| downAction: function(event) {
|
| if (this.holdDown && this.ripples.length > 0) {
|
| return;
|
| @@ -4487,22 +3237,12 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Provokes a ripple up effect via a UI event,
|
| - * respecting the `noink` property.
|
| - * @param {Event=} event
|
| - */
|
| uiUpAction: function(event) {
|
| if (!this.noink) {
|
| this.upAction(event);
|
| }
|
| },
|
|
|
| - /**
|
| - * Provokes a ripple up effect via a UI event,
|
| - * *not* respecting the `noink` property.
|
| - * @param {Event=} event
|
| - */
|
| upAction: function(event) {
|
| if (this.holdDown) {
|
| return;
|
| @@ -4589,8 +3329,6 @@ Polymer({
|
| this.uiUpAction();
|
| },
|
|
|
| - // note: holdDown does not respect noink since it can be a focus based
|
| - // effect.
|
| _holdDownChanged: function(newVal, oldVal) {
|
| if (oldVal === undefined) {
|
| return;
|
| @@ -4602,58 +3340,26 @@ Polymer({
|
| }
|
| }
|
|
|
| - /**
|
| - Fired when the animation finishes.
|
| - This is useful if you want to wait until
|
| - the ripple animation finishes to perform some action.
|
| -
|
| - @event transitionend
|
| - @param {{node: Object}} detail Contains the animated node.
|
| - */
|
| });
|
| })();
|
| -/**
|
| - * `Polymer.PaperRippleBehavior` dynamically implements a ripple
|
| - * when the element has focus via pointer or keyboard.
|
| - *
|
| - * NOTE: This behavior is intended to be used in conjunction with and after
|
| - * `Polymer.IronButtonState` and `Polymer.IronControlState`.
|
| - *
|
| - * @polymerBehavior Polymer.PaperRippleBehavior
|
| - */
|
| Polymer.PaperRippleBehavior = {
|
| properties: {
|
| - /**
|
| - * If true, the element will not produce a ripple effect when interacted
|
| - * with via the pointer.
|
| - */
|
| noink: {
|
| type: Boolean,
|
| observer: '_noinkChanged'
|
| },
|
|
|
| - /**
|
| - * @type {Element|undefined}
|
| - */
|
| _rippleContainer: {
|
| type: Object,
|
| }
|
| },
|
|
|
| - /**
|
| - * Ensures a `<paper-ripple>` element is available when the element is
|
| - * focused.
|
| - */
|
| _buttonStateChanged: function() {
|
| if (this.focused) {
|
| this.ensureRipple();
|
| }
|
| },
|
|
|
| - /**
|
| - * In addition to the functionality provided in `IronButtonState`, ensures
|
| - * a ripple effect is created when the element is in a `pressed` state.
|
| - */
|
| _downHandler: function(event) {
|
| Polymer.IronButtonStateImpl._downHandler.call(this, event);
|
| if (this.pressed) {
|
| @@ -4661,12 +3367,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Ensures this element contains a ripple effect. For startup efficiency
|
| - * the ripple effect is dynamically on demand when needed.
|
| - * @param {!Event=} optTriggeringEvent (optional) event that triggered the
|
| - * ripple.
|
| - */
|
| ensureRipple: function(optTriggeringEvent) {
|
| if (!this.hasRipple()) {
|
| this._ripple = this._createRipple();
|
| @@ -4676,9 +3376,6 @@ Polymer({
|
| Polymer.dom(rippleContainer).appendChild(this._ripple);
|
| }
|
| if (optTriggeringEvent) {
|
| - // Check if the event happened inside of the ripple container
|
| - // Fall back to host instead of the root because distributed text
|
| - // nodes are not valid event targets
|
| var domContainer = Polymer.dom(this._rippleContainer || this);
|
| var target = Polymer.dom(optTriggeringEvent).rootTarget;
|
| if (domContainer.deepContains( /** @type {Node} */(target))) {
|
| @@ -4688,30 +3385,15 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Returns the `<paper-ripple>` element used by this element to create
|
| - * ripple effects. The element's ripple is created on demand, when
|
| - * necessary, and calling this method will force the
|
| - * ripple to be created.
|
| - */
|
| getRipple: function() {
|
| this.ensureRipple();
|
| return this._ripple;
|
| },
|
|
|
| - /**
|
| - * Returns true if this element currently contains a ripple effect.
|
| - * @return {boolean}
|
| - */
|
| hasRipple: function() {
|
| return Boolean(this._ripple);
|
| },
|
|
|
| - /**
|
| - * Create the element's ripple effect via creating a `<paper-ripple>`.
|
| - * Override this method to customize the ripple element.
|
| - * @return {!PaperRippleElement} Returns a `<paper-ripple>` element.
|
| - */
|
| _createRipple: function() {
|
| return /** @type {!PaperRippleElement} */ (
|
| document.createElement('paper-ripple'));
|
| @@ -4726,15 +3408,6 @@ Polymer({
|
| /** @polymerBehavior Polymer.PaperButtonBehavior */
|
| Polymer.PaperButtonBehaviorImpl = {
|
| properties: {
|
| - /**
|
| - * The z-depth of this element, from 0-5. Setting to 0 will remove the
|
| - * shadow, and each increasing number greater than 0 will be "deeper"
|
| - * than the last.
|
| - *
|
| - * @attribute elevation
|
| - * @type number
|
| - * @default 1
|
| - */
|
| elevation: {
|
| type: Number,
|
| reflectToAttribute: true,
|
| @@ -4769,26 +3442,13 @@ Polymer({
|
| this.toggleClass('keyboard-focus', receivedFocusFromKeyboard);
|
| },
|
|
|
| - /**
|
| - * In addition to `IronButtonState` behavior, when space key goes down,
|
| - * create a ripple down effect.
|
| - *
|
| - * @param {!KeyboardEvent} event .
|
| - */
|
| _spaceKeyDownHandler: function(event) {
|
| Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this, event);
|
| - // Ensure that there is at most one ripple when the space key is held down.
|
| if (this.hasRipple() && this.getRipple().ripples.length < 1) {
|
| this._ripple.uiDownAction();
|
| }
|
| },
|
|
|
| - /**
|
| - * In addition to `IronButtonState` behavior, when space key goes up,
|
| - * create a ripple up effect.
|
| - *
|
| - * @param {!KeyboardEvent} event .
|
| - */
|
| _spaceKeyUpHandler: function(event) {
|
| Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event);
|
| if (this.hasRipple()) {
|
| @@ -4812,9 +3472,6 @@ Polymer({
|
| ],
|
|
|
| properties: {
|
| - /**
|
| - * If true, the button should be styled with a shadow.
|
| - */
|
| raised: {
|
| type: Boolean,
|
| reflectToAttribute: true,
|
| @@ -4831,18 +3488,9 @@ Polymer({
|
| }
|
| }
|
|
|
| - /**
|
| - Fired when the animation finishes.
|
| - This is useful if you want to wait until
|
| - the ripple animation finishes to perform some action.
|
| -
|
| - @event transitionend
|
| - Event param: {{node: Object}} detail Contains the animated node.
|
| - */
|
| });
|
| (function() {
|
|
|
| - // monostate data
|
| var metaDatas = {};
|
| var metaArrays = {};
|
| var singleton = null;
|
| @@ -4853,44 +3501,28 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The type of meta-data. All meta-data of the same type is stored
|
| - * together.
|
| - */
|
| type: {
|
| type: String,
|
| value: 'default',
|
| observer: '_typeChanged'
|
| },
|
|
|
| - /**
|
| - * The key used to store `value` under the `type` namespace.
|
| - */
|
| key: {
|
| type: String,
|
| observer: '_keyChanged'
|
| },
|
|
|
| - /**
|
| - * The meta-data to store or retrieve.
|
| - */
|
| value: {
|
| type: Object,
|
| notify: true,
|
| observer: '_valueChanged'
|
| },
|
|
|
| - /**
|
| - * If true, `value` is set to the iron-meta instance itself.
|
| - */
|
| self: {
|
| type: Boolean,
|
| observer: '_selfChanged'
|
| },
|
|
|
| - /**
|
| - * Array of all meta-data values for the given type.
|
| - */
|
| list: {
|
| type: Array,
|
| notify: true
|
| @@ -4902,12 +3534,6 @@ Polymer({
|
| hidden: true
|
| },
|
|
|
| - /**
|
| - * Only runs if someone invokes the factory/constructor directly
|
| - * e.g. `new Polymer.IronMeta()`
|
| - *
|
| - * @param {{type: (string|undefined), key: (string|undefined), value}=} config
|
| - */
|
| factoryImpl: function(config) {
|
| if (config) {
|
| for (var n in config) {
|
| @@ -4923,7 +3549,6 @@ Polymer({
|
| },
|
|
|
| created: function() {
|
| - // TODO(sjmiles): good for debugging?
|
| this._metaDatas = metaDatas;
|
| this._metaArrays = metaArrays;
|
| },
|
| @@ -4955,13 +3580,6 @@ Polymer({
|
| this._registerKeyValue(this.key, this.value);
|
| },
|
|
|
| - /**
|
| - * Retrieves meta data value by key.
|
| - *
|
| - * @method byKey
|
| - * @param {string} key The key of the meta-data to be returned.
|
| - * @return {*}
|
| - */
|
| byKey: function(key) {
|
| return this._metaData && this._metaData[key];
|
| },
|
| @@ -5005,62 +3623,29 @@ Polymer({
|
| return singleton;
|
| };
|
|
|
| - /**
|
| - `iron-meta-query` can be used to access infomation stored in `iron-meta`.
|
| -
|
| - Examples:
|
| -
|
| - If I create an instance like this:
|
| -
|
| - <iron-meta key="info" value="foo/bar"></iron-meta>
|
| -
|
| - Note that value="foo/bar" is the metadata I've defined. I could define more
|
| - attributes or use child nodes to define additional metadata.
|
| -
|
| - Now I can access that element (and it's metadata) from any `iron-meta-query` instance:
|
| -
|
| - var value = new Polymer.IronMetaQuery({key: 'info'}).value;
|
| -
|
| - @group Polymer Iron Elements
|
| - @element iron-meta-query
|
| - */
|
| Polymer.IronMetaQuery = Polymer({
|
|
|
| is: 'iron-meta-query',
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The type of meta-data. All meta-data of the same type is stored
|
| - * together.
|
| - */
|
| type: {
|
| type: String,
|
| value: 'default',
|
| observer: '_typeChanged'
|
| },
|
|
|
| - /**
|
| - * Specifies a key to use for retrieving `value` from the `type`
|
| - * namespace.
|
| - */
|
| key: {
|
| type: String,
|
| observer: '_keyChanged'
|
| },
|
|
|
| - /**
|
| - * The meta-data to store or retrieve.
|
| - */
|
| value: {
|
| type: Object,
|
| notify: true,
|
| readOnly: true
|
| },
|
|
|
| - /**
|
| - * Array of all meta-data values for the given type.
|
| - */
|
| list: {
|
| type: Array,
|
| notify: true
|
| @@ -5068,12 +3653,6 @@ Polymer({
|
|
|
| },
|
|
|
| - /**
|
| - * Actually a factory method, not a true constructor. Only runs if
|
| - * someone invokes it directly (via `new Polymer.IronMeta()`);
|
| - *
|
| - * @param {{type: (string|undefined), key: (string|undefined)}=} config
|
| - */
|
| factoryImpl: function(config) {
|
| if (config) {
|
| for (var n in config) {
|
| @@ -5088,7 +3667,6 @@ Polymer({
|
| },
|
|
|
| created: function() {
|
| - // TODO(sjmiles): good for debugging?
|
| this._metaDatas = metaDatas;
|
| this._metaArrays = metaArrays;
|
| },
|
| @@ -5105,11 +3683,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Retrieves meta data value by key.
|
| - * @param {string} key The key of the meta-data to be returned.
|
| - * @return {*}
|
| - */
|
| byKey: function(key) {
|
| return this._metaData && this._metaData[key];
|
| }
|
| @@ -5123,37 +3696,21 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The name of the icon to use. The name should be of the form:
|
| - * `iconset_name:icon_name`.
|
| - */
|
| icon: {
|
| type: String,
|
| observer: '_iconChanged'
|
| },
|
|
|
| - /**
|
| - * The name of the theme to used, if one is specified by the
|
| - * iconset.
|
| - */
|
| theme: {
|
| type: String,
|
| observer: '_updateIcon'
|
| },
|
|
|
| - /**
|
| - * If using iron-icon without an iconset, you can set the src to be
|
| - * the URL of an individual icon image file. Note that this will take
|
| - * precedence over a given icon attribute.
|
| - */
|
| src: {
|
| type: String,
|
| observer: '_srcChanged'
|
| },
|
|
|
| - /**
|
| - * @type {!Polymer.IronMeta}
|
| - */
|
| _meta: {
|
| value: Polymer.Base.create('iron-meta', {type: 'iconset'}),
|
| observer: '_updateIcon'
|
| @@ -5214,11 +3771,6 @@ Polymer({
|
| }
|
|
|
| });
|
| -/**
|
| - * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has keyboard focus.
|
| - *
|
| - * @polymerBehavior Polymer.PaperInkyFocusBehavior
|
| - */
|
| Polymer.PaperInkyFocusBehaviorImpl = {
|
| observers: [
|
| '_focusedChanged(receivedFocusFromKeyboard)'
|
| @@ -5262,26 +3814,14 @@ Polymer({
|
| ],
|
|
|
| properties: {
|
| - /**
|
| - * The URL of an image for the icon. If the src property is specified,
|
| - * the icon property should not be.
|
| - */
|
| src: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * Specifies the icon name or index in the set of icons available in
|
| - * the icon's icon set. If the icon property is specified,
|
| - * the src property should not be.
|
| - */
|
| icon: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * Specifies the alternate text for the button, for accessibility.
|
| - */
|
| alt: {
|
| type: String,
|
| observer: "_altChanged"
|
| @@ -5291,7 +3831,6 @@ Polymer({
|
| _altChanged: function(newValue, oldValue) {
|
| var label = this.getAttribute('aria-label');
|
|
|
| - // Don't stomp over a user-set aria-label.
|
| if (!label || oldValue == label) {
|
| this.setAttribute('aria-label', newValue);
|
| }
|
| @@ -5308,10 +3847,6 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * If true, the tab will forward keyboard clicks (enter/space) to
|
| - * the first anchor element found in its descendants
|
| - */
|
| link: {
|
| type: Boolean,
|
| value: false,
|
| @@ -5350,8 +3885,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // Don't get stuck in a loop delegating
|
| - // the listener from the child anchor
|
| if (event.target === anchor) {
|
| return;
|
| }
|
| @@ -5365,27 +3898,17 @@ Polymer({
|
| Polymer.IronMultiSelectableBehaviorImpl = {
|
| properties: {
|
|
|
| - /**
|
| - * If true, multiple selections are allowed.
|
| - */
|
| multi: {
|
| type: Boolean,
|
| value: false,
|
| observer: 'multiChanged'
|
| },
|
|
|
| - /**
|
| - * Gets or sets the selected elements. This is used instead of `selected` when `multi`
|
| - * is true.
|
| - */
|
| selectedValues: {
|
| type: Array,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * Returns an array of currently selected items.
|
| - */
|
| selectedItems: {
|
| type: Array,
|
| readOnly: true,
|
| @@ -5398,13 +3921,6 @@ Polymer({
|
| '_updateSelected(selectedValues.splices)'
|
| ],
|
|
|
| - /**
|
| - * Selects the given value. If the `multi` property is true, then the selected state of the
|
| - * `value` will be toggled; otherwise the `value` will be selected.
|
| - *
|
| - * @method select
|
| - * @param {string|number} value the value to select.
|
| - */
|
| select: function(value) {
|
| if (this.multi) {
|
| if (this.selectedValues) {
|
| @@ -5449,13 +3965,10 @@ Polymer({
|
| _selectMulti: function(values) {
|
| if (values) {
|
| var selectedItems = this._valuesToItems(values);
|
| - // clear all but the current selected items
|
| this._selection.clear(selectedItems);
|
| - // select only those not selected yet
|
| for (var i = 0; i < selectedItems.length; i++) {
|
| this._selection.setItemSelected(selectedItems[i], true);
|
| }
|
| - // Check for items, since this array is populated only when attached
|
| if (this.fallbackSelection && this.items.length && !this._selection.get().length) {
|
| var fallback = this._valueToItem(this.fallbackSelection);
|
| if (fallback) {
|
| @@ -5499,31 +4012,16 @@ Polymer({
|
| Polymer.IronSelectableBehavior,
|
| Polymer.IronMultiSelectableBehaviorImpl
|
| ];
|
| -/**
|
| - * `Polymer.IronMenuBehavior` implements accessible menu behavior.
|
| - *
|
| - * @demo demo/index.html
|
| - * @polymerBehavior Polymer.IronMenuBehavior
|
| - */
|
| Polymer.IronMenuBehaviorImpl = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Returns the currently focused item.
|
| - * @type {?Object}
|
| - */
|
| focusedItem: {
|
| observer: '_focusedItemChanged',
|
| readOnly: true,
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * The attribute to use on menu items to look up the item title. Typing the first
|
| - * letter of an item when the menu is open focuses that item. If unset, `textContent`
|
| - * will be used.
|
| - */
|
| attrForItemTitle: {
|
| type: String
|
| }
|
| @@ -5555,15 +4053,7 @@ Polymer({
|
| this._resetTabindices();
|
| },
|
|
|
| - /**
|
| - * Selects the given value. If the `multi` property is true, then the selected state of the
|
| - * `value` will be toggled; otherwise the `value` will be selected.
|
| - *
|
| - * @param {string|number} value the value to select.
|
| - */
|
| select: function(value) {
|
| - // Cancel automatically focusing a default item if the menu received focus
|
| - // through a user action selecting a particular item.
|
| if (this._defaultFocusAsync) {
|
| this.cancelAsync(this._defaultFocusAsync);
|
| this._defaultFocusAsync = null;
|
| @@ -5574,12 +4064,6 @@ Polymer({
|
| Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments);
|
| },
|
|
|
| - /**
|
| - * Resets all tabindex attributes to the appropriate value based on the
|
| - * current selection state. The appropriate value is `0` (focusable) for
|
| - * the default selected item, and `-1` (not keyboard focusable) for all
|
| - * other items.
|
| - */
|
| _resetTabindices: function() {
|
| var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[0]) : this.selectedItem;
|
|
|
| @@ -5588,12 +4072,6 @@ Polymer({
|
| }, this);
|
| },
|
|
|
| - /**
|
| - * Sets appropriate ARIA based on whether or not the menu is meant to be
|
| - * multi-selectable.
|
| - *
|
| - * @param {boolean} multi True if the menu should be multi-selectable.
|
| - */
|
| _updateMultiselectable: function(multi) {
|
| if (multi) {
|
| this.setAttribute('aria-multiselectable', 'true');
|
| @@ -5602,12 +4080,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Given a KeyboardEvent, this method will focus the appropriate item in the
|
| - * menu (if there is a relevant item, and it is possible to focus it).
|
| - *
|
| - * @param {KeyboardEvent} event A KeyboardEvent.
|
| - */
|
| _focusWithKeyboardEvent: function(event) {
|
| for (var i = 0, item; item = this.items[i]; i++) {
|
| var attr = this.attrForItemTitle || 'textContent';
|
| @@ -5621,11 +4093,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Focuses the previous item (relative to the currently focused item) in the
|
| - * menu, disabled items will be skipped.
|
| - * Loop until length + 1 to handle case of single item in menu.
|
| - */
|
| _focusPrevious: function() {
|
| var length = this.items.length;
|
| var curFocusIndex = Number(this.indexOf(this.focusedItem));
|
| @@ -5638,11 +4105,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Focuses the next item (relative to the currently focused item) in the
|
| - * menu, disabled items will be skipped.
|
| - * Loop until length + 1 to handle case of single item in menu.
|
| - */
|
| _focusNext: function() {
|
| var length = this.items.length;
|
| var curFocusIndex = Number(this.indexOf(this.focusedItem));
|
| @@ -5655,14 +4117,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Mutates items in the menu based on provided selection details, so that
|
| - * all items correctly reflect selection state.
|
| - *
|
| - * @param {Element} item An item in the menu.
|
| - * @param {boolean} isSelected True if the item should be shown in a
|
| - * selected state, otherwise false.
|
| - */
|
| _applySelection: function(item, isSelected) {
|
| if (isSelected) {
|
| item.setAttribute('aria-selected', 'true');
|
| @@ -5672,14 +4126,6 @@ Polymer({
|
| Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
|
| },
|
|
|
| - /**
|
| - * Discretely updates tabindex values among menu items as the focused item
|
| - * changes.
|
| - *
|
| - * @param {Element} focusedItem The element that is currently focused.
|
| - * @param {?Element} old The last element that was considered focused, if
|
| - * applicable.
|
| - */
|
| _focusedItemChanged: function(focusedItem, old) {
|
| old && old.setAttribute('tabindex', '-1');
|
| if (focusedItem) {
|
| @@ -5688,24 +4134,12 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * A handler that responds to mutation changes related to the list of items
|
| - * in the menu.
|
| - *
|
| - * @param {CustomEvent} event An event containing mutation records as its
|
| - * detail.
|
| - */
|
| _onIronItemsChanged: function(event) {
|
| if (event.detail.addedNodes.length) {
|
| this._resetTabindices();
|
| }
|
| },
|
|
|
| - /**
|
| - * Handler that is called when a shift+tab keypress is detected by the menu.
|
| - *
|
| - * @param {CustomEvent} event A key combination event.
|
| - */
|
| _onShiftTabDown: function(event) {
|
| var oldTabIndex = this.getAttribute('tabindex');
|
|
|
| @@ -5718,33 +4152,21 @@ Polymer({
|
| this.async(function() {
|
| this.setAttribute('tabindex', oldTabIndex);
|
| Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
|
| - // NOTE(cdata): polymer/polymer#1305
|
| }, 1);
|
| },
|
|
|
| - /**
|
| - * Handler that is called when the menu receives focus.
|
| - *
|
| - * @param {FocusEvent} event A focus event.
|
| - */
|
| _onFocus: function(event) {
|
| if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
|
| - // do not focus the menu itself
|
| return;
|
| }
|
|
|
| - // Do not focus the selected tab if the deepest target is part of the
|
| - // menu element's local DOM and is focusable.
|
| var rootTarget = /** @type {?HTMLElement} */(
|
| Polymer.dom(event).rootTarget);
|
| if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !this.isLightDescendant(rootTarget)) {
|
| return;
|
| }
|
|
|
| - // clear the cached focus item
|
| this._defaultFocusAsync = this.async(function() {
|
| - // focus the selected item when the menu receives focus, or the first item
|
| - // if no item is selected
|
| var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[0]) : this.selectedItem;
|
|
|
| this._setFocusedItem(null);
|
| @@ -5752,57 +4174,32 @@ Polymer({
|
| if (selectedItem) {
|
| this._setFocusedItem(selectedItem);
|
| } else if (this.items[0]) {
|
| - // We find the first none-disabled item (if one exists)
|
| this._focusNext();
|
| }
|
| });
|
| },
|
|
|
| - /**
|
| - * Handler that is called when the up key is pressed.
|
| - *
|
| - * @param {CustomEvent} event A key combination event.
|
| - */
|
| _onUpKey: function(event) {
|
| - // up and down arrows moves the focus
|
| this._focusPrevious();
|
| event.detail.keyboardEvent.preventDefault();
|
| },
|
|
|
| - /**
|
| - * Handler that is called when the down key is pressed.
|
| - *
|
| - * @param {CustomEvent} event A key combination event.
|
| - */
|
| _onDownKey: function(event) {
|
| this._focusNext();
|
| event.detail.keyboardEvent.preventDefault();
|
| },
|
|
|
| - /**
|
| - * Handler that is called when the esc key is pressed.
|
| - *
|
| - * @param {CustomEvent} event A key combination event.
|
| - */
|
| _onEscKey: function(event) {
|
| - // esc blurs the control
|
| this.focusedItem.blur();
|
| },
|
|
|
| - /**
|
| - * Handler that is called when a keydown event is detected.
|
| - *
|
| - * @param {KeyboardEvent} event A keyboard event.
|
| - */
|
| _onKeydown: function(event) {
|
| if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
|
| - // all other keys focus the menu item starting with that character
|
| this._focusWithKeyboardEvent(event);
|
| }
|
| event.stopPropagation();
|
| },
|
|
|
| - // override _activateHandler
|
| _activateHandler: function(event) {
|
| Polymer.IronSelectableBehavior._activateHandler.call(this, event);
|
| event.stopPropagation();
|
| @@ -5817,11 +4214,6 @@ Polymer({
|
| Polymer.IronA11yKeysBehavior,
|
| Polymer.IronMenuBehaviorImpl
|
| ];
|
| -/**
|
| - * `Polymer.IronMenubarBehavior` implements accessible menubar behavior.
|
| - *
|
| - * @polymerBehavior Polymer.IronMenubarBehavior
|
| - */
|
| Polymer.IronMenubarBehaviorImpl = {
|
|
|
| hostAttributes: {
|
| @@ -5870,7 +4262,6 @@ Polymer({
|
| return;
|
| }
|
|
|
| - // all other keys focus the menu item starting with that character
|
| this._focusWithKeyboardEvent(event);
|
| }
|
|
|
| @@ -5881,57 +4272,16 @@ Polymer({
|
| Polymer.IronMenuBehavior,
|
| Polymer.IronMenubarBehaviorImpl
|
| ];
|
| -/**
|
| - * The `iron-iconset-svg` element allows users to define their own icon sets
|
| - * that contain svg icons. The svg icon elements should be children of the
|
| - * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
|
| - *
|
| - * Using svg elements to create icons has a few advantages over traditional
|
| - * bitmap graphics like jpg or png. Icons that use svg are vector based so
|
| - * they are resolution independent and should look good on any device. They
|
| - * are stylable via css. Icons can be themed, colorized, and even animated.
|
| - *
|
| - * Example:
|
| - *
|
| - * <iron-iconset-svg name="my-svg-icons" size="24">
|
| - * <svg>
|
| - * <defs>
|
| - * <g id="shape">
|
| - * <rect x="12" y="0" width="12" height="24" />
|
| - * <circle cx="12" cy="12" r="12" />
|
| - * </g>
|
| - * </defs>
|
| - * </svg>
|
| - * </iron-iconset-svg>
|
| - *
|
| - * This will automatically register the icon set "my-svg-icons" to the iconset
|
| - * database. To use these icons from within another element, make a
|
| - * `iron-iconset` element and call the `byId` method
|
| - * to retrieve a given iconset. To apply a particular icon inside an
|
| - * element use the `applyIcon` method. For example:
|
| - *
|
| - * iconset.applyIcon(iconNode, 'car');
|
| - *
|
| - * @element iron-iconset-svg
|
| - * @demo demo/index.html
|
| - * @implements {Polymer.Iconset}
|
| - */
|
| Polymer({
|
| is: 'iron-iconset-svg',
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The name of the iconset.
|
| - */
|
| name: {
|
| type: String,
|
| observer: '_nameChanged'
|
| },
|
|
|
| - /**
|
| - * The size of an individual icon. Note that icons must be square.
|
| - */
|
| size: {
|
| type: Number,
|
| value: 24
|
| @@ -5943,11 +4293,6 @@ Polymer({
|
| this.style.display = 'none';
|
| },
|
|
|
| - /**
|
| - * Construct an array of all icon names in this iconset.
|
| - *
|
| - * @return {!Array} Array of icon names.
|
| - */
|
| getIconNames: function() {
|
| this._icons = this._createIconMap();
|
| return Object.keys(this._icons).map(function(n) {
|
| @@ -5955,23 +4300,9 @@ Polymer({
|
| }, this);
|
| },
|
|
|
| - /**
|
| - * Applies an icon to the given element.
|
| - *
|
| - * An svg icon is prepended to the element's shadowRoot if it exists,
|
| - * otherwise to the element itself.
|
| - *
|
| - * @method applyIcon
|
| - * @param {Element} element Element to which the icon is applied.
|
| - * @param {string} iconName Name of the icon to apply.
|
| - * @return {?Element} The svg element which renders the icon.
|
| - */
|
| applyIcon: function(element, iconName) {
|
| - // insert svg element into shadow root, if it exists
|
| element = element.root || element;
|
| - // Remove old svg element
|
| this.removeIcon(element);
|
| - // install new svg element
|
| var svg = this._cloneIcon(iconName);
|
| if (svg) {
|
| var pde = Polymer.dom(element);
|
| @@ -5981,25 +4312,13 @@ Polymer({
|
| return null;
|
| },
|
|
|
| - /**
|
| - * Remove an icon from the given element by undoing the changes effected
|
| - * by `applyIcon`.
|
| - *
|
| - * @param {Element} element The element from which the icon is removed.
|
| - */
|
| removeIcon: function(element) {
|
| - // Remove old svg element
|
| if (element._svgIcon) {
|
| Polymer.dom(element).removeChild(element._svgIcon);
|
| element._svgIcon = null;
|
| }
|
| },
|
|
|
| - /**
|
| - *
|
| - * When name is changed, register iconset metadata
|
| - *
|
| - */
|
| _nameChanged: function() {
|
| new Polymer.IronMeta({type: 'iconset', key: this.name, value: this});
|
| this.async(function() {
|
| @@ -6007,15 +4326,7 @@ Polymer({
|
| });
|
| },
|
|
|
| - /**
|
| - * Create a map of child SVG elements by id.
|
| - *
|
| - * @return {!Object} Map of id's to SVG elements.
|
| - */
|
| _createIconMap: function() {
|
| - // Objects chained to Object.prototype (`{}`) have members. Specifically,
|
| - // on FF there is a `watch` method that confuses the icon map, so we
|
| - // need to use a null-based object here.
|
| var icons = Object.create(null);
|
| Polymer.dom(this).querySelectorAll('[id]')
|
| .forEach(function(icon) {
|
| @@ -6024,25 +4335,11 @@ Polymer({
|
| return icons;
|
| },
|
|
|
| - /**
|
| - * Produce installable clone of the SVG element matching `id` in this
|
| - * iconset, or `undefined` if there is no matching element.
|
| - *
|
| - * @return {Element} Returns an installable clone of the SVG element
|
| - * matching `id`.
|
| - */
|
| _cloneIcon: function(id) {
|
| - // create the icon map on-demand, since the iconset itself has no discrete
|
| - // signal to know when it's children are fully parsed
|
| this._icons = this._icons || this._createIconMap();
|
| return this._prepareSvgClone(this._icons[id], this.size);
|
| },
|
|
|
| - /**
|
| - * @param {Element} sourceSvg
|
| - * @param {number} size
|
| - * @return {Element}
|
| - */
|
| _prepareSvgClone: function(sourceSvg, size) {
|
| if (sourceSvg) {
|
| var content = sourceSvg.cloneNode(true),
|
| @@ -6050,8 +4347,6 @@ Polymer({
|
| viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
|
| svg.setAttribute('viewBox', viewBox);
|
| svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
| - // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136
|
| - // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root
|
| svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;';
|
| svg.appendChild(content).removeAttribute('id');
|
| return svg;
|
| @@ -6069,69 +4364,42 @@ Polymer({
|
| ],
|
|
|
| properties: {
|
| - /**
|
| - * If true, ink ripple effect is disabled. When this property is changed,
|
| - * all descendant `<paper-tab>` elements have their `noink` property
|
| - * changed to the new value as well.
|
| - */
|
| noink: {
|
| type: Boolean,
|
| value: false,
|
| observer: '_noinkChanged'
|
| },
|
|
|
| - /**
|
| - * If true, the bottom bar to indicate the selected tab will not be shown.
|
| - */
|
| noBar: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, the slide effect for the bottom bar is disabled.
|
| - */
|
| noSlide: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, tabs are scrollable and the tab width is based on the label width.
|
| - */
|
| scrollable: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, tabs expand to fit their container. This currently only applies when
|
| - * scrollable is true.
|
| - */
|
| fitContainer: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, dragging on the tabs to scroll is disabled.
|
| - */
|
| disableDrag: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, scroll buttons (left/right arrow) will be hidden for scrollable tabs.
|
| - */
|
| hideScrollButtons: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * If true, the tabs are aligned to bottom (the selection bar appears at the top).
|
| - */
|
| alignBottom: {
|
| type: Boolean,
|
| value: false
|
| @@ -6142,20 +4410,11 @@ Polymer({
|
| value: 'paper-tab'
|
| },
|
|
|
| - /**
|
| - * If true, tabs are automatically selected when focused using the
|
| - * keyboard.
|
| - */
|
| autoselect: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * The delay (in milliseconds) between when the user stops interacting
|
| - * with the tabs through the keyboard and when the focused item is
|
| - * automatically selected (if `autoselect` is true).
|
| - */
|
| autoselectDelay: {
|
| type: Number,
|
| value: 0
|
| @@ -6256,7 +4515,6 @@ Polymer({
|
| return '';
|
| },
|
|
|
| - // TODO(cdata): Add `track` response back in when gesture lands.
|
|
|
| _onTabSizingChanged: function() {
|
| this.debounce('_onTabSizingChanged', function() {
|
| @@ -6275,30 +4533,21 @@ Polymer({
|
| this.debounce('tab-changed', function() {
|
| this._tabChanged(null, this._previousTab);
|
| this._previousTab = null;
|
| - // See polymer/polymer#1305
|
| }, 1);
|
| },
|
|
|
| _activateHandler: function() {
|
| - // Cancel item activations scheduled by keyboard events when any other
|
| - // action causes an item to be activated (e.g. clicks).
|
| this._cancelPendingActivation();
|
|
|
| Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments);
|
| },
|
|
|
| - /**
|
| - * Activates an item after a delay (in milliseconds).
|
| - */
|
| _scheduleActivation: function(item, delay) {
|
| this._pendingActivationItem = item;
|
| this._pendingActivationTimeout = this.async(
|
| this._bindDelayedActivationHandler, delay);
|
| },
|
|
|
| - /**
|
| - * Activates the last item given to `_scheduleActivation`.
|
| - */
|
| _delayedActivationHandler: function() {
|
| var item = this._pendingActivationItem;
|
| this._pendingActivationItem = undefined;
|
| @@ -6309,10 +4558,6 @@ Polymer({
|
| });
|
| },
|
|
|
| - /**
|
| - * Cancels a previously scheduled item activation made with
|
| - * `_scheduleActivation`.
|
| - */
|
| _cancelPendingActivation: function() {
|
| if (this._pendingActivationTimeout !== undefined) {
|
| this.cancelAsync(this._pendingActivationTimeout);
|
| @@ -6328,8 +4573,6 @@ Polymer({
|
| },
|
|
|
| _onBlurCapture: function(event) {
|
| - // Cancel a scheduled item activation (if any) when that item is
|
| - // blurred.
|
| if (event.target === this._pendingActivationItem) {
|
| this._cancelPendingActivation();
|
| }
|
| @@ -6353,8 +4596,6 @@ Polymer({
|
| },
|
|
|
| _down: function(e) {
|
| - // go one beat async to defeat IronMenuBehavior
|
| - // autorefocus-on-no-selection timeout
|
| this.async(function() {
|
| if (this._defaultFocusAsync) {
|
| this.cancelAsync(this._defaultFocusAsync);
|
| @@ -6397,7 +4638,6 @@ Polymer({
|
|
|
| _tabChanged: function(tab, old) {
|
| if (!tab) {
|
| - // Remove the bar without animation.
|
| this.$.selectionBar.classList.remove('expand');
|
| this.$.selectionBar.classList.remove('contract');
|
| this._positionBar(0, 0);
|
| @@ -6415,7 +4655,6 @@ Polymer({
|
| };
|
|
|
| if (this.noSlide || old == null) {
|
| - // Position the bar without animation.
|
| this.$.selectionBar.classList.remove('expand');
|
| this.$.selectionBar.classList.remove('contract');
|
| this._positionBar(this._pos.width, this._pos.left);
|
| @@ -6427,7 +4666,6 @@ Polymer({
|
| var index = this.items.indexOf(tab);
|
| var m = 5;
|
|
|
| - // bar animation: expand
|
| this.$.selectionBar.classList.add('expand');
|
|
|
| var moveRight = oldIndex < index;
|
| @@ -6478,12 +4716,10 @@ Polymer({
|
|
|
| _onBarTransitionEnd: function(e) {
|
| var cl = this.$.selectionBar.classList;
|
| - // bar animation: expand -> contract
|
| if (cl.contains('expand')) {
|
| cl.remove('expand');
|
| cl.add('contract');
|
| this._positionBar(this._pos.width, this._pos.left);
|
| - // bar animation done
|
| } else if (cl.contains('contract')) {
|
| cl.remove('contract');
|
| }
|
| @@ -6497,11 +4733,6 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The value of mode is used to set the `aria-live` attribute
|
| - * for the element that will be announced. Valid values are: `off`,
|
| - * `polite` and `assertive`.
|
| - */
|
| mode: {
|
| type: String,
|
| value: 'polite'
|
| @@ -6521,11 +4752,6 @@ Polymer({
|
| document.body.addEventListener('iron-announce', this._onIronAnnounce.bind(this));
|
| },
|
|
|
| - /**
|
| - * Cause a text string to be announced by screen readers.
|
| - *
|
| - * @param {string} text The text that should be announced.
|
| - */
|
| announce: function(text) {
|
| this._text = '';
|
| this.async(function() {
|
| @@ -6550,49 +4776,16 @@ Polymer({
|
| document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
|
| };
|
| })();
|
| -/**
|
| - * Singleton IronMeta instance.
|
| - */
|
| Polymer.IronValidatableBehaviorMeta = null;
|
|
|
| - /**
|
| - * `Use Polymer.IronValidatableBehavior` to implement an element that validates user input.
|
| - * Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input.
|
| - *
|
| - * By default, an `<iron-form>` element validates its fields when the user presses the submit button.
|
| - * To validate a form imperatively, call the form's `validate()` method, which in turn will
|
| - * call `validate()` on all its children. By using `Polymer.IronValidatableBehavior`, your
|
| - * custom element will get a public `validate()`, which
|
| - * will return the validity of the element, and a corresponding `invalid` attribute,
|
| - * which can be used for styling.
|
| - *
|
| - * To implement the custom validation logic of your element, you must override
|
| - * the protected `_getValidity()` method of this behaviour, rather than `validate()`.
|
| - * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/simple-element.html)
|
| - * for an example.
|
| - *
|
| - * ### Accessibility
|
| - *
|
| - * Changing the `invalid` property, either manually or by calling `validate()` will update the
|
| - * `aria-invalid` attribute.
|
| - *
|
| - * @demo demo/index.html
|
| - * @polymerBehavior
|
| - */
|
| Polymer.IronValidatableBehavior = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Name of the validator to use.
|
| - */
|
| validator: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * True if the last call to `validate` is invalid.
|
| - */
|
| invalid: {
|
| notify: true,
|
| reflectToAttribute: true,
|
| @@ -6600,19 +4793,10 @@ Polymer({
|
| value: false
|
| },
|
|
|
| - /**
|
| - * This property is deprecated and should not be used. Use the global
|
| - * validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead.
|
| - */
|
| _validatorMeta: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * Namespace for this validator. This property is deprecated and should
|
| - * not be used. For all intents and purposes, please consider it a
|
| - * read-only, config-time property.
|
| - */
|
| validatorType: {
|
| type: String,
|
| value: 'validator'
|
| @@ -6640,36 +4824,15 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * @return {boolean} True if the validator `validator` exists.
|
| - */
|
| hasValidator: function() {
|
| return this._validator != null;
|
| },
|
|
|
| - /**
|
| - * Returns true if the `value` is valid, and updates `invalid`. If you want
|
| - * your element to have custom validation logic, do not override this method;
|
| - * override `_getValidity(value)` instead.
|
| -
|
| - * @param {Object} value The value to be validated. By default, it is passed
|
| - * to the validator's `validate()` function, if a validator is set.
|
| - * @return {boolean} True if `value` is valid.
|
| - */
|
| validate: function(value) {
|
| this.invalid = !this._getValidity(value);
|
| return !this.invalid;
|
| },
|
|
|
| - /**
|
| - * Returns true if `value` is valid. By default, it is passed
|
| - * to the validator's `validate()` function, if a validator is set. You
|
| - * should override this method if you want to implement custom validity
|
| - * logic for your element.
|
| - *
|
| - * @param {Object} value The value to be validated.
|
| - * @return {boolean} True if `value` is valid.
|
| - */
|
|
|
| _getValidity: function(value) {
|
| if (this.hasValidator()) {
|
| @@ -6683,39 +4846,6 @@ Polymer({
|
| Polymer.IronValidatableBehaviorMeta.byKey(this.validator);
|
| }
|
| };
|
| -/*
|
| -`<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior`
|
| -to `<input>`.
|
| -
|
| -### Two-way binding
|
| -
|
| -By default you can only get notified of changes to an `input`'s `value` due to user input:
|
| -
|
| - <input value="{{myValue::input}}">
|
| -
|
| -`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used
|
| -for two-way data binding. `bind-value` will notify if it is changed either by user input or by script.
|
| -
|
| - <input is="iron-input" bind-value="{{myValue}}">
|
| -
|
| -### Custom validators
|
| -
|
| -You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`.
|
| -
|
| - <input is="iron-input" validator="my-custom-validator">
|
| -
|
| -### Stopping invalid input
|
| -
|
| -It may be desirable to only allow users to enter certain characters. You can use the
|
| -`prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature
|
| -is separate from validation, and `allowed-pattern` does not affect how the input is validated.
|
| -
|
| - \x3c!-- only allow characters that match [0-9] --\x3e
|
| - <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]">
|
| -
|
| -@hero hero.svg
|
| -@demo demo/index.html
|
| -*/
|
|
|
| Polymer({
|
|
|
| @@ -6729,32 +4859,15 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Use this property instead of `value` for two-way data binding.
|
| - */
|
| bindValue: {
|
| observer: '_bindValueChanged',
|
| type: String
|
| },
|
|
|
| - /**
|
| - * Set to true to prevent the user from entering invalid input. If `allowedPattern` is set,
|
| - * any character typed by the user will be matched against that pattern, and rejected if it's not a match.
|
| - * Pasted input will have each character checked individually; if any character
|
| - * doesn't match `allowedPattern`, the entire pasted string will be rejected.
|
| - * If `allowedPattern` is not set, it will use the `type` attribute (only supported for `type=number`).
|
| - */
|
| preventInvalidInput: {
|
| type: Boolean
|
| },
|
|
|
| - /**
|
| - * Regular expression that list the characters allowed as input.
|
| - * This pattern represents the allowed characters for the field; as the user inputs text,
|
| - * each individual character will be checked against the pattern (rather than checking
|
| - * the entire value as a whole). The recommended format should be a list of allowed characters;
|
| - * for example, `[a-zA-Z0-9.+-!;:]`
|
| - */
|
| allowedPattern: {
|
| type: String,
|
| observer: "_allowedPatternChanged"
|
| @@ -6779,7 +4892,6 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
|
|
| /** @suppress {checkTypes} */
|
| registered: function() {
|
| - // Feature detect whether we need to patch dispatchEvent (i.e. on FF and IE).
|
| if (!this._canDispatchEventOnDisabled()) {
|
| this._origDispatchEvent = this.dispatchEvent;
|
| this.dispatchEvent = this._dispatchEventFirefoxIE;
|
| @@ -6807,11 +4919,6 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| },
|
|
|
| _dispatchEventFirefoxIE: function() {
|
| - // Due to Firefox bug, events fired on disabled form controls can throw
|
| - // errors; furthermore, neither IE nor Firefox will actually dispatch
|
| - // events from disabled form controls; as such, we toggle disable around
|
| - // the dispatch to allow notifying properties to notify
|
| - // See issue #47 for details
|
| var disabled = this.disabled;
|
| this.disabled = false;
|
| this._origDispatchEvent.apply(this, arguments);
|
| @@ -6836,25 +4943,18 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| this.bindValue = this.value;
|
| },
|
|
|
| - /**
|
| - * @suppress {checkTypes}
|
| - */
|
| _bindValueChanged: function() {
|
| if (this.value !== this.bindValue) {
|
| this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue === false) ? '' : this.bindValue;
|
| }
|
| - // manually notify because we don't want to notify until after setting value
|
| this.fire('bind-value-changed', {value: this.bindValue});
|
| },
|
|
|
| _allowedPatternChanged: function() {
|
| - // Force to prevent invalid input when an `allowed-pattern` is set
|
| this.preventInvalidInput = this.allowedPattern ? true : false;
|
| },
|
|
|
| _onInput: function() {
|
| - // Need to validate each of the characters pasted if they haven't
|
| - // been validated inside `_onKeypress` already.
|
| if (this.preventInvalidInput && !this._patternAlreadyChecked) {
|
| var valid = this._checkPatternValidity();
|
| if (!valid) {
|
| @@ -6869,24 +4969,13 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| },
|
|
|
| _isPrintable: function(event) {
|
| - // What a control/printable character is varies wildly based on the browser.
|
| - // - most control characters (arrows, backspace) do not send a `keypress` event
|
| - // in Chrome, but the *do* on Firefox
|
| - // - in Firefox, when they do send a `keypress` event, control chars have
|
| - // a charCode = 0, keyCode = xx (for ex. 40 for down arrow)
|
| - // - printable characters always send a keypress event.
|
| - // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the keyCode
|
| - // always matches the charCode.
|
| - // None of this makes any sense.
|
| -
|
| - // For these keys, ASCII code == browser keycode.
|
| +
|
| var anyNonPrintable =
|
| (event.keyCode == 8) || // backspace
|
| (event.keyCode == 9) || // tab
|
| (event.keyCode == 13) || // enter
|
| (event.keyCode == 27); // escape
|
|
|
| - // For these keys, make sure it's a browser keycode and not an ASCII code.
|
| var mozNonPrintable =
|
| (event.keyCode == 19) || // pause
|
| (event.keyCode == 20) || // caps lock
|
| @@ -6909,11 +4998,9 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| return;
|
| }
|
|
|
| - // Handle special keys and backspace
|
| if (event.metaKey || event.ctrlKey || event.altKey)
|
| return;
|
|
|
| - // Check the pattern either here or in `_onInput`, but not in both.
|
| this._patternAlreadyChecked = true;
|
|
|
| var thisChar = String.fromCharCode(event.charCode);
|
| @@ -6936,20 +5023,10 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| return true;
|
| },
|
|
|
| - /**
|
| - * Returns true if `value` is valid. The validator provided in `validator` will be used first,
|
| - * then any constraints.
|
| - * @return {boolean} True if the value is valid.
|
| - */
|
| validate: function() {
|
| - // First, check what the browser thinks. Some inputs (like type=number)
|
| - // behave weirdly and will set the value to "" if something invalid is
|
| - // entered, but will set the validity correctly.
|
| var valid = this.checkValidity();
|
|
|
| - // Only do extra checking if the browser thought this was valid.
|
| if (valid) {
|
| - // Empty, required input is invalid
|
| if (this.required && this.value === '') {
|
| valid = false;
|
| } else if (this.hasValidator()) {
|
| @@ -6967,60 +5044,36 @@ is separate from validation, and `allowed-pattern` does not affect how the input
|
| }
|
| });
|
|
|
| - /*
|
| - The `iron-input-validate` event is fired whenever `validate()` is called.
|
| - @event iron-input-validate
|
| - */
|
| Polymer({
|
| is: 'paper-input-container',
|
|
|
| properties: {
|
| - /**
|
| - * Set to true to disable the floating label. The label disappears when the input value is
|
| - * not null.
|
| - */
|
| noLabelFloat: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Set to true to always float the floating label.
|
| - */
|
| alwaysFloatLabel: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * The attribute to listen for value changes on.
|
| - */
|
| attrForValue: {
|
| type: String,
|
| value: 'bind-value'
|
| },
|
|
|
| - /**
|
| - * Set to true to auto-validate the input value when it changes.
|
| - */
|
| autoValidate: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * True if the input is invalid. This property is set automatically when the input value
|
| - * changes if auto-validating, or when the `iron-input-validate` event is heard from a child.
|
| - */
|
| invalid: {
|
| observer: '_invalidChanged',
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * True if the input has focus.
|
| - */
|
| focused: {
|
| readOnly: true,
|
| type: Boolean,
|
| @@ -7030,9 +5083,6 @@ Polymer({
|
|
|
| _addons: {
|
| type: Array
|
| - // do not set a default value here intentionally - it will be initialized lazily when a
|
| - // distributed child is attached, which may occur before configuration for this element
|
| - // in polyfill.
|
| },
|
|
|
| _inputHasContent: {
|
| @@ -7110,7 +5160,6 @@ Polymer({
|
| this.addEventListener('input', this._onInput);
|
| }
|
|
|
| - // Only validate when attached if the input already has a value.
|
| if (this._inputElementValue != '') {
|
| this._handleValueAndAutoValidate(this._inputElement);
|
| } else {
|
| @@ -7151,7 +5200,6 @@ Polymer({
|
| _handleValue: function(inputElement) {
|
| var value = this._inputElementValue;
|
|
|
| - // type="number" hack needed because this.value is empty until it's valid
|
| if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) {
|
| this._inputHasContent = true;
|
| } else {
|
| @@ -7176,7 +5224,6 @@ Polymer({
|
| this.invalid = !valid;
|
| }
|
|
|
| - // Call this last to notify the add-ons.
|
| this._handleValue(inputElement);
|
| },
|
|
|
| @@ -7190,10 +5237,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Call this to update the state of add-ons.
|
| - * @param {Object} state Add-on state.
|
| - */
|
| updateAddons: function(state) {
|
| for (var addon, index = 0; addon = this._addons[index]; index++) {
|
| addon.update(state);
|
| @@ -7207,8 +5250,6 @@ Polymer({
|
|
|
| if (alwaysFloatLabel || _inputHasContent) {
|
| cls += ' label-is-floating';
|
| - // If the label is floating, ignore any offsets that may have been
|
| - // applied from a prefix element.
|
| this.$.labelAndInputContainer.style.position = 'static';
|
|
|
| if (invalid) {
|
| @@ -7217,7 +5258,6 @@ Polymer({
|
| cls += " label-is-highlighted";
|
| }
|
| } else {
|
| - // When the label is not floating, it should overlap the input element.
|
| if (label) {
|
| this.$.labelAndInputContainer.style.position = 'relative';
|
| }
|
| @@ -7259,9 +5299,6 @@ Polymer({
|
| },
|
|
|
| properties: {
|
| - /**
|
| - * Displays the spinner.
|
| - */
|
| active: {
|
| type: Boolean,
|
| value: false,
|
| @@ -7269,11 +5306,6 @@ Polymer({
|
| observer: '__activeChanged'
|
| },
|
|
|
| - /**
|
| - * Alternative text content for accessibility support.
|
| - * If alt is present, it will add an aria-label whose content matches alt when active.
|
| - * If alt is not present, it will default to 'loading' as the alt value.
|
| - */
|
| alt: {
|
| type: String,
|
| value: 'loading',
|
| @@ -7299,7 +5331,6 @@ Polymer({
|
| },
|
|
|
| __altChanged: function(alt) {
|
| - // user-provided `aria-label` takes precedence over prototype default
|
| if (alt === this.getPropertyInfo('alt').value) {
|
| this.alt = this.getAttribute('aria-label') || alt;
|
| } else {
|
| @@ -7333,11 +5364,6 @@ Polymer({
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * Implements an incremental search field which can be shown and hidden.
|
| - * Canonical implementation is <cr-search-field>.
|
| - * @polymerBehavior
|
| - */
|
| var CrSearchFieldBehavior = {
|
| properties: {
|
| label: {
|
| @@ -7365,27 +5391,13 @@ var CrSearchFieldBehavior = {
|
| },
|
| },
|
|
|
| - /**
|
| - * @abstract
|
| - * @return {!HTMLInputElement} The input field element the behavior should
|
| - * use.
|
| - */
|
| getSearchInput: function() {},
|
|
|
| - /**
|
| - * @return {string} The value of the search field.
|
| - */
|
| getValue: function() {
|
| return this.getSearchInput().value;
|
| },
|
|
|
| - /**
|
| - * Sets the value of the search field.
|
| - * @param {string} value
|
| - */
|
| setValue: function(value) {
|
| - // Use bindValue when setting the input value so that changes propagate
|
| - // correctly.
|
| this.getSearchInput().bindValue = value;
|
| this.onValueChanged_(value);
|
| },
|
| @@ -7404,12 +5416,6 @@ var CrSearchFieldBehavior = {
|
| this.onValueChanged_(this.getValue());
|
| },
|
|
|
| - /**
|
| - * Updates the internal state of the search field based on a change that has
|
| - * already happened.
|
| - * @param {string} newValue
|
| - * @private
|
| - */
|
| onValueChanged_: function(newValue) {
|
| if (newValue == this.lastValue_)
|
| return;
|
| @@ -7438,7 +5444,6 @@ var CrSearchFieldBehavior = {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -// TODO(tsergeant): Add tests for cr-toolbar-search-field.
|
| Polymer({
|
| is: 'cr-toolbar-search-field',
|
|
|
| @@ -7450,14 +5455,10 @@ Polymer({
|
| reflectToAttribute: true,
|
| },
|
|
|
| - // Prompt text to display in the search field.
|
| label: String,
|
|
|
| - // Tooltip to display on the clear search button.
|
| clearLabel: String,
|
|
|
| - // When true, show a loading spinner to indicate that the backend is
|
| - // processing the search. Will only show if the search field is open.
|
| spinnerActive: {
|
| type: Boolean,
|
| reflectToAttribute: true
|
| @@ -7482,21 +5483,10 @@ Polymer({
|
| return this.$.searchTerm.focused;
|
| },
|
|
|
| - /**
|
| - * @param {boolean} narrow
|
| - * @return {number}
|
| - * @private
|
| - */
|
| computeIconTabIndex_: function(narrow) {
|
| return narrow ? 0 : -1;
|
| },
|
|
|
| - /**
|
| - * @param {boolean} spinnerActive
|
| - * @param {boolean} showingSearch
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| isSpinnerShown_: function(spinnerActive, showingSearch) {
|
| return spinnerActive && showingSearch;
|
| },
|
| @@ -7507,12 +5497,6 @@ Polymer({
|
| this.showingSearch = false;
|
| },
|
|
|
| - /**
|
| - * Update the state of the search field whenever the underlying input value
|
| - * changes. Unlike onsearch or onkeypress, this is reliably called immediately
|
| - * after any change, whether the result of user input or JS modification.
|
| - * @private
|
| - */
|
| onBindValueChanged_: function() {
|
| var newValue = this.$.searchInput.bindValue;
|
| this.hasSearchText_ = newValue != '';
|
| @@ -7520,19 +5504,11 @@ Polymer({
|
| this.showingSearch = true;
|
| },
|
|
|
| - /**
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| showSearch_: function(e) {
|
| if (e.target != this.$.clearSearch)
|
| this.showingSearch = true;
|
| },
|
|
|
| - /**
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| hideSearch_: function(e) {
|
| this.showingSearch = false;
|
| e.stopPropagation();
|
| @@ -7546,20 +5522,14 @@ Polymer({
|
| is: 'cr-toolbar',
|
|
|
| properties: {
|
| - // Name to display in the toolbar, in titlecase.
|
| pageName: String,
|
|
|
| - // Prompt text to display in the search field.
|
| searchPrompt: String,
|
|
|
| - // Tooltip to display on the clear search button.
|
| clearLabel: String,
|
|
|
| - // Value is proxied through to cr-toolbar-search-field. When true,
|
| - // the search field will show a processing spinner.
|
| spinnerActive: Boolean,
|
|
|
| - // Controls whether the menu button is shown at the start of the menu.
|
| showMenu: {
|
| type: Boolean,
|
| reflectToAttribute: true,
|
| @@ -7596,32 +5566,23 @@ Polymer({
|
| Polymer({
|
| is: 'history-toolbar',
|
| properties: {
|
| - // Number of history items currently selected.
|
| - // TODO(calamity): bind this to
|
| - // listContainer.selectedItem.selectedPaths.length.
|
| count: {
|
| type: Number,
|
| value: 0,
|
| observer: 'changeToolbarView_'
|
| },
|
|
|
| - // True if 1 or more history items are selected. When this value changes
|
| - // the background colour changes.
|
| itemsSelected_: {
|
| type: Boolean,
|
| value: false,
|
| reflectToAttribute: true
|
| },
|
|
|
| - // The most recent term entered in the search field. Updated incrementally
|
| - // as the user types.
|
| searchTerm: {
|
| type: String,
|
| notify: true,
|
| },
|
|
|
| - // True if the backend is processing and a spinner should be shown in the
|
| - // toolbar.
|
| spinnerActive: {
|
| type: Boolean,
|
| value: false
|
| @@ -7633,13 +5594,11 @@ Polymer({
|
| reflectToAttribute: true,
|
| },
|
|
|
| - // Whether domain-grouped history is enabled.
|
| isGroupedMode: {
|
| type: Boolean,
|
| reflectToAttribute: true,
|
| },
|
|
|
| - // The period to search over. Matches BrowsingHistoryHandler::Range.
|
| groupedRange: {
|
| type: Number,
|
| value: 0,
|
| @@ -7647,27 +5606,15 @@ Polymer({
|
| notify: true
|
| },
|
|
|
| - // The start time of the query range.
|
| queryStartTime: String,
|
|
|
| - // The end time of the query range.
|
| queryEndTime: String,
|
| },
|
|
|
| - /**
|
| - * Changes the toolbar background color depending on whether any history items
|
| - * are currently selected.
|
| - * @private
|
| - */
|
| changeToolbarView_: function() {
|
| this.itemsSelected_ = this.count > 0;
|
| },
|
|
|
| - /**
|
| - * When changing the search term externally, update the search field to
|
| - * reflect the new search term.
|
| - * @param {string} search
|
| - */
|
| setSearchTerm: function(search) {
|
| if (this.searchTerm == search)
|
| return;
|
| @@ -7679,10 +5626,6 @@ Polymer({
|
| searchField.setValue(search);
|
| },
|
|
|
| - /**
|
| - * @param {!CustomEvent} event
|
| - * @private
|
| - */
|
| onSearchChanged_: function(event) {
|
| this.searchTerm = /** @type {string} */ (event.detail);
|
| },
|
| @@ -7705,10 +5648,6 @@ Polymer({
|
| .showAndFocus();
|
| },
|
|
|
| - /**
|
| - * If the user is a supervised user the delete button is not shown.
|
| - * @private
|
| - */
|
| deletingAllowed_: function() {
|
| return loadTimeData.getBoolean('allowDeletingHistory');
|
| },
|
| @@ -7718,7 +5657,6 @@ Polymer({
|
| },
|
|
|
| getHistoryInterval_: function(queryStartTime, queryEndTime) {
|
| - // TODO(calamity): Fix the format of these dates.
|
| return loadTimeData.getStringF(
|
| 'historyInterval', queryStartTime, queryEndTime);
|
| },
|
| @@ -7732,15 +5670,6 @@ Polymer({
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @fileoverview 'cr-dialog' is a component for showing a modal dialog. If the
|
| - * dialog is closed via close(), a 'close' event is fired. If the dialog is
|
| - * canceled via cancel(), a 'cancel' event is fired followed by a 'close' event.
|
| - * Additionally clients can inspect the dialog's |returnValue| property inside
|
| - * the 'close' event listener to determine whether it was canceled or just
|
| - * closed, where a truthy value means success, and a falsy value means it was
|
| - * canceled.
|
| - */
|
| Polymer({
|
| is: 'cr-dialog',
|
| extends: 'dialog',
|
| @@ -7750,10 +5679,6 @@ Polymer({
|
| HTMLDialogElement.prototype.close.call(this, '');
|
| },
|
|
|
| - /**
|
| - * @param {string=} opt_returnValue
|
| - * @override
|
| - */
|
| close: function(opt_returnValue) {
|
| HTMLDialogElement.prototype.close.call(this, 'success');
|
| },
|
| @@ -7763,52 +5688,11 @@ Polymer({
|
| return this.$.close;
|
| },
|
| });
|
| -/**
|
| -`Polymer.IronFitBehavior` fits an element in another element using `max-height` and `max-width`, and
|
| -optionally centers it in the window or another element.
|
| -
|
| -The element will only be sized and/or positioned if it has not already been sized and/or positioned
|
| -by CSS.
|
| -
|
| -CSS properties | Action
|
| ------------------------------|-------------------------------------------
|
| -`position` set | Element is not centered horizontally or vertically
|
| -`top` or `bottom` set | Element is not vertically centered
|
| -`left` or `right` set | Element is not horizontally centered
|
| -`max-height` set | Element respects `max-height`
|
| -`max-width` set | Element respects `max-width`
|
| -
|
| -`Polymer.IronFitBehavior` can position an element into another element using
|
| -`verticalAlign` and `horizontalAlign`. This will override the element's css position.
|
| -
|
| - <div class="container">
|
| - <iron-fit-impl vertical-align="top" horizontal-align="auto">
|
| - Positioned into the container
|
| - </iron-fit-impl>
|
| - </div>
|
| -
|
| -Use `noOverlap` to position the element around another element without overlapping it.
|
| -
|
| - <div class="container">
|
| - <iron-fit-impl no-overlap vertical-align="auto" horizontal-align="auto">
|
| - Positioned around the container
|
| - </iron-fit-impl>
|
| - </div>
|
| -
|
| -@demo demo/index.html
|
| -@polymerBehavior
|
| -*/
|
|
|
| Polymer.IronFitBehavior = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * The element that will receive a `max-height`/`width`. By default it is the same as `this`,
|
| - * but it can be set to a child element. This is useful, for example, for implementing a
|
| - * scrolling region inside the element.
|
| - * @type {!Element}
|
| - */
|
| sizingTarget: {
|
| type: Object,
|
| value: function() {
|
| @@ -7816,77 +5700,43 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * The element to fit `this` into.
|
| - */
|
| fitInto: {
|
| type: Object,
|
| value: window
|
| },
|
|
|
| - /**
|
| - * Will position the element around the positionTarget without overlapping it.
|
| - */
|
| noOverlap: {
|
| type: Boolean
|
| },
|
|
|
| - /**
|
| - * The element that should be used to position the element. If not set, it will
|
| - * default to the parent node.
|
| - * @type {!Element}
|
| - */
|
| positionTarget: {
|
| type: Element
|
| },
|
|
|
| - /**
|
| - * The orientation against which to align the element horizontally
|
| - * relative to the `positionTarget`. Possible values are "left", "right", "auto".
|
| - */
|
| horizontalAlign: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The orientation against which to align the element vertically
|
| - * relative to the `positionTarget`. Possible values are "top", "bottom", "auto".
|
| - */
|
| verticalAlign: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * If true, it will use `horizontalAlign` and `verticalAlign` values as preferred alignment
|
| - * and if there's not enough space, it will pick the values which minimize the cropping.
|
| - */
|
| dynamicAlign: {
|
| type: Boolean
|
| },
|
|
|
| - /**
|
| - * The same as setting margin-left and margin-right css properties.
|
| - * @deprecated
|
| - */
|
| horizontalOffset: {
|
| type: Number,
|
| value: 0,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * The same as setting margin-top and margin-bottom css properties.
|
| - * @deprecated
|
| - */
|
| verticalOffset: {
|
| type: Number,
|
| value: 0,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * Set to true to auto-fit on attach.
|
| - */
|
| autoFitOnAttach: {
|
| type: Boolean,
|
| value: false
|
| @@ -7938,10 +5788,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return fitTop;
|
| },
|
|
|
| - /**
|
| - * The element that should be used to position the element,
|
| - * if no position target is configured.
|
| - */
|
| get _defaultPositionTarget() {
|
| var parent = Polymer.dom(this).parentNode;
|
|
|
| @@ -7952,12 +5798,8 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return parent;
|
| },
|
|
|
| - /**
|
| - * The horizontal align value, accounting for the RTL/LTR text direction.
|
| - */
|
| get _localeHorizontalAlign() {
|
| if (this._isRTL) {
|
| - // In RTL, "left" becomes "right".
|
| if (this.horizontalAlign === 'right') {
|
| return 'left';
|
| }
|
| @@ -7969,7 +5811,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| },
|
|
|
| attached: function() {
|
| - // Memoize this to avoid expensive calculations & relayouts.
|
| this._isRTL = window.getComputedStyle(this).direction == 'rtl';
|
| this.positionTarget = this.positionTarget || this._defaultPositionTarget;
|
| if (this.autoFitOnAttach) {
|
| @@ -7983,19 +5824,12 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Positions and fits the element into the `fitInto` element.
|
| - */
|
| fit: function() {
|
| this.position();
|
| this.constrain();
|
| this.center();
|
| },
|
|
|
| - /**
|
| - * Memoize information needed to position and size the target element.
|
| - * @suppress {deprecated}
|
| - */
|
| _discoverInfo: function() {
|
| if (this._fitInfo) {
|
| return;
|
| @@ -8034,7 +5868,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| };
|
|
|
| - // Support these properties until they are removed.
|
| if (this.verticalOffset) {
|
| this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffset;
|
| this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
|
| @@ -8049,10 +5882,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Resets the target element's position and size constraints, and clear
|
| - * the memoized data.
|
| - */
|
| resetFit: function() {
|
| var info = this._fitInfo || {};
|
| for (var property in info.sizerInlineStyle) {
|
| @@ -8065,12 +5894,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this._fitInfo = null;
|
| },
|
|
|
| - /**
|
| - * Equivalent to calling `resetFit()` and `fit()`. Useful to call this after
|
| - * the element or the `fitInto` element has been resized, or if any of the
|
| - * positioning properties (e.g. `horizontalAlign, verticalAlign`) is updated.
|
| - * It preserves the scroll position of the sizingTarget.
|
| - */
|
| refit: function() {
|
| var scrollLeft = this.sizingTarget.scrollLeft;
|
| var scrollTop = this.sizingTarget.scrollTop;
|
| @@ -8080,20 +5903,14 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.sizingTarget.scrollTop = scrollTop;
|
| },
|
|
|
| - /**
|
| - * Positions the element according to `horizontalAlign, verticalAlign`.
|
| - */
|
| position: function() {
|
| if (!this.horizontalAlign && !this.verticalAlign) {
|
| - // needs to be centered, and it is done after constrain.
|
| return;
|
| }
|
| this._discoverInfo();
|
|
|
| this.style.position = 'fixed';
|
| - // Need border-box for margin/padding.
|
| this.sizingTarget.style.boxSizing = 'border-box';
|
| - // Set to 0, 0 in order to discover any offset caused by parent stacking contexts.
|
| this.style.left = '0px';
|
| this.style.top = '0px';
|
|
|
| @@ -8103,7 +5920,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
|
|
| var margin = this._fitInfo.margin;
|
|
|
| - // Consider the margin as part of the size for position calculations.
|
| var size = {
|
| width: rect.width + margin.left + margin.right,
|
| height: rect.height + margin.top + margin.bottom
|
| @@ -8114,7 +5930,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| var left = position.left + margin.left;
|
| var top = position.top + margin.top;
|
|
|
| - // Use original size (without margin).
|
| var right = Math.min(fitRect.right - margin.right, left + rect.width);
|
| var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
|
|
|
| @@ -8136,15 +5951,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.sizingTarget.style.maxWidth = (right - left) + 'px';
|
| this.sizingTarget.style.maxHeight = (bottom - top) + 'px';
|
|
|
| - // Remove the offset caused by any stacking context.
|
| this.style.left = (left - rect.left) + 'px';
|
| this.style.top = (top - rect.top) + 'px';
|
| },
|
|
|
| - /**
|
| - * Constrains the size of the element to `fitInto` by setting `max-height`
|
| - * and/or `max-width`.
|
| - */
|
| constrain: function() {
|
| if (this.horizontalAlign || this.verticalAlign) {
|
| return;
|
| @@ -8152,7 +5962,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this._discoverInfo();
|
|
|
| var info = this._fitInfo;
|
| - // position at (0px, 0px) if not already positioned, so we can measure the natural size.
|
| if (!info.positionedBy.vertically) {
|
| this.style.position = 'fixed';
|
| this.style.top = '0px';
|
| @@ -8162,9 +5971,7 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.style.left = '0px';
|
| }
|
|
|
| - // need border-box for margin/padding
|
| this.sizingTarget.style.boxSizing = 'border-box';
|
| - // constrain the width and height if not already set
|
| var rect = this.getBoundingClientRect();
|
| if (!info.sizedBy.height) {
|
| this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
|
| @@ -8174,17 +5981,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * @protected
|
| - * @deprecated
|
| - */
|
| _sizeDimension: function(rect, positionedBy, start, end, extent) {
|
| this.__sizeDimension(rect, positionedBy, start, end, extent);
|
| },
|
|
|
| - /**
|
| - * @private
|
| - */
|
| __sizeDimension: function(rect, positionedBy, start, end, extent) {
|
| var info = this._fitInfo;
|
| var fitRect = this.__getNormalizedRect(this.fitInto);
|
| @@ -8197,10 +5997,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.sizingTarget.style['max' + extent] = (max - margin - offset - sizingOffset) + 'px';
|
| },
|
|
|
| - /**
|
| - * Centers horizontally and vertically if not already positioned. This also sets
|
| - * `position:fixed`.
|
| - */
|
| center: function() {
|
| if (this.horizontalAlign || this.verticalAlign) {
|
| return;
|
| @@ -8209,21 +6005,15 @@ Use `noOverlap` to position the element around another element without overlappi
|
|
|
| var positionedBy = this._fitInfo.positionedBy;
|
| if (positionedBy.vertically && positionedBy.horizontally) {
|
| - // Already positioned.
|
| return;
|
| }
|
| - // Need position:fixed to center
|
| this.style.position = 'fixed';
|
| - // Take into account the offset caused by parents that create stacking
|
| - // contexts (e.g. with transform: translate3d). Translate to 0,0 and
|
| - // measure the bounding rect.
|
| if (!positionedBy.vertically) {
|
| this.style.top = '0px';
|
| }
|
| if (!positionedBy.horizontally) {
|
| this.style.left = '0px';
|
| }
|
| - // It will take in consideration margins and transforms
|
| var rect = this.getBoundingClientRect();
|
| var fitRect = this.__getNormalizedRect(this.fitInto);
|
| if (!positionedBy.vertically) {
|
| @@ -8258,8 +6048,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
|
|
|
|
| __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
|
| - // All the possible configurations.
|
| - // Ordered as top-left, top-right, bottom-left, bottom-right.
|
| var positions = [{
|
| verticalAlign: 'top',
|
| horizontalAlign: 'left',
|
| @@ -8283,7 +6071,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }];
|
|
|
| if (this.noOverlap) {
|
| - // Duplicate.
|
| for (var i = 0, l = positions.length; i < l; i++) {
|
| var copy = {};
|
| for (var key in positions[i]) {
|
| @@ -8291,15 +6078,12 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| positions.push(copy);
|
| }
|
| - // Horizontal overlap only.
|
| positions[0].top = positions[1].top += positionRect.height;
|
| positions[2].top = positions[3].top -= positionRect.height;
|
| - // Vertical overlap only.
|
| positions[4].left = positions[6].left += positionRect.width;
|
| positions[5].left = positions[7].left -= positionRect.width;
|
| }
|
|
|
| - // Consider auto as null for coding convenience.
|
| vAlign = vAlign === 'auto' ? null : vAlign;
|
| hAlign = hAlign === 'auto' ? null : hAlign;
|
|
|
| @@ -8307,23 +6091,15 @@ Use `noOverlap` to position the element around another element without overlappi
|
| for (var i = 0; i < positions.length; i++) {
|
| var pos = positions[i];
|
|
|
| - // If both vAlign and hAlign are defined, return exact match.
|
| - // For dynamicAlign and noOverlap we'll have more than one candidate, so
|
| - // we'll have to check the croppedArea to make the best choice.
|
| if (!this.dynamicAlign && !this.noOverlap &&
|
| pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) {
|
| position = pos;
|
| break;
|
| }
|
|
|
| - // Align is ok if alignment preferences are respected. If no preferences,
|
| - // it is considered ok.
|
| var alignOk = (!vAlign || pos.verticalAlign === vAlign) &&
|
| (!hAlign || pos.horizontalAlign === hAlign);
|
|
|
| - // Filter out elements that don't match the alignment (if defined).
|
| - // With dynamicAlign, we need to consider all the positions to find the
|
| - // one that minimizes the cropped area.
|
| if (!this.dynamicAlign && !alignOk) {
|
| continue;
|
| }
|
| @@ -8331,13 +6107,9 @@ Use `noOverlap` to position the element around another element without overlappi
|
| position = position || pos;
|
| pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
|
| var diff = pos.croppedArea - position.croppedArea;
|
| - // Check which crops less. If it crops equally, check if align is ok.
|
| if (diff < 0 || (diff === 0 && alignOk)) {
|
| position = pos;
|
| }
|
| - // If not cropped and respects the align requirements, keep it.
|
| - // This allows to prefer positions overlapping horizontally over the
|
| - // ones overlapping vertically.
|
| if (position.croppedArea === 0 && alignOk) {
|
| break;
|
| }
|
| @@ -8356,9 +6128,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Returns true if the backdrop is opened.
|
| - */
|
| opened: {
|
| reflectToAttribute: true,
|
| type: Boolean,
|
| @@ -8373,7 +6142,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| },
|
|
|
| created: function() {
|
| - // Used to cancel previous requestAnimationFrame calls when opened changes.
|
| this.__openedRaf = null;
|
| },
|
|
|
| @@ -8381,32 +6149,20 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.opened && this._openedChanged(this.opened);
|
| },
|
|
|
| - /**
|
| - * Appends the backdrop to document body if needed.
|
| - */
|
| prepare: function() {
|
| if (this.opened && !this.parentNode) {
|
| Polymer.dom(document.body).appendChild(this);
|
| }
|
| },
|
|
|
| - /**
|
| - * Shows the backdrop.
|
| - */
|
| open: function() {
|
| this.opened = true;
|
| },
|
|
|
| - /**
|
| - * Hides the backdrop.
|
| - */
|
| close: function() {
|
| this.opened = false;
|
| },
|
|
|
| - /**
|
| - * Removes the backdrop from document body if needed.
|
| - */
|
| complete: function() {
|
| if (!this.opened && this.parentNode === document.body) {
|
| Polymer.dom(this.parentNode).removeChild(this);
|
| @@ -8419,17 +6175,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * @param {boolean} opened
|
| - * @private
|
| - */
|
| _openedChanged: function(opened) {
|
| if (opened) {
|
| - // Auto-attach.
|
| this.prepare();
|
| } else {
|
| - // Animation might be disabled via the mixin or opacity custom property.
|
| - // If it is disabled in other ways, it's up to the user to call complete.
|
| var cs = window.getComputedStyle(this);
|
| if (cs.transitionDuration === '0s' || cs.opacity == 0) {
|
| this.complete();
|
| @@ -8440,12 +6189,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return;
|
| }
|
|
|
| - // Always cancel previous requestAnimationFrame.
|
| if (this.__openedRaf) {
|
| window.cancelAnimationFrame(this.__openedRaf);
|
| this.__openedRaf = null;
|
| }
|
| - // Force relayout to ensure proper transitions.
|
| this.scrollTop = this.scrollTop;
|
| this.__openedRaf = window.requestAnimationFrame(function() {
|
| this.__openedRaf = null;
|
| @@ -8455,32 +6202,13 @@ Use `noOverlap` to position the element around another element without overlappi
|
| });
|
|
|
| })();
|
| -/**
|
| - * @struct
|
| - * @constructor
|
| - * @private
|
| - */
|
| Polymer.IronOverlayManagerClass = function() {
|
| - /**
|
| - * Used to keep track of the opened overlays.
|
| - * @private {Array<Element>}
|
| - */
|
| this._overlays = [];
|
|
|
| - /**
|
| - * iframes have a default z-index of 100,
|
| - * so this default should be at least that.
|
| - * @private {number}
|
| - */
|
| this._minimumZ = 101;
|
|
|
| - /**
|
| - * Memoized backdrop element.
|
| - * @private {Element|null}
|
| - */
|
| this._backdropElement = null;
|
|
|
| - // Enable document-wide tap recognizer.
|
| Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this));
|
|
|
| document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
|
| @@ -8491,10 +6219,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
|
|
| constructor: Polymer.IronOverlayManagerClass,
|
|
|
| - /**
|
| - * The shared backdrop element.
|
| - * @type {!Element} backdropElement
|
| - */
|
| get backdropElement() {
|
| if (!this._backdropElement) {
|
| this._backdropElement = document.createElement('iron-overlay-backdrop');
|
| @@ -8502,14 +6226,7 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return this._backdropElement;
|
| },
|
|
|
| - /**
|
| - * The deepest active element.
|
| - * @type {!Element} activeElement the active element
|
| - */
|
| get deepActiveElement() {
|
| - // document.activeElement can be null
|
| - // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
|
| - // In case of null, default it to document.body.
|
| var active = document.activeElement || document.body;
|
| while (active.root && Polymer.dom(active.root).activeElement) {
|
| active = Polymer.dom(active.root).activeElement;
|
| @@ -8517,11 +6234,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return active;
|
| },
|
|
|
| - /**
|
| - * Brings the overlay at the specified index to the front.
|
| - * @param {number} i
|
| - * @private
|
| - */
|
| _bringOverlayAtIndexToFront: function(i) {
|
| var overlay = this._overlays[i];
|
| if (!overlay) {
|
| @@ -8529,21 +6241,17 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| var lastI = this._overlays.length - 1;
|
| var currentOverlay = this._overlays[lastI];
|
| - // Ensure always-on-top overlay stays on top.
|
| if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
|
| lastI--;
|
| }
|
| - // If already the top element, return.
|
| if (i >= lastI) {
|
| return;
|
| }
|
| - // Update z-index to be on top.
|
| var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
|
| if (this._getZ(overlay) <= minimumZ) {
|
| this._applyOverlayZ(overlay, minimumZ);
|
| }
|
|
|
| - // Shift other overlays behind the new on top.
|
| while (i < lastI) {
|
| this._overlays[i] = this._overlays[i + 1];
|
| i++;
|
| @@ -8551,11 +6259,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this._overlays[lastI] = overlay;
|
| },
|
|
|
| - /**
|
| - * Adds the overlay and updates its z-index if it's opened, or removes it if it's closed.
|
| - * Also updates the backdrop z-index.
|
| - * @param {!Element} overlay
|
| - */
|
| addOrRemoveOverlay: function(overlay) {
|
| if (overlay.opened) {
|
| this.addOverlay(overlay);
|
| @@ -8564,11 +6267,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Tracks overlays for z-index and focus management.
|
| - * Ensures the last added overlay with always-on-top remains on top.
|
| - * @param {!Element} overlay
|
| - */
|
| addOverlay: function(overlay) {
|
| var i = this._overlays.indexOf(overlay);
|
| if (i >= 0) {
|
| @@ -8581,17 +6279,13 @@ Use `noOverlap` to position the element around another element without overlappi
|
| var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
|
| var newZ = this._getZ(overlay);
|
|
|
| - // Ensure always-on-top overlay stays on top.
|
| if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
|
| - // This bumps the z-index of +2.
|
| this._applyOverlayZ(currentOverlay, minimumZ);
|
| insertionIndex--;
|
| - // Update minimumZ to match previous overlay's z-index.
|
| var previousOverlay = this._overlays[insertionIndex - 1];
|
| minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
|
| }
|
|
|
| - // Update z-index and insert overlay.
|
| if (newZ <= minimumZ) {
|
| this._applyOverlayZ(overlay, minimumZ);
|
| }
|
| @@ -8600,9 +6294,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.trackBackdrop();
|
| },
|
|
|
| - /**
|
| - * @param {!Element} overlay
|
| - */
|
| removeOverlay: function(overlay) {
|
| var i = this._overlays.indexOf(overlay);
|
| if (i === -1) {
|
| @@ -8613,28 +6304,15 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.trackBackdrop();
|
| },
|
|
|
| - /**
|
| - * Returns the current overlay.
|
| - * @return {Element|undefined}
|
| - */
|
| currentOverlay: function() {
|
| var i = this._overlays.length - 1;
|
| return this._overlays[i];
|
| },
|
|
|
| - /**
|
| - * Returns the current overlay z-index.
|
| - * @return {number}
|
| - */
|
| currentOverlayZ: function() {
|
| return this._getZ(this.currentOverlay());
|
| },
|
|
|
| - /**
|
| - * Ensures that the minimum z-index of new overlays is at least `minimumZ`.
|
| - * This does not effect the z-index of any existing overlays.
|
| - * @param {number} minimumZ
|
| - */
|
| ensureMinimumZ: function(minimumZ) {
|
| this._minimumZ = Math.max(this._minimumZ, minimumZ);
|
| },
|
| @@ -8646,12 +6324,8 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Updates the backdrop z-index.
|
| - */
|
| trackBackdrop: function() {
|
| var overlay = this._overlayWithBackdrop();
|
| - // Avoid creating the backdrop if there is no overlay with backdrop.
|
| if (!overlay && !this._backdropElement) {
|
| return;
|
| }
|
| @@ -8659,9 +6333,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| this.backdropElement.opened = !!overlay;
|
| },
|
|
|
| - /**
|
| - * @return {Array<Element>}
|
| - */
|
| getBackdrops: function() {
|
| var backdrops = [];
|
| for (var i = 0; i < this._overlays.length; i++) {
|
| @@ -8672,19 +6343,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return backdrops;
|
| },
|
|
|
| - /**
|
| - * Returns the z-index for the backdrop.
|
| - * @return {number}
|
| - */
|
| backdropZ: function() {
|
| return this._getZ(this._overlayWithBackdrop()) - 1;
|
| },
|
|
|
| - /**
|
| - * Returns the first opened overlay that has a backdrop.
|
| - * @return {Element|undefined}
|
| - * @private
|
| - */
|
| _overlayWithBackdrop: function() {
|
| for (var i = 0; i < this._overlays.length; i++) {
|
| if (this._overlays[i].withBackdrop) {
|
| @@ -8693,17 +6355,10 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Calculates the minimum z-index for the overlay.
|
| - * @param {Element=} overlay
|
| - * @private
|
| - */
|
| _getZ: function(overlay) {
|
| var z = this._minimumZ;
|
| if (overlay) {
|
| var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).zIndex);
|
| - // Check if is a number
|
| - // Number.isNaN not supported in IE 10+
|
| if (z1 === z1) {
|
| z = z1;
|
| }
|
| @@ -8711,31 +6366,14 @@ Use `noOverlap` to position the element around another element without overlappi
|
| return z;
|
| },
|
|
|
| - /**
|
| - * @param {!Element} element
|
| - * @param {number|string} z
|
| - * @private
|
| - */
|
| _setZ: function(element, z) {
|
| element.style.zIndex = z;
|
| },
|
|
|
| - /**
|
| - * @param {!Element} overlay
|
| - * @param {number} aboveZ
|
| - * @private
|
| - */
|
| _applyOverlayZ: function(overlay, aboveZ) {
|
| this._setZ(overlay, aboveZ + 2);
|
| },
|
|
|
| - /**
|
| - * Returns the deepest overlay in the path.
|
| - * @param {Array<Element>=} path
|
| - * @return {Element|undefined}
|
| - * @suppress {missingProperties}
|
| - * @private
|
| - */
|
| _overlayInPath: function(path) {
|
| path = path || [];
|
| for (var i = 0; i < path.length; i++) {
|
| @@ -8745,24 +6383,13 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Ensures the click event is delegated to the right overlay.
|
| - * @param {!Event} event
|
| - * @private
|
| - */
|
| _onCaptureClick: function(event) {
|
| var overlay = /** @type {?} */ (this.currentOverlay());
|
| - // Check if clicked outside of top overlay.
|
| if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
|
| overlay._onCaptureClick(event);
|
| }
|
| },
|
|
|
| - /**
|
| - * Ensures the focus event is delegated to the right overlay.
|
| - * @param {!Event} event
|
| - * @private
|
| - */
|
| _onCaptureFocus: function(event) {
|
| var overlay = /** @type {?} */ (this.currentOverlay());
|
| if (overlay) {
|
| @@ -8770,11 +6397,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Ensures TAB and ESC keyboard events are delegated to the right overlay.
|
| - * @param {!Event} event
|
| - * @private
|
| - */
|
| _onCaptureKeyDown: function(event) {
|
| var overlay = /** @type {?} */ (this.currentOverlay());
|
| if (overlay) {
|
| @@ -8786,14 +6408,6 @@ Use `noOverlap` to position the element around another element without overlappi
|
| }
|
| },
|
|
|
| - /**
|
| - * Returns if the overlay1 should be behind overlay2.
|
| - * @param {!Element} overlay1
|
| - * @param {!Element} overlay2
|
| - * @return {boolean}
|
| - * @suppress {missingProperties}
|
| - * @private
|
| - */
|
| _shouldBeBehindOverlay: function(overlay1, overlay2) {
|
| return !overlay1.alwaysOnTop && overlay2.alwaysOnTop;
|
| }
|
| @@ -8803,56 +6417,11 @@ Use `noOverlap` to position the element around another element without overlappi
|
| (function() {
|
| 'use strict';
|
|
|
| -/**
|
| -Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or shown, and displays
|
| -on top of other content. It includes an optional backdrop, and can be used to implement a variety
|
| -of UI controls including dialogs and drop downs. Multiple overlays may be displayed at once.
|
| -
|
| -See the [demo source code](https://github.com/PolymerElements/iron-overlay-behavior/blob/master/demo/simple-overlay.html)
|
| -for an example.
|
| -
|
| -### Closing and canceling
|
| -
|
| -An overlay may be hidden by closing or canceling. The difference between close and cancel is user
|
| -intent. Closing generally implies that the user acknowledged the content on the overlay. By default,
|
| -it will cancel whenever the user taps outside it or presses the escape key. This behavior is
|
| -configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click` properties.
|
| -`close()` should be called explicitly by the implementer when the user interacts with a control
|
| -in the overlay element. When the dialog is canceled, the overlay fires an 'iron-overlay-canceled'
|
| -event. Call `preventDefault` on this event to prevent the overlay from closing.
|
| -
|
| -### Positioning
|
| -
|
| -By default the element is sized and positioned to fit and centered inside the window. You can
|
| -position and size it manually using CSS. See `Polymer.IronFitBehavior`.
|
| -
|
| -### Backdrop
|
| -
|
| -Set the `with-backdrop` attribute to display a backdrop behind the overlay. The backdrop is
|
| -appended to `<body>` and is of type `<iron-overlay-backdrop>`. See its doc page for styling
|
| -options.
|
| -
|
| -In addition, `with-backdrop` will wrap the focus within the content in the light DOM.
|
| -Override the [`_focusableNodes` getter](#Polymer.IronOverlayBehavior:property-_focusableNodes)
|
| -to achieve a different behavior.
|
| -
|
| -### Limitations
|
| -
|
| -The element is styled to appear on top of other content by setting its `z-index` property. You
|
| -must ensure no element has a stacking context with a higher `z-index` than its parent stacking
|
| -context. You should place this element as a child of `<body>` whenever possible.
|
| -
|
| -@demo demo/index.html
|
| -@polymerBehavior Polymer.IronOverlayBehavior
|
| -*/
|
|
|
| Polymer.IronOverlayBehaviorImpl = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * True if the overlay is currently displayed.
|
| - */
|
| opened: {
|
| observer: '_openedChanged',
|
| type: Boolean,
|
| @@ -8860,9 +6429,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * True if the overlay was canceled when it was last closed.
|
| - */
|
| canceled: {
|
| observer: '_canceledChanged',
|
| readOnly: true,
|
| @@ -8870,80 +6436,44 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Set to true to display a backdrop behind the overlay. It traps the focus
|
| - * within the light DOM of the overlay.
|
| - */
|
| withBackdrop: {
|
| observer: '_withBackdropChanged',
|
| type: Boolean
|
| },
|
|
|
| - /**
|
| - * Set to true to disable auto-focusing the overlay or child nodes with
|
| - * the `autofocus` attribute` when the overlay is opened.
|
| - */
|
| noAutoFocus: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Set to true to disable canceling the overlay with the ESC key.
|
| - */
|
| noCancelOnEscKey: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Set to true to disable canceling the overlay by clicking outside it.
|
| - */
|
| noCancelOnOutsideClick: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Contains the reason(s) this overlay was last closed (see `iron-overlay-closed`).
|
| - * `IronOverlayBehavior` provides the `canceled` reason; implementers of the
|
| - * behavior can provide other reasons in addition to `canceled`.
|
| - */
|
| closingReason: {
|
| - // was a getter before, but needs to be a property so other
|
| - // behaviors can override this.
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * Set to true to enable restoring of focus when overlay is closed.
|
| - */
|
| restoreFocusOnClose: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Set to true to keep overlay always on top.
|
| - */
|
| alwaysOnTop: {
|
| type: Boolean
|
| },
|
|
|
| - /**
|
| - * Shortcut to access to the overlay manager.
|
| - * @private
|
| - * @type {Polymer.IronOverlayManagerClass}
|
| - */
|
| _manager: {
|
| type: Object,
|
| value: Polymer.IronOverlayManager
|
| },
|
|
|
| - /**
|
| - * The node being focused.
|
| - * @type {?Node}
|
| - */
|
| _focusedChild: {
|
| type: Object
|
| }
|
| @@ -8954,34 +6484,15 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| 'iron-resize': '_onIronResize'
|
| },
|
|
|
| - /**
|
| - * The backdrop element.
|
| - * @type {Element}
|
| - */
|
| get backdropElement() {
|
| return this._manager.backdropElement;
|
| },
|
|
|
| - /**
|
| - * Returns the node to give focus to.
|
| - * @type {Node}
|
| - */
|
| get _focusNode() {
|
| return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]') || this;
|
| },
|
|
|
| - /**
|
| - * Array of nodes that can receive focus (overlay included), ordered by `tabindex`.
|
| - * This is used to retrieve which is the first and last focusable nodes in order
|
| - * to wrap the focus for overlays `with-backdrop`.
|
| - *
|
| - * If you know what is your content (specifically the first and last focusable children),
|
| - * you can override this method to return only `[firstFocusable, lastFocusable];`
|
| - * @type {Array<Node>}
|
| - * @protected
|
| - */
|
| get _focusableNodes() {
|
| - // Elements that can be focused even if they have [disabled] attribute.
|
| var FOCUSABLE_WITH_DISABLED = [
|
| 'a[href]',
|
| 'area[href]',
|
| @@ -8990,7 +6501,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| '[contentEditable=true]'
|
| ];
|
|
|
| - // Elements that cannot be focused if they have [disabled] attribute.
|
| var FOCUSABLE_WITHOUT_DISABLED = [
|
| 'input',
|
| 'select',
|
| @@ -8998,7 +6508,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| 'button'
|
| ];
|
|
|
| - // Discard elements with tabindex=-1 (makes them not focusable).
|
| var selector = FOCUSABLE_WITH_DISABLED.join(':not([tabindex="-1"]),') +
|
| ':not([tabindex="-1"]),' +
|
| FOCUSABLE_WITHOUT_DISABLED.join(':not([disabled]):not([tabindex="-1"]),') +
|
| @@ -9006,11 +6515,8 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|
|
| var focusables = Polymer.dom(this).querySelectorAll(selector);
|
| if (this.tabIndex >= 0) {
|
| - // Insert at the beginning because we might have all elements with tabIndex = 0,
|
| - // and the overlay should be the first of the list.
|
| focusables.splice(0, 0, this);
|
| }
|
| - // Sort by tabindex.
|
| return focusables.sort(function (a, b) {
|
| if (a.tabIndex === b.tabIndex) {
|
| return 0;
|
| @@ -9023,22 +6529,15 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| },
|
|
|
| ready: function() {
|
| - // Used to skip calls to notifyResize and refit while the overlay is animating.
|
| this.__isAnimating = false;
|
| - // with-backdrop needs tabindex to be set in order to trap the focus.
|
| - // If it is not set, IronOverlayBehavior will set it, and remove it if with-backdrop = false.
|
| this.__shouldRemoveTabIndex = false;
|
| - // Used for wrapping the focus on TAB / Shift+TAB.
|
| this.__firstFocusableNode = this.__lastFocusableNode = null;
|
| - // Used by __onNextAnimationFrame to cancel any previous callback.
|
| this.__raf = null;
|
| - // Focused node before overlay gets opened. Can be restored on close.
|
| this.__restoreFocusNode = null;
|
| this._ensureSetup();
|
| },
|
|
|
| attached: function() {
|
| - // Call _openedChanged here so that position can be computed correctly.
|
| if (this.opened) {
|
| this._openedChanged(this.opened);
|
| }
|
| @@ -9055,34 +6554,21 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| this._manager.removeOverlay(this);
|
| },
|
|
|
| - /**
|
| - * Toggle the opened state of the overlay.
|
| - */
|
| toggle: function() {
|
| this._setCanceled(false);
|
| this.opened = !this.opened;
|
| },
|
|
|
| - /**
|
| - * Open the overlay.
|
| - */
|
| open: function() {
|
| this._setCanceled(false);
|
| this.opened = true;
|
| },
|
|
|
| - /**
|
| - * Close the overlay.
|
| - */
|
| close: function() {
|
| this._setCanceled(false);
|
| this.opened = false;
|
| },
|
|
|
| - /**
|
| - * Cancels the overlay.
|
| - * @param {Event=} event The original event
|
| - */
|
| cancel: function(event) {
|
| var cancelEvent = this.fire('iron-overlay-canceled', event, {cancelable: true});
|
| if (cancelEvent.defaultPrevented) {
|
| @@ -9102,11 +6588,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| this.style.display = 'none';
|
| },
|
|
|
| - /**
|
| - * Called when `opened` changes.
|
| - * @param {boolean=} opened
|
| - * @protected
|
| - */
|
| _openedChanged: function(opened) {
|
| if (opened) {
|
| this.removeAttribute('aria-hidden');
|
| @@ -9114,15 +6595,12 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| this.setAttribute('aria-hidden', 'true');
|
| }
|
|
|
| - // Defer any animation-related code on attached
|
| - // (_openedChanged gets called again on attached).
|
| if (!this.isAttached) {
|
| return;
|
| }
|
|
|
| this.__isAnimating = true;
|
|
|
| - // Use requestAnimationFrame for non-blocking rendering.
|
| this.__onNextAnimationFrame(this.__openedChanged);
|
| },
|
|
|
| @@ -9132,7 +6610,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| },
|
|
|
| _withBackdropChanged: function() {
|
| - // If tabindex is already set, no need to override it.
|
| if (this.withBackdrop && !this.hasAttribute('tabindex')) {
|
| this.setAttribute('tabindex', '-1');
|
| this.__shouldRemoveTabIndex = true;
|
| @@ -9145,53 +6622,31 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * tasks which must occur before opening; e.g. making the element visible.
|
| - * @protected
|
| - */
|
| _prepareRenderOpened: function() {
|
| - // Store focused node.
|
| this.__restoreFocusNode = this._manager.deepActiveElement;
|
|
|
| - // Needed to calculate the size of the overlay so that transitions on its size
|
| - // will have the correct starting points.
|
| this._preparePositioning();
|
| this.refit();
|
| this._finishPositioning();
|
|
|
| - // Safari will apply the focus to the autofocus element when displayed
|
| - // for the first time, so we make sure to return the focus where it was.
|
| if (this.noAutoFocus && document.activeElement === this._focusNode) {
|
| this._focusNode.blur();
|
| this.__restoreFocusNode.focus();
|
| }
|
| },
|
|
|
| - /**
|
| - * Tasks which cause the overlay to actually open; typically play an animation.
|
| - * @protected
|
| - */
|
| _renderOpened: function() {
|
| this._finishRenderOpened();
|
| },
|
|
|
| - /**
|
| - * Tasks which cause the overlay to actually close; typically play an animation.
|
| - * @protected
|
| - */
|
| _renderClosed: function() {
|
| this._finishRenderClosed();
|
| },
|
|
|
| - /**
|
| - * Tasks to be performed at the end of open action. Will fire `iron-overlay-opened`.
|
| - * @protected
|
| - */
|
| _finishRenderOpened: function() {
|
| this.notifyResize();
|
| this.__isAnimating = false;
|
|
|
| - // Store it so we don't query too much.
|
| var focusableNodes = this._focusableNodes;
|
| this.__firstFocusableNode = focusableNodes[0];
|
| this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
|
| @@ -9199,14 +6654,8 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| this.fire('iron-overlay-opened');
|
| },
|
|
|
| - /**
|
| - * Tasks to be performed at the end of close action. Will fire `iron-overlay-closed`.
|
| - * @protected
|
| - */
|
| _finishRenderClosed: function() {
|
| - // Hide the overlay.
|
| this.style.display = 'none';
|
| - // Reset z-index only at the end of the animation.
|
| this.style.zIndex = '';
|
| this.notifyResize();
|
| this.__isAnimating = false;
|
| @@ -9220,24 +6669,14 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| },
|
|
|
| _finishPositioning: function() {
|
| - // First, make it invisible & reactivate animations.
|
| this.style.display = 'none';
|
| - // Force reflow before re-enabling animations so that they don't start.
|
| - // Set scrollTop to itself so that Closure Compiler doesn't remove this.
|
| this.scrollTop = this.scrollTop;
|
| this.style.transition = this.style.webkitTransition = '';
|
| this.style.transform = this.style.webkitTransform = '';
|
| - // Now that animations are enabled, make it visible again
|
| this.style.display = '';
|
| - // Force reflow, so that following animations are properly started.
|
| - // Set scrollTop to itself so that Closure Compiler doesn't remove this.
|
| this.scrollTop = this.scrollTop;
|
| },
|
|
|
| - /**
|
| - * Applies focus according to the opened state.
|
| - * @protected
|
| - */
|
| _applyFocus: function() {
|
| if (this.opened) {
|
| if (!this.noAutoFocus) {
|
| @@ -9247,14 +6686,10 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| else {
|
| this._focusNode.blur();
|
| this._focusedChild = null;
|
| - // Restore focus.
|
| if (this.restoreFocusOnClose && this.__restoreFocusNode) {
|
| this.__restoreFocusNode.focus();
|
| }
|
| this.__restoreFocusNode = null;
|
| - // If many overlays get closed at the same time, one of them would still
|
| - // be the currentOverlay even if already closed, and would call _applyFocus
|
| - // infinitely, so we check for this not to be the current overlay.
|
| var currentOverlay = this._manager.currentOverlay();
|
| if (currentOverlay && this !== currentOverlay) {
|
| currentOverlay._applyFocus();
|
| @@ -9262,22 +6697,12 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * Cancels (closes) the overlay. Call when click happens outside the overlay.
|
| - * @param {!Event} event
|
| - * @protected
|
| - */
|
| _onCaptureClick: function(event) {
|
| if (!this.noCancelOnOutsideClick) {
|
| this.cancel(event);
|
| }
|
| },
|
|
|
| - /**
|
| - * Keeps track of the focused child. If withBackdrop, traps focus within overlay.
|
| - * @param {!Event} event
|
| - * @protected
|
| - */
|
| _onCaptureFocus: function (event) {
|
| if (!this.withBackdrop) {
|
| return;
|
| @@ -9291,103 +6716,54 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * Handles the ESC key event and cancels (closes) the overlay.
|
| - * @param {!Event} event
|
| - * @protected
|
| - */
|
| _onCaptureEsc: function(event) {
|
| if (!this.noCancelOnEscKey) {
|
| this.cancel(event);
|
| }
|
| },
|
|
|
| - /**
|
| - * Handles TAB key events to track focus changes.
|
| - * Will wrap focus for overlays withBackdrop.
|
| - * @param {!Event} event
|
| - * @protected
|
| - */
|
| _onCaptureTab: function(event) {
|
| if (!this.withBackdrop) {
|
| return;
|
| }
|
| - // TAB wraps from last to first focusable.
|
| - // Shift + TAB wraps from first to last focusable.
|
| var shift = event.shiftKey;
|
| var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusableNode;
|
| var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNode;
|
| var shouldWrap = false;
|
| if (nodeToCheck === nodeToSet) {
|
| - // If nodeToCheck is the same as nodeToSet, it means we have an overlay
|
| - // with 0 or 1 focusables; in either case we still need to trap the
|
| - // focus within the overlay.
|
| shouldWrap = true;
|
| } else {
|
| - // In dom=shadow, the manager will receive focus changes on the main
|
| - // root but not the ones within other shadow roots, so we can't rely on
|
| - // _focusedChild, but we should check the deepest active element.
|
| var focusedNode = this._manager.deepActiveElement;
|
| - // If the active element is not the nodeToCheck but the overlay itself,
|
| - // it means the focus is about to go outside the overlay, hence we
|
| - // should prevent that (e.g. user opens the overlay and hit Shift+TAB).
|
| shouldWrap = (focusedNode === nodeToCheck || focusedNode === this);
|
| }
|
|
|
| if (shouldWrap) {
|
| - // When the overlay contains the last focusable element of the document
|
| - // and it's already focused, pressing TAB would move the focus outside
|
| - // the document (e.g. to the browser search bar). Similarly, when the
|
| - // overlay contains the first focusable element of the document and it's
|
| - // already focused, pressing Shift+TAB would move the focus outside the
|
| - // document (e.g. to the browser search bar).
|
| - // In both cases, we would not receive a focus event, but only a blur.
|
| - // In order to achieve focus wrapping, we prevent this TAB event and
|
| - // force the focus. This will also prevent the focus to temporarily move
|
| - // outside the overlay, which might cause scrolling.
|
| event.preventDefault();
|
| this._focusedChild = nodeToSet;
|
| this._applyFocus();
|
| }
|
| },
|
|
|
| - /**
|
| - * Refits if the overlay is opened and not animating.
|
| - * @protected
|
| - */
|
| _onIronResize: function() {
|
| if (this.opened && !this.__isAnimating) {
|
| this.__onNextAnimationFrame(this.refit);
|
| }
|
| },
|
|
|
| - /**
|
| - * Will call notifyResize if overlay is opened.
|
| - * Can be overridden in order to avoid multiple observers on the same node.
|
| - * @protected
|
| - */
|
| _onNodesChange: function() {
|
| if (this.opened && !this.__isAnimating) {
|
| this.notifyResize();
|
| }
|
| },
|
|
|
| - /**
|
| - * Tasks executed when opened changes: prepare for the opening, move the
|
| - * focus, update the manager, render opened/closed.
|
| - * @private
|
| - */
|
| __openedChanged: function() {
|
| if (this.opened) {
|
| - // Make overlay visible, then add it to the manager.
|
| this._prepareRenderOpened();
|
| this._manager.addOverlay(this);
|
| - // Move the focus to the child node with [autofocus].
|
| this._applyFocus();
|
|
|
| this._renderOpened();
|
| } else {
|
| - // Remove overlay, then restore the focus before actually closing.
|
| this._manager.removeOverlay(this);
|
| this._applyFocus();
|
|
|
| @@ -9395,14 +6771,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * Executes a callback on the next animation frame, overriding any previous
|
| - * callback awaiting for the next animation frame. e.g.
|
| - * `__onNextAnimationFrame(callback1) && __onNextAnimationFrame(callback2)`;
|
| - * `callback1` will never be invoked.
|
| - * @param {!Function} callback Its `this` parameter is the overlay itself.
|
| - * @private
|
| - */
|
| __onNextAnimationFrame: function(callback) {
|
| if (this.__raf) {
|
| window.cancelAnimationFrame(this.__raf);
|
| @@ -9419,56 +6787,23 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| /** @polymerBehavior */
|
| Polymer.IronOverlayBehavior = [Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
|
|
|
| - /**
|
| - * Fired after the overlay opens.
|
| - * @event iron-overlay-opened
|
| - */
|
| -
|
| - /**
|
| - * Fired when the overlay is canceled, but before it is closed.
|
| - * @event iron-overlay-canceled
|
| - * @param {Event} event The closing of the overlay can be prevented
|
| - * by calling `event.preventDefault()`. The `event.detail` is the original event that
|
| - * originated the canceling (e.g. ESC keyboard event or click event outside the overlay).
|
| - */
|
| -
|
| - /**
|
| - * Fired after the overlay closes.
|
| - * @event iron-overlay-closed
|
| - * @param {Event} event The `event.detail` is the `closingReason` property
|
| - * (contains `canceled`, whether the overlay was canceled).
|
| - */
|
| +
|
| +
|
|
|
| })();
|
| -/**
|
| - * `Polymer.NeonAnimatableBehavior` is implemented by elements containing animations for use with
|
| - * elements implementing `Polymer.NeonAnimationRunnerBehavior`.
|
| - * @polymerBehavior
|
| - */
|
| Polymer.NeonAnimatableBehavior = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Animation configuration. See README for more info.
|
| - */
|
| animationConfig: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * Convenience property for setting an 'entry' animation. Do not set `animationConfig.entry`
|
| - * manually if using this. The animated node is set to `this` if using this property.
|
| - */
|
| entryAnimation: {
|
| observer: '_entryAnimationChanged',
|
| type: String
|
| },
|
|
|
| - /**
|
| - * Convenience property for setting an 'exit' animation. Do not set `animationConfig.exit`
|
| - * manually if using this. The animated node is set to `this` if using this property.
|
| - */
|
| exitAnimation: {
|
| observer: '_exitAnimationChanged',
|
| type: String
|
| @@ -9493,7 +6828,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| },
|
|
|
| _copyProperties: function(config1, config2) {
|
| - // shallowly copy properties from config2 to config1
|
| for (var property in config2) {
|
| config1[property] = config2[property];
|
| }
|
| @@ -9517,7 +6851,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| return;
|
| }
|
|
|
| - // type is optional
|
| var thisConfig;
|
| if (type) {
|
| thisConfig = this.animationConfig[type];
|
| @@ -9529,7 +6862,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| thisConfig = [thisConfig];
|
| }
|
|
|
| - // iterate animations and recurse to process configurations from child nodes
|
| if (thisConfig) {
|
| for (var config, index = 0; config = thisConfig[index]; index++) {
|
| if (config.animatable) {
|
| @@ -9538,14 +6870,12 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| if (config.id) {
|
| var cachedConfig = map[config.id];
|
| if (cachedConfig) {
|
| - // merge configurations with the same id, making a clone lazily
|
| if (!cachedConfig.isClone) {
|
| map[config.id] = this._cloneConfig(cachedConfig)
|
| cachedConfig = map[config.id];
|
| }
|
| this._copyProperties(cachedConfig, config);
|
| } else {
|
| - // put any configs with an id into a map
|
| map[config.id] = config;
|
| }
|
| } else {
|
| @@ -9556,17 +6886,10 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * An element implementing `Polymer.NeonAnimationRunnerBehavior` calls this method to configure
|
| - * an animation with an optional type. Elements implementing `Polymer.NeonAnimatableBehavior`
|
| - * should define the property `animationConfig`, which is either a configuration object
|
| - * or a map of animation type to array of configuration objects.
|
| - */
|
| getAnimationConfig: function(type) {
|
| var map = {};
|
| var allConfigs = [];
|
| this._getAnimationConfigRecursive(type, map, allConfigs);
|
| - // append the configurations saved in the map to the array
|
| for (var key in map) {
|
| allConfigs.push(map[key]);
|
| }
|
| @@ -9574,11 +6897,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
|
|
| };
|
| -/**
|
| - * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations.
|
| - *
|
| - * @polymerBehavior Polymer.NeonAnimationRunnerBehavior
|
| - */
|
| Polymer.NeonAnimationRunnerBehaviorImpl = {
|
|
|
| _configureAnimations: function(configs) {
|
| @@ -9586,13 +6904,10 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| if (configs.length > 0) {
|
| for (var config, index = 0; config = configs[index]; index++) {
|
| var neonAnimation = document.createElement(config.name);
|
| - // is this element actually a neon animation?
|
| if (neonAnimation.isNeonAnimation) {
|
| var result = null;
|
| - // configuration or play could fail if polyfills aren't loaded
|
| try {
|
| result = neonAnimation.configure(config);
|
| - // Check if we have an Effect rather than an Animation
|
| if (typeof result.cancel != 'function') {
|
| result = document.timeline.play(result);
|
| }
|
| @@ -9635,11 +6950,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * Plays an animation with an optional `type`.
|
| - * @param {string=} type
|
| - * @param {!Object=} cookie
|
| - */
|
| playAnimation: function(type, cookie) {
|
| var configs = this.getAnimationConfig(type);
|
| if (!configs) {
|
| @@ -9671,9 +6981,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| }
|
| },
|
|
|
| - /**
|
| - * Cancels the currently running animations.
|
| - */
|
| cancelAnimation: function() {
|
| for (var k in this._animations) {
|
| this._animations[k].cancel();
|
| @@ -9687,17 +6994,10 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| Polymer.NeonAnimatableBehavior,
|
| Polymer.NeonAnimationRunnerBehaviorImpl
|
| ];
|
| -/**
|
| - * Use `Polymer.NeonAnimationBehavior` to implement an animation.
|
| - * @polymerBehavior
|
| - */
|
| Polymer.NeonAnimationBehavior = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Defines the animation timing.
|
| - */
|
| animationTiming: {
|
| type: Object,
|
| value: function() {
|
| @@ -9711,21 +7011,9 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|
|
| },
|
|
|
| - /**
|
| - * Can be used to determine that elements implement this behavior.
|
| - */
|
| isNeonAnimation: true,
|
|
|
| - /**
|
| - * Do any animation configuration here.
|
| - */
|
| - // configure: function(config) {
|
| - // },
|
|
|
| - /**
|
| - * Returns the animation timing by mixing in properties from `config` to the defaults defined
|
| - * by the animation.
|
| - */
|
| timingFromConfig: function(config) {
|
| if (config.timing) {
|
| for (var property in config.timing) {
|
| @@ -9735,9 +7023,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| return this.animationTiming;
|
| },
|
|
|
| - /**
|
| - * Sets `transform` and `transformOrigin` properties along with the prefixed versions.
|
| - */
|
| setPrefixedProperty: function(node, property, value) {
|
| var map = {
|
| 'transform': ['webkitTransform'],
|
| @@ -9750,9 +7035,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
| node.style[property] = value;
|
| },
|
|
|
| - /**
|
| - * Called when the animation finishes.
|
| - */
|
| complete: function() {}
|
|
|
| };
|
| @@ -9781,38 +7063,20 @@ Polymer({
|
| });
|
| (function() {
|
| 'use strict';
|
| - // Used to calculate the scroll direction during touch events.
|
| var LAST_TOUCH_POSITION = {
|
| pageX: 0,
|
| pageY: 0
|
| };
|
| - // Used to avoid computing event.path and filter scrollable nodes (better perf).
|
| var ROOT_TARGET = null;
|
| var SCROLLABLE_NODES = [];
|
|
|
| - /**
|
| - * The IronDropdownScrollManager is intended to provide a central source
|
| - * of authority and control over which elements in a document are currently
|
| - * allowed to scroll.
|
| - */
|
|
|
| Polymer.IronDropdownScrollManager = {
|
|
|
| - /**
|
| - * The current element that defines the DOM boundaries of the
|
| - * scroll lock. This is always the most recently locking element.
|
| - */
|
| get currentLockingElement() {
|
| return this._lockingElements[this._lockingElements.length - 1];
|
| },
|
|
|
| - /**
|
| - * Returns true if the provided element is "scroll locked", which is to
|
| - * say that it cannot be scrolled via pointer or keyboard interactions.
|
| - *
|
| - * @param {HTMLElement} element An HTML element instance which may or may
|
| - * not be scroll locked.
|
| - */
|
| elementIsScrollLocked: function(element) {
|
| var currentLockingElement = this.currentLockingElement;
|
|
|
| @@ -9842,18 +7106,7 @@ Polymer({
|
| return scrollLocked;
|
| },
|
|
|
| - /**
|
| - * Push an element onto the current scroll lock stack. The most recently
|
| - * pushed element and its children will be considered scrollable. All
|
| - * other elements will not be scrollable.
|
| - *
|
| - * Scroll locking is implemented as a stack so that cases such as
|
| - * dropdowns within dropdowns are handled well.
|
| - *
|
| - * @param {HTMLElement} element The element that should lock scroll.
|
| - */
|
| pushScrollLock: function(element) {
|
| - // Prevent pushing the same element twice
|
| if (this._lockingElements.indexOf(element) >= 0) {
|
| return;
|
| }
|
| @@ -9868,15 +7121,6 @@ Polymer({
|
| this._unlockedElementCache = [];
|
| },
|
|
|
| - /**
|
| - * Remove an element from the scroll lock stack. The element being
|
| - * removed does not need to be the most recently pushed element. However,
|
| - * the scroll lock constraints only change when the most recently pushed
|
| - * element is removed.
|
| - *
|
| - * @param {HTMLElement} element The element to remove from the scroll
|
| - * lock stack.
|
| - */
|
| removeScrollLock: function(element) {
|
| var index = this._lockingElements.indexOf(element);
|
|
|
| @@ -9909,12 +7153,6 @@ Polymer({
|
| },
|
|
|
| _composedTreeContains: function(element, child) {
|
| - // NOTE(cdata): This method iterates over content elements and their
|
| - // corresponding distributed nodes to implement a contains-like method
|
| - // that pierces through the composed tree of the ShadowDOM. Results of
|
| - // this operation are cached (elsewhere) on a per-scroll-lock basis, to
|
| - // guard against potentially expensive lookups happening repeatedly as
|
| - // a user scrolls / touchmoves.
|
| var contentElements;
|
| var distributedNodes;
|
| var contentIndex;
|
| @@ -9942,12 +7180,9 @@ Polymer({
|
| },
|
|
|
| _scrollInteractionHandler: function(event) {
|
| - // Avoid canceling an event with cancelable=false, e.g. scrolling is in
|
| - // progress and cannot be interrupted.
|
| if (event.cancelable && this._shouldPreventScrolling(event)) {
|
| event.preventDefault();
|
| }
|
| - // If event has targetTouches (touch event), update last touch position.
|
| if (event.targetTouches) {
|
| var touch = event.targetTouches[0];
|
| LAST_TOUCH_POSITION.pageX = touch.pageX;
|
| @@ -9958,15 +7193,10 @@ Polymer({
|
| _lockScrollInteractions: function() {
|
| this._boundScrollHandler = this._boundScrollHandler ||
|
| this._scrollInteractionHandler.bind(this);
|
| - // Modern `wheel` event for mouse wheel scrolling:
|
| document.addEventListener('wheel', this._boundScrollHandler, true);
|
| - // Older, non-standard `mousewheel` event for some FF:
|
| document.addEventListener('mousewheel', this._boundScrollHandler, true);
|
| - // IE:
|
| document.addEventListener('DOMMouseScroll', this._boundScrollHandler, true);
|
| - // Save the SCROLLABLE_NODES on touchstart, to be used on touchmove.
|
| document.addEventListener('touchstart', this._boundScrollHandler, true);
|
| - // Mobile devices can scroll on touch move:
|
| document.addEventListener('touchmove', this._boundScrollHandler, true);
|
| },
|
|
|
| @@ -9978,57 +7208,32 @@ Polymer({
|
| document.removeEventListener('touchmove', this._boundScrollHandler, true);
|
| },
|
|
|
| - /**
|
| - * Returns true if the event causes scroll outside the current locking
|
| - * element, e.g. pointer/keyboard interactions, or scroll "leaking"
|
| - * outside the locking element when it is already at its scroll boundaries.
|
| - * @param {!Event} event
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| _shouldPreventScrolling: function(event) {
|
|
|
| - // Update if root target changed. For touch events, ensure we don't
|
| - // update during touchmove.
|
| var target = Polymer.dom(event).rootTarget;
|
| if (event.type !== 'touchmove' && ROOT_TARGET !== target) {
|
| ROOT_TARGET = target;
|
| SCROLLABLE_NODES = this._getScrollableNodes(Polymer.dom(event).path);
|
| }
|
|
|
| - // Prevent event if no scrollable nodes.
|
| if (!SCROLLABLE_NODES.length) {
|
| return true;
|
| }
|
| - // Don't prevent touchstart event inside the locking element when it has
|
| - // scrollable nodes.
|
| if (event.type === 'touchstart') {
|
| return false;
|
| }
|
| - // Get deltaX/Y.
|
| var info = this._getScrollInfo(event);
|
| - // Prevent if there is no child that can scroll.
|
| return !this._getScrollingNode(SCROLLABLE_NODES, info.deltaX, info.deltaY);
|
| },
|
|
|
| - /**
|
| - * Returns an array of scrollable nodes up to the current locking element,
|
| - * which is included too if scrollable.
|
| - * @param {!Array<Node>} nodes
|
| - * @return {Array<Node>} scrollables
|
| - * @private
|
| - */
|
| _getScrollableNodes: function(nodes) {
|
| var scrollables = [];
|
| var lockingIndex = nodes.indexOf(this.currentLockingElement);
|
| - // Loop from root target to locking element (included).
|
| for (var i = 0; i <= lockingIndex; i++) {
|
| var node = nodes[i];
|
| - // Skip document fragments.
|
| if (node.nodeType === 11) {
|
| continue;
|
| }
|
| - // Check inline style before checking computed style.
|
| var style = node.style;
|
| if (style.overflow !== 'scroll' && style.overflow !== 'auto') {
|
| style = window.getComputedStyle(node);
|
| @@ -10040,32 +7245,18 @@ Polymer({
|
| return scrollables;
|
| },
|
|
|
| - /**
|
| - * Returns the node that is scrolling. If there is no scrolling,
|
| - * returns undefined.
|
| - * @param {!Array<Node>} nodes
|
| - * @param {number} deltaX Scroll delta on the x-axis
|
| - * @param {number} deltaY Scroll delta on the y-axis
|
| - * @return {Node|undefined}
|
| - * @private
|
| - */
|
| _getScrollingNode: function(nodes, deltaX, deltaY) {
|
| - // No scroll.
|
| if (!deltaX && !deltaY) {
|
| return;
|
| }
|
| - // Check only one axis according to where there is more scroll.
|
| - // Prefer vertical to horizontal.
|
| var verticalScroll = Math.abs(deltaY) >= Math.abs(deltaX);
|
| for (var i = 0; i < nodes.length; i++) {
|
| var node = nodes[i];
|
| var canScroll = false;
|
| if (verticalScroll) {
|
| - // delta < 0 is scroll up, delta > 0 is scroll down.
|
| canScroll = deltaY < 0 ? node.scrollTop > 0 :
|
| node.scrollTop < node.scrollHeight - node.clientHeight;
|
| } else {
|
| - // delta < 0 is scroll left, delta > 0 is scroll right.
|
| canScroll = deltaX < 0 ? node.scrollLeft > 0 :
|
| node.scrollLeft < node.scrollWidth - node.clientWidth;
|
| }
|
| @@ -10075,42 +7266,24 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Returns scroll `deltaX` and `deltaY`.
|
| - * @param {!Event} event The scroll event
|
| - * @return {{
|
| - * deltaX: number The x-axis scroll delta (positive: scroll right,
|
| - * negative: scroll left, 0: no scroll),
|
| - * deltaY: number The y-axis scroll delta (positive: scroll down,
|
| - * negative: scroll up, 0: no scroll)
|
| - * }} info
|
| - * @private
|
| - */
|
| _getScrollInfo: function(event) {
|
| var info = {
|
| deltaX: event.deltaX,
|
| deltaY: event.deltaY
|
| };
|
| - // Already available.
|
| if ('deltaX' in event) {
|
| - // do nothing, values are already good.
|
| }
|
| - // Safari has scroll info in `wheelDeltaX/Y`.
|
| else if ('wheelDeltaX' in event) {
|
| info.deltaX = -event.wheelDeltaX;
|
| info.deltaY = -event.wheelDeltaY;
|
| }
|
| - // Firefox has scroll info in `detail` and `axis`.
|
| else if ('axis' in event) {
|
| info.deltaX = event.axis === 1 ? event.detail : 0;
|
| info.deltaY = event.axis === 2 ? event.detail : 0;
|
| }
|
| - // On mobile devices, calculate scroll direction.
|
| else if (event.targetTouches) {
|
| var touch = event.targetTouches[0];
|
| - // Touch moves from right to left => scrolling goes right.
|
| info.deltaX = LAST_TOUCH_POSITION.pageX - touch.pageX;
|
| - // Touch moves from down to up => scrolling goes down.
|
| info.deltaY = LAST_TOUCH_POSITION.pageY - touch.pageY;
|
| }
|
| return info;
|
| @@ -10131,77 +7304,40 @@ Polymer({
|
| ],
|
|
|
| properties: {
|
| - /**
|
| - * The orientation against which to align the dropdown content
|
| - * horizontally relative to the dropdown trigger.
|
| - * Overridden from `Polymer.IronFitBehavior`.
|
| - */
|
| horizontalAlign: {
|
| type: String,
|
| value: 'left',
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * The orientation against which to align the dropdown content
|
| - * vertically relative to the dropdown trigger.
|
| - * Overridden from `Polymer.IronFitBehavior`.
|
| - */
|
| verticalAlign: {
|
| type: String,
|
| value: 'top',
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * An animation config. If provided, this will be used to animate the
|
| - * opening of the dropdown.
|
| - */
|
| openAnimationConfig: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * An animation config. If provided, this will be used to animate the
|
| - * closing of the dropdown.
|
| - */
|
| closeAnimationConfig: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * If provided, this will be the element that will be focused when
|
| - * the dropdown opens.
|
| - */
|
| focusTarget: {
|
| type: Object
|
| },
|
|
|
| - /**
|
| - * Set to true to disable animations when opening and closing the
|
| - * dropdown.
|
| - */
|
| noAnimations: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * By default, the dropdown will constrain scrolling on the page
|
| - * to itself when opened.
|
| - * Set to true in order to prevent scroll from being constrained
|
| - * to the dropdown when it opens.
|
| - */
|
| allowOutsideScroll: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * Callback for scroll events.
|
| - * @type {Function}
|
| - * @private
|
| - */
|
| _boundOnCaptureScroll: {
|
| type: Function,
|
| value: function() {
|
| @@ -10218,26 +7354,17 @@ Polymer({
|
| '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)'
|
| ],
|
|
|
| - /**
|
| - * The element that is contained by the dropdown, if any.
|
| - */
|
| get containedElement() {
|
| return Polymer.dom(this.$.content).getDistributedNodes()[0];
|
| },
|
|
|
| - /**
|
| - * The element that should be focused when the dropdown opens.
|
| - * @deprecated
|
| - */
|
| get _focusTarget() {
|
| return this.focusTarget || this.containedElement;
|
| },
|
|
|
| ready: function() {
|
| - // Memoized scrolling position, used to block scrolling outside.
|
| this._scrollTop = 0;
|
| this._scrollLeft = 0;
|
| - // Used to perform a non-blocking refit on scroll.
|
| this._refitOnScrollRAF = null;
|
| },
|
|
|
| @@ -10246,10 +7373,6 @@ Polymer({
|
| Polymer.IronDropdownScrollManager.removeScrollLock(this);
|
| },
|
|
|
| - /**
|
| - * Called when the value of `opened` changes.
|
| - * Overridden from `IronOverlayBehavior`
|
| - */
|
| _openedChanged: function() {
|
| if (this.opened && this.disabled) {
|
| this.cancel();
|
| @@ -10269,9 +7392,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Overridden from `IronOverlayBehavior`.
|
| - */
|
| _renderOpened: function() {
|
| if (!this.noAnimations && this.animationConfig.open) {
|
| this.$.contentWrapper.classList.add('animating');
|
| @@ -10281,9 +7401,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Overridden from `IronOverlayBehavior`.
|
| - */
|
| _renderClosed: function() {
|
|
|
| if (!this.noAnimations && this.animationConfig.close) {
|
| @@ -10294,12 +7411,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Called when animation finishes on the dropdown (when opening or
|
| - * closing). Responsible for "completing" the process of opening or
|
| - * closing the dropdown by positioning it or setting its display to
|
| - * none.
|
| - */
|
| _onNeonAnimationFinish: function() {
|
| this.$.contentWrapper.classList.remove('animating');
|
| if (this.opened) {
|
| @@ -10318,31 +7429,21 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Memoizes the scroll position of the outside scrolling element.
|
| - * @private
|
| - */
|
| _saveScrollPosition: function() {
|
| if (document.scrollingElement) {
|
| this._scrollTop = document.scrollingElement.scrollTop;
|
| this._scrollLeft = document.scrollingElement.scrollLeft;
|
| } else {
|
| - // Since we don't know if is the body or html, get max.
|
| this._scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
|
| this._scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
|
| }
|
| },
|
|
|
| - /**
|
| - * Resets the scroll position of the outside scrolling element.
|
| - * @private
|
| - */
|
| _restoreScrollPosition: function() {
|
| if (document.scrollingElement) {
|
| document.scrollingElement.scrollTop = this._scrollTop;
|
| document.scrollingElement.scrollLeft = this._scrollLeft;
|
| } else {
|
| - // Since we don't know if is the body or html, set both.
|
| document.documentElement.scrollTop = this._scrollTop;
|
| document.documentElement.scrollLeft = this._scrollLeft;
|
| document.body.scrollTop = this._scrollTop;
|
| @@ -10350,10 +7451,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Constructs the final animation config from different properties used
|
| - * to configure specific parts of the opening and closing animations.
|
| - */
|
| _updateAnimationConfig: function() {
|
| var animations = (this.openAnimationConfig || []).concat(this.closeAnimationConfig || []);
|
| for (var i = 0; i < animations.length; i++) {
|
| @@ -10365,20 +7462,12 @@ Polymer({
|
| };
|
| },
|
|
|
| - /**
|
| - * Updates the overlay position based on configured horizontal
|
| - * and vertical alignment.
|
| - */
|
| _updateOverlayPosition: function() {
|
| if (this.isAttached) {
|
| - // This triggers iron-resize, and iron-overlay-behavior will call refit if needed.
|
| this.notifyResize();
|
| }
|
| },
|
|
|
| - /**
|
| - * Apply focus to focusTarget or containedElement
|
| - */
|
| _applyFocus: function () {
|
| var focusTarget = this.focusTarget || this.containedElement;
|
| if (focusTarget && this.opened && !this.noAutoFocus) {
|
| @@ -10537,11 +7626,6 @@ Polymer({
|
| notify: true,
|
| },
|
|
|
| - /**
|
| - * The contextual item that this menu was clicked for.
|
| - * e.g. the data used to render an item in an <iron-list> or <dom-repeat>
|
| - * @type {?Object}
|
| - */
|
| itemData: {
|
| type: Object,
|
| value: null,
|
| @@ -10603,22 +7687,10 @@ Polymer({
|
| 'dropdown.iron-overlay-canceled': 'onOverlayCanceled_',
|
| },
|
|
|
| - /**
|
| - * The last anchor that was used to open a menu. It's necessary for toggling.
|
| - * @private {?Element}
|
| - */
|
| lastAnchor_: null,
|
|
|
| - /**
|
| - * The first focusable child in the menu's light DOM.
|
| - * @private {?Element}
|
| - */
|
| firstFocus_: null,
|
|
|
| - /**
|
| - * The last focusable child in the menu's light DOM.
|
| - * @private {?Element}
|
| - */
|
| lastFocus_: null,
|
|
|
| /** @override */
|
| @@ -10629,18 +7701,11 @@ Polymer({
|
| /** Closes the menu. */
|
| closeMenu: function() {
|
| if (this.root.activeElement == null) {
|
| - // Something else has taken focus away from the menu. Do not attempt to
|
| - // restore focus to the button which opened the menu.
|
| this.$.dropdown.restoreFocusOnClose = false;
|
| }
|
| this.menuOpen = false;
|
| },
|
|
|
| - /**
|
| - * Opens the menu at the anchor location.
|
| - * @param {!Element} anchor The location to display the menu.
|
| - * @param {!Object} itemData The contextual item's data.
|
| - */
|
| openMenu: function(anchor, itemData) {
|
| if (this.lastAnchor_ == anchor && this.menuOpen)
|
| return;
|
| @@ -10660,16 +7725,10 @@ Polymer({
|
| this.lastFocus_ = focusableChildren[focusableChildren.length - 1];
|
| }
|
|
|
| - // Move the menu to the anchor.
|
| this.$.dropdown.positionTarget = anchor;
|
| this.menuOpen = true;
|
| },
|
|
|
| - /**
|
| - * Toggles the menu for the anchor that is passed in.
|
| - * @param {!Element} anchor The location to display the menu.
|
| - * @param {!Object} itemData The contextual item's data.
|
| - */
|
| toggleMenu: function(anchor, itemData) {
|
| if (anchor == this.lastAnchor_ && this.menuOpen)
|
| this.closeMenu();
|
| @@ -10677,13 +7736,6 @@ Polymer({
|
| this.openMenu(anchor, itemData);
|
| },
|
|
|
| - /**
|
| - * Trap focus inside the menu. As a very basic heuristic, will wrap focus from
|
| - * the first element with a nonzero tabindex to the last such element.
|
| - * TODO(tsergeant): Use iron-focus-wrap-behavior once it is available
|
| - * (https://github.com/PolymerElements/iron-overlay-behavior/issues/179).
|
| - * @param {CustomEvent} e
|
| - */
|
| onTabPressed_: function(e) {
|
| if (!this.firstFocus_ || !this.lastFocus_)
|
| return;
|
| @@ -10702,11 +7754,6 @@ Polymer({
|
| toFocus.focus();
|
| },
|
|
|
| - /**
|
| - * Ensure the menu is reset properly when it is closed by the dropdown (eg,
|
| - * clicking outside).
|
| - * @private
|
| - */
|
| menuOpenChanged_: function() {
|
| if (!this.menuOpen) {
|
| this.itemData = null;
|
| @@ -10714,12 +7761,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Prevent focus restoring when tapping outside the menu. This stops the
|
| - * focus moving around unexpectedly when closing the menu with the mouse.
|
| - * @param {CustomEvent} e
|
| - * @private
|
| - */
|
| onOverlayCanceled_: function(e) {
|
| if (e.detail.type == 'tap')
|
| this.$.dropdown.restoreFocusOnClose = false;
|
| @@ -10756,22 +7797,12 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * If true, the orientation is horizontal; otherwise is vertical.
|
| - *
|
| - * @attribute horizontal
|
| - */
|
| horizontal: {
|
| type: Boolean,
|
| value: false,
|
| observer: '_horizontalChanged'
|
| },
|
|
|
| - /**
|
| - * Set opened to true to show the collapse element and to false to hide it.
|
| - *
|
| - * @attribute opened
|
| - */
|
| opened: {
|
| type: Boolean,
|
| value: false,
|
| @@ -10779,11 +7810,6 @@ Polymer({
|
| observer: '_openedChanged'
|
| },
|
|
|
| - /**
|
| - * Set noAnimation to true to disable animations
|
| - *
|
| - * @attribute noAnimation
|
| - */
|
| noAnimation: {
|
| type: Boolean
|
| },
|
| @@ -10794,18 +7820,10 @@ Polymer({
|
| return this.horizontal ? 'width' : 'height';
|
| },
|
|
|
| - /**
|
| - * `maxWidth` or `maxHeight`.
|
| - * @private
|
| - */
|
| get _dimensionMax() {
|
| return this.horizontal ? 'maxWidth' : 'maxHeight';
|
| },
|
|
|
| - /**
|
| - * `max-width` or `max-height`.
|
| - * @private
|
| - */
|
| get _dimensionMaxCss() {
|
| return this.horizontal ? 'max-width' : 'max-height';
|
| },
|
| @@ -10821,15 +7839,9 @@ Polymer({
|
| },
|
|
|
| attached: function() {
|
| - // It will take care of setting correct classes and styles.
|
| this._transitionEnd();
|
| },
|
|
|
| - /**
|
| - * Toggle the opened state.
|
| - *
|
| - * @method toggle
|
| - */
|
| toggle: function() {
|
| this.opened = !this.opened;
|
| },
|
| @@ -10842,38 +7854,23 @@ Polymer({
|
| this.opened = false;
|
| },
|
|
|
| - /**
|
| - * Updates the size of the element.
|
| - * @param {string} size The new value for `maxWidth`/`maxHeight` as css property value, usually `auto` or `0px`.
|
| - * @param {boolean=} animated if `true` updates the size with an animation, otherwise without.
|
| - */
|
| updateSize: function(size, animated) {
|
| - // No change!
|
| var curSize = this.style[this._dimensionMax];
|
| if (curSize === size || (size === 'auto' && !curSize)) {
|
| return;
|
| }
|
|
|
| this._updateTransition(false);
|
| - // If we can animate, must do some prep work.
|
| if (animated && !this.noAnimation && this._isDisplayed) {
|
| - // Animation will start at the current size.
|
| var startSize = this._calcSize();
|
| - // For `auto` we must calculate what is the final size for the animation.
|
| - // After the transition is done, _transitionEnd will set the size back to `auto`.
|
| if (size === 'auto') {
|
| this.style[this._dimensionMax] = '';
|
| size = this._calcSize();
|
| }
|
| - // Go to startSize without animation.
|
| this.style[this._dimensionMax] = startSize;
|
| - // Force layout to ensure transition will go. Set scrollTop to itself
|
| - // so that compilers won't remove it.
|
| this.scrollTop = this.scrollTop;
|
| - // Enable animation.
|
| this._updateTransition(true);
|
| }
|
| - // Set the final size.
|
| if (size === 'auto') {
|
| this.style[this._dimensionMax] = '';
|
| } else {
|
| @@ -10881,13 +7878,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * enableTransition() is deprecated, but left over so it doesn't break existing code.
|
| - * Please use `noAnimation` property instead.
|
| - *
|
| - * @method enableTransition
|
| - * @deprecated since version 1.0.4
|
| - */
|
| enableTransition: function(enabled) {
|
| Polymer.Base._warn('`enableTransition()` is deprecated, use `noAnimation` instead.');
|
| this.noAnimation = !enabled;
|
| @@ -10912,7 +7902,6 @@ Polymer({
|
| this.toggleClass('iron-collapse-opened', false);
|
| this.updateSize(this.opened ? 'auto' : '0px', true);
|
|
|
| - // Focus the current collapse.
|
| if (this.opened) {
|
| this.focus();
|
| }
|
| @@ -10931,11 +7920,6 @@ Polymer({
|
| this.notifyResize();
|
| },
|
|
|
| - /**
|
| - * Simplistic heuristic to detect if element has a parent with display: none
|
| - *
|
| - * @private
|
| - */
|
| get _isDisplayed() {
|
| var rect = this.getBoundingClientRect();
|
| for (var prop in rect) {
|
| @@ -10949,67 +7933,31 @@ Polymer({
|
| }
|
|
|
| });
|
| -/**
|
| - Polymer.IronFormElementBehavior enables a custom element to be included
|
| - in an `iron-form`.
|
| -
|
| - @demo demo/index.html
|
| - @polymerBehavior
|
| - */
|
| Polymer.IronFormElementBehavior = {
|
|
|
| properties: {
|
| - /**
|
| - * Fired when the element is added to an `iron-form`.
|
| - *
|
| - * @event iron-form-element-register
|
| - */
|
| -
|
| - /**
|
| - * Fired when the element is removed from an `iron-form`.
|
| - *
|
| - * @event iron-form-element-unregister
|
| - */
|
| -
|
| - /**
|
| - * The name of this element.
|
| - */
|
| +
|
| +
|
| name: {
|
| type: String
|
| },
|
|
|
| - /**
|
| - * The value for this element.
|
| - */
|
| value: {
|
| notify: true,
|
| type: String
|
| },
|
|
|
| - /**
|
| - * Set to true to mark the input as required. If used in a form, a
|
| - * custom element that uses this behavior should also use
|
| - * Polymer.IronValidatableBehavior and define a custom validation method.
|
| - * Otherwise, a `required` element will always be considered valid.
|
| - * It's also strongly recommended to provide a visual style for the element
|
| - * when its value is invalid.
|
| - */
|
| required: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * The form that the element is registered to.
|
| - */
|
| _parentForm: {
|
| type: Object
|
| }
|
| },
|
|
|
| attached: function() {
|
| - // Note: the iron-form that this element belongs to will set this
|
| - // element's _parentForm property when handling this event.
|
| this.fire('iron-form-element-register');
|
| },
|
|
|
| @@ -11020,27 +7968,10 @@ Polymer({
|
| }
|
|
|
| };
|
| -/**
|
| - * Use `Polymer.IronCheckedElementBehavior` to implement a custom element
|
| - * that has a `checked` property, which can be used for validation if the
|
| - * element is also `required`. Element instances implementing this behavior
|
| - * will also be registered for use in an `iron-form` element.
|
| - *
|
| - * @demo demo/index.html
|
| - * @polymerBehavior Polymer.IronCheckedElementBehavior
|
| - */
|
| Polymer.IronCheckedElementBehaviorImpl = {
|
|
|
| properties: {
|
| - /**
|
| - * Fired when the checked state changes.
|
| - *
|
| - * @event iron-change
|
| - */
|
| -
|
| - /**
|
| - * Gets or sets the state, `true` is checked and `false` is unchecked.
|
| - */
|
| +
|
| checked: {
|
| type: Boolean,
|
| value: false,
|
| @@ -11049,10 +7980,6 @@ Polymer({
|
| observer: '_checkedChanged'
|
| },
|
|
|
| - /**
|
| - * If true, the button toggles the active state with each tap or press
|
| - * of the spacebar.
|
| - */
|
| toggles: {
|
| type: Boolean,
|
| value: true,
|
| @@ -11072,24 +7999,13 @@ Polymer({
|
| ],
|
|
|
| created: function() {
|
| - // Used by `iron-form` to handle the case that an element with this behavior
|
| - // doesn't have a role of 'checkbox' or 'radio', but should still only be
|
| - // included when the form is serialized if `this.checked === true`.
|
| this._hasIronCheckedElementBehavior = true;
|
| },
|
|
|
| - /**
|
| - * Returns false if the element is required and not checked, and true otherwise.
|
| - * @param {*=} _value Ignored.
|
| - * @return {boolean} true if `required` is false or if `checked` is true.
|
| - */
|
| _getValidity: function(_value) {
|
| return this.disabled || !this.required || this.checked;
|
| },
|
|
|
| - /**
|
| - * Update the aria-required label when `required` is changed.
|
| - */
|
| _requiredChanged: function() {
|
| if (this.required) {
|
| this.setAttribute('aria-required', 'true');
|
| @@ -11098,17 +8014,11 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Fire `iron-changed` when the checked state changes.
|
| - */
|
| _checkedChanged: function() {
|
| this.active = this.checked;
|
| this.fire('iron-change');
|
| },
|
|
|
| - /**
|
| - * Reset value to 'on' if it is set to `undefined`.
|
| - */
|
| _valueChanged: function() {
|
| if (this.value === undefined || this.value === null) {
|
| this.value = 'on';
|
| @@ -11122,16 +8032,7 @@ Polymer({
|
| Polymer.IronValidatableBehavior,
|
| Polymer.IronCheckedElementBehaviorImpl
|
| ];
|
| -/**
|
| - * Use `Polymer.PaperCheckedElementBehavior` to implement a custom element
|
| - * that has a `checked` property similar to `Polymer.IronCheckedElementBehavior`
|
| - * and is compatible with having a ripple effect.
|
| - * @polymerBehavior Polymer.PaperCheckedElementBehavior
|
| - */
|
| Polymer.PaperCheckedElementBehaviorImpl = {
|
| - /**
|
| - * Synchronizes the element's checked state with its ripple effect.
|
| - */
|
| _checkedChanged: function() {
|
| Polymer.IronCheckedElementBehaviorImpl._checkedChanged.call(this);
|
| if (this.hasRipple()) {
|
| @@ -11143,9 +8044,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Synchronizes the element's `active` and `checked` state.
|
| - */
|
| _buttonStateChanged: function() {
|
| Polymer.PaperRippleBehavior._buttonStateChanged.call(this);
|
| if (this.disabled) {
|
| @@ -11177,17 +8075,7 @@ Polymer({
|
| },
|
|
|
| properties: {
|
| - /**
|
| - * Fired when the checked state changes due to user interaction.
|
| - *
|
| - * @event change
|
| - */
|
| -
|
| - /**
|
| - * Fired when the checked state changes.
|
| - *
|
| - * @event iron-change
|
| - */
|
| +
|
| ariaActiveAttribute: {
|
| type: String,
|
| value: 'aria-checked'
|
| @@ -11209,7 +8097,6 @@ Polymer({
|
| return checked ? '' : 'hidden';
|
| },
|
|
|
| - // create ripple inside the checkboxContainer
|
| _createRipple: function() {
|
| this._rippleContainer = this.$.checkboxContainer;
|
| return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this);
|
| @@ -11239,9 +8126,6 @@ Polymer({
|
| this.getRipple().upAction();
|
| },
|
|
|
| - /**
|
| - * @param {...*} var_args
|
| - */
|
| ensureRipple: function(var_args) {
|
| var lastRipple = this._ripple;
|
| Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments);
|
| @@ -11256,37 +8140,17 @@ Polymer({
|
| // found in the LICENSE file.
|
|
|
| cr.define('cr.icon', function() {
|
| - /**
|
| - * @return {!Array<number>} The scale factors supported by this platform for
|
| - * webui resources.
|
| - */
|
| function getSupportedScaleFactors() {
|
| var supportedScaleFactors = [];
|
| if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) {
|
| - // All desktop platforms support zooming which also updates the
|
| - // renderer's device scale factors (a.k.a devicePixelRatio), and
|
| - // these platforms has high DPI assets for 2.0x. Use 1x and 2x in
|
| - // image-set on these platforms so that the renderer can pick the
|
| - // closest image for the current device scale factor.
|
| supportedScaleFactors.push(1);
|
| supportedScaleFactors.push(2);
|
| } else {
|
| - // For other platforms that use fixed device scale factor, use
|
| - // the window's device pixel ratio.
|
| - // TODO(oshima): Investigate if Android/iOS need to use image-set.
|
| supportedScaleFactors.push(window.devicePixelRatio);
|
| }
|
| return supportedScaleFactors;
|
| }
|
|
|
| - /**
|
| - * Returns the URL of the image, or an image set of URLs for the profile
|
| - * avatar. Default avatars have resources available for multiple scalefactors,
|
| - * whereas the GAIA profile image only comes in one size.
|
| - *
|
| - * @param {string} path The path of the image.
|
| - * @return {string} The url, or an image set of URLs of the avatar image.
|
| - */
|
| function getProfileAvatarIcon(path) {
|
| var chromeThemePath = 'chrome://theme';
|
| var isDefaultAvatar =
|
| @@ -11294,15 +8158,6 @@ cr.define('cr.icon', function() {
|
| return isDefaultAvatar ? imageset(path + '@scalefactorx'): url(path);
|
| }
|
|
|
| - /**
|
| - * Generates a CSS -webkit-image-set for a chrome:// url.
|
| - * An entry in the image set is added for each of getSupportedScaleFactors().
|
| - * The scale-factor-specific url is generated by replacing the first instance
|
| - * of 'scalefactor' in |path| with the numeric scale factor.
|
| - * @param {string} path The URL to generate an image set for.
|
| - * 'scalefactor' should be a substring of |path|.
|
| - * @return {string} The CSS -webkit-image-set.
|
| - */
|
| function imageset(path) {
|
| var supportedScaleFactors = getSupportedScaleFactors();
|
|
|
| @@ -11324,29 +8179,14 @@ cr.define('cr.icon', function() {
|
| return '-webkit-image-set(' + s + ')';
|
| }
|
|
|
| - /**
|
| - * A regular expression for identifying favicon URLs.
|
| - * @const {!RegExp}
|
| - */
|
| var FAVICON_URL_REGEX = /\.ico$/i;
|
|
|
| - /**
|
| - * Creates a CSS -webkit-image-set for a favicon request.
|
| - * @param {string} url Either the URL of the original page or of the favicon
|
| - * itself.
|
| - * @param {number=} opt_size Optional preferred size of the favicon.
|
| - * @param {string=} opt_type Optional type of favicon to request. Valid values
|
| - * are 'favicon' and 'touch-icon'. Default is 'favicon'.
|
| - * @return {string} -webkit-image-set for the favicon.
|
| - */
|
| function getFaviconImageSet(url, opt_size, opt_type) {
|
| var size = opt_size || 16;
|
| var type = opt_type || 'favicon';
|
|
|
| return imageset(
|
| 'chrome://' + type + '/size/' + size + '@scalefactorx/' +
|
| - // Note: Literal 'iconurl' must match |kIconURLParameter| in
|
| - // components/favicon_base/favicon_url_parser.cc.
|
| (FAVICON_URL_REGEX.test(url) ? 'iconurl/' : '') + url);
|
| }
|
|
|
| @@ -11360,10 +8200,6 @@ cr.define('cr.icon', function() {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @fileoverview Defines a singleton object, md_history.BrowserService, which
|
| - * provides access to chrome.send APIs.
|
| - */
|
|
|
| cr.define('md_history', function() {
|
| /** @constructor */
|
| @@ -11375,13 +8211,8 @@ cr.define('md_history', function() {
|
| }
|
|
|
| BrowserService.prototype = {
|
| - /**
|
| - * @param {!Array<!HistoryEntry>} items
|
| - * @return {Promise<!Array<!HistoryEntry>>}
|
| - */
|
| deleteItems: function(items) {
|
| if (this.pendingDeleteItems_ != null) {
|
| - // There's already a deletion in progress, reject immediately.
|
| return new Promise(function(resolve, reject) { reject(items); });
|
| }
|
|
|
| @@ -11400,26 +8231,14 @@ cr.define('md_history', function() {
|
| return this.pendingDeletePromise_.promise;
|
| },
|
|
|
| - /**
|
| - * @param {!string} url
|
| - */
|
| removeBookmark: function(url) {
|
| chrome.send('removeBookmark', [url]);
|
| },
|
|
|
| - /**
|
| - * @param {string} sessionTag
|
| - */
|
| openForeignSessionAllTabs: function(sessionTag) {
|
| chrome.send('openForeignSession', [sessionTag]);
|
| },
|
|
|
| - /**
|
| - * @param {string} sessionTag
|
| - * @param {number} windowId
|
| - * @param {number} tabId
|
| - * @param {MouseEvent} e
|
| - */
|
| openForeignSessionTab: function(sessionTag, windowId, tabId, e) {
|
| chrome.send('openForeignSession', [
|
| sessionTag, String(windowId), String(tabId), e.button || 0, e.altKey,
|
| @@ -11427,9 +8246,6 @@ cr.define('md_history', function() {
|
| ]);
|
| },
|
|
|
| - /**
|
| - * @param {string} sessionTag
|
| - */
|
| deleteForeignSession: function(sessionTag) {
|
| chrome.send('deleteForeignSession', [sessionTag]);
|
| },
|
| @@ -11438,18 +8254,10 @@ cr.define('md_history', function() {
|
| chrome.send('clearBrowsingData');
|
| },
|
|
|
| - /**
|
| - * Record an action in UMA.
|
| - * @param {string} actionDesc The name of the action to be logged.
|
| - */
|
| recordAction: function(actionDesc) {
|
| chrome.send('metricsHandler:recordAction', [actionDesc]);
|
| },
|
|
|
| - /**
|
| - * @param {boolean} successful
|
| - * @private
|
| - */
|
| resolveDelete_: function(successful) {
|
| if (this.pendingDeleteItems_ == null ||
|
| this.pendingDeletePromise_ == null) {
|
| @@ -11471,16 +8279,10 @@ cr.define('md_history', function() {
|
| return {BrowserService: BrowserService};
|
| });
|
|
|
| -/**
|
| - * Called by the history backend when deletion was succesful.
|
| - */
|
| function deleteComplete() {
|
| md_history.BrowserService.getInstance().resolveDelete_(true);
|
| }
|
|
|
| -/**
|
| - * Called by the history backend when the deletion failed.
|
| - */
|
| function deleteFailed() {
|
| md_history.BrowserService.getInstance().resolveDelete_(false);
|
| };
|
| @@ -11492,20 +8294,13 @@ Polymer({
|
| is: 'history-searched-label',
|
|
|
| properties: {
|
| - // The text to show in this label.
|
| title: String,
|
|
|
| - // The search term to bold within the title.
|
| searchTerm: String,
|
| },
|
|
|
| observers: ['setSearchedTextToBold_(title, searchTerm)'],
|
|
|
| - /**
|
| - * Updates the page title. If a search term is specified, highlights any
|
| - * occurrences of the search term in bold.
|
| - * @private
|
| - */
|
| setSearchedTextToBold_: function() {
|
| var i = 0;
|
| var titleElem = this.$.container;
|
| @@ -11524,7 +8319,6 @@ Polymer({
|
| titleElem.appendChild(document.createTextNode(
|
| titleText.slice(i, match.index)));
|
| i = re.lastIndex;
|
| - // Mark the highlighted text in bold.
|
| var b = document.createElement('b');
|
| b.textContent = titleText.substring(match.index, i);
|
| titleElem.appendChild(b);
|
| @@ -11543,11 +8337,8 @@ cr.define('md_history', function() {
|
| is: 'history-item',
|
|
|
| properties: {
|
| - // Underlying HistoryEntry data for this item. Contains read-only fields
|
| - // from the history backend, as well as fields computed by history-list.
|
| item: {type: Object, observer: 'showIcon_'},
|
|
|
| - // Search term used to obtain this history-item.
|
| searchTerm: {type: String},
|
|
|
| selected: {type: Boolean, notify: true},
|
| @@ -11558,26 +8349,16 @@ cr.define('md_history', function() {
|
|
|
| isCardEnd: {type: Boolean, reflectToAttribute: true},
|
|
|
| - // True if the item is being displayed embedded in another element and
|
| - // should not manage its own borders or size.
|
| embedded: {type: Boolean, reflectToAttribute: true},
|
|
|
| hasTimeGap: {type: Boolean},
|
|
|
| numberOfItems: {type: Number},
|
|
|
| - // The path of this history item inside its parent.
|
| path: String,
|
| },
|
|
|
| - /**
|
| - * When a history-item is selected the toolbar is notified and increases
|
| - * or decreases its count of selected items accordingly.
|
| - * @param {MouseEvent} e
|
| - * @private
|
| - */
|
| onCheckboxSelected_: function(e) {
|
| - // TODO(calamity): Fire this event whenever |selected| changes.
|
| this.fire('history-checkbox-select', {
|
| element: this,
|
| shiftKey: e.shiftKey,
|
| @@ -11585,20 +8366,11 @@ cr.define('md_history', function() {
|
| e.preventDefault();
|
| },
|
|
|
| - /**
|
| - * @param {MouseEvent} e
|
| - * @private
|
| - */
|
| onCheckboxMousedown_: function(e) {
|
| - // Prevent shift clicking a checkbox from selecting text.
|
| if (e.shiftKey)
|
| e.preventDefault();
|
| },
|
|
|
| - /**
|
| - * Remove bookmark of current item when bookmark-star is clicked.
|
| - * @private
|
| - */
|
| onRemoveBookmarkTap_: function() {
|
| if (!this.item.starred)
|
| return;
|
| @@ -11611,10 +8383,6 @@ cr.define('md_history', function() {
|
| this.fire('remove-bookmark-stars', this.item.url);
|
| },
|
|
|
| - /**
|
| - * Fires a custom event when the menu button is clicked. Sends the details
|
| - * of the history item and where the menu should appear.
|
| - */
|
| onMenuButtonTap_: function(e) {
|
| this.fire('toggle-menu', {
|
| target: Polymer.dom(e).localTarget,
|
| @@ -11622,14 +8390,9 @@ cr.define('md_history', function() {
|
| path: this.path,
|
| });
|
|
|
| - // Stops the 'tap' event from closing the menu when it opens.
|
| e.stopPropagation();
|
| },
|
|
|
| - /**
|
| - * Set the favicon image, based on the URL of the history item.
|
| - * @private
|
| - */
|
| showIcon_: function() {
|
| this.$.icon.style.backgroundImage =
|
| cr.icon.getFaviconImageSet(this.item.url);
|
| @@ -11639,12 +8402,6 @@ cr.define('md_history', function() {
|
| return !loadTimeData.getBoolean('allowDeletingHistory');
|
| },
|
|
|
| - /**
|
| - * Generates the title for this history card.
|
| - * @param {number} numberOfItems The number of items in the card.
|
| - * @param {string} search The search term associated with these results.
|
| - * @private
|
| - */
|
| cardTitle_: function(numberOfItems, historyDate, search) {
|
| if (!search)
|
| return this.item.dateRelativeDay;
|
| @@ -11654,12 +8411,6 @@ cr.define('md_history', function() {
|
| loadTimeData.getString(resultId), search);
|
| },
|
|
|
| - /**
|
| - * Crop long item titles to reduce their effect on layout performance. See
|
| - * crbug.com/621347.
|
| - * @param {string} title
|
| - * @return {string}
|
| - */
|
| cropItemTitle_: function(title) {
|
| return (title.length > TITLE_MAX_LENGTH) ?
|
| title.substr(0, TITLE_MAX_LENGTH) :
|
| @@ -11667,15 +8418,6 @@ cr.define('md_history', function() {
|
| }
|
| });
|
|
|
| - /**
|
| - * Check whether the time difference between the given history item and the
|
| - * next one is large enough for a spacer to be required.
|
| - * @param {Array<HistoryEntry>} visits
|
| - * @param {number} currentIndex
|
| - * @param {string} searchedTerm
|
| - * @return {boolean} Whether or not time gap separator is required.
|
| - * @private
|
| - */
|
| HistoryItem.needsTimeGap = function(visits, currentIndex, searchedTerm) {
|
| if (currentIndex >= visits.length - 1 || visits.length == 0)
|
| return false;
|
| @@ -11696,10 +8438,6 @@ cr.define('md_history', function() {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @constructor
|
| - * @param {string} currentPath
|
| - */
|
| var SelectionTreeNode = function(currentPath) {
|
| /** @type {string} */
|
| this.currentPath = currentPath;
|
| @@ -11711,10 +8449,6 @@ var SelectionTreeNode = function(currentPath) {
|
| this.children = [];
|
| };
|
|
|
| -/**
|
| - * @param {number} index
|
| - * @param {string} path
|
| - */
|
| SelectionTreeNode.prototype.addChild = function(index, path) {
|
| this.indexes.push(index);
|
| this.children[index] = new SelectionTreeNode(path);
|
| @@ -11723,10 +8457,6 @@ SelectionTreeNode.prototype.addChild = function(index, path) {
|
| /** @polymerBehavior */
|
| var HistoryListBehavior = {
|
| properties: {
|
| - /**
|
| - * Polymer paths to the history items contained in this list.
|
| - * @type {!Set<string>} selectedPaths
|
| - */
|
| selectedPaths: {
|
| type: Object,
|
| value: /** @return {!Set<string>} */ function() { return new Set(); }
|
| @@ -11739,19 +8469,8 @@ var HistoryListBehavior = {
|
| 'history-checkbox-select': 'itemSelected_',
|
| },
|
|
|
| - /**
|
| - * @param {number} historyDataLength
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| hasResults: function(historyDataLength) { return historyDataLength > 0; },
|
|
|
| - /**
|
| - * @param {string} searchedTerm
|
| - * @param {boolean} isLoading
|
| - * @return {string}
|
| - * @private
|
| - */
|
| noResultsMessage: function(searchedTerm, isLoading) {
|
| if (isLoading)
|
| return '';
|
| @@ -11760,9 +8479,6 @@ var HistoryListBehavior = {
|
| return loadTimeData.getString(messageId);
|
| },
|
|
|
| - /**
|
| - * Deselect each item in |selectedPaths|.
|
| - */
|
| unselectAllItems: function() {
|
| this.selectedPaths.forEach(function(path) {
|
| this.set(path + '.selected', false);
|
| @@ -11771,12 +8487,6 @@ var HistoryListBehavior = {
|
| this.selectedPaths.clear();
|
| },
|
|
|
| - /**
|
| - * Performs a request to the backend to delete all selected items. If
|
| - * successful, removes them from the view. Does not prompt the user before
|
| - * deleting -- see <history-list-container> for a version of this method which
|
| - * does prompt.
|
| - */
|
| deleteSelected: function() {
|
| var toBeRemoved =
|
| Array.from(this.selectedPaths.values()).map(function(path) {
|
| @@ -11791,19 +8501,6 @@ var HistoryListBehavior = {
|
| }.bind(this));
|
| },
|
|
|
| - /**
|
| - * Removes the history items in |paths|. Assumes paths are of a.0.b.0...
|
| - * structure.
|
| - *
|
| - * We want to use notifySplices to update the arrays for performance reasons
|
| - * which requires manually batching and sending the notifySplices for each
|
| - * level. To do this, we build a tree where each node is an array and then
|
| - * depth traverse it to remove items. Each time a node has all children
|
| - * deleted, we can also remove the node.
|
| - *
|
| - * @param {Array<string>} paths
|
| - * @private
|
| - */
|
| removeItemsByPath: function(paths) {
|
| if (paths.length == 0)
|
| return;
|
| @@ -11811,19 +8508,9 @@ var HistoryListBehavior = {
|
| this.removeItemsBeneathNode_(this.buildRemovalTree_(paths));
|
| },
|
|
|
| - /**
|
| - * Creates the tree to traverse in order to remove |paths| from this list.
|
| - * Assumes paths are of a.0.b.0...
|
| - * structure.
|
| - *
|
| - * @param {Array<string>} paths
|
| - * @return {SelectionTreeNode}
|
| - * @private
|
| - */
|
| buildRemovalTree_: function(paths) {
|
| var rootNode = new SelectionTreeNode(paths[0].split('.')[0]);
|
|
|
| - // Build a tree to each history item specified in |paths|.
|
| paths.forEach(function(path) {
|
| var components = path.split('.');
|
| var node = rootNode;
|
| @@ -11844,13 +8531,6 @@ var HistoryListBehavior = {
|
| return rootNode;
|
| },
|
|
|
| - /**
|
| - * Removes the history items underneath |node| and deletes container arrays as
|
| - * they become empty.
|
| - * @param {SelectionTreeNode} node
|
| - * @return {boolean} Whether this node's array should be deleted.
|
| - * @private
|
| - */
|
| removeItemsBeneathNode_: function(node) {
|
| var array = this.get(node.currentPath);
|
| var splices = [];
|
| @@ -11872,23 +8552,15 @@ var HistoryListBehavior = {
|
| if (array.length == 0)
|
| return true;
|
|
|
| - // notifySplices gives better performance than individually splicing as it
|
| - // batches all of the updates together.
|
| this.notifySplices(node.currentPath, splices);
|
| return false;
|
| },
|
|
|
| - /**
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| itemSelected_: function(e) {
|
| var item = e.detail.element;
|
| var paths = [];
|
| var itemPath = item.path;
|
|
|
| - // Handle shift selection. Change the selection state of all items between
|
| - // |path| and |lastSelected| to the selection state of |item|.
|
| if (e.detail.shiftKey && this.lastSelectedPath) {
|
| var itemPathComponents = itemPath.split('.');
|
| var itemIndex = Number(itemPathComponents.pop());
|
| @@ -11925,18 +8597,8 @@ var HistoryListBehavior = {
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @typedef {{domain: string,
|
| - * visits: !Array<HistoryEntry>,
|
| - * rendered: boolean,
|
| - * expanded: boolean}}
|
| - */
|
| var HistoryDomain;
|
|
|
| -/**
|
| - * @typedef {{title: string,
|
| - * domains: !Array<HistoryDomain>}}
|
| - */
|
| var HistoryGroup;
|
|
|
| Polymer({
|
| @@ -11945,14 +8607,10 @@ Polymer({
|
| behaviors: [HistoryListBehavior],
|
|
|
| properties: {
|
| - // An array of history entries in reverse chronological order.
|
| historyData: {
|
| type: Array,
|
| },
|
|
|
| - /**
|
| - * @type {Array<HistoryGroup>}
|
| - */
|
| groupedHistoryData_: {
|
| type: Array,
|
| },
|
| @@ -11974,16 +8632,10 @@ Polymer({
|
| 'updateGroupedHistoryData_(range, historyData)'
|
| ],
|
|
|
| - /**
|
| - * Make a list of domains from visits.
|
| - * @param {!Array<!HistoryEntry>} visits
|
| - * @return {!Array<!HistoryDomain>}
|
| - */
|
| createHistoryDomains_: function(visits) {
|
| var domainIndexes = {};
|
| var domains = [];
|
|
|
| - // Group the visits into a dictionary and generate a list of domains.
|
| for (var i = 0, visit; visit = visits[i]; i++) {
|
| var domain = visit.domain;
|
| if (domainIndexes[domain] == undefined) {
|
| @@ -12012,7 +8664,6 @@ Polymer({
|
| }
|
|
|
| if (this.range == HistoryRange.WEEK) {
|
| - // Group each day into a list of results.
|
| var days = [];
|
| var currentDayVisits = [this.historyData[0]];
|
|
|
| @@ -12043,7 +8694,6 @@ Polymer({
|
|
|
| this.groupedHistoryData_ = days;
|
| } else if (this.range == HistoryRange.MONTH) {
|
| - // Group each all visits into a single list.
|
| this.groupedHistoryData_ = [{
|
| title: this.queryStartTime + ' – ' + this.queryEndTime,
|
| domains: this.createHistoryDomains_(this.historyData)
|
| @@ -12051,26 +8701,13 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * @param {{model:Object, currentTarget:IronCollapseElement}} e
|
| - */
|
| toggleDomainExpanded_: function(e) {
|
| var collapse = e.currentTarget.parentNode.querySelector('iron-collapse');
|
| e.model.set('domain.rendered', true);
|
|
|
| - // Give the history-items time to render.
|
| setTimeout(function() { collapse.toggle() }, 0);
|
| },
|
|
|
| - /**
|
| - * Check whether the time difference between the given history item and the
|
| - * next one is large enough for a spacer to be required.
|
| - * @param {number} groupIndex
|
| - * @param {number} domainIndex
|
| - * @param {number} itemIndex
|
| - * @return {boolean} Whether or not time gap separator is required.
|
| - * @private
|
| - */
|
| needsTimeGap_: function(groupIndex, domainIndex, itemIndex) {
|
| var visits =
|
| this.groupedHistoryData_[groupIndex].domains[domainIndex].visits;
|
| @@ -12079,13 +8716,6 @@ Polymer({
|
| visits, itemIndex, this.searchedTerm);
|
| },
|
|
|
| - /**
|
| - * @param {number} groupIndex
|
| - * @param {number} domainIndex
|
| - * @param {number} itemIndex
|
| - * @return {string}
|
| - * @private
|
| - */
|
| pathForItem_: function(groupIndex, domainIndex, itemIndex) {
|
| return [
|
| 'groupedHistoryData_', groupIndex, 'domains', domainIndex, 'visits',
|
| @@ -12093,74 +8723,19 @@ Polymer({
|
| ].join('.');
|
| },
|
|
|
| - /**
|
| - * @param {HistoryDomain} domain
|
| - * @return {string}
|
| - * @private
|
| - */
|
| getWebsiteIconStyle_: function(domain) {
|
| return 'background-image: ' +
|
| cr.icon.getFaviconImageSet(domain.visits[0].url);
|
| },
|
|
|
| - /**
|
| - * @param {boolean} expanded
|
| - * @return {string}
|
| - * @private
|
| - */
|
| getDropdownIcon_: function(expanded) {
|
| return expanded ? 'cr:expand-less' : 'cr:expand-more';
|
| },
|
| });
|
| -/**
|
| - * `Polymer.IronScrollTargetBehavior` allows an element to respond to scroll events from a
|
| - * designated scroll target.
|
| - *
|
| - * Elements that consume this behavior can override the `_scrollHandler`
|
| - * method to add logic on the scroll event.
|
| - *
|
| - * @demo demo/scrolling-region.html Scrolling Region
|
| - * @demo demo/document.html Document Element
|
| - * @polymerBehavior
|
| - */
|
| Polymer.IronScrollTargetBehavior = {
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Specifies the element that will handle the scroll event
|
| - * on the behalf of the current element. This is typically a reference to an element,
|
| - * but there are a few more posibilities:
|
| - *
|
| - * ### Elements id
|
| - *
|
| - *```html
|
| - * <div id="scrollable-element" style="overflow: auto;">
|
| - * <x-element scroll-target="scrollable-element">
|
| - * \x3c!-- Content--\x3e
|
| - * </x-element>
|
| - * </div>
|
| - *```
|
| - * In this case, the `scrollTarget` will point to the outer div element.
|
| - *
|
| - * ### Document scrolling
|
| - *
|
| - * For document scrolling, you can use the reserved word `document`:
|
| - *
|
| - *```html
|
| - * <x-element scroll-target="document">
|
| - * \x3c!-- Content --\x3e
|
| - * </x-element>
|
| - *```
|
| - *
|
| - * ### Elements reference
|
| - *
|
| - *```js
|
| - * appHeader.scrollTarget = document.querySelector('#scrollable-element');
|
| - *```
|
| - *
|
| - * @type {HTMLElement}
|
| - */
|
| scrollTarget: {
|
| type: HTMLElement,
|
| value: function() {
|
| @@ -12185,7 +8760,6 @@ Polymer({
|
| if (!isAttached) {
|
| return;
|
| }
|
| - // Support element id references
|
| if (scrollTarget === 'document') {
|
|
|
| this.scrollTarget = this._doc;
|
| @@ -12205,37 +8779,16 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Runs on every scroll event. Consumer of this behavior may override this method.
|
| - *
|
| - * @protected
|
| - */
|
| _scrollHandler: function scrollHandler() {},
|
|
|
| - /**
|
| - * The default scroll target. Consumers of this behavior may want to customize
|
| - * the default scroll target.
|
| - *
|
| - * @type {Element}
|
| - */
|
| get _defaultScrollTarget() {
|
| return this._doc;
|
| },
|
|
|
| - /**
|
| - * Shortcut for the document element
|
| - *
|
| - * @type {Element}
|
| - */
|
| get _doc() {
|
| return this.ownerDocument.documentElement;
|
| },
|
|
|
| - /**
|
| - * Gets the number of pixels that the content of an element is scrolled upward.
|
| - *
|
| - * @type {number}
|
| - */
|
| get _scrollTop() {
|
| if (this._isValidScrollTarget()) {
|
| return this.scrollTarget === this._doc ? window.pageYOffset : this.scrollTarget.scrollTop;
|
| @@ -12243,11 +8796,6 @@ Polymer({
|
| return 0;
|
| },
|
|
|
| - /**
|
| - * Gets the number of pixels that the content of an element is scrolled to the left.
|
| - *
|
| - * @type {number}
|
| - */
|
| get _scrollLeft() {
|
| if (this._isValidScrollTarget()) {
|
| return this.scrollTarget === this._doc ? window.pageXOffset : this.scrollTarget.scrollLeft;
|
| @@ -12255,11 +8803,6 @@ Polymer({
|
| return 0;
|
| },
|
|
|
| - /**
|
| - * Sets the number of pixels that the content of an element is scrolled upward.
|
| - *
|
| - * @type {number}
|
| - */
|
| set _scrollTop(top) {
|
| if (this.scrollTarget === this._doc) {
|
| window.scrollTo(window.pageXOffset, top);
|
| @@ -12268,11 +8811,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Sets the number of pixels that the content of an element is scrolled to the left.
|
| - *
|
| - * @type {number}
|
| - */
|
| set _scrollLeft(left) {
|
| if (this.scrollTarget === this._doc) {
|
| window.scrollTo(left, window.pageYOffset);
|
| @@ -12281,13 +8819,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Scrolls the content to a particular place.
|
| - *
|
| - * @method scroll
|
| - * @param {number} left The left position
|
| - * @param {number} top The top position
|
| - */
|
| scroll: function(left, top) {
|
| if (this.scrollTarget === this._doc) {
|
| window.scrollTo(left, top);
|
| @@ -12297,11 +8828,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Gets the width of the scroll target.
|
| - *
|
| - * @type {number}
|
| - */
|
| get _scrollTargetWidth() {
|
| if (this._isValidScrollTarget()) {
|
| return this.scrollTarget === this._doc ? window.innerWidth : this.scrollTarget.offsetWidth;
|
| @@ -12309,11 +8835,6 @@ Polymer({
|
| return 0;
|
| },
|
|
|
| - /**
|
| - * Gets the height of the scroll target.
|
| - *
|
| - * @type {number}
|
| - */
|
| get _scrollTargetHeight() {
|
| if (this._isValidScrollTarget()) {
|
| return this.scrollTarget === this._doc ? window.innerHeight : this.scrollTarget.offsetHeight;
|
| @@ -12321,11 +8842,6 @@ Polymer({
|
| return 0;
|
| },
|
|
|
| - /**
|
| - * Returns true if the scroll target is a valid HTMLElement.
|
| - *
|
| - * @return {boolean}
|
| - */
|
| _isValidScrollTarget: function() {
|
| return this.scrollTarget instanceof HTMLElement;
|
| }
|
| @@ -12345,101 +8861,51 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * An array containing items determining how many instances of the template
|
| - * to stamp and that that each template instance should bind to.
|
| - */
|
| items: {
|
| type: Array
|
| },
|
|
|
| - /**
|
| - * The max count of physical items the pool can extend to.
|
| - */
|
| maxPhysicalCount: {
|
| type: Number,
|
| value: 500
|
| },
|
|
|
| - /**
|
| - * The name of the variable to add to the binding scope for the array
|
| - * element associated with a given template instance.
|
| - */
|
| as: {
|
| type: String,
|
| value: 'item'
|
| },
|
|
|
| - /**
|
| - * The name of the variable to add to the binding scope with the index
|
| - * for the row.
|
| - */
|
| indexAs: {
|
| type: String,
|
| value: 'index'
|
| },
|
|
|
| - /**
|
| - * The name of the variable to add to the binding scope to indicate
|
| - * if the row is selected.
|
| - */
|
| selectedAs: {
|
| type: String,
|
| value: 'selected'
|
| },
|
|
|
| - /**
|
| - * When true, the list is rendered as a grid. Grid items must have
|
| - * fixed width and height set via CSS. e.g.
|
| - *
|
| - * ```html
|
| - * <iron-list grid>
|
| - * <template>
|
| - * <div style="width: 100px; height: 100px;"> 100x100 </div>
|
| - * </template>
|
| - * </iron-list>
|
| - * ```
|
| - */
|
| grid: {
|
| type: Boolean,
|
| value: false,
|
| reflectToAttribute: true
|
| },
|
|
|
| - /**
|
| - * When true, tapping a row will select the item, placing its data model
|
| - * in the set of selected items retrievable via the selection property.
|
| - *
|
| - * Note that tapping focusable elements within the list item will not
|
| - * result in selection, since they are presumed to have their * own action.
|
| - */
|
| selectionEnabled: {
|
| type: Boolean,
|
| value: false
|
| },
|
|
|
| - /**
|
| - * When `multiSelection` is false, this is the currently selected item, or `null`
|
| - * if no item is selected.
|
| - */
|
| selectedItem: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * When `multiSelection` is true, this is an array that contains the selected items.
|
| - */
|
| selectedItems: {
|
| type: Object,
|
| notify: true
|
| },
|
|
|
| - /**
|
| - * When `true`, multiple items may be selected at once (in this case,
|
| - * `selected` is an array of currently selected items). When `false`,
|
| - * only one item may be selected at a time.
|
| - */
|
| multiSelection: {
|
| type: Boolean,
|
| value: false
|
| @@ -12466,209 +8932,89 @@ Polymer({
|
| 'enter': '_didEnter'
|
| },
|
|
|
| - /**
|
| - * The ratio of hidden tiles that should remain in the scroll direction.
|
| - * Recommended value ~0.5, so it will distribute tiles evely in both directions.
|
| - */
|
| _ratio: 0.5,
|
|
|
| - /**
|
| - * The padding-top value for the list.
|
| - */
|
| _scrollerPaddingTop: 0,
|
|
|
| - /**
|
| - * This value is the same as `scrollTop`.
|
| - */
|
| _scrollPosition: 0,
|
|
|
| - /**
|
| - * The sum of the heights of all the tiles in the DOM.
|
| - */
|
| _physicalSize: 0,
|
|
|
| - /**
|
| - * The average `offsetHeight` of the tiles observed till now.
|
| - */
|
| _physicalAverage: 0,
|
|
|
| - /**
|
| - * The number of tiles which `offsetHeight` > 0 observed until now.
|
| - */
|
| _physicalAverageCount: 0,
|
|
|
| - /**
|
| - * The Y position of the item rendered in the `_physicalStart`
|
| - * tile relative to the scrolling list.
|
| - */
|
| _physicalTop: 0,
|
|
|
| - /**
|
| - * The number of items in the list.
|
| - */
|
| _virtualCount: 0,
|
|
|
| - /**
|
| - * A map between an item key and its physical item index
|
| - */
|
| _physicalIndexForKey: null,
|
|
|
| - /**
|
| - * The estimated scroll height based on `_physicalAverage`
|
| - */
|
| _estScrollHeight: 0,
|
|
|
| - /**
|
| - * The scroll height of the dom node
|
| - */
|
| _scrollHeight: 0,
|
|
|
| - /**
|
| - * The height of the list. This is referred as the viewport in the context of list.
|
| - */
|
| _viewportHeight: 0,
|
|
|
| - /**
|
| - * The width of the list. This is referred as the viewport in the context of list.
|
| - */
|
| _viewportWidth: 0,
|
|
|
| - /**
|
| - * An array of DOM nodes that are currently in the tree
|
| - * @type {?Array<!TemplatizerNode>}
|
| - */
|
| _physicalItems: null,
|
|
|
| - /**
|
| - * An array of heights for each item in `_physicalItems`
|
| - * @type {?Array<number>}
|
| - */
|
| _physicalSizes: null,
|
|
|
| - /**
|
| - * A cached value for the first visible index.
|
| - * See `firstVisibleIndex`
|
| - * @type {?number}
|
| - */
|
| _firstVisibleIndexVal: null,
|
|
|
| - /**
|
| - * A cached value for the last visible index.
|
| - * See `lastVisibleIndex`
|
| - * @type {?number}
|
| - */
|
| _lastVisibleIndexVal: null,
|
|
|
| - /**
|
| - * A Polymer collection for the items.
|
| - * @type {?Polymer.Collection}
|
| - */
|
| _collection: null,
|
|
|
| - /**
|
| - * True if the current item list was rendered for the first time
|
| - * after attached.
|
| - */
|
| _itemsRendered: false,
|
|
|
| - /**
|
| - * The page that is currently rendered.
|
| - */
|
| _lastPage: null,
|
|
|
| - /**
|
| - * The max number of pages to render. One page is equivalent to the height of the list.
|
| - */
|
| _maxPages: 3,
|
|
|
| - /**
|
| - * The currently focused physical item.
|
| - */
|
| _focusedItem: null,
|
|
|
| - /**
|
| - * The index of the `_focusedItem`.
|
| - */
|
| _focusedIndex: -1,
|
|
|
| - /**
|
| - * The the item that is focused if it is moved offscreen.
|
| - * @private {?TemplatizerNode}
|
| - */
|
| _offscreenFocusedItem: null,
|
|
|
| - /**
|
| - * The item that backfills the `_offscreenFocusedItem` in the physical items
|
| - * list when that item is moved offscreen.
|
| - */
|
| _focusBackfillItem: null,
|
|
|
| - /**
|
| - * The maximum items per row
|
| - */
|
| _itemsPerRow: 1,
|
|
|
| - /**
|
| - * The width of each grid item
|
| - */
|
| _itemWidth: 0,
|
|
|
| - /**
|
| - * The height of the row in grid layout.
|
| - */
|
| _rowHeight: 0,
|
|
|
| - /**
|
| - * The bottom of the physical content.
|
| - */
|
| get _physicalBottom() {
|
| return this._physicalTop + this._physicalSize;
|
| },
|
|
|
| - /**
|
| - * The bottom of the scroll.
|
| - */
|
| get _scrollBottom() {
|
| return this._scrollPosition + this._viewportHeight;
|
| },
|
|
|
| - /**
|
| - * The n-th item rendered in the last physical item.
|
| - */
|
| get _virtualEnd() {
|
| return this._virtualStart + this._physicalCount - 1;
|
| },
|
|
|
| - /**
|
| - * The height of the physical content that isn't on the screen.
|
| - */
|
| get _hiddenContentSize() {
|
| var size = this.grid ? this._physicalRows * this._rowHeight : this._physicalSize;
|
| return size - this._viewportHeight;
|
| },
|
|
|
| - /**
|
| - * The maximum scroll top value.
|
| - */
|
| get _maxScrollTop() {
|
| return this._estScrollHeight - this._viewportHeight + this._scrollerPaddingTop;
|
| },
|
|
|
| - /**
|
| - * The lowest n-th value for an item such that it can be rendered in `_physicalStart`.
|
| - */
|
| _minVirtualStart: 0,
|
|
|
| - /**
|
| - * The largest n-th value for an item such that it can be rendered in `_physicalStart`.
|
| - */
|
| get _maxVirtualStart() {
|
| return Math.max(0, this._virtualCount - this._physicalCount);
|
| },
|
|
|
| - /**
|
| - * The n-th item rendered in the `_physicalStart` tile.
|
| - */
|
| _virtualStartVal: 0,
|
|
|
| set _virtualStart(val) {
|
| @@ -12679,9 +9025,6 @@ Polymer({
|
| return this._virtualStartVal || 0;
|
| },
|
|
|
| - /**
|
| - * The k-th tile that is at the top of the scrolling list.
|
| - */
|
| _physicalStartVal: 0,
|
|
|
| set _physicalStart(val) {
|
| @@ -12696,9 +9039,6 @@ Polymer({
|
| return this._physicalStartVal || 0;
|
| },
|
|
|
| - /**
|
| - * The number of tiles in the DOM.
|
| - */
|
| _physicalCountVal: 0,
|
|
|
| set _physicalCount(val) {
|
| @@ -12710,18 +9050,8 @@ Polymer({
|
| return this._physicalCountVal;
|
| },
|
|
|
| - /**
|
| - * The k-th tile that is at the bottom of the scrolling list.
|
| - */
|
| _physicalEnd: 0,
|
|
|
| - /**
|
| - * An optimal physical size such that we will have enough physical items
|
| - * to fill up the viewport and recycle when the user scrolls.
|
| - *
|
| - * This default value assumes that we will at least have the equivalent
|
| - * to a viewport of physical items above and below the user's viewport.
|
| - */
|
| get _optPhysicalSize() {
|
| if (this.grid) {
|
| return this._estRowsInView * this._rowHeight * this._maxPages;
|
| @@ -12733,18 +9063,10 @@ Polymer({
|
| return this._estRowsInView * this._itemsPerRow * this._maxPages;
|
| },
|
|
|
| - /**
|
| - * True if the current list is visible.
|
| - */
|
| get _isVisible() {
|
| return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this.scrollTarget.offsetHeight);
|
| },
|
|
|
| - /**
|
| - * Gets the index of the first visible item in the viewport.
|
| - *
|
| - * @type {number}
|
| - */
|
| get firstVisibleIndex() {
|
| if (this._firstVisibleIndexVal === null) {
|
| var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddingTop);
|
| @@ -12756,7 +9078,6 @@ Polymer({
|
| if (physicalOffset > this._scrollPosition) {
|
| return this.grid ? vidx - (vidx % this._itemsPerRow) : vidx;
|
| }
|
| - // Handle a partially rendered final row in grid mode
|
| if (this.grid && this._virtualCount - 1 === vidx) {
|
| return vidx - (vidx % this._itemsPerRow);
|
| }
|
| @@ -12765,11 +9086,6 @@ Polymer({
|
| return this._firstVisibleIndexVal;
|
| },
|
|
|
| - /**
|
| - * Gets the index of the last visible item in the viewport.
|
| - *
|
| - * @type {number}
|
| - */
|
| get lastVisibleIndex() {
|
| if (this._lastVisibleIndexVal === null) {
|
| if (this.grid) {
|
| @@ -12781,7 +9097,6 @@ Polymer({
|
| if (physicalOffset < this._scrollBottom) {
|
| this._lastVisibleIndexVal = vidx;
|
| } else {
|
| - // Break _iterateItems
|
| return true;
|
| }
|
| physicalOffset += this._getPhysicalSizeIncrement(pidx);
|
| @@ -12813,8 +9128,6 @@ Polymer({
|
| attached: function() {
|
| this.updateViewportBoundaries();
|
| this._render();
|
| - // `iron-resize` is fired when the list is attached if the event is added
|
| - // before attached causing unnecessary work.
|
| this.listen(this, 'iron-resize', '_resizeHandler');
|
| },
|
|
|
| @@ -12823,20 +9136,11 @@ Polymer({
|
| this.unlisten(this, 'iron-resize', '_resizeHandler');
|
| },
|
|
|
| - /**
|
| - * Set the overflow property if this element has its own scrolling region
|
| - */
|
| _setOverflow: function(scrollTarget) {
|
| this.style.webkitOverflowScrolling = scrollTarget === this ? 'touch' : '';
|
| this.style.overflow = scrollTarget === this ? 'auto' : '';
|
| },
|
|
|
| - /**
|
| - * Invoke this method if you dynamically update the viewport's
|
| - * size or CSS padding.
|
| - *
|
| - * @method updateViewportBoundaries
|
| - */
|
| updateViewportBoundaries: function() {
|
| this._scrollerPaddingTop = this.scrollTarget === this ? 0 :
|
| parseInt(window.getComputedStyle(this)['padding-top'], 10);
|
| @@ -12847,12 +9151,7 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Update the models, the position of the
|
| - * items in the viewport and recycle tiles as needed.
|
| - */
|
| _scrollHandler: function() {
|
| - // clamp the `scrollTop` value
|
| var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop));
|
| var delta = scrollTop - this._scrollPosition;
|
| var tileHeight, tileTop, kth, recycledTileSet, scrollBottom, physicalBottom;
|
| @@ -12862,22 +9161,18 @@ Polymer({
|
| var currentRatio = ratio;
|
| var movingUp = [];
|
|
|
| - // track the last `scrollTop`
|
| this._scrollPosition = scrollTop;
|
|
|
| - // clear cached visible indexes
|
| this._firstVisibleIndexVal = null;
|
| this._lastVisibleIndexVal = null;
|
|
|
| scrollBottom = this._scrollBottom;
|
| physicalBottom = this._physicalBottom;
|
|
|
| - // random access
|
| if (Math.abs(delta) > this._physicalSize) {
|
| this._physicalTop += delta;
|
| recycledTiles = Math.round(delta / this._physicalAverage);
|
| }
|
| - // scroll up
|
| else if (delta < 0) {
|
| var topSpace = scrollTop - this._physicalTop;
|
| var virtualStart = this._virtualStart;
|
| @@ -12887,15 +9182,10 @@ Polymer({
|
| kth = this._physicalEnd;
|
| currentRatio = topSpace / hiddenContentSize;
|
|
|
| - // move tiles from bottom to top
|
| while (
|
| - // approximate `currentRatio` to `ratio`
|
| currentRatio < ratio &&
|
| - // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| - // ensure that these recycled tiles are needed
|
| virtualStart - recycledTiles > 0 &&
|
| - // ensure that the tile is not visible
|
| physicalBottom - this._getPhysicalSizeIncrement(kth) > scrollBottom
|
| ) {
|
|
|
| @@ -12910,7 +9200,6 @@ Polymer({
|
| movingUp = recycledTileSet;
|
| recycledTiles = -recycledTiles;
|
| }
|
| - // scroll down
|
| else if (delta > 0) {
|
| var bottomSpace = physicalBottom - scrollBottom;
|
| var virtualEnd = this._virtualEnd;
|
| @@ -12921,15 +9210,10 @@ Polymer({
|
| kth = this._physicalStart;
|
| currentRatio = bottomSpace / hiddenContentSize;
|
|
|
| - // move tiles from top to bottom
|
| while (
|
| - // approximate `currentRatio` to `ratio`
|
| currentRatio < ratio &&
|
| - // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| - // ensure that these recycled tiles are needed
|
| virtualEnd + recycledTiles < lastVirtualItemIndex &&
|
| - // ensure that the tile is not visible
|
| this._physicalTop + this._getPhysicalSizeIncrement(kth) < scrollTop
|
| ) {
|
|
|
| @@ -12944,7 +9228,6 @@ Polymer({
|
| }
|
|
|
| if (recycledTiles === 0) {
|
| - // Try to increase the pool if the list's client height isn't filled up with physical items
|
| if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) {
|
| this._increasePoolIfNeeded();
|
| }
|
| @@ -12955,36 +9238,21 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Update the list of items, starting from the `_virtualStart` item.
|
| - * @param {!Array<number>=} itemSet
|
| - * @param {!Array<number>=} movingUp
|
| - */
|
| _update: function(itemSet, movingUp) {
|
| - // manage focus
|
| this._manageFocus();
|
| - // update models
|
| this._assignModels(itemSet);
|
| - // measure heights
|
| this._updateMetrics(itemSet);
|
| - // adjust offset after measuring
|
| if (movingUp) {
|
| while (movingUp.length) {
|
| var idx = movingUp.pop();
|
| this._physicalTop -= this._getPhysicalSizeIncrement(idx);
|
| }
|
| }
|
| - // update the position of the items
|
| this._positionItems();
|
| - // set the scroller size
|
| this._updateScrollerSize();
|
| - // increase the pool of physical items
|
| this._increasePoolIfNeeded();
|
| },
|
|
|
| - /**
|
| - * Creates a pool of DOM elements and attaches them to the local dom.
|
| - */
|
| _createPool: function(size) {
|
| var physicalItems = new Array(size);
|
|
|
| @@ -12992,42 +9260,27 @@ Polymer({
|
|
|
| for (var i = 0; i < size; i++) {
|
| var inst = this.stamp(null);
|
| - // First element child is item; Safari doesn't support children[0]
|
| - // on a doc fragment
|
| physicalItems[i] = inst.root.querySelector('*');
|
| Polymer.dom(this).appendChild(inst.root);
|
| }
|
| return physicalItems;
|
| },
|
|
|
| - /**
|
| - * Increases the pool of physical items only if needed.
|
| - *
|
| - * @return {boolean} True if the pool was increased.
|
| - */
|
| _increasePoolIfNeeded: function() {
|
| - // Base case 1: the list has no height.
|
| if (this._viewportHeight === 0) {
|
| return false;
|
| }
|
| - // Base case 2: If the physical size is optimal and the list's client height is full
|
| - // with physical items, don't increase the pool.
|
| var isClientHeightFull = this._physicalBottom >= this._scrollBottom && this._physicalTop <= this._scrollPosition;
|
| if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) {
|
| return false;
|
| }
|
| - // this value should range between [0 <= `currentPage` <= `_maxPages`]
|
| var currentPage = Math.floor(this._physicalSize / this._viewportHeight);
|
|
|
| if (currentPage === 0) {
|
| - // fill the first page
|
| this._debounceTemplate(this._increasePool.bind(this, Math.round(this._physicalCount * 0.5)));
|
| } else if (this._lastPage !== currentPage && isClientHeightFull) {
|
| - // paint the page and defer the next increase
|
| - // wait 16ms which is rough enough to get paint cycle.
|
| Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increasePool.bind(this, this._itemsPerRow), 16));
|
| } else {
|
| - // fill the rest of the pages
|
| this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow));
|
| }
|
|
|
| @@ -13036,9 +9289,6 @@ Polymer({
|
| return true;
|
| },
|
|
|
| - /**
|
| - * Increases the pool size.
|
| - */
|
| _increasePool: function(missingItems) {
|
| var nextPhysicalCount = Math.min(
|
| this._physicalCount + missingItems,
|
| @@ -13057,9 +9307,6 @@ Polymer({
|
|
|
| this._physicalCount = prevPhysicalCount + delta;
|
|
|
| - // update the physical start if we need to preserve the model of the focused item.
|
| - // In this situation, the focused item is currently rendered and its model would
|
| - // have changed after increasing the pool if the physical start remained unchanged.
|
| if (this._physicalStart > this._physicalEnd &&
|
| this._isIndexRendered(this._focusedIndex) &&
|
| this._getPhysicalIndex(this._focusedIndex) < this._physicalEnd) {
|
| @@ -13068,10 +9315,6 @@ Polymer({
|
| this._update();
|
| },
|
|
|
| - /**
|
| - * Render a new list of items. This method does exactly the same as `update`,
|
| - * but it also ensures that only one `update` cycle is created.
|
| - */
|
| _render: function() {
|
| var requiresUpdate = this._virtualCount > 0 || this._physicalCount > 0;
|
|
|
| @@ -13082,12 +9325,8 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Templetizes the user template.
|
| - */
|
| _ensureTemplatized: function() {
|
| if (!this.ctor) {
|
| - // Template instance props that should be excluded from forwarding
|
| var props = {};
|
| props.__key__ = true;
|
| props[this.as] = true;
|
| @@ -13106,18 +9345,10 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Implements extension point from Templatizer mixin.
|
| - */
|
| _getStampedChildren: function() {
|
| return this._physicalItems;
|
| },
|
|
|
| - /**
|
| - * Implements extension point from Templatizer
|
| - * Called as a side effect of a template instance path change, responsible
|
| - * for notifying items.<key-for-instance>.<path> change up to host.
|
| - */
|
| _forwardInstancePath: function(inst, path, value) {
|
| if (path.indexOf(this.as + '.') === 0) {
|
| this.notifyPath('items.' + inst.__key__ + '.' +
|
| @@ -13125,11 +9356,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Implements extension point from Templatizer mixin
|
| - * Called as side-effect of a host property change, responsible for
|
| - * notifying parent path change on each row.
|
| - */
|
| _forwardParentProp: function(prop, value) {
|
| if (this._physicalItems) {
|
| this._physicalItems.forEach(function(item) {
|
| @@ -13138,11 +9364,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Implements extension point from Templatizer
|
| - * Called as side-effect of a host path change, responsible for
|
| - * notifying parent.<path> path change on each row.
|
| - */
|
| _forwardParentPath: function(path, value) {
|
| if (this._physicalItems) {
|
| this._physicalItems.forEach(function(item) {
|
| @@ -13151,10 +9372,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Called as a side effect of a host items.<key>.<path> path change,
|
| - * responsible for notifying item.<path> changes.
|
| - */
|
| _forwardItemPath: function(path, value) {
|
| if (!this._physicalIndexForKey) {
|
| return;
|
| @@ -13173,7 +9390,6 @@ Polymer({
|
| path = this.as + '.' + path.substring(dot+1);
|
| el._templateInstance.notifyPath(path, value, true);
|
| } else {
|
| - // Update selection if needed
|
| var currentItem = el._templateInstance[this.as];
|
| if (Array.isArray(this.selectedItems)) {
|
| for (var i = 0; i < this.selectedItems.length; i++) {
|
| @@ -13189,13 +9405,8 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Called when the items have changed. That is, ressignments
|
| - * to `items`, splices or updates to a single item.
|
| - */
|
| _itemsChanged: function(change) {
|
| if (change.path === 'items') {
|
| - // reset items
|
| this._virtualStart = 0;
|
| this._physicalTop = 0;
|
| this._virtualCount = this.items ? this.items.length : 0;
|
| @@ -13206,7 +9417,6 @@ Polymer({
|
|
|
| this._resetScrollPosition(0);
|
| this._removeFocusedItem();
|
| - // create the initial physical items
|
| if (!this._physicalItems) {
|
| this._physicalCount = Math.max(1, Math.min(DEFAULT_PHYSICAL_COUNT, this._virtualCount));
|
| this._physicalItems = this._createPool(this._physicalCount);
|
| @@ -13221,7 +9431,6 @@ Polymer({
|
| this._virtualCount = this.items ? this.items.length : 0;
|
|
|
| } else {
|
| - // update a single item
|
| this._forwardItemPath(change.path.split('.').slice(1).join('.'), change.value);
|
| return;
|
| }
|
| @@ -13230,14 +9439,9 @@ Polymer({
|
| this._debounceTemplate(this._render);
|
| },
|
|
|
| - /**
|
| - * @param {!Array<!PolymerSplice>} splices
|
| - */
|
| _adjustVirtualIndex: function(splices) {
|
| splices.forEach(function(splice) {
|
| - // deselect removed items
|
| splice.removed.forEach(this._removeItem, this);
|
| - // We only need to care about changes happening above the current position
|
| if (splice.index < this._virtualStart) {
|
| var delta = Math.max(
|
| splice.addedCount - splice.removed.length,
|
| @@ -13254,19 +9458,11 @@ Polymer({
|
|
|
| _removeItem: function(item) {
|
| this.$.selector.deselect(item);
|
| - // remove the current focused item
|
| if (this._focusedItem && this._focusedItem._templateInstance[this.as] === item) {
|
| this._removeFocusedItem();
|
| }
|
| },
|
|
|
| - /**
|
| - * Executes a provided function per every physical index in `itemSet`
|
| - * `itemSet` default value is equivalent to the entire set of physical indexes.
|
| - *
|
| - * @param {!function(number, number)} fn
|
| - * @param {!Array<number>=} itemSet
|
| - */
|
| _iterateItems: function(fn, itemSet) {
|
| var pidx, vidx, rtn, i;
|
|
|
| @@ -13295,12 +9491,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Returns the virtual index for a given physical index
|
| - *
|
| - * @param {number} pidx Physical index
|
| - * @return {number}
|
| - */
|
| _computeVidx: function(pidx) {
|
| if (pidx >= this._physicalStart) {
|
| return this._virtualStart + (pidx - this._physicalStart);
|
| @@ -13308,10 +9498,6 @@ Polymer({
|
| return this._virtualStart + (this._physicalCount - this._physicalStart) + pidx;
|
| },
|
|
|
| - /**
|
| - * Assigns the data models to a given set of items.
|
| - * @param {!Array<number>=} itemSet
|
| - */
|
| _assignModels: function(itemSet) {
|
| this._iterateItems(function(pidx, vidx) {
|
| var el = this._physicalItems[pidx];
|
| @@ -13333,14 +9519,7 @@ Polymer({
|
| }, itemSet);
|
| },
|
|
|
| - /**
|
| - * Updates the height for a given set of items.
|
| - *
|
| - * @param {!Array<number>=} itemSet
|
| - */
|
| _updateMetrics: function(itemSet) {
|
| - // Make sure we distributed all the physical items
|
| - // so we can measure them
|
| Polymer.dom.flush();
|
|
|
| var newPhysicalSize = 0;
|
| @@ -13365,7 +9544,6 @@ Polymer({
|
| this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize;
|
| }
|
|
|
| - // update the average if we measured something
|
| if (this._physicalAverageCount !== prevAvgCount) {
|
| this._physicalAverage = Math.round(
|
| ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) /
|
| @@ -13375,17 +9553,11 @@ Polymer({
|
|
|
| _updateGridMetrics: function() {
|
| this._viewportWidth = this.$.items.offsetWidth;
|
| - // Set item width to the value of the _physicalItems offsetWidth
|
| this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].getBoundingClientRect().width : DEFAULT_GRID_SIZE;
|
| - // Set row height to the value of the _physicalItems offsetHeight
|
| this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetHeight : DEFAULT_GRID_SIZE;
|
| - // If in grid mode compute how many items with exist in each row
|
| this._itemsPerRow = this._itemWidth ? Math.floor(this._viewportWidth / this._itemWidth) : this._itemsPerRow;
|
| },
|
|
|
| - /**
|
| - * Updates the position of the physical items.
|
| - */
|
| _positionItems: function() {
|
| this._adjustScrollPosition();
|
|
|
| @@ -13427,37 +9599,22 @@ Polymer({
|
| return this._rowHeight;
|
| },
|
|
|
| - /**
|
| - * Returns, based on the current index,
|
| - * whether or not the next index will need
|
| - * to be rendered on a new row.
|
| - *
|
| - * @param {number} vidx Virtual index
|
| - * @return {boolean}
|
| - */
|
| _shouldRenderNextRow: function(vidx) {
|
| return vidx % this._itemsPerRow === this._itemsPerRow - 1;
|
| },
|
|
|
| - /**
|
| - * Adjusts the scroll position when it was overestimated.
|
| - */
|
| _adjustScrollPosition: function() {
|
| var deltaHeight = this._virtualStart === 0 ? this._physicalTop :
|
| Math.min(this._scrollPosition + this._physicalTop, 0);
|
|
|
| if (deltaHeight) {
|
| this._physicalTop = this._physicalTop - deltaHeight;
|
| - // juking scroll position during interial scrolling on iOS is no bueno
|
| if (!IOS_TOUCH_SCROLLING && this._physicalTop !== 0) {
|
| this._resetScrollPosition(this._scrollTop - deltaHeight);
|
| }
|
| }
|
| },
|
|
|
| - /**
|
| - * Sets the position of the scroll.
|
| - */
|
| _resetScrollPosition: function(pos) {
|
| if (this.scrollTarget) {
|
| this._scrollTop = pos;
|
| @@ -13465,11 +9622,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Sets the scroll height, that's the height of the content,
|
| - *
|
| - * @param {boolean=} forceUpdate If true, updates the height no matter what.
|
| - */
|
| _updateScrollerSize: function(forceUpdate) {
|
| if (this.grid) {
|
| this._estScrollHeight = this._virtualRowCount * this._rowHeight;
|
| @@ -13482,31 +9634,16 @@ Polymer({
|
| forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight - this._physicalSize;
|
| forceUpdate = forceUpdate || this.grid && this.$.items.style.height < this._estScrollHeight;
|
|
|
| - // amortize height adjustment, so it won't trigger repaints very often
|
| if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >= this._optPhysicalSize) {
|
| this.$.items.style.height = this._estScrollHeight + 'px';
|
| this._scrollHeight = this._estScrollHeight;
|
| }
|
| },
|
|
|
| - /**
|
| - * Scroll to a specific item in the virtual list regardless
|
| - * of the physical items in the DOM tree.
|
| - *
|
| - * @method scrollToItem
|
| - * @param {(Object)} item The item to be scrolled to
|
| - */
|
| scrollToItem: function(item){
|
| return this.scrollToIndex(this.items.indexOf(item));
|
| },
|
|
|
| - /**
|
| - * Scroll to a specific index in the virtual list regardless
|
| - * of the physical items in the DOM tree.
|
| - *
|
| - * @method scrollToIndex
|
| - * @param {number} idx The index of the item
|
| - */
|
| scrollToIndex: function(idx) {
|
| if (typeof idx !== 'number' || idx < 0 || idx > this.items.length - 1) {
|
| return;
|
| @@ -13515,18 +9652,13 @@ Polymer({
|
| Polymer.dom.flush();
|
|
|
| idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
|
| - // update the virtual start only when needed
|
| if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
|
| this._virtualStart = this.grid ? (idx - this._itemsPerRow * 2) : (idx - 1);
|
| }
|
| - // manage focus
|
| this._manageFocus();
|
| - // assign new models
|
| this._assignModels();
|
| - // measure the new sizes
|
| this._updateMetrics();
|
|
|
| - // estimate new physical offset
|
| var estPhysicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * this._physicalAverage;
|
| this._physicalTop = estPhysicalTop;
|
|
|
| @@ -13535,45 +9667,28 @@ Polymer({
|
| var targetOffsetTop = 0;
|
| var hiddenContentSize = this._hiddenContentSize;
|
|
|
| - // scroll to the item as much as we can
|
| while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) {
|
| targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(currentTopItem);
|
| currentTopItem = (currentTopItem + 1) % this._physicalCount;
|
| currentVirtualItem++;
|
| }
|
| - // update the scroller size
|
| this._updateScrollerSize(true);
|
| - // update the position of the items
|
| this._positionItems();
|
| - // set the new scroll position
|
| this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + targetOffsetTop);
|
| - // increase the pool of physical items if needed
|
| this._increasePoolIfNeeded();
|
| - // clear cached visible index
|
| this._firstVisibleIndexVal = null;
|
| this._lastVisibleIndexVal = null;
|
| },
|
|
|
| - /**
|
| - * Reset the physical average and the average count.
|
| - */
|
| _resetAverage: function() {
|
| this._physicalAverage = 0;
|
| this._physicalAverageCount = 0;
|
| },
|
|
|
| - /**
|
| - * A handler for the `iron-resize` event triggered by `IronResizableBehavior`
|
| - * when the element is resized.
|
| - */
|
| _resizeHandler: function() {
|
| - // iOS fires the resize event when the address bar slides up
|
| if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100) {
|
| return;
|
| }
|
| - // In Desktop Safari 9.0.3, if the scroll bars are always shown,
|
| - // changing the scroll position from a resize handler would result in
|
| - // the scroll position being reset. Waiting 1ms fixes the issue.
|
| Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() {
|
| this.updateViewportBoundaries();
|
| this._render();
|
| @@ -13595,11 +9710,6 @@ Polymer({
|
| return null;
|
| },
|
|
|
| - /**
|
| - * Gets a valid item instance from its index or the object value.
|
| - *
|
| - * @param {(Object|number)} item The item object or its index
|
| - */
|
| _getNormalizedItem: function(item) {
|
| if (this._collection.getKey(item) === undefined) {
|
| if (typeof item === 'number') {
|
| @@ -13614,12 +9724,6 @@ Polymer({
|
| return item;
|
| },
|
|
|
| - /**
|
| - * Select the list item at the given index.
|
| - *
|
| - * @method selectItem
|
| - * @param {(Object|number)} item The item object or its index
|
| - */
|
| selectItem: function(item) {
|
| item = this._getNormalizedItem(item);
|
| var model = this._getModelFromItem(item);
|
| @@ -13634,13 +9738,6 @@ Polymer({
|
| this.updateSizeForItem(item);
|
| },
|
|
|
| - /**
|
| - * Deselects the given item list if it is already selected.
|
| - *
|
| -
|
| - * @method deselect
|
| - * @param {(Object|number)} item The item object or its index
|
| - */
|
| deselectItem: function(item) {
|
| item = this._getNormalizedItem(item);
|
| var model = this._getModelFromItem(item);
|
| @@ -13652,13 +9749,6 @@ Polymer({
|
| this.updateSizeForItem(item);
|
| },
|
|
|
| - /**
|
| - * Select or deselect a given item depending on whether the item
|
| - * has already been selected.
|
| - *
|
| - * @method toggleSelectionForItem
|
| - * @param {(Object|number)} item The item object or its index
|
| - */
|
| toggleSelectionForItem: function(item) {
|
| item = this._getNormalizedItem(item);
|
| if (/** @type {!ArraySelectorElement} */ (this.$.selector).isSelected(item)) {
|
| @@ -13668,11 +9758,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Clears the current selection state of the list.
|
| - *
|
| - * @method clearSelection
|
| - */
|
| clearSelection: function() {
|
| function unselect(item) {
|
| var model = this._getModelFromItem(item);
|
| @@ -13690,18 +9775,11 @@ Polymer({
|
| /** @type {!ArraySelectorElement} */ (this.$.selector).clearSelection();
|
| },
|
|
|
| - /**
|
| - * Add an event listener to `tap` if `selectionEnabled` is true,
|
| - * it will remove the listener otherwise.
|
| - */
|
| _selectionEnabledChanged: function(selectionEnabled) {
|
| var handler = selectionEnabled ? this.listen : this.unlisten;
|
| handler.call(this, this, 'tap', '_selectionHandler');
|
| },
|
|
|
| - /**
|
| - * Select an item from an event object.
|
| - */
|
| _selectionHandler: function(e) {
|
| var model = this.modelForElement(e.target);
|
| if (!model) {
|
| @@ -13711,20 +9789,15 @@ Polymer({
|
| var target = Polymer.dom(e).path[0];
|
| var activeEl = Polymer.dom(this.domHost ? this.domHost.root : document).activeElement;
|
| var physicalItem = this._physicalItems[this._getPhysicalIndex(model[this.indexAs])];
|
| - // Safari does not focus certain form controls via mouse
|
| - // https://bugs.webkit.org/show_bug.cgi?id=118043
|
| if (target.localName === 'input' ||
|
| target.localName === 'button' ||
|
| target.localName === 'select') {
|
| return;
|
| }
|
| - // Set a temporary tabindex
|
| modelTabIndex = model.tabIndex;
|
| model.tabIndex = SECRET_TABINDEX;
|
| activeElTabIndex = activeEl ? activeEl.tabIndex : -1;
|
| model.tabIndex = modelTabIndex;
|
| - // Only select the item if the tap wasn't on a focusable child
|
| - // or the element bound to `tabIndex`
|
| if (activeEl && physicalItem.contains(activeEl) && activeElTabIndex !== SECRET_TABINDEX) {
|
| return;
|
| }
|
| @@ -13736,12 +9809,6 @@ Polymer({
|
| this.$.selector.multi = multiSelection;
|
| },
|
|
|
| - /**
|
| - * Updates the size of an item.
|
| - *
|
| - * @method updateSizeForItem
|
| - * @param {(Object|number)} item The item object or its index
|
| - */
|
| updateSizeForItem: function(item) {
|
| item = this._getNormalizedItem(item);
|
| var key = this._collection.getKey(item);
|
| @@ -13753,26 +9820,16 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Creates a temporary backfill item in the rendered pool of physical items
|
| - * to replace the main focused item. The focused item has tabIndex = 0
|
| - * and might be currently focused by the user.
|
| - *
|
| - * This dynamic replacement helps to preserve the focus state.
|
| - */
|
| _manageFocus: function() {
|
| var fidx = this._focusedIndex;
|
|
|
| if (fidx >= 0 && fidx < this._virtualCount) {
|
| - // if it's a valid index, check if that index is rendered
|
| - // in a physical item.
|
| if (this._isIndexRendered(fidx)) {
|
| this._restoreFocusedItem();
|
| } else {
|
| this._createFocusBackfillItem();
|
| }
|
| } else if (this._virtualCount > 0 && this._physicalCount > 0) {
|
| - // otherwise, assign the initial focused index.
|
| this._focusedIndex = this._virtualStart;
|
| this._focusedItem = this._physicalItems[this._physicalStart];
|
| }
|
| @@ -13795,7 +9852,6 @@ Polymer({
|
| return;
|
| }
|
| this._restoreFocusedItem();
|
| - // scroll to index to make sure it's rendered
|
| if (!this._isIndexRendered(idx)) {
|
| this.scrollToIndex(idx);
|
| }
|
| @@ -13804,19 +9860,14 @@ Polymer({
|
| var model = physicalItem._templateInstance;
|
| var focusable;
|
|
|
| - // set a secret tab index
|
| model.tabIndex = SECRET_TABINDEX;
|
| - // check if focusable element is the physical item
|
| if (physicalItem.tabIndex === SECRET_TABINDEX) {
|
| focusable = physicalItem;
|
| }
|
| - // search for the element which tabindex is bound to the secret tab index
|
| if (!focusable) {
|
| focusable = Polymer.dom(physicalItem).querySelector('[tabindex="' + SECRET_TABINDEX + '"]');
|
| }
|
| - // restore the tab index
|
| model.tabIndex = 0;
|
| - // focus the focusable element
|
| this._focusedIndex = idx;
|
| focusable && focusable.focus();
|
| },
|
| @@ -13837,20 +9888,15 @@ Polymer({
|
| return;
|
| }
|
| if (!this._focusBackfillItem) {
|
| - // create a physical item, so that it backfills the focused item.
|
| var stampedTemplate = this.stamp(null);
|
| this._focusBackfillItem = stampedTemplate.root.querySelector('*');
|
| Polymer.dom(this).appendChild(stampedTemplate.root);
|
| }
|
| - // get the physical index for the focused index
|
| pidx = this._getPhysicalIndex(fidx);
|
|
|
| if (pidx != null) {
|
| - // set the offcreen focused physical item
|
| this._offscreenFocusedItem = this._physicalItems[pidx];
|
| - // backfill the focused physical item
|
| this._physicalItems[pidx] = this._focusBackfillItem;
|
| - // hide the focused physical
|
| this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem);
|
| }
|
| },
|
| @@ -13861,19 +9907,13 @@ Polymer({
|
| if (!this._offscreenFocusedItem || this._focusedIndex < 0) {
|
| return;
|
| }
|
| - // assign models to the focused index
|
| this._assignModels();
|
| - // get the new physical index for the focused index
|
| pidx = this._getPhysicalIndex(fidx);
|
|
|
| if (pidx != null) {
|
| - // flip the focus backfill
|
| this._focusBackfillItem = this._physicalItems[pidx];
|
| - // restore the focused physical item
|
| this._physicalItems[pidx] = this._offscreenFocusedItem;
|
| - // reset the offscreen focused item
|
| this._offscreenFocusedItem = null;
|
| - // hide the physical item that backfills
|
| this.translate3d(0, HIDDEN_Y, 0, this._focusBackfillItem);
|
| }
|
| },
|
| @@ -13888,15 +9928,12 @@ Polymer({
|
| return;
|
| }
|
| if (focusedModel === targetModel) {
|
| - // if the user focused the same item, then bring it into view if it's not visible
|
| if (!this._isIndexVisible(fidx)) {
|
| this.scrollToIndex(fidx);
|
| }
|
| } else {
|
| this._restoreFocusedItem();
|
| - // restore tabIndex for the currently focused item
|
| focusedModel.tabIndex = -1;
|
| - // set the tabIndex for the next focused item
|
| targetModel.tabIndex = 0;
|
| fidx = targetModel[this.indexAs];
|
| this._focusedIndex = fidx;
|
| @@ -13913,7 +9950,6 @@ Polymer({
|
| },
|
|
|
| _didMoveDown: function(e) {
|
| - // disable scroll when pressing the down key
|
| e.detail.keyboardEvent.preventDefault();
|
| this._focusPhysicalItem(this._focusedIndex + 1);
|
| },
|
| @@ -13931,27 +9967,16 @@ Polymer({
|
|
|
| properties: {
|
|
|
| - /**
|
| - * Distance from the top (or left, for horizontal) bound of the scroller
|
| - * where the "upper trigger" will fire.
|
| - */
|
| upperThreshold: {
|
| type: Number,
|
| value: 100
|
| },
|
|
|
| - /**
|
| - * Distance from the bottom (or right, for horizontal) bound of the scroller
|
| - * where the "lower trigger" will fire.
|
| - */
|
| lowerThreshold: {
|
| type: Number,
|
| value: 100
|
| },
|
|
|
| - /**
|
| - * Read-only value that tracks the triggered state of the upper threshold.
|
| - */
|
| upperTriggered: {
|
| type: Boolean,
|
| value: false,
|
| @@ -13959,9 +9984,6 @@ Polymer({
|
| readOnly: true
|
| },
|
|
|
| - /**
|
| - * Read-only value that tracks the triggered state of the lower threshold.
|
| - */
|
| lowerTriggered: {
|
| type: Boolean,
|
| value: false,
|
| @@ -13969,9 +9991,6 @@ Polymer({
|
| readOnly: true
|
| },
|
|
|
| - /**
|
| - * True if the orientation of the scroller is horizontal.
|
| - */
|
| horizontal: {
|
| type: Boolean,
|
| value: false
|
| @@ -13996,7 +10015,6 @@ Polymer({
|
| },
|
|
|
| _scrollHandler: function() {
|
| - // throttle the work on the scroll event
|
| var THROTTLE_THRESHOLD = 200;
|
| if (!this.isDebouncerActive('_checkTheshold')) {
|
| this.debounce('_checkTheshold', function() {
|
| @@ -14014,12 +10032,6 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Checks the scroll thresholds.
|
| - * This method is automatically called by iron-scroll-threshold.
|
| - *
|
| - * @method checkScrollThesholds
|
| - */
|
| checkScrollThesholds: function() {
|
| if (!this.scrollTarget || (this.lowerTriggered && this.upperTriggered)) {
|
| return;
|
| @@ -14029,39 +10041,22 @@ Polymer({
|
| this.scrollTarget.scrollWidth - this._scrollTargetWidth - this._scrollLeft :
|
| this.scrollTarget.scrollHeight - this._scrollTargetHeight - this._scrollTop;
|
|
|
| - // Detect upper threshold
|
| if (upperScrollValue <= this.upperThreshold && !this.upperTriggered) {
|
| this._setUpperTriggered(true);
|
| this.fire('upper-threshold');
|
| }
|
| - // Detect lower threshold
|
| if (lowerScrollValue <= this.lowerThreshold && !this.lowerTriggered) {
|
| this._setLowerTriggered(true);
|
| this.fire('lower-threshold');
|
| }
|
| },
|
|
|
| - /**
|
| - * Clear the upper and lower threshold states.
|
| - *
|
| - * @method clearTriggers
|
| - */
|
| clearTriggers: function() {
|
| this._setUpperTriggered(false);
|
| this._setLowerTriggered(false);
|
| }
|
|
|
| - /**
|
| - * Fires when the lower threshold has been reached.
|
| - *
|
| - * @event lower-threshold
|
| - */
|
|
|
| - /**
|
| - * Fires when the upper threshold has been reached.
|
| - *
|
| - * @event upper-threshold
|
| - */
|
|
|
| });
|
| // Copyright 2015 The Chromium Authors. All rights reserved.
|
| @@ -14074,7 +10069,6 @@ Polymer({
|
| behaviors: [HistoryListBehavior],
|
|
|
| properties: {
|
| - // The search term for the current query. Set when the query returns.
|
| searchedTerm: {
|
| type: String,
|
| value: '',
|
| @@ -14084,7 +10078,6 @@ Polymer({
|
|
|
| querying: Boolean,
|
|
|
| - // An array of history entries in reverse chronological order.
|
| historyData_: Array,
|
|
|
| resultLoadingDisabled_: {
|
| @@ -14100,19 +10093,11 @@ Polymer({
|
|
|
| /** @override */
|
| attached: function() {
|
| - // It is possible (eg, when middle clicking the reload button) for all other
|
| - // resize events to fire before the list is attached and can be measured.
|
| - // Adding another resize here ensures it will get sized correctly.
|
| /** @type {IronListElement} */(this.$['infinite-list']).notifyResize();
|
| this.$['infinite-list'].scrollTarget = this;
|
| this.$['scroll-threshold'].scrollTarget = this;
|
| },
|
|
|
| - /**
|
| - * Remove bookmark star for history items with matching URLs.
|
| - * @param {{detail: !string}} e
|
| - * @private
|
| - */
|
| removeBookmarkStars_: function(e) {
|
| var url = e.detail;
|
|
|
| @@ -14125,18 +10110,10 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * Disables history result loading when there are no more history results.
|
| - */
|
| disableResultLoading: function() {
|
| this.resultLoadingDisabled_ = true;
|
| },
|
|
|
| - /**
|
| - * Adds the newly updated history results into historyData_. Adds new fields
|
| - * for each result.
|
| - * @param {!Array<!HistoryEntry>} historyResults The new history results.
|
| - */
|
| addNewResults: function(historyResults) {
|
| var results = historyResults.slice();
|
| /** @type {IronScrollThresholdElement} */(this.$['scroll-threshold'])
|
| @@ -14151,21 +10128,13 @@ Polymer({
|
| }
|
|
|
| if (this.historyData_) {
|
| - // If we have previously received data, push the new items onto the
|
| - // existing array.
|
| results.unshift('historyData_');
|
| this.push.apply(this, results);
|
| } else {
|
| - // The first time we receive data, use set() to ensure the iron-list is
|
| - // initialized correctly.
|
| this.set('historyData_', results);
|
| }
|
| },
|
|
|
| - /**
|
| - * Called when the page is scrolled to near the bottom of the list.
|
| - * @private
|
| - */
|
| loadMoreData_: function() {
|
| if (this.resultLoadingDisabled_ || this.querying)
|
| return;
|
| @@ -14173,28 +10142,11 @@ Polymer({
|
| this.fire('load-more-history');
|
| },
|
|
|
| - /**
|
| - * Check whether the time difference between the given history item and the
|
| - * next one is large enough for a spacer to be required.
|
| - * @param {HistoryEntry} item
|
| - * @param {number} index The index of |item| in |historyData_|.
|
| - * @param {number} length The length of |historyData_|.
|
| - * @return {boolean} Whether or not time gap separator is required.
|
| - * @private
|
| - */
|
| needsTimeGap_: function(item, index, length) {
|
| return md_history.HistoryItem.needsTimeGap(
|
| this.historyData_, index, this.searchedTerm);
|
| },
|
|
|
| - /**
|
| - * True if the given item is the beginning of a new card.
|
| - * @param {HistoryEntry} item
|
| - * @param {number} i Index of |item| within |historyData_|.
|
| - * @param {number} length
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| isCardStart_: function(item, i, length) {
|
| if (length == 0 || i > length - 1)
|
| return false;
|
| @@ -14203,14 +10155,6 @@ Polymer({
|
| this.historyData_[i - 1].dateRelativeDay;
|
| },
|
|
|
| - /**
|
| - * True if the given item is the end of a card.
|
| - * @param {HistoryEntry} item
|
| - * @param {number} i Index of |item| within |historyData_|.
|
| - * @param {number} length
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| isCardEnd_: function(item, i, length) {
|
| if (length == 0 || i > length - 1)
|
| return false;
|
| @@ -14219,27 +10163,14 @@ Polymer({
|
| this.historyData_[i + 1].dateRelativeDay;
|
| },
|
|
|
| - /**
|
| - * @param {number} index
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| isFirstItem_: function(index) {
|
| return index == 0;
|
| },
|
|
|
| - /**
|
| - * @private
|
| - */
|
| notifyListScroll_: function() {
|
| this.fire('history-list-scrolled');
|
| },
|
|
|
| - /**
|
| - * @param {number} index
|
| - * @return {string}
|
| - * @private
|
| - */
|
| pathForItem_: function(index) {
|
| return 'historyData_.' + index;
|
| },
|
| @@ -14248,19 +10179,6 @@ Polymer({
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @fileoverview
|
| - * history-lazy-render is a simple variant of dom-if designed for lazy rendering
|
| - * of elements that are accessed imperatively.
|
| - * Usage:
|
| - * <template is="history-lazy-render" id="menu">
|
| - * <heavy-menu></heavy-menu>
|
| - * </template>
|
| - *
|
| - * this.$.menu.get().then(function(menu) {
|
| - * menu.show();
|
| - * });
|
| - */
|
|
|
| Polymer({
|
| is: 'history-lazy-render',
|
| @@ -14276,11 +10194,6 @@ Polymer({
|
| /** @private {TemplateInstance} */
|
| _instance: null,
|
|
|
| - /**
|
| - * Stamp the template into the DOM tree asynchronously
|
| - * @return {Promise<Element>} Promise which resolves when the template has
|
| - * been stamped.
|
| - */
|
| get: function() {
|
| if (!this._renderPromise) {
|
| this._renderPromise = new Promise(function(resolve) {
|
| @@ -14294,10 +10207,6 @@ Polymer({
|
| return this._renderPromise;
|
| },
|
|
|
| - /**
|
| - * @return {?Element} The element contained in the template, if it has
|
| - * already been stamped.
|
| - */
|
| getIfExists: function() {
|
| if (this._instance) {
|
| var children = this._instance._children;
|
| @@ -14321,19 +10230,11 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * @param {string} prop
|
| - * @param {Object} value
|
| - */
|
| _forwardParentProp: function(prop, value) {
|
| if (this._instance)
|
| this._instance.__setProperty(prop, value, true);
|
| },
|
|
|
| - /**
|
| - * @param {string} path
|
| - * @param {Object} value
|
| - */
|
| _forwardParentPath: function(path, value) {
|
| if (this._instance)
|
| this._instance._notifyPath(path, value, true);
|
| @@ -14347,10 +10248,8 @@ Polymer({
|
| is: 'history-list-container',
|
|
|
| properties: {
|
| - // The path of the currently selected page.
|
| selectedPage_: String,
|
|
|
| - // Whether domain-grouped history is enabled.
|
| grouped: Boolean,
|
|
|
| /** @type {!QueryState} */
|
| @@ -14370,11 +10269,6 @@ Polymer({
|
| 'toggle-menu': 'toggleMenu_',
|
| },
|
|
|
| - /**
|
| - * @param {HistoryQuery} info An object containing information about the
|
| - * query.
|
| - * @param {!Array<HistoryEntry>} results A list of results.
|
| - */
|
| historyResult: function(info, results) {
|
| this.initializeResults_(info, results);
|
| this.closeMenu_();
|
| @@ -14390,23 +10284,14 @@ Polymer({
|
| list.disableResultLoading();
|
| },
|
|
|
| - /**
|
| - * Queries the history backend for results based on queryState.
|
| - * @param {boolean} incremental Whether the new query should continue where
|
| - * the previous query stopped.
|
| - */
|
| queryHistory: function(incremental) {
|
| var queryState = this.queryState;
|
| - // Disable querying until the first set of results have been returned. If
|
| - // there is a search, query immediately to support search query params from
|
| - // the URL.
|
| var noResults = !this.queryResult || this.queryResult.results == null;
|
| if (queryState.queryingDisabled ||
|
| (!this.queryState.searchTerm && noResults)) {
|
| return;
|
| }
|
|
|
| - // Close any open dialog if a new query is initiated.
|
| var dialog = this.$.dialog.getIfExists();
|
| if (!incremental && dialog && dialog.open)
|
| dialog.close();
|
| @@ -14437,10 +10322,6 @@ Polymer({
|
| this.getSelectedList_().unselectAllItems(count);
|
| },
|
|
|
| - /**
|
| - * Delete all the currently selected history items. Will prompt the user with
|
| - * a dialog to confirm that the deletion should be performed.
|
| - */
|
| deleteSelectedWithPrompt: function() {
|
| if (!loadTimeData.getBoolean('allowDeletingHistory'))
|
| return;
|
| @@ -14449,10 +10330,6 @@ Polymer({
|
| });
|
| },
|
|
|
| - /**
|
| - * @param {HistoryRange} range
|
| - * @private
|
| - */
|
| groupedRangeChanged_: function(range) {
|
| this.selectedPage_ = this.queryState.range == HistoryRange.ALL_TIME ?
|
| 'infinite-list' : 'grouped-list';
|
| @@ -14463,11 +10340,6 @@ Polymer({
|
| /** @private */
|
| loadMoreHistory_: function() { this.queryHistory(true); },
|
|
|
| - /**
|
| - * @param {HistoryQuery} info
|
| - * @param {!Array<HistoryEntry>} results
|
| - * @private
|
| - */
|
| initializeResults_: function(info, results) {
|
| if (results.length == 0)
|
| return;
|
| @@ -14475,7 +10347,6 @@ Polymer({
|
| var currentDate = results[0].dateRelativeDay;
|
|
|
| for (var i = 0; i < results.length; i++) {
|
| - // Sets the default values for these fields to prevent undefined types.
|
| results[i].selected = false;
|
| results[i].readableTimestamp =
|
| info.term == '' ? results[i].dateTimeOfDay : results[i].dateShort;
|
| @@ -14499,23 +10370,12 @@ Polymer({
|
| dialog.close();
|
| },
|
|
|
| - /**
|
| - * Closes the overflow menu.
|
| - * @private
|
| - */
|
| closeMenu_: function() {
|
| var menu = this.$.sharedMenu.getIfExists();
|
| if (menu)
|
| menu.closeMenu();
|
| },
|
|
|
| - /**
|
| - * Opens the overflow menu unless the menu is already open and the same button
|
| - * is pressed.
|
| - * @param {{detail: {item: !HistoryEntry, target: !HTMLElement}}} e
|
| - * @return {Promise<Element>}
|
| - * @private
|
| - */
|
| toggleMenu_: function(e) {
|
| var target = e.detail.target;
|
| return this.$.sharedMenu.get().then(function(menu) {
|
| @@ -14539,18 +10399,11 @@ Polymer({
|
| .deleteItems([itemData.item])
|
| .then(function(items) {
|
| this.getSelectedList_().removeItemsByPath([itemData.path]);
|
| - // This unselect-all is to reset the toolbar when deleting a selected
|
| - // item. TODO(tsergeant): Make this automatic based on observing list
|
| - // modifications.
|
| this.fire('unselect-all');
|
| }.bind(this));
|
| menu.closeMenu();
|
| },
|
|
|
| - /**
|
| - * @return {HTMLElement}
|
| - * @private
|
| - */
|
| getSelectedList_: function() {
|
| return this.$.content.selectedItem;
|
| },
|
| @@ -14563,45 +10416,25 @@ Polymer({
|
| is: 'history-synced-device-card',
|
|
|
| properties: {
|
| - // Name of the synced device.
|
| device: String,
|
|
|
| - // When the device information was last updated.
|
| lastUpdateTime: String,
|
|
|
| - /**
|
| - * The list of tabs open for this device.
|
| - * @type {!Array<!ForeignSessionTab>}
|
| - */
|
| tabs: {
|
| type: Array,
|
| value: function() { return []; },
|
| observer: 'updateIcons_'
|
| },
|
|
|
| - /**
|
| - * The indexes where a window separator should be shown. The use of a
|
| - * separate array here is necessary for window separators to appear
|
| - * correctly in search. See http://crrev.com/2022003002 for more details.
|
| - * @type {!Array<number>}
|
| - */
|
| separatorIndexes: Array,
|
|
|
| - // Whether the card is open.
|
| cardOpen_: {type: Boolean, value: true},
|
|
|
| searchTerm: String,
|
|
|
| - // Internal identifier for the device.
|
| sessionTag: String,
|
| },
|
|
|
| - /**
|
| - * Open a single synced tab. Listens to 'click' rather than 'tap'
|
| - * to determine what modifier keys were pressed.
|
| - * @param {DomRepeatClickEvent} e
|
| - * @private
|
| - */
|
| openTab_: function(e) {
|
| var tab = /** @type {ForeignSessionTab} */(e.model.tab);
|
| md_history.BrowserService.getInstance().openForeignSessionTab(
|
| @@ -14609,20 +10442,12 @@ Polymer({
|
| e.preventDefault();
|
| },
|
|
|
| - /**
|
| - * Toggles the dropdown display of synced tabs for each device card.
|
| - */
|
| toggleTabCard: function() {
|
| this.$.collapse.toggle();
|
| this.$['dropdown-indicator'].icon =
|
| this.$.collapse.opened ? 'cr:expand-less' : 'cr:expand-more';
|
| },
|
|
|
| - /**
|
| - * When the synced tab information is set, the icon associated with the tab
|
| - * website is also set.
|
| - * @private
|
| - */
|
| updateIcons_: function() {
|
| this.async(function() {
|
| var icons = Polymer.dom(this.root).querySelectorAll('.website-icon');
|
| @@ -14639,19 +10464,11 @@ Polymer({
|
| return this.separatorIndexes.indexOf(index) != -1;
|
| },
|
|
|
| - /**
|
| - * @param {boolean} cardOpen
|
| - * @return {string}
|
| - */
|
| getCollapseTitle_: function(cardOpen) {
|
| return cardOpen ? loadTimeData.getString('collapseSessionButton') :
|
| loadTimeData.getString('expandSessionButton');
|
| },
|
|
|
| - /**
|
| - * @param {CustomEvent} e
|
| - * @private
|
| - */
|
| onMenuButtonTap_: function(e) {
|
| this.fire('toggle-menu', {
|
| target: Polymer.dom(e).localTarget,
|
| @@ -14664,23 +10481,12 @@ Polymer({
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -/**
|
| - * @typedef {{device: string,
|
| - * lastUpdateTime: string,
|
| - * separatorIndexes: !Array<number>,
|
| - * timestamp: number,
|
| - * tabs: !Array<!ForeignSessionTab>,
|
| - * tag: string}}
|
| - */
|
| var ForeignDeviceInternal;
|
|
|
| Polymer({
|
| is: 'history-synced-device-manager',
|
|
|
| properties: {
|
| - /**
|
| - * @type {?Array<!ForeignSession>}
|
| - */
|
| sessionList: {
|
| type: Array,
|
| observer: 'updateSyncedDevices'
|
| @@ -14691,10 +10497,6 @@ Polymer({
|
| observer: 'searchTermChanged'
|
| },
|
|
|
| - /**
|
| - * An array of synced devices with synced tab data.
|
| - * @type {!Array<!ForeignDeviceInternal>}
|
| - */
|
| syncedDevices_: {
|
| type: Array,
|
| value: function() { return []; }
|
| @@ -14725,14 +10527,9 @@ Polymer({
|
|
|
| /** @override */
|
| attached: function() {
|
| - // Update the sign in state.
|
| chrome.send('otherDevicesInitialized');
|
| },
|
|
|
| - /**
|
| - * @param {!ForeignSession} session
|
| - * @return {!ForeignDeviceInternal}
|
| - */
|
| createInternalDevice_: function(session) {
|
| var tabs = [];
|
| var separatorIndexes = [];
|
| @@ -14748,7 +10545,6 @@ Polymer({
|
|
|
| var windowAdded = false;
|
| if (!this.searchTerm) {
|
| - // Add all the tabs if there is no search term.
|
| tabs = tabs.concat(newTabs);
|
| windowAdded = true;
|
| } else {
|
| @@ -14803,13 +10599,6 @@ Polymer({
|
| this.syncedDevices_ = [];
|
| },
|
|
|
| - /**
|
| - * Decide whether or not should display no synced tabs message.
|
| - * @param {boolean} signInState
|
| - * @param {number} syncedDevicesLength
|
| - * @param {boolean} guestSession
|
| - * @return {boolean}
|
| - */
|
| showNoSyncedMessage: function(
|
| signInState, syncedDevicesLength, guestSession) {
|
| if (guestSession)
|
| @@ -14818,13 +10607,6 @@ Polymer({
|
| return signInState && syncedDevicesLength == 0;
|
| },
|
|
|
| - /**
|
| - * Shows the signin guide when the user is not signed in and not in a guest
|
| - * session.
|
| - * @param {boolean} signInState
|
| - * @param {boolean} guestSession
|
| - * @return {boolean}
|
| - */
|
| showSignInGuide: function(signInState, guestSession) {
|
| var show = !signInState && !guestSession;
|
| if (show) {
|
| @@ -14835,32 +10617,17 @@ Polymer({
|
| return show;
|
| },
|
|
|
| - /**
|
| - * Decide what message should be displayed when user is logged in and there
|
| - * are no synced tabs.
|
| - * @param {boolean} fetchingSyncedTabs
|
| - * @return {string}
|
| - */
|
| noSyncedTabsMessage: function(fetchingSyncedTabs) {
|
| return loadTimeData.getString(
|
| fetchingSyncedTabs ? 'loading' : 'noSyncedResults');
|
| },
|
|
|
| - /**
|
| - * Replaces the currently displayed synced tabs with |sessionList|. It is
|
| - * common for only a single session within the list to have changed, We try to
|
| - * avoid doing extra work in this case. The logic could be more intelligent
|
| - * about updating individual tabs rather than replacing whole sessions, but
|
| - * this approach seems to have acceptable performance.
|
| - * @param {?Array<!ForeignSession>} sessionList
|
| - */
|
| updateSyncedDevices: function(sessionList) {
|
| this.fetchingSyncedTabs_ = false;
|
|
|
| if (!sessionList)
|
| return;
|
|
|
| - // First, update any existing devices that have changed.
|
| var updateCount = Math.min(sessionList.length, this.syncedDevices_.length);
|
| for (var i = 0; i < updateCount; i++) {
|
| var oldDevice = this.syncedDevices_[i];
|
| @@ -14871,41 +10638,26 @@ Polymer({
|
| }
|
| }
|
|
|
| - // Then, append any new devices.
|
| for (var i = updateCount; i < sessionList.length; i++) {
|
| this.push('syncedDevices_', this.createInternalDevice_(sessionList[i]));
|
| }
|
| },
|
|
|
| - /**
|
| - * End fetching synced tabs when sync is disabled.
|
| - */
|
| tabSyncDisabled: function() {
|
| this.fetchingSyncedTabs_ = false;
|
| this.clearDisplayedSyncedDevices_();
|
| },
|
|
|
| - /**
|
| - * Get called when user's sign in state changes, this will affect UI of synced
|
| - * tabs page. Sign in promo gets displayed when user is signed out, and
|
| - * different messages are shown when there are no synced tabs.
|
| - * @param {boolean} isUserSignedIn
|
| - */
|
| updateSignInState: function(isUserSignedIn) {
|
| - // If user's sign in state didn't change, then don't change message or
|
| - // update UI.
|
| if (this.signInState_ == isUserSignedIn)
|
| return;
|
|
|
| this.signInState_ = isUserSignedIn;
|
|
|
| - // User signed out, clear synced device list and show the sign in promo.
|
| if (!isUserSignedIn) {
|
| this.clearDisplayedSyncedDevices_();
|
| return;
|
| }
|
| - // User signed in, show the loading message when querying for synced
|
| - // devices.
|
| this.fetchingSyncedTabs_ = true;
|
| },
|
|
|
| @@ -14914,66 +10666,6 @@ Polymer({
|
| this.updateSyncedDevices(this.sessionList);
|
| }
|
| });
|
| -/**
|
| - `iron-selector` is an element which can be used to manage a list of elements
|
| - that can be selected. Tapping on the item will make the item selected. The `selected` indicates
|
| - which item is being selected. The default is to use the index of the item.
|
| -
|
| - Example:
|
| -
|
| - <iron-selector selected="0">
|
| - <div>Item 1</div>
|
| - <div>Item 2</div>
|
| - <div>Item 3</div>
|
| - </iron-selector>
|
| -
|
| - If you want to use the attribute value of an element for `selected` instead of the index,
|
| - set `attrForSelected` to the name of the attribute. For example, if you want to select item by
|
| - `name`, set `attrForSelected` to `name`.
|
| -
|
| - Example:
|
| -
|
| - <iron-selector attr-for-selected="name" selected="foo">
|
| - <div name="foo">Foo</div>
|
| - <div name="bar">Bar</div>
|
| - <div name="zot">Zot</div>
|
| - </iron-selector>
|
| -
|
| - You can specify a default fallback with `fallbackSelection` in case the `selected` attribute does
|
| - not match the `attrForSelected` attribute of any elements.
|
| -
|
| - Example:
|
| -
|
| - <iron-selector attr-for-selected="name" selected="non-existing"
|
| - fallback-selection="default">
|
| - <div name="foo">Foo</div>
|
| - <div name="bar">Bar</div>
|
| - <div name="default">Default</div>
|
| - </iron-selector>
|
| -
|
| - Note: When the selector is multi, the selection will set to `fallbackSelection` iff
|
| - the number of matching elements is zero.
|
| -
|
| - `iron-selector` is not styled. Use the `iron-selected` CSS class to style the selected element.
|
| -
|
| - Example:
|
| -
|
| - <style>
|
| - .iron-selected {
|
| - background: #eee;
|
| - }
|
| - </style>
|
| -
|
| - ...
|
| -
|
| - <iron-selector selected="0">
|
| - <div>Item 1</div>
|
| - <div>Item 2</div>
|
| - <div>Item 3</div>
|
| - </iron-selector>
|
| -
|
| - @demo demo/index.html
|
| - */
|
|
|
| Polymer({
|
|
|
| @@ -15001,7 +10693,6 @@ Polymer({
|
|
|
| showFooter: Boolean,
|
|
|
| - // If true, the sidebar is contained within an app-drawer.
|
| drawer: {
|
| type: Boolean,
|
| reflectToAttribute: true
|
| @@ -15013,20 +10704,11 @@ Polymer({
|
| this.fire('history-close-drawer');
|
| },
|
|
|
| - /**
|
| - * Relocates the user to the clear browsing data section of the settings page.
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| onClearBrowsingDataTap_: function(e) {
|
| md_history.BrowserService.getInstance().openClearBrowsingData();
|
| e.preventDefault();
|
| },
|
|
|
| - /**
|
| - * @param {Object} route
|
| - * @private
|
| - */
|
| getQueryString_: function(route) {
|
| return window.location.search;
|
| }
|
| @@ -15041,10 +10723,8 @@ Polymer({
|
| properties: {
|
| showSidebarFooter: Boolean,
|
|
|
| - // The id of the currently selected page.
|
| selectedPage_: {type: String, value: 'history', observer: 'unselectAll'},
|
|
|
| - // Whether domain-grouped history is enabled.
|
| grouped_: {type: Boolean, reflectToAttribute: true},
|
|
|
| /** @type {!QueryState} */
|
| @@ -15052,14 +10732,11 @@ Polymer({
|
| type: Object,
|
| value: function() {
|
| return {
|
| - // Whether the most recent query was incremental.
|
| incremental: false,
|
| - // A query is initiated by page load.
|
| querying: true,
|
| queryingDisabled: false,
|
| _range: HistoryRange.ALL_TIME,
|
| searchTerm: '',
|
| - // TODO(calamity): Make history toolbar buttons change the offset
|
| groupedOffset: 0,
|
|
|
| set range(val) { this._range = Number(val); },
|
| @@ -15080,28 +10757,22 @@ Polymer({
|
| }
|
| },
|
|
|
| - // Route data for the current page.
|
| routeData_: Object,
|
|
|
| - // The query params for the page.
|
| queryParams_: Object,
|
|
|
| - // True if the window is narrow enough for the page to have a drawer.
|
| hasDrawer_: Boolean,
|
| },
|
|
|
| observers: [
|
| - // routeData_.page <=> selectedPage
|
| 'routeDataChanged_(routeData_.page)',
|
| 'selectedPageChanged_(selectedPage_)',
|
|
|
| - // queryParams_.q <=> queryState.searchTerm
|
| 'searchTermChanged_(queryState_.searchTerm)',
|
| 'searchQueryParamChanged_(queryParams_.q)',
|
|
|
| ],
|
|
|
| - // TODO(calamity): Replace these event listeners with data bound properties.
|
| listeners: {
|
| 'cr-menu-tap': 'onMenuTap_',
|
| 'history-checkbox-select': 'checkboxSelected',
|
| @@ -15119,7 +10790,6 @@ Polymer({
|
| document.addEventListener('canExecute', this.onCanExecute_.bind(this));
|
| document.addEventListener('command', this.onCommand_.bind(this));
|
|
|
| - // Redirect legacy search URLs to URLs compatible with material history.
|
| if (window.location.hash) {
|
| window.location.href = window.location.href.split('#')[0] + '?' +
|
| window.location.hash.substr(1);
|
| @@ -15133,22 +10803,12 @@ Polymer({
|
| drawer.toggle();
|
| },
|
|
|
| - /**
|
| - * Listens for history-item being selected or deselected (through checkbox)
|
| - * and changes the view of the top toolbar.
|
| - * @param {{detail: {countAddition: number}}} e
|
| - */
|
| checkboxSelected: function(e) {
|
| var toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
|
| toolbar.count = /** @type {HistoryListContainerElement} */ (this.$.history)
|
| .getSelectedItemCount();
|
| },
|
|
|
| - /**
|
| - * Listens for call to cancel selection and loops through all items to set
|
| - * checkbox to be unselected.
|
| - * @private
|
| - */
|
| unselectAll: function() {
|
| var listContainer =
|
| /** @type {HistoryListContainerElement} */ (this.$.history);
|
| @@ -15161,11 +10821,6 @@ Polymer({
|
| this.$.history.deleteSelectedWithPrompt();
|
| },
|
|
|
| - /**
|
| - * @param {HistoryQuery} info An object containing information about the
|
| - * query.
|
| - * @param {!Array<HistoryEntry>} results A list of results.
|
| - */
|
| historyResult: function(info, results) {
|
| this.set('queryState_.querying', false);
|
| this.set('queryResult_.info', info);
|
| @@ -15175,16 +10830,8 @@ Polymer({
|
| listContainer.historyResult(info, results);
|
| },
|
|
|
| - /**
|
| - * Fired when the user presses 'More from this site'.
|
| - * @param {{detail: {domain: string}}} e
|
| - */
|
| searchDomain_: function(e) { this.$.toolbar.setSearchTerm(e.detail.domain); },
|
|
|
| - /**
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| onCanExecute_: function(e) {
|
| e = /** @type {cr.ui.CanExecuteEvent} */(e);
|
| switch (e.command.id) {
|
| @@ -15200,27 +10847,15 @@ Polymer({
|
| }
|
| },
|
|
|
| - /**
|
| - * @param {string} searchTerm
|
| - * @private
|
| - */
|
| searchTermChanged_: function(searchTerm) {
|
| this.set('queryParams_.q', searchTerm || null);
|
| this.$['history'].queryHistory(false);
|
| },
|
|
|
| - /**
|
| - * @param {string} searchQuery
|
| - * @private
|
| - */
|
| searchQueryParamChanged_: function(searchQuery) {
|
| this.$.toolbar.setSearchTerm(searchQuery || '');
|
| },
|
|
|
| - /**
|
| - * @param {Event} e
|
| - * @private
|
| - */
|
| onCommand_: function(e) {
|
| if (e.command.id == 'find-command' || e.command.id == 'slash-command')
|
| this.$.toolbar.showSearchField();
|
| @@ -15228,11 +10863,6 @@ Polymer({
|
| this.deleteSelected();
|
| },
|
|
|
| - /**
|
| - * @param {!Array<!ForeignSession>} sessionList Array of objects describing
|
| - * the sessions from other devices.
|
| - * @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile?
|
| - */
|
| setForeignSessions: function(sessionList, isTabSyncEnabled) {
|
| if (!isTabSyncEnabled) {
|
| var syncedDeviceManagerElem =
|
| @@ -15246,10 +10876,6 @@ Polymer({
|
| this.set('queryResult_.sessionList', sessionList);
|
| },
|
|
|
| - /**
|
| - * Update sign in state of synced device manager after user logs in or out.
|
| - * @param {boolean} isUserSignedIn
|
| - */
|
| updateSignInState: function(isUserSignedIn) {
|
| var syncedDeviceManagerElem =
|
| /** @type {HistorySyncedDeviceManagerElement} */this
|
| @@ -15258,53 +10884,22 @@ Polymer({
|
| syncedDeviceManagerElem.updateSignInState(isUserSignedIn);
|
| },
|
|
|
| - /**
|
| - * @param {string} selectedPage
|
| - * @return {boolean}
|
| - * @private
|
| - */
|
| syncedTabsSelected_: function(selectedPage) {
|
| return selectedPage == 'syncedTabs';
|
| },
|
|
|
| - /**
|
| - * @param {boolean} querying
|
| - * @param {boolean} incremental
|
| - * @param {string} searchTerm
|
| - * @return {boolean} Whether a loading spinner should be shown (implies the
|
| - * backend is querying a new search term).
|
| - * @private
|
| - */
|
| shouldShowSpinner_: function(querying, incremental, searchTerm) {
|
| return querying && !incremental && searchTerm != '';
|
| },
|
|
|
| - /**
|
| - * @param {string} page
|
| - * @private
|
| - */
|
| routeDataChanged_: function(page) {
|
| this.selectedPage_ = page;
|
| },
|
|
|
| - /**
|
| - * @param {string} selectedPage
|
| - * @private
|
| - */
|
| selectedPageChanged_: function(selectedPage) {
|
| this.set('routeData_.page', selectedPage);
|
| },
|
|
|
| - /**
|
| - * This computed binding is needed to make the iron-pages selector update when
|
| - * the synced-device-manager is instantiated for the first time. Otherwise the
|
| - * fallback selection will continue to be used after the corresponding item is
|
| - * added as a child of iron-pages.
|
| - * @param {string} selectedPage
|
| - * @param {Array} items
|
| - * @return {string}
|
| - * @private
|
| - */
|
| getSelectedPage_: function(selectedPage, items) {
|
| return selectedPage;
|
| },
|
|
|