Skip to content

Commit

Permalink
Merge branch 'master' into clean-up-externs
Browse files Browse the repository at this point in the history
  • Loading branch information
dfreedm committed Oct 16, 2017
2 parents 1e5ea94 + e9e2cda commit 6bf97eb
Show file tree
Hide file tree
Showing 7 changed files with 467 additions and 40 deletions.
41 changes: 41 additions & 0 deletions externs/closure-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,18 @@ Polymer_ElementMixin._parseTemplateContent = function(template, templateInfo, no
*/
Polymer_ElementMixin.finalize = function(){};
/**
* @param {string} is Tag name for this element
* @param {!HTMLTemplateElement} template Template to process
* @param {string} baseURI Base URI to rebase CSS paths against
* @return {string}
*/
Polymer_ElementMixin._processStyleText = function(is, template, baseURI){};
/**
* @param {string} is Tag name (or type extension name) for this element
* @param {string=} ext For type extensions, the tag name that was extended
*/
Polymer_ElementMixin._finalizeTemplate = function(is, ext){};
/**
* @interface
*/
function Polymer_GestureEventListeners(){}
Expand All @@ -766,6 +778,35 @@ Polymer_GestureEventListeners.prototype._addEventListenerToNode = function(node,
Polymer_GestureEventListeners.prototype._removeEventListenerFromNode = function(node, eventName, handler){};
/**
* @interface
* @extends {Polymer_PropertyAccessors}
*/
function Polymer_DirMixin(){}
/** @type {boolean} */
Polymer_DirMixin.prototype.__autoDirOptOut;

/**
* @return {undefined}
*/
Polymer_DirMixin.prototype.ready = function(){};
/**
* @return {undefined}
*/
Polymer_DirMixin.prototype.connectedCallback = function(){};
/**
* @return {undefined}
*/
Polymer_DirMixin.prototype.disconnectedCallback = function(){};
/**
* @override
*/
Polymer_DirMixin._processStyleText = function(is, template, baseURI){};
/**
* @param {string} text CSS text to replace DIR
* @return {string}
*/
Polymer_DirMixin._replaceDirInCssText = function(text){};
/**
* @interface
* @extends {Polymer_ElementMixin}
* @extends {Polymer_GestureEventListeners}
*/
Expand Down
4 changes: 3 additions & 1 deletion lib/legacy/legacy-element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<link rel="import" href="../../../shadycss/apply-shim.html">
<link rel="import" href="../mixins/element-mixin.html">
<link rel="import" href="../mixins/gesture-event-listeners.html">
<link rel="import" href="../mixins/dir-mixin.html">
<link rel="import" href="../utils/mixin.html">
<link rel="import" href="../utils/import-href.html">
<link rel="import" href="../utils/render-status.html">
Expand Down Expand Up @@ -46,8 +47,9 @@
* @extends {base}
* @implements {Polymer_ElementMixin}
* @implements {Polymer_GestureEventListeners}
* @implements {Polymer_DirMixin}
*/
const legacyElementBase = Polymer.GestureEventListeners(Polymer.ElementMixin(base));
const legacyElementBase = Polymer.DirMixin(Polymer.GestureEventListeners(Polymer.ElementMixin(base)));

/**
* Map of simple names to touch action names
Expand Down
174 changes: 174 additions & 0 deletions lib/mixins/dir-mixin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="property-accessors.html">

<script>
(function() {
'use strict';

const HOST_DIR = /:host\(:dir\((ltr|rtl)\)\)/g;
const HOST_DIR_REPLACMENT = ':host([dir="$1"])';

const EL_DIR = /([\s\w#\.\[\]\*]*):dir\((ltr|rtl)\)/g;
const EL_DIR_REPLACMENT = ':host([dir="$2"]) $1';

/**
* @type {!Array<!Polymer_DirMixin>}
*/
const DIR_INSTANCES = [];

/** @type {MutationObserver} */
let observer = null;

let DOCUMENT_DIR = '';

function getRTL() {
DOCUMENT_DIR = document.documentElement.getAttribute('dir');
}

/**
* @param {!Polymer_DirMixin} instance Instance to set RTL status on
*/
function setRTL(instance) {
if (!instance.__autoDirOptOut) {
const el = /** @type {!HTMLElement} */(instance);
el.setAttribute('dir', DOCUMENT_DIR);
}
}

function updateDirection() {
getRTL();
DOCUMENT_DIR = document.documentElement.getAttribute('dir');
for (let i = 0; i < DIR_INSTANCES.length; i++) {
setRTL(DIR_INSTANCES[i]);
}
}

function takeRecords() {
if (observer && observer.takeRecords().length) {
updateDirection();
}
}

/**
* Element class mixin that allows elements to use the `:dir` CSS Selector to have
* text direction specific styling.
*
* With this mixin, any stylesheet provided in the template will transform `:dir` into
* `:host([dir])` and sync direction with the page via the element's `dir` attribute.
*
* Elements can opt out of the global page text direction by setting the `dir` attribute
* directly in `ready()` or in HTML.
*
* Caveats:
* - Applications must set `<html dir="ltr">` or `<html dir="rtl">` to sync direction
* - Automatic left-to-right or right-to-left styling is sync'd with the `<html>` element only.
* - Changing `dir` at runtime is supported.
* - Opting out of the global direction styling is permanent
*
* @mixinFunction
* @polymer
* @appliesMixin Polymer.PropertyAccessors
* @memberof Polymer
*/
Polymer.DirMixin = Polymer.dedupingMixin((base) => {

if (!observer) {
getRTL();
observer = new MutationObserver(updateDirection);
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['dir']});
}

/**
* @constructor
* @extends {base}
* @implements {Polymer_PropertyAccessors}
*/
const elementBase = Polymer.PropertyAccessors(base);

/**
* @polymer
* @mixinClass
* @implements {Polymer_DirMixin}
*/
class Dir extends elementBase {

/**
* @override
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
*/
static _processStyleText(is, template, baseURI) {
let cssText = super._processStyleText(is, template, baseURI);
cssText = this._replaceDirInCssText(cssText);
return cssText;
}

/**
* Replace `:dir` in the given CSS text
*
* @param {string} text CSS text to replace DIR
* @return {string} Modified CSS
*/
static _replaceDirInCssText(text) {
let replacedText = text;
replacedText = replacedText.replace(HOST_DIR, HOST_DIR_REPLACMENT);
replacedText = replacedText.replace(EL_DIR, EL_DIR_REPLACMENT);
if (text !== replacedText) {
this.__activateDir = true;
}
return replacedText;
}

constructor() {
super();
/** @type {boolean} */
this.__autoDirOptOut = false;
}

/**
* @suppress {invalidCasts} Closure doesn't understand that `this` is an HTMLElement
*/
ready() {
super.ready();
this.__autoDirOptOut = /** @type {!HTMLElement} */(this).hasAttribute('dir');
}

/** @suppress {missingProperties} If it exists on elementBase, it can be super'd */
connectedCallback() {
if (elementBase.prototype.connectedCallback) {
super.connectedCallback();
}
if (this.constructor.__activateDir) {
takeRecords();
DIR_INSTANCES.push(this);
setRTL(this);
}
}

/** @suppress {missingProperties} If it exists on elementBase, it can be super'd */
disconnectedCallback() {
if (elementBase.prototype.disconnectedCallback) {
super.disconnectedCallback();
}
if (this.constructor.__activateDir) {
const idx = DIR_INSTANCES.indexOf(this);
if (idx > -1) {
DIR_INSTANCES.splice(idx, 1);
}
}
}
}

Dir.__activateDir = false;

return Dir;
});
})();
</script>
82 changes: 45 additions & 37 deletions lib/mixins/element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -399,36 +399,6 @@
}
}

/**
* Configures an element `proto` to function with a given `template`.
* The element name `is` and extends `ext` must be specified for ShadyCSS
* style scoping.
*
* @param {PolymerElement} proto Element class prototype to add accessors
* and effects to
* @param {!HTMLTemplateElement} template Template to process and bind
* @param {string} baseURI URL against which to resolve urls in
* style element cssText
* @param {string} is Tag name (or type extension name) for this element
* @param {string=} ext For type extensions, the tag name that was extended
* @private
*/
function finalizeTemplate(proto, template, baseURI, is, ext) {
// support `include="module-name"`
let cssText =
Polymer.StyleGather.cssFromModuleImports(is) +
Polymer.StyleGather.cssFromTemplate(template, baseURI);
if (cssText) {
let style = document.createElement('style');
style.textContent = cssText;
template.content.insertBefore(style, template.content.firstChild);
}
if (window.ShadyCSS) {
window.ShadyCSS.prepareTemplate(template, is, ext);
}
proto._bindTemplate(template);
}

/**
* @polymer
* @mixinClass
Expand Down Expand Up @@ -577,13 +547,7 @@
const importPath = this.constructor.importPath;
// note: finalize template when we have access to `localName` to
// avoid dependence on `is` for polyfilling styling.
if (this._template && !this._template.__polymerFinalized) {
this._template.__polymerFinalized = true;
const baseURI =
importPath ? Polymer.ResolveUrl.resolveUrl(importPath) : '';
finalizeTemplate(/** @type {!PolymerElement} */(this.__proto__), this._template, baseURI,
/**@type {!HTMLElement}*/(this).localName);
}
this.constructor._finalizeTemplate(/** @type {!HTMLElement} */(this).localName);
super._initializeProperties();
// set path defaults
this.rootPath = Polymer.rootPath;
Expand Down Expand Up @@ -613,6 +577,50 @@
}
}

/**
* Gather style text for the template
*
* @param {string} is Tag name for this element
* @param {!HTMLTemplateElement} template Template to process
* @param {string} baseURI Base URI to rebase CSS paths against
* @return {string} The combined CSS text
* @protected
*/
static _processStyleText(is, template, baseURI) {
return Polymer.StyleGather.cssFromModuleImports(is) +
Polymer.StyleGather.cssFromTemplate(template, baseURI);
}

/**
* Configures an element `proto` to function with a given `template`.
* The element name `is` and extends `ext` must be specified for ShadyCSS
* style scoping.
*
* @param {string} is Tag name (or type extension name) for this element
* @param {string=} ext For type extensions, the tag name that was extended
* @protected
*/
static _finalizeTemplate(is, ext) {
/** @const {HTMLTemplateElement} */
const template = this.prototype._template;
if (template && !template.__polymerFinalized) {
template.__polymerFinalized = true;
const importPath = this.importPath;
const baseURI = importPath ? Polymer.ResolveUrl.resolveUrl(importPath) : '';
// support `include="module-name"`
let cssText = this._processStyleText(is, template, baseURI);
if (cssText) {
let style = document.createElement('style');
style.textContent = cssText;
template.content.insertBefore(style, template.content.firstChild);
}
if (window.ShadyCSS) {
window.ShadyCSS.prepareTemplate(template, is, ext);
}
this.prototype._bindTemplate(template);
}
}

/**
* Provides a default implementation of the standard Custom Elements
* `connectedCallback`.
Expand Down
3 changes: 2 additions & 1 deletion test/runner.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
'unit/logging.html',
'unit/mixin-utils.html',
'unit/mixin-behaviors.html',
'unit/render-status.html'
'unit/render-status.html',
'unit/dir.html'
];

// http://eddmann.com/posts/cartesian-product-in-javascript/
Expand Down
Loading

0 comments on commit 6bf97eb

Please sign in to comment.