forked from Polymer/polymer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into clean-up-externs
- Loading branch information
Showing
7 changed files
with
467 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.