i18n-number
Advanced tools
Comparing version 3.0.1 to 4.0.0-pre.1
{ | ||
"name": "i18n-number", | ||
"license": "https://github.com/t2ym/i18n-format/blob/master/LICENSE.md" | ||
"license": "BSD-2-Clause" | ||
} |
@@ -20,3 +20,2 @@ /** | ||
@group I18nBehavior | ||
@element i18n-number | ||
@@ -26,310 +25,24 @@ @hero hero.svg | ||
*/ | ||
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js'; | ||
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
import { polyfill } from 'wc-putty/polyfill.js'; | ||
import { html, render } from 'lit-html/lit-html.js'; | ||
var intlLibraryScript; | ||
var intlLibraryLoadingStatus = 'initializing'; | ||
var _setupIntlPolyfillCalled = false; | ||
var formatCache = new Map(); | ||
const formatCache = new Map(); | ||
/** | ||
* Set up Intl polyfill if required | ||
*/ | ||
function _setupIntlPolyfill () { | ||
// Polyfill Intl if required | ||
var intlLibraryUrl = this.resolveUrl('../intl/dist/Intl.min.js', this.importMeta.url); | ||
if (window.Intl) { | ||
if (window.IntlPolyfill && window.Intl === window.IntlPolyfill) { | ||
intlLibraryLoadingStatus = 'loaded'; | ||
} | ||
else { | ||
intlLibraryLoadingStatus = 'native'; | ||
} | ||
export class I18nNumber extends polyfill(HTMLElement) { | ||
static get importMeta() { | ||
return import.meta; | ||
} | ||
else { | ||
intlLibraryLoadingStatus = 'loading'; | ||
intlLibraryScript = document.createElement('script'); | ||
intlLibraryScript.setAttribute('src', intlLibraryUrl); | ||
intlLibraryScript.setAttribute('id', 'intl-js-library'); | ||
intlLibraryScript.addEventListener('load', function intlLibraryLoaded (e) { | ||
intlLibraryLoadingStatus = 'loaded'; | ||
e.target.removeEventListener('load', intlLibraryLoaded); | ||
return false; | ||
}); | ||
var s = document.querySelector('script') || document.body; | ||
s.parentNode.insertBefore(intlLibraryScript, s); | ||
static get is() { | ||
return 'i18n-number'; | ||
} | ||
} | ||
/** | ||
* Set up polyfill locale of Intl if required | ||
* | ||
* @param {String} locale Target locale to polyfill | ||
* @param {Function} callback Callback function to handle locale load | ||
* @return {Boolean} true if supported; false if callback will be called | ||
*/ | ||
function _setupIntlPolyfillLocale (locale, callback) { | ||
if (!window.IntlPolyfill) { | ||
switch (intlLibraryLoadingStatus) { | ||
case 'loading': | ||
/* istanbul ignore else: intlLibraryScript is always set when the status is 'loading' */ | ||
if (intlLibraryScript) { | ||
var libraryLoadedBindThis = function (e) { | ||
_setupIntlPolyfillLocale.call(this, locale, callback); | ||
e.target.removeEventListener('load', libraryLoadedBindThis); | ||
}.bind(this); | ||
intlLibraryScript.addEventListener('load', libraryLoadedBindThis); | ||
return false; | ||
} | ||
else { | ||
console.error('Intl.js is not being loaded'); | ||
} | ||
/* istanbul ignore next: intlLibraryScript is always set when the status is 'loading' */ | ||
break; | ||
// impossible cases | ||
case 'initializing': | ||
case 'loaded': | ||
case 'native': | ||
default: | ||
/* istanbul ignore next: these cases are impossible */ | ||
break; | ||
} | ||
static get observedAttributes() { | ||
return [ 'lang', 'options', 'offset' ]; | ||
} | ||
else { | ||
if (intlLibraryLoadingStatus !== 'native') { | ||
var supported = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup' }); | ||
var script; | ||
var intlScript; | ||
if (supported.length === 0) { | ||
// load the locale | ||
var fallbackLanguages = _enumerateFallbackLanguages(locale); | ||
locale = fallbackLanguages.shift(); | ||
script = document.querySelector('script#intl-js-locale-' + locale); | ||
if (!script) { | ||
script = document.createElement('script'); | ||
script.setAttribute('id', 'intl-js-locale-' + locale); | ||
script.setAttribute('src', this.resolveUrl('../intl/locale-data/jsonp/' + locale + '.js', this.importMeta.url)); | ||
var intlLocaleLoadedBindThis = function (e) { | ||
if (e.target === script) { | ||
e.target.removeEventListener('load', intlLocaleLoadedBindThis); | ||
callback.call(this, locale); | ||
} | ||
return false; | ||
}.bind(this); | ||
var intlLocaleLoadErrorBindThis = function (e) { | ||
if (e.target === script) { | ||
e.target.removeEventListener('error', intlLocaleLoadErrorBindThis); | ||
script.setAttribute('loaderror',''); | ||
locale = fallbackLanguages.shift(); | ||
if (!locale) { | ||
locale = this.DEFAULT_LANG; | ||
} | ||
var fallbackSupport = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup'}); | ||
if (fallbackSupport.length > 0) { | ||
callback.call(this, locale); | ||
} | ||
else { | ||
_setupIntlPolyfillLocale.call(this, locale, callback); | ||
} | ||
return false; | ||
} | ||
}.bind(this); | ||
script.addEventListener('load', intlLocaleLoadedBindThis); | ||
script.addEventListener('error', intlLocaleLoadErrorBindThis); | ||
intlScript = document.querySelector('script#intl-js-library') || document.body; | ||
intlScript.parentNode.insertBefore(script, intlScript.nextSibling); | ||
} | ||
else if (!script.hasAttribute('loaderror')) { | ||
// already loading | ||
var anotherIntlLocaleLoadedBindThis = function (e) { | ||
if (e.target === script) { | ||
callback.call(this, locale); | ||
e.target.removeEventListener('load', anotherIntlLocaleLoadedBindThis); | ||
return false; | ||
} | ||
}.bind(this); | ||
var anotherIntlLocaleLoadErrorBindThis = function (e) { | ||
if (e.target === script) { | ||
e.target.removeEventListener('error', anotherIntlLocaleLoadErrorBindThis); | ||
locale = fallbackLanguages.shift(); | ||
if (!locale) { | ||
locale = this.DEFAULT_LANG; | ||
} | ||
var fallbackSupport = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup'}); | ||
if (fallbackSupport.length > 0) { | ||
callback.call(this, locale); | ||
} | ||
else { | ||
_setupIntlPolyfillLocale.call(this, locale, callback); | ||
} | ||
return false; | ||
} | ||
}.bind(this); | ||
script.addEventListener('load', anotherIntlLocaleLoadedBindThis); | ||
script.addEventListener('error', anotherIntlLocaleLoadErrorBindThis); | ||
} | ||
else { | ||
var enSupport = Intl.NumberFormat.supportedLocalesOf(this.DEFAULT_LANG, { localeMatcher: 'lookup'}); | ||
if (enSupport.length > 0) { | ||
callback.call(this, this.DEFAULT_LANG); | ||
} | ||
else { | ||
_setupIntlPolyfillLocale.call(this, this.DEFAULT_LANG, callback); | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Enumerate fallback locales for the target locale. | ||
* | ||
* Subset implementation of BCP47 (https://tools.ietf.org/html/bcp47). | ||
* | ||
* ### Examples: | ||
* | ||
*| Target Locale | Fallback 1 | Fallback 2 | Fallback 3 | | ||
*|:--------------|:-----------|:-----------|:-----------| | ||
*| ru | N/A | N/A | N/A | | ||
*| en-GB | en | N/A | N/A | | ||
*| en-Latn-GB | en-GB | en-Latn | en | | ||
*| fr-CA | fr | N/A | N/A | | ||
*| zh-Hans-CN | zh-Hans | zh | N/A | | ||
*| zh-CN | zh-Hans | zh | N/A | | ||
*| zh-TW | zh-Hant | zh | N/A | | ||
* | ||
* #### Note: | ||
* | ||
* For zh language, the script Hans or Hant is supplied as its default script when a country/region code is supplied. | ||
* | ||
* @param {string} lang Target locale. | ||
* @return {Array} List of fallback locales including the target locale at the index 0. | ||
*/ | ||
function _enumerateFallbackLanguages (lang) { | ||
var result = []; | ||
var parts; | ||
var match; | ||
var isExtLangCode = 0; | ||
var extLangCode; | ||
var isScriptCode = 0; | ||
var scriptCode; | ||
var isCountryCode = 0; | ||
var countryCode; | ||
var n; | ||
/* istanbul ignore if: lang is always a non-null string */ | ||
if (!lang || lang.length === 0) { | ||
result.push(''); | ||
__render() { | ||
return html`<span id="number">${this.formatted || ''}</span>`; | ||
} | ||
else { | ||
parts = lang.split(/[-_]/); | ||
// normalize ISO-639-1 language codes | ||
if (parts.length > 0 && | ||
parts[0].match(/^[A-Za-z]{2,3}$/)) { | ||
// language codes have to be lowercased | ||
// e.g. JA -> ja, FR -> fr | ||
// TODO: normalize 3-letter codes to 2-letter codes | ||
parts[0] = parts[0].toLowerCase(); | ||
} | ||
// normalize ISO-639-3 extension language codes | ||
if (parts.length >= 2 && | ||
parts[1].match(/^[A-Za-z]{3}$/) && | ||
!parts[1].match(/^[Cc][Hh][SsTt]$/)) { // exclude CHS,CHT | ||
// extension language codes have to be lowercased | ||
// e.g. YUE -> yue | ||
isExtLangCode = 1; | ||
extLangCode = parts[1] = parts[1].toLowerCase(); | ||
} | ||
// normalize ISO-15924 script codes | ||
if (parts.length >= isExtLangCode + 2 && | ||
(match = parts[isExtLangCode + 1].match(/^([A-Za-z])([A-Za-z]{3})$/))) { | ||
// script codes have to be capitalized only at the first character | ||
// e.g. HANs -> Hans, lAtN -> Latn | ||
isScriptCode = 1; | ||
scriptCode = parts[isExtLangCode + 1] = match[1].toUpperCase() + match[2].toLowerCase(); | ||
} | ||
// normalize ISO-3166-1 country/region codes | ||
if (parts.length >= isExtLangCode + isScriptCode + 2 && | ||
(match = parts[isExtLangCode + isScriptCode + 1].match(/^[A-Za-z0-9]{2,3}$/))) { | ||
// country/region codes have to be capitalized | ||
// e.g. cn -> CN, jP -> JP | ||
isCountryCode = 1; | ||
countryCode = parts[isExtLangCode + isScriptCode + 1] = match[0].toUpperCase(); | ||
} | ||
// extensions have to be in lowercases | ||
// e.g. U-cA-Buddhist -> u-ca-buddhist, X-LiNux -> x-linux | ||
if (parts.length >= isExtLangCode + isScriptCode + isCountryCode + 2) { | ||
for (n = isExtLangCode + isScriptCode + isCountryCode + 1; n < parts.length; n++) { | ||
parts[n] = parts[n].toLowerCase(); | ||
} | ||
} | ||
// enumerate fallback languages | ||
while (parts.length > 0) { | ||
// normalize delimiters as - | ||
// e.g. ja_JP -> ja-JP | ||
if (!parts[parts.length - 1].match(/^[xu]$/)) { | ||
result.push(parts.join('-')); | ||
} | ||
if (isScriptCode && | ||
isCountryCode && | ||
parts.length == isExtLangCode + isScriptCode + 2) { | ||
// script code can be omitted to default | ||
// e.g. en-Latn-GB -> en-GB, zh-Hans-CN -> zh-CN | ||
parts.splice(isExtLangCode + isScriptCode, 1); | ||
result.push(parts.join('-')); | ||
parts.splice(isExtLangCode + isScriptCode, 0, scriptCode); | ||
} | ||
if (isExtLangCode && | ||
isCountryCode && | ||
parts.length == isExtLangCode + isScriptCode + 2) { | ||
// ext lang code can be omitted to default | ||
// e.g. zh-yue-Hans-CN -> zh-Hans-CN | ||
parts.splice(isExtLangCode, 1); | ||
result.push(parts.join('-')); | ||
parts.splice(isExtLangCode, 0, extLangCode); | ||
} | ||
if (isExtLangCode && | ||
isScriptCode && | ||
parts.length == isExtLangCode + isScriptCode + 1) { | ||
// ext lang code can be omitted to default | ||
// e.g. zh-yue-Hans -> zh-Hans | ||
parts.splice(isExtLangCode, 1); | ||
result.push(parts.join('-')); | ||
parts.splice(isExtLangCode, 0, extLangCode); | ||
} | ||
if (!isScriptCode && | ||
!isExtLangCode && | ||
isCountryCode && | ||
parts.length == 2) { | ||
// default script code can be added in certain cases with country codes | ||
// e.g. zh-CN -> zh-Hans-CN, zh-TW -> zh-Hant-TW | ||
switch (result[result.length - 1]) { | ||
case 'zh-CN': | ||
case 'zh-CHS': | ||
result.push('zh-Hans'); | ||
break; | ||
case 'zh-TW': | ||
case 'zh-SG': | ||
case 'zh-HK': | ||
case 'zh-CHT': | ||
result.push('zh-Hant'); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
parts.pop(); | ||
} | ||
} | ||
return result; | ||
} | ||
Polymer({ | ||
importMeta: import.meta, | ||
is: 'i18n-number', | ||
_template: (t => { t.setAttribute('strip-whitespace', ''); return t; })(html`<span id="number"></span>`), | ||
/** | ||
@@ -341,4 +54,11 @@ * Fired whenever the formatted text is rendered. | ||
properties: { | ||
constructor() { | ||
super(); | ||
this.attachShadow({ mode: 'open' }); | ||
/** | ||
* Default locale constant 'en' | ||
*/ | ||
this.DEFAULT_LANG = 'en'; | ||
/** | ||
* The locale for the formatted number. | ||
@@ -348,97 +68,85 @@ * The typical value is bound to `{{effectiveLang}}` when the containing element has | ||
*/ | ||
_lang: { | ||
type: String, | ||
value: 'en', | ||
observer: '_langChanged', | ||
reflectToAttribute: false | ||
}, | ||
this.lang = this.DEFAULT_LANG; | ||
/** | ||
* Options object for Intl.NumberFormat | ||
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) | ||
* Offset for number | ||
* | ||
* Note: number = rawNumber - offset | ||
*/ | ||
options: { | ||
type: Object, | ||
observer: '_optionsChanged', | ||
notify: true | ||
}, | ||
this.offset = 0; | ||
/** | ||
* Raw string synchronized with textContent | ||
*/ | ||
raw: { | ||
type: String, | ||
observer: '_rawChanged' | ||
}, | ||
//this.raw = undefined; | ||
/** | ||
* Offset for number | ||
* | ||
* Note: number = rawNumber - offset | ||
* Options object for Intl.NumberFormat | ||
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) | ||
*/ | ||
offset: { | ||
type: Number, | ||
value: 0, | ||
observer: '_offsetChanged' | ||
}, | ||
//this.options = undefined; | ||
/** | ||
* Raw number parsed from raw | ||
*/ | ||
rawNumber: { | ||
type: Number, | ||
notify: true | ||
}, | ||
//this.rawNumber = undefined; | ||
/** | ||
* Number calculated from rawNumber and offset | ||
*/ | ||
number: { | ||
type: Number, | ||
notify: true | ||
}, | ||
//this.number = undefined; | ||
/** | ||
* Formatted string rendered for UI | ||
* | ||
* Note: | ||
* - While Intl.js Polyfill locale module is being loaded, the value is set as `undefined` until load completion. | ||
*/ | ||
formatted: { | ||
type: String, | ||
notify: true | ||
//this.formatted = undefined; | ||
this._setupObservers(); | ||
this.raw = this.textNode.data; | ||
} | ||
attributeChangedCallback(name, oldValue, newValue) { | ||
switch (name) { | ||
case 'lang': | ||
this._langChanged(newValue); | ||
break; | ||
case 'options': | ||
try { | ||
this.options = JSON.parse(newValue); | ||
} | ||
catch (ex) { | ||
this.options = undefined; | ||
} | ||
break; | ||
case 'offset': | ||
this.offset = parseInt(newValue); | ||
break; | ||
/* istanbul ignore next */ | ||
default: | ||
/* istanbul ignore next */ | ||
break; | ||
} | ||
}, | ||
} | ||
observers: [ | ||
'_onOptionsPropertyChanged(options.*)' | ||
], | ||
get options() { | ||
return this._options; | ||
} | ||
/** | ||
* Default locale constant 'en' | ||
*/ | ||
DEFAULT_LANG: 'en', | ||
set options(value) { | ||
this._optionsChanged(this._options = value); | ||
} | ||
/** | ||
* Start loading Intl polyfill only once | ||
*/ | ||
registered: function () { | ||
if (!_setupIntlPolyfillCalled) { | ||
_setupIntlPolyfillCalled = true; | ||
_setupIntlPolyfill.call(this); | ||
} | ||
}, | ||
get raw() { | ||
return this._raw; | ||
} | ||
ready: function () { | ||
this._setupObservers(); | ||
this.raw = this.textNode.data; | ||
if (!this.lang) { | ||
// Polyfill non-functional default value for lang property in Safari 7 | ||
this.lang = this.DEFAULT_LANG; | ||
} | ||
}, | ||
set raw(value) { | ||
this._rawChanged(this._raw = value); | ||
} | ||
attached: function () { | ||
get offset() { | ||
return this._offset; | ||
} | ||
set offset(value) { | ||
this._offsetChanged(this._offset = value); | ||
} | ||
connectedCallback() { | ||
this.raw = this.textNode.data; | ||
}, | ||
this.invalidate(); | ||
} | ||
@@ -448,8 +156,8 @@ /** | ||
*/ | ||
_setupObservers: function () { | ||
_setupObservers() { | ||
let i = 0; | ||
do { | ||
this.textNode = dom(this).childNodes[i++]; | ||
this.textNode = this.childNodes[i++]; | ||
if (!this.textNode) { | ||
this.textNode = dom(this).childNodes[0]; | ||
this.textNode = this.childNodes[0]; | ||
break; | ||
@@ -460,24 +168,34 @@ } | ||
if (!this.textNode) { | ||
dom(this).appendChild(document.createTextNode('')); | ||
this.textNode = dom(this).childNodes[0]; | ||
this.appendChild(document.createTextNode('')); | ||
this.textNode = this.childNodes[0]; | ||
} | ||
this.observer = new MutationObserver(this._textMutated.bind(this)); | ||
this.observer.observe(this.textNode, { characterData: true }); | ||
this.observer.observe(this, { attributes: true, attributeFilter: [ 'lang' ] }); | ||
this.nodeObserver = dom(this).observeNodes(function (info) { | ||
let i = 0; | ||
do { | ||
if (info.addedNodes[i] && | ||
info.addedNodes[i].nodeType === info.addedNodes[i].TEXT_NODE) { | ||
this.textNode = info.addedNodes[i]; | ||
this.raw = this.textNode.data; | ||
//console.log('i18n-number: text node added with ' + this.raw); | ||
this.observer.observe(this.textNode, { characterData: true }); | ||
this.nodeObserver = new MutationObserver(function (mutations) { | ||
mutations.forEach(function(mutation) { | ||
switch (mutation.type) { | ||
case 'childList': | ||
let i = 0; | ||
do { | ||
if (mutation.addedNodes[i] && | ||
mutation.addedNodes[i].nodeType === mutation.addedNodes[i].TEXT_NODE) { | ||
this.textNode = mutation.addedNodes[i]; | ||
this.raw = this.textNode.data; | ||
//console.log('i18n-number: text node added with ' + this.raw); | ||
this.observer.observe(this.textNode, { characterData: true }); | ||
break; | ||
} | ||
i++; | ||
} | ||
while (i < mutation.addedNodes.length); | ||
break; | ||
/* istanbul ignore next */ | ||
default: | ||
/* istanbul ignore next: mutation.type is characterData or attributes */ | ||
break; | ||
} | ||
i++; | ||
} | ||
while (i < info.addedNodes.length); | ||
}, this); | ||
}.bind(this)); | ||
}, | ||
this.nodeObserver.observe(this, { childList: true }); | ||
} | ||
@@ -489,3 +207,3 @@ /** | ||
*/ | ||
_textMutated: function (mutations) { | ||
_textMutated(mutations) { | ||
mutations.forEach(function(mutation) { | ||
@@ -499,13 +217,9 @@ switch (mutation.type) { | ||
break; | ||
case 'attributes': | ||
if (mutation.attributeName === 'lang') { | ||
this._lang = this.lang; | ||
} | ||
break; | ||
/* istanbul ignore next: mutation.type is characterData */ | ||
default: | ||
/* istanbul ignore next: mutation.type is characterData or attributes */ | ||
/* istanbul ignore next: mutation.type is characterData */ | ||
break; | ||
} | ||
}, this); | ||
}, | ||
} | ||
@@ -517,3 +231,3 @@ /** | ||
*/ | ||
_rawChanged: function (raw) { | ||
_rawChanged(raw) { | ||
if (this.textNode) { | ||
@@ -526,3 +240,3 @@ if (raw !== this.textNode.data) { | ||
} | ||
}, | ||
} | ||
@@ -534,3 +248,3 @@ /** | ||
*/ | ||
_langChanged: function (lang) { | ||
_langChanged(lang) { | ||
if (!lang) { | ||
@@ -544,3 +258,3 @@ this.lang = this.DEFAULT_LANG; | ||
} | ||
}, | ||
} | ||
@@ -552,3 +266,3 @@ /** | ||
*/ | ||
_optionsChanged: function (options) { | ||
_optionsChanged(options) { | ||
if (this.textNode) { | ||
@@ -558,8 +272,16 @@ //console.log('i18n-number: _optionsChanged: options = ' + JSON.stringify(options)); | ||
} | ||
}, | ||
} | ||
/** | ||
* Partially emulates notifyPath() in Polymer library | ||
* Just calls _onOptionsPropertyChanged() to re-render | ||
*/ | ||
notifyPath(path, value) { | ||
this._onOptionsPropertyChanged(); | ||
} | ||
/** | ||
* Observer of `options` sub-properties to re-render the formatted number. | ||
*/ | ||
_onOptionsPropertyChanged: function (/* changeRecord */) { | ||
_onOptionsPropertyChanged(/* changeRecord */) { | ||
if (this.textNode) { | ||
@@ -569,3 +291,3 @@ //console.log('_onOptionsPropertyChanged: path = ' + changeRecord.path + ' value = ' + JSON.stringify(changeRecord.value)); | ||
} | ||
}, | ||
} | ||
@@ -577,3 +299,3 @@ /** | ||
*/ | ||
_offsetChanged: function (offset) { | ||
_offsetChanged(offset) { | ||
if (this.textNode) { | ||
@@ -583,3 +305,3 @@ //console.log('i18n-number: _offsetChanged: offset = ' + offset); | ||
} | ||
}, | ||
} | ||
@@ -601,3 +323,3 @@ /** | ||
return formatObject; | ||
}, | ||
} | ||
@@ -612,39 +334,13 @@ /** | ||
*/ | ||
_formatNumber: function (lang, options, number) { | ||
_formatNumber(lang, options, number) { | ||
if (!lang) { | ||
lang = this.DEFAULT_LANG; | ||
} | ||
switch (intlLibraryLoadingStatus) { | ||
case 'loaded': | ||
case 'loading': | ||
default: | ||
try { | ||
if (_setupIntlPolyfillLocale.call(this, lang, function (locale) { | ||
this.effectiveLang = locale; | ||
this._render.call(this, locale, this.options, this.raw, this.offset); | ||
}.bind(this))) { | ||
return this._getNumberFormatObject(lang, options).format(number); | ||
} | ||
else { | ||
// waiting for callback | ||
return undefined; | ||
} | ||
} | ||
catch (e) { | ||
return number.toString(); | ||
} | ||
/* istanbul ignore next: unreachable code due to returns in the same case */ | ||
break; | ||
case 'native': | ||
// native | ||
try { | ||
return this._getNumberFormatObject(lang, options).format(number); | ||
} | ||
catch (e) { | ||
return number.toString(); | ||
} | ||
/* istanbul ignore next: unreachable code due to returns in the same case */ | ||
break; | ||
try { | ||
return this._getNumberFormatObject(lang, options).format(number); | ||
} | ||
}, | ||
catch (e) { | ||
return number.toString(); | ||
} | ||
} | ||
@@ -659,3 +355,3 @@ /** | ||
*/ | ||
_render: function (lang, options, raw, offset) { | ||
_render(lang, options, raw, offset) { | ||
// TODO: rendering may be done redundantly on property initializations | ||
@@ -677,8 +373,22 @@ raw = raw.trim(); | ||
} | ||
this.$.number.textContent = this.formatted ? this.formatted : ''; | ||
this.invalidate(); | ||
//console.log('i18n-number: _render ' + this.formatted); | ||
if (typeof this.formatted !== 'undefined') { | ||
this.fire('rendered'); | ||
} | ||
/** | ||
* Renders shadowRoot with this.__render() | ||
*/ | ||
invalidate() { | ||
if (!this.needsRender) { | ||
this.needsRender = true; | ||
Promise.resolve().then(() => { | ||
this.needsRender = false; | ||
render(this.__render(), this.shadowRoot); | ||
//console.log(`rendered "${this.formatted}"`); | ||
if (typeof this.formatted !== 'undefined') { | ||
this.dispatchEvent(new Event('rendered', { bubbles: true, cancelable: false, composed: true })); | ||
} | ||
}); | ||
} | ||
}, | ||
} | ||
@@ -701,5 +411,6 @@ /** | ||
*/ | ||
render: function () { | ||
render() { | ||
this._render(this.lang, this.options, this.raw, this.offset); | ||
} | ||
}); | ||
} | ||
customElements.define(I18nNumber.is, I18nNumber); |
{ | ||
"description": "Wrapper element for Intl.NumberFormat", | ||
"keywords": [ | ||
"polymer", | ||
"lit-html", | ||
"web-component", | ||
@@ -18,3 +18,3 @@ "web-components", | ||
"name": "i18n-number", | ||
"version": "3.0.1", | ||
"version": "4.0.0-pre.1", | ||
"main": "i18n-number.js", | ||
@@ -49,2 +49,3 @@ "directories": { | ||
"lcov-result-merger": "^1.2.0", | ||
"@polymer/polymer": "^3.0.0", | ||
"wct-browser-legacy": "^1.0.0", | ||
@@ -62,5 +63,5 @@ "wct-istanbul": "^0.14.3", | ||
"dependencies": { | ||
"@polymer/polymer": "^3.0.0", | ||
"intl": "^1.2.0" | ||
"lit-html": "^1.0.0", | ||
"wc-putty": "^0.1.0" | ||
} | ||
} |
@@ -7,3 +7,2 @@ { | ||
"extraDependencies": [ | ||
"node_modules/intl/**", | ||
"node_modules/@webcomponents/webcomponentsjs/**" | ||
@@ -10,0 +9,0 @@ ], |
@@ -43,3 +43,11 @@ /** | ||
} | ||
}, | ||
attached: function() { | ||
this.$.num.setAttribute('lang', this.$.num.getAttribute('lang')); | ||
this.$.num.setAttribute('lang', this.$.num.getAttribute('lang')); | ||
this.$.num.setAttribute('attr', 'value'); | ||
this.$.num.setAttribute('options', '<'); | ||
this.$.num.constructor.importMeta; | ||
} | ||
}); |
@@ -40,3 +40,3 @@ { | ||
"platform": "OS X 10.11", | ||
"version": "9" | ||
"version": "10" | ||
} | ||
@@ -43,0 +43,0 @@ ] |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22
262700
18
5409
1
+ Addedlit-html@^1.0.0
+ Addedwc-putty@^0.1.0
+ Addedlit-html@1.4.1(transitive)
+ Addedwc-putty@0.1.0(transitive)
- Removed@polymer/polymer@^3.0.0
- Removedintl@^1.2.0
- Removed@polymer/polymer@3.5.2(transitive)
- Removed@webcomponents/shadycss@1.11.2(transitive)
- Removedintl@1.2.5(transitive)