i18n-element
Version:
I18N Base Element for lit-html and Polymer
14,588 lines • 504 kB
HTML
<html lang="en"><head><!--
@license https://github.com/t2ym/i18n-behavior/blob/master/LICENSE.md
Copyright (c) 2016, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
-->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<script>
/*!
* @license https://github.com/t2ym/i18n-behavior/blob/master/LICENSE.md
* Copyright (c) 2016, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
*/
</script>
<script src="../../../webcomponentsjs/webcomponents.min.js"></script>
<script src="../../../wct-browser-legacy/browser.js"></script>
<script>"use strict";
var fakeServerContents =
{
"/commented-simple-text-element/commented-simple-text-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"third-level-div\": \"great grandchild text within div\",\n \"second-level-div:div_1\": \"great grandchild text within div without id\",\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items:li\": \"line item with id 1\",\n \"line-items:li_1\": \"line item with id 2\",\n \"line-items:li_2\": \"line item with id 3\",\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/commented-simple-text-element/locales/commented-simple-text-element.fr.json": "{\n \"model\": {},\n \"text\": \"fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \"fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"div_9:span\": \"fr simple text within div\",\n \"div_9:span_1\": \"fr simple text within div 2\",\n \"div_9:div_2:div\": \"fr great grandchild text within div\",\n \"div_10:text\": \"fr simple text as the first element in div \",\n \"div_10:span_1\": \"fr simple text within div\",\n \"div_10:text_2\": \"fr simple text in the middle of div \",\n \"div_10:span_3\": \"fr simple text within div 2\",\n \"div_10:div_4:div\": \"fr great grandchild text within div\",\n \"div_10:text_5\": \"fr simple text at the last element in div \",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"third-level-div\": \"fr great grandchild text within div\",\n \"second-level-div:div_1\": \"fr great grandchild text within div without id\",\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items:li\": \"fr line item with id 1\",\n \"line-items:li_1\": \"fr line item with id 2\",\n \"line-items:li_2\": \"fr line item with id 3\",\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \"fr outermost text at the end \"\n}\n",
"/compound-binding-dom-bind.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": [\n \" outermost text at the beginning with compound {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"h1_3\": [\n \"outermost header 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"text_4\": [\n \" outermost text in the middle with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_5\": [\n \"simple text without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_6\": [\n \"simple text without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-1\": [\n \"simple text with id and {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-2\": [\n \"simple text with id and {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span_1\": [\n \"simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:div_2:div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text\": [\n \" simple text as the first element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_1\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_2\": [\n \" simple text in the middle of div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_3\": [\n \"simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:div_4:div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_5\": [\n \" simple text at the last element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span_1\": [\n \"simple text within div 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"third-level-div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"second-level-div:div_1\": [\n \"great grandchild text within div without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li\": [\n \"line item without id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_1\": [\n \"line item without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_2\": [\n \"line item without id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li\": [\n \"line item with id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_1\": [\n \"line item with id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_2\": [\n \"line item with id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"paragraph\": [\n \"A paragraph with {1}, {2}, and {3} is converted to {4}.\",\n \"id\",\n \"{{param1}}\",\n \"{{param2}}\",\n \"<i18n-format>\"\n ],\n \"text_15\": [\n \" outermost text at the end with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ]\n}",
"/compound-binding-element/compound-binding-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": [\n \" outermost text at the beginning with compound {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"h1_3\": [\n \"outermost header 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"text_4\": [\n \" outermost text in the middle with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_5\": [\n \"simple text without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_6\": [\n \"simple text without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-1\": [\n \"simple text with id and {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-2\": [\n \"simple text with id and {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span_1\": [\n \"simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:div_2:div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text\": [\n \" simple text as the first element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_1\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_2\": [\n \" simple text in the middle of div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_3\": [\n \"simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:div_4:div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_5\": [\n \" simple text at the last element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span\": [\n \"simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span_1\": [\n \"simple text within div 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"third-level-div\": [\n \"great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"second-level-div:div_1\": [\n \"great grandchild text within div without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li\": [\n \"line item without id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_1\": [\n \"line item without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_2\": [\n \"line item without id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li\": [\n \"line item with id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_1\": [\n \"line item with id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_2\": [\n \"line item with id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"paragraph\": [\n \"A paragraph with {1}, {2}, and {3} is converted to {4}.\",\n \"id\",\n \"{{param1}}\",\n \"{{param2}}\",\n \"<i18n-format>\"\n ],\n \"text_15\": [\n \" outermost text at the end with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ]\n}",
"/compound-binding-element/locales/compound-binding-element.fr.json": "{\n \"model\": {},\n \"text\": [\n \"fr outermost text at the beginning with compound {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"h1_3\": [\n \"fr outermost header 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"text_4\": [\n \"fr outermost text in the middle with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_5\": [\n \"fr simple text without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_6\": [\n \"fr simple text without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-1\": [\n \"fr simple text with id and {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-2\": [\n \"fr simple text with id and {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span_1\": [\n \"fr simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:div_2:div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text\": [\n \"fr simple text as the first element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_1\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_2\": [\n \"fr simple text in the middle of div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_3\": [\n \"fr simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:div_4:div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_5\": [\n \"fr simple text at the last element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span_1\": [\n \"fr simple text within div 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"third-level-div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"second-level-div:div_1\": [\n \"fr great grandchild text within div without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li\": [\n \"fr line item without id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_1\": [\n \"fr line item without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_2\": [\n \"fr line item without id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li\": [\n \"fr line item with id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_1\": [\n \"fr line item with id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_2\": [\n \"fr line item with id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1}, {2}, and {3} is converted to {4}.\",\n \"fr id\",\n \"{{param1}}\",\n \"{{param2}}\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": [\n \"fr outermost text at the end with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ]\n}\n",
"/edge-case-dom-bind.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": [\n \" name = {1} \",\n \"{{text.name}}\"\n ],\n \"i18n-number_1\": \"1\",\n \"i18n-format_2\": [\n \"{{text.format}}\",\n \"1\"\n ],\n \"i18n-format_3\": [\n \"format\",\n \"\"\n ],\n \"p_8\": [\n \"hello {1}{2} {3} world\",\n \"<br>\",\n \"<span>\",\n \"<span>\"\n ],\n \"p_9\": [\n \"hello{1}world\",\n \"<br>\"\n ],\n \"text_10\": \" hello \",\n \"text_14\": \" world \"\n}",
"/edge-case/advanced-binding-element.json": "{\n \"meta\": {},\n \"model\": {\n \"aria-attributes\": {\n \"title\": \"tooltip text\",\n \"aria-label\": \"aria label text\",\n \"aria-valuetext\": \"aria value text\"\n }\n },\n \"annotated-format\": [\n \"{{tr(status,text.statusMessageFormats)}}\",\n \"{{parameter}}\",\n \"string parameter\"\n ],\n \"span_5\": [\n \"{1} {2}\",\n \"{{text.defaultValue}}\",\n \"{{text.defaultValue}}\"\n ],\n \"statusMessages\": {\n \"ok\": \"healthy status\",\n \"busy\": \"busy status\",\n \"error\": \"error status\",\n \"default\": \"unknown status\"\n },\n \"defaultValue\": \"default value\",\n \"statusMessageFormats\": {\n \"ok\": \"healthy status\",\n \"busy\": \"busy status with {2}\",\n \"error\": \"error status with {1} and {2}\",\n \"default\": \"unknown status\"\n },\n \"nodefault\": {\n \"ok\": \"ok status\"\n }\n}",
"/edge-case/complex-compound-binding-element.json": "{\n \"model\": {},\n \"item-update2:text\": [\n \"updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update2:text_2\": \" xxx \",\n \"item-update2:template_3:span:b\": \"IF CONTENT\",\n \"item-update2:b_4\": \"abc\",\n \"item-update2:template_5:text\": \"IF CONTENT 2\",\n \"item-update2:text_6\": \" hello \",\n \"item-update\": [\n \"updated: {1}, by: \\n {2}\\n xxx\\n {3}\\n {4}\\n {5}\\n hello\\n \\n {6}\\n {7} \",\n \"{{text.updated}}\",\n \" {{item.name}} \",\n \"IF CONTENT\",\n \"abc\",\n \"IF CONTENT 2\",\n \"<template>\",\n \"{{text.updated}}\"\n ],\n \"item-update3:text\": [\n \"updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update3:text_2\": \" xxx \",\n \"item-update3:template_3:b\": \"IF\",\n \"item-update3:template_3:b_1\": \"CONTENT\",\n \"item-update3:b_4\": \"abc\",\n \"item-update3:template_5:text\": \"IF CONTENT 2\",\n \"item-update3:text_6\": \" hello \",\n \"item-update4:text\": [\n \"updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update4:template_1:text\": [\n \" {1} = {2} \",\n \"{{item.name}}\",\n \"{{text.updated}}\"\n ],\n \"item-update4:text_2\": \" xxx \",\n \"item-update4:template_3:b\": \"IF CONTENT\",\n \"item-update4:b_4\": \"abc\",\n \"item-update4:template_5:text\": \"IF CONTENT 2\",\n \"item-update4:text_6\": \" hello \",\n \"paragraph\": [\n \"A paragraph with \\n {1}\\n is converted to \\n {2}. \",\n \"{{item}} \",\n \"<i18n-format>\"\n ],\n \"paragraph2:text\": \"A paragraph with deep \",\n \"paragraph2:text_2\": \" is \",\n \"paragraph2:b_3\": \"not\",\n \"paragraph2:text_4\": \" converted to \",\n \"paragraph2:code_5\": \"<i18n-format>\",\n \"paragraph2:text_6\": \". \",\n \"authors\": [\n {\n \"name\": \"Joe\"\n },\n {\n \"name\": \"Alice\"\n }\n ],\n \"updated\": \"Jan 1st, 2016\",\n \"parameters\": [\n \"parameter 1\",\n \"parameter 2\"\n ]\n}",
"/edge-case/empty-element.json": "{}",
"/edge-case/locales/advanced-binding-element.fr.json": "{\n \"meta\": {},\n \"model\": {\n \"aria-attributes\": {\n \"title\": \"fr tooltip text\",\n \"aria-label\": \"fr aria label text\",\n \"aria-valuetext\": \"fr aria value text\"\n }\n },\n \"annotated-format\": [\n \"{{tr(status,text.statusMessageFormats)}}\",\n \"{{parameter}}\",\n \"fr string parameter\"\n ],\n \"span_5\": [\n \"fr {1} {2}\",\n \"{{text.defaultValue}}\",\n \"{{text.defaultValue}}\"\n ],\n \"statusMessages\": {\n \"ok\": \"fr healthy status\",\n \"busy\": \"fr busy status\",\n \"error\": \"fr error status\",\n \"default\": \"fr unknown status\"\n },\n \"defaultValue\": \"fr default value\",\n \"statusMessageFormats\": {\n \"ok\": \"fr healthy status\",\n \"busy\": \"fr busy status with {2}\",\n \"error\": \"fr error status with {1} and {2}\",\n \"default\": \"fr unknown status\"\n },\n \"nodefault\": {\n \"ok\": \"fr ok status\"\n }\n}",
"/edge-case/locales/complex-compound-binding-element.fr.json": "{\n \"meta\": {},\n \"model\": {},\n \"item-update2:text\": [\n \"fr updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update2:text_2\": \"fr xxx \",\n \"item-update2:template_3:span:b\": \"fr IF CONTENT\",\n \"item-update2:b_4\": \"fr abc\",\n \"item-update2:template_5:text\": \"fr IF CONTENT 2\",\n \"item-update2:text_6\": \"fr hello \",\n \"item-update\": [\n \"fr updated: {1}, by: \\n {2}\\n xxx\\n {3}\\n {4}\\n {5}\\n hello\\n \\n {6}\\n {7} \",\n \"{{text.updated}}\",\n \" {{item.name}} \",\n \"fr IF CONTENT\",\n \"fr abc\",\n \"fr IF CONTENT 2\",\n \"<template>\",\n \"{{text.updated}}\"\n ],\n \"item-update3:text\": [\n \"fr updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update3:text_2\": \"fr xxx \",\n \"item-update3:template_3:b\": \"fr IF\",\n \"item-update3:template_3:b_1\": \"fr CONTENT\",\n \"item-update3:b_4\": \"fr abc\",\n \"item-update3:template_5:text\": \"fr IF CONTENT 2\",\n \"item-update3:text_6\": \"fr hello \",\n \"item-update4:text\": [\n \"fr updated: {1}, by: \",\n \"{{text.updated}}\"\n ],\n \"item-update4:template_1:text\": [\n \"fr {1} = {2} \",\n \"{{item.name}}\",\n \"{{text.updated}}\"\n ],\n \"item-update4:text_2\": \"fr xxx \",\n \"item-update4:template_3:b\": \"fr IF CONTENT\",\n \"item-update4:b_4\": \"fr abc\",\n \"item-update4:template_5:text\": \"fr IF CONTENT 2\",\n \"item-update4:text_6\": \"fr hello \",\n \"paragraph\": [\n \"fr A paragraph with \\n {1}\\n is converted to \\n {2}. \",\n \"{{item}} \",\n \"fr <i18n-format>\"\n ],\n \"paragraph2:text\": \"fr A paragraph with deep \",\n \"paragraph2:text_2\": \"fr is \",\n \"paragraph2:b_3\": \"fr not\",\n \"paragraph2:text_4\": \"fr converted to \",\n \"paragraph2:code_5\": \"fr <i18n-format>\",\n \"paragraph2:text_6\": \"fr . \",\n \"authors\": [\n {\n \"name\": \"fr Joe\"\n },\n {\n \"name\": \"fr Alice\"\n }\n ],\n \"updated\": \"fr Jan 1st, 2016\",\n \"parameters\": [\n \"fr parameter 1\",\n \"fr parameter 2\"\n ]\n}",
"/edge-case/locales/empty-element.fr.json": "{}",
"/fallback-text-element/fallback-text-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"third-level-div\": \"great grandchild text within div\",\n \"second-level-div:div_1\": \"great grandchild text within div without id\",\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items:li\": \"line item with id 1\",\n \"line-items:li_1\": \"line item with id 2\",\n \"line-items:li_2\": \"line item with id 3\",\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/fallback-text-element/locales/fallback-text-element.fr-CA.json": "{\n \"model\": {},\n \"text\": \"fr-CA outermost text at the beginning \",\n \"h1_3\": \"fr-CA outermost header 1\",\n \"text_4\": \"fr-CA outermost text in the middle \",\n \"span_5\": \"fr-CA simple text without id\",\n \"span_6\": \"fr-CA simple text without id 2\",\n \"label-1\": \"fr-CA simple text with id\",\n \"label-2\": \"fr-CA simple text with id 2\",\n \"div_10:span_1\": \"fr-CA simple text within div\",\n \"toplevel-div:span\": \"fr-CA simple text within div\",\n \"toplevel-div:span_1\": \"fr-CA simple text within div 2\",\n \"third-level-div\": \"fr-CA great grandchild text within div\",\n \"second-level-div:div_1\": \"fr-CA great grandchild text within div without id\",\n \"p_13\": [\n \"fr-CA A paragraph with {1} is converted to {2}.\",\n \"fr-CA parameters\",\n \"fr-CA <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr-CA A paragraph with {1} is converted to {2}.\",\n \"fr-CA id\",\n \"fr-CA <i18n-format>\"\n ],\n \"text_15\": \"fr-CA outermost text at the end \"\n}\n",
"/fallback-text-element/locales/fallback-text-element.fr.json": "{\n \"model\": {},\n \"text\": \"fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \"fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"third-level-div\": \"fr great grandchild text within div\",\n \"second-level-div:div_1\": \"fr great grandchild text within div without id\",\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items:li\": \"fr line item with id 1\",\n \"line-items:li_1\": \"fr line item with id 2\",\n \"line-items:li_2\": \"fr line item with id 3\",\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \"fr outermost text at the end \"\n}\n",
"/locales/compound-binding-dom-bind.fr.json": "{\n \"model\": {},\n \"text\": [\n \"fr outermost text at the beginning with compound {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"h1_3\": [\n \"fr outermost header 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"text_4\": [\n \"fr outermost text in the middle with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_5\": [\n \"fr simple text without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"span_6\": [\n \"fr simple text without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-1\": [\n \"fr simple text with id and {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"label-2\": [\n \"fr simple text with id and {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:span_1\": [\n \"fr simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_9:div_2:div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text\": [\n \"fr simple text as the first element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_1\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_2\": [\n \"fr simple text in the middle of div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:span_3\": [\n \"fr simple text within div with {1} and {2} variables 2\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:div_4:div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_10:text_5\": [\n \"fr simple text at the last element in div with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span\": [\n \"fr simple text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"toplevel-div:span_1\": [\n \"fr simple text within div 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"third-level-div\": [\n \"fr great grandchild text within div with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"second-level-div:div_1\": [\n \"fr great grandchild text within div without id with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li\": [\n \"fr line item without id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_1\": [\n \"fr line item without id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"div_12:ul:li_2\": [\n \"fr line item without id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li\": [\n \"fr line item with id 1 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_1\": [\n \"fr line item with id 2 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"line-items:li_2\": [\n \"fr line item with id 3 with {1} and {2} variables\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"{{param1}}\",\n \"{{param2}}\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1}, {2}, and {3} is converted to {4}.\",\n \"fr id\",\n \"{{param1}}\",\n \"{{param2}}\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": [\n \"fr outermost text at the end with {1} and {2} variables \",\n \"{{param1}}\",\n \"{{param2}}\"\n ]\n}\n",
"/locales/simple-attribute-dom-bind.fr.json": "{\n \"model\": {\n \"standard-input\": {\n \"placeholder\": \"fr standard HTML5 attribute\"\n },\n \"outer-div:input_2\": {\n \"placeholder\": \"fr standard HTML5 attribute without id\"\n },\n \"paper-input-element\": {\n \"label\": \"fr paper-input label\",\n \"error-message\": \"fr paper-input error message\",\n \"placeholder\": \"fr paper-input placeholder\"\n },\n \"outer-div:paper-input_4\": {\n \"label\": \"fr paper-input label without id\",\n \"error-message\": \"fr paper-input error message without id\",\n \"placeholder\": \"fr paper-input placeholder without id\"\n },\n \"pie-chart\": {\n \"options\": {\n \"title\": \"fr Distribution of days in 2001H1\"\n },\n \"cols\": [\n {\n \"label\": \"fr Month\",\n \"type\": \"string\"\n },\n {\n \"label\": \"fr Days\",\n \"type\": \"number\"\n }\n ],\n \"rows\": [\n [\n \"fr Jan\",\n 31\n ],\n [\n \"fr Feb\",\n 28\n ],\n [\n \"fr Mar\",\n 31\n ],\n [\n \"fr Apr\",\n 30\n ],\n [\n \"fr May\",\n 31\n ],\n [\n \"fr Jun\",\n 30\n ]\n ]\n },\n \"column-chart\": {\n \"options\": {\n \"title\": \"fr Inventory\"\n },\n \"data\": [\n [\n \"fr Year\",\n \"fr Things\",\n \"fr Stuff\"\n ],\n [\n \"2004\",\n 1000,\n 400\n ],\n [\n \"2005\",\n 1170,\n 460\n ],\n [\n \"2006\",\n 660,\n 1120\n ],\n [\n \"2007\",\n 1030,\n 540\n ]\n ]\n },\n \"custom-attr\": {\n \"custom-text-attr1\": \"fr custom text attribute 1\",\n \"custom-text-attr2\": \"fr custom text attribute 2\",\n \"custom-text-attr3\": \"fr custom text attribute 3\"\n },\n \"selective-attr\": {\n \"custom-text-attr4\": [\n \"fr {1} custom-text-attr4 attribute with param {2} and param {3} {4}\",\n \"{{text.ordinary-div}}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\",\n \"{{text.ordinary-div}}\"\n ],\n \"custom-text-attr5\": [\n \"[[text.ordinary-div]]\",\n \"fr custom-text-attr5 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \"fr and param \",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target\": [\n \"fr i18n-target attribute with param {1} and param {2}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target2\": [\n \"fr i18n-target2 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \"fr and param \",\n \"[[text.ordinary-div]]\"\n ]\n },\n \"selective-attr2\": {\n \"i18n-target\": \"fr i18n-target attribute 2\"\n },\n \"selective-attr3\": {\n \"i18n-target6\": \"fr i18n-target6 attribute 2\"\n },\n \"selective-attr4\": {\n \"i18n-target6\": \"fr i18n-target6 attribute 3\"\n },\n \"json-data-id\": {\n \"attr1\": \"fr this attr1 is extracted\",\n \"i18n-target-attr\": \"fr this attribute is also extracted\"\n },\n \"template_2:json-data_1\": {\n \"attr1\": \"fr this attr1 without id is extracted\",\n \"i18n-target-attr\": \"fr this attribute without id is also extracted\"\n }\n },\n \"ordinary-div\": \"fr text 1\"\n}\n",
"/locales/simple-text-dom-bind.fr.json": "{\n \"model\": {},\n \"text\": \"fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \"fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"div_9:span\": \"fr simple text within div\",\n \"div_9:span_1\": \"fr simple text within div 2\",\n \"div_9:div_2:div\": \"fr great grandchild text within div\",\n \"div_10:text\": \"fr simple text as the first element in div \",\n \"div_10:span_1\": \"fr simple text within div\",\n \"div_10:text_2\": \"fr simple text in the middle of div \",\n \"div_10:span_3\": \"fr simple text within div 2\",\n \"div_10:div_4:div\": \"fr great grandchild text within div\",\n \"div_10:text_5\": \"fr simple text at the last element in div \",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"third-level-div\": \"fr great grandchild text within div\",\n \"second-level-div:div_1\": \"fr great grandchild text within div without id\",\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items:li\": \"fr line item with id 1\",\n \"line-items:li_1\": \"fr line item with id 2\",\n \"line-items:li_2\": \"fr line item with id 3\",\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \"fr outermost text at the end \"\n}\n",
"/multiple-case/item-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"label\": \"A\"\n}",
"/multiple-case/locales/item-element.fr.json": "{\n \"meta\": {},\n \"model\": {},\n \"label\": \"fr A\"\n}",
"/multiple-case/locales/multiple-element.fr.json": "{\n \"meta\": {},\n \"model\": {}\n}",
"/multiple-case/multiple-element.json": "{\n \"meta\": {},\n \"model\": {}\n}",
"/plural-gender-element/locales/plural-gender-element.fr.json": "{\n \"model\": {},\n \"compound-format-text\": [\n {\n \"0\": \"fr You ({3}) gave no gifts.\",\n \"1\": {\n \"male\": \"fr You ({3}) gave him ({4}) {5}.\",\n \"female\": \"fr You ({3}) gave her ({4}) {5}.\",\n \"other\": \"fr You ({3}) gave them ({4}) {5}.\"\n },\n \"one\": {\n \"male\": \"fr You ({3}) gave him ({4}) and one other person {5}.\",\n \"female\": \"fr You ({3}) gave her ({4}) and one other person {5}.\",\n \"other\": \"fr You ({3}) gave them ({4}) and one other person {5}.\"\n },\n \"other\": \"fr You ({3}) gave them ({4}) and {1} other people gifts.\"\n },\n \"{{recipients.length - 1}}\",\n \"{{recipients.0.gender}}\",\n \"{{sender.name}}\",\n \"{{recipients.0.name}}\",\n \"fr a gift\"\n ]\n}\n",
"/plural-gender-element/plural-gender-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"compound-format-text\": [\n {\n \"0\": \"You ({3}) gave no gifts.\",\n \"1\": {\n \"male\": \"You ({3}) gave him ({4}) {5}.\",\n \"female\": \"You ({3}) gave her ({4}) {5}.\",\n \"other\": \"You ({3}) gave them ({4}) {5}.\"\n },\n \"one\": {\n \"male\": \"You ({3}) gave him ({4}) and one other person {5}.\",\n \"female\": \"You ({3}) gave her ({4}) and one other person {5}.\",\n \"other\": \"You ({3}) gave them ({4}) and one other person {5}.\"\n },\n \"other\": \"You ({3}) gave them ({4}) and {1} other people gifts.\"\n },\n \"{{recipients.length - 1}}\",\n \"{{recipients.0.gender}}\",\n \"{{sender.name}}\",\n \"{{recipients.0.name}}\",\n \"a gift\"\n ]\n}",
"/preference/preference-element.json": "{\n \"meta\": {},\n \"model\": {}\n}",
"/simple-attribute-dom-bind.json": "{\n \"meta\": {},\n \"model\": {\n \"standard-input\": {\n \"placeholder\": \"standard HTML5 attribute\"\n },\n \"outer-div:input_2\": {\n \"placeholder\": \"standard HTML5 attribute without id\"\n },\n \"paper-input-element\": {\n \"label\": \"paper-input label\",\n \"error-message\": \"paper-input error message\",\n \"placeholder\": \"paper-input placeholder\"\n },\n \"outer-div:paper-input_4\": {\n \"label\": \"paper-input label without id\",\n \"error-message\": \"paper-input error message without id\",\n \"placeholder\": \"paper-input placeholder without id\"\n },\n \"pie-chart\": {\n \"options\": {\n \"title\": \"Distribution of days in 2001H1\"\n },\n \"cols\": [\n {\n \"label\": \"Month\",\n \"type\": \"string\"\n },\n {\n \"label\": \"Days\",\n \"type\": \"number\"\n }\n ],\n \"rows\": [\n [\n \"Jan\",\n 31\n ],\n [\n \"Feb\",\n 28\n ],\n [\n \"Mar\",\n 31\n ],\n [\n \"Apr\",\n 30\n ],\n [\n \"May\",\n 31\n ],\n [\n \"Jun\",\n 30\n ]\n ]\n },\n \"column-chart\": {\n \"options\": {\n \"title\": \"Inventory\"\n },\n \"data\": [\n [\n \"Year\",\n \"Things\",\n \"Stuff\"\n ],\n [\n \"2004\",\n 1000,\n 400\n ],\n [\n \"2005\",\n 1170,\n 460\n ],\n [\n \"2006\",\n 660,\n 1120\n ],\n [\n \"2007\",\n 1030,\n 540\n ]\n ]\n },\n \"custom-attr\": {\n \"custom-text-attr1\": \"custom text attribute 1\",\n \"custom-text-attr2\": \"custom text attribute 2\",\n \"custom-text-attr3\": \"custom text attribute 3\"\n },\n \"selective-attr\": {\n \"custom-text-attr4\": [\n \"{1} custom-text-attr4 attribute with param {2} and param {3} {4}\",\n \"{{text.ordinary-div}}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\",\n \"{{text.ordinary-div}}\"\n ],\n \"custom-text-attr5\": [\n \"[[text.ordinary-div]]\",\n \" custom-text-attr5 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \" and param \",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target\": [\n \"i18n-target attribute with param {1} and param {2}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target2\": [\n \"i18n-target2 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \" and param \",\n \"[[text.ordinary-div]]\"\n ]\n },\n \"selective-attr2\": {\n \"i18n-target\": \"i18n-target attribute 2\"\n },\n \"selective-attr3\": {\n \"i18n-target6\": \"i18n-target6 attribute 2\"\n },\n \"selective-attr4\": {\n \"i18n-target6\": \"i18n-target6 attribute 3\"\n },\n \"json-data-id\": {\n \"attr1\": \"this attr1 is extracted\",\n \"i18n-target-attr\": \"this attribute is also extracted\"\n },\n \"template_2:json-data_1\": {\n \"attr1\": \"this attr1 without id is extracted\",\n \"i18n-target-attr\": \"this attribute without id is also extracted\"\n }\n },\n \"ordinary-div\": \"text 1\"\n}",
"/simple-attribute-element/locales/simple-attribute-element.fr.json": "{\n \"model\": {\n \"standard-input\": {\n \"placeholder\": \"fr standard HTML5 attribute\"\n },\n \"outer-div:input_2\": {\n \"placeholder\": \"fr standard HTML5 attribute without id\"\n },\n \"paper-input-element\": {\n \"label\": \"fr paper-input label\",\n \"error-message\": \"fr paper-input error message\",\n \"placeholder\": \"fr paper-input placeholder\"\n },\n \"outer-div:paper-input_4\": {\n \"label\": \"fr paper-input label without id\",\n \"error-message\": \"fr paper-input error message without id\",\n \"placeholder\": \"fr paper-input placeholder without id\"\n },\n \"pie-chart\": {\n \"options\": {\n \"title\": \"fr Distribution of days in 2001H1\"\n },\n \"cols\": [\n {\n \"label\": \"fr Month\",\n \"type\": \"string\"\n },\n {\n \"label\": \"fr Days\",\n \"type\": \"number\"\n }\n ],\n \"rows\": [\n [\n \"fr Jan\",\n 31\n ],\n [\n \"fr Feb\",\n 28\n ],\n [\n \"fr Mar\",\n 31\n ],\n [\n \"fr Apr\",\n 30\n ],\n [\n \"fr May\",\n 31\n ],\n [\n \"fr Jun\",\n 30\n ]\n ]\n },\n \"column-chart\": {\n \"options\": {\n \"title\": \"fr Inventory\"\n },\n \"data\": [\n [\n \"fr Year\",\n \"fr Things\",\n \"fr Stuff\"\n ],\n [\n \"2004\",\n 1000,\n 400\n ],\n [\n \"2005\",\n 1170,\n 460\n ],\n [\n \"2006\",\n 660,\n 1120\n ],\n [\n \"2007\",\n 1030,\n 540\n ]\n ]\n },\n \"custom-attr\": {\n \"custom-text-attr1\": \"fr custom text attribute 1\",\n \"custom-text-attr2\": \"fr custom text attribute 2\",\n \"custom-text-attr3\": \"fr custom text attribute 3\"\n },\n \"selective-attr\": {\n \"custom-text-attr4\": [\n \"fr {1} custom-text-attr4 attribute with param {2} and param {3} {4}\",\n \"{{text.ordinary-div}}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\",\n \"{{text.ordinary-div}}\"\n ],\n \"custom-text-attr5\": [\n \"[[text.ordinary-div]]\",\n \"fr custom-text-attr5 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \"fr and param \",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target\": [\n \"fr i18n-target attribute with param {1} and param {2}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target2\": [\n \"fr i18n-target2 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \"fr and param \",\n \"[[text.ordinary-div]]\"\n ]\n },\n \"selective-attr2\": {\n \"i18n-target\": \"fr i18n-target attribute 2\"\n },\n \"selective-attr3\": {\n \"i18n-target6\": \"fr i18n-target6 attribute 2\"\n },\n \"selective-attr4\": {\n \"i18n-target6\": \"fr i18n-target6 attribute 3\"\n },\n \"json-data-id\": {\n \"attr1\": \"fr this attr1 is extracted\",\n \"i18n-target-attr\": \"fr this attribute is also extracted\"\n },\n \"template_2:json-data_1\": {\n \"attr1\": \"fr this attr1 without id is extracted\",\n \"i18n-target-attr\": \"fr this attribute without id is also extracted\"\n }\n },\n \"ordinary-div\": \"fr text 1\"\n}\n",
"/simple-attribute-element/locales/text-attribute-element.fr.json": "{\n \"meta\": {},\n \"model\": {},\n \"span_4\": \"fr text\"\n}\n",
"/simple-attribute-element/simple-attribute-element.json": "{\n \"meta\": {},\n \"model\": {\n \"standard-input\": {\n \"placeholder\": \"standard HTML5 attribute\"\n },\n \"outer-div:input_2\": {\n \"placeholder\": \"standard HTML5 attribute without id\"\n },\n \"paper-input-element\": {\n \"label\": \"paper-input label\",\n \"error-message\": \"paper-input error message\",\n \"placeholder\": \"paper-input placeholder\"\n },\n \"outer-div:paper-input_4\": {\n \"label\": \"paper-input label without id\",\n \"error-message\": \"paper-input error message without id\",\n \"placeholder\": \"paper-input placeholder without id\"\n },\n \"pie-chart\": {\n \"options\": {\n \"title\": \"Distribution of days in 2001H1\"\n },\n \"cols\": [\n {\n \"label\": \"Month\",\n \"type\": \"string\"\n },\n {\n \"label\": \"Days\",\n \"type\": \"number\"\n }\n ],\n \"rows\": [\n [\n \"Jan\",\n 31\n ],\n [\n \"Feb\",\n 28\n ],\n [\n \"Mar\",\n 31\n ],\n [\n \"Apr\",\n 30\n ],\n [\n \"May\",\n 31\n ],\n [\n \"Jun\",\n 30\n ]\n ]\n },\n \"column-chart\": {\n \"options\": {\n \"title\": \"Inventory\"\n },\n \"data\": [\n [\n \"Year\",\n \"Things\",\n \"Stuff\"\n ],\n [\n \"2004\",\n 1000,\n 400\n ],\n [\n \"2005\",\n 1170,\n 460\n ],\n [\n \"2006\",\n 660,\n 1120\n ],\n [\n \"2007\",\n 1030,\n 540\n ]\n ]\n },\n \"custom-attr\": {\n \"custom-text-attr1\": \"custom text attribute 1\",\n \"custom-text-attr2\": \"custom text attribute 2\",\n \"custom-text-attr3\": \"custom text attribute 3\"\n },\n \"selective-attr\": {\n \"custom-text-attr4\": [\n \"{1} custom-text-attr4 attribute with param {2} and param {3} {4}\",\n \"{{text.ordinary-div}}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\",\n \"{{text.ordinary-div}}\"\n ],\n \"custom-text-attr5\": [\n \"[[text.ordinary-div]]\",\n \" custom-text-attr5 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \" and param \",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target\": [\n \"i18n-target attribute with param {1} and param {2}\",\n \"{{text.ordinary-div}}\",\n \"[[text.ordinary-div]]\"\n ],\n \"i18n-target2\": [\n \"i18n-target2 attribute with param \",\n \"{{or('',text.ordinary-div)}}\",\n \" and param \",\n \"[[text.ordinary-div]]\"\n ]\n },\n \"selective-attr2\": {\n \"i18n-target\": \"i18n-target attribute 2\"\n },\n \"selective-attr3\": {\n \"i18n-target6\": \"i18n-target6 attribute 2\"\n },\n \"selective-attr4\": {\n \"i18n-target6\": \"i18n-target6 attribute 3\"\n },\n \"json-data-id\": {\n \"attr1\": \"this attr1 is extracted\",\n \"i18n-target-attr\": \"this attribute is also extracted\"\n },\n \"template_2:json-data_1\": {\n \"attr1\": \"this attr1 without id is extracted\",\n \"i18n-target-attr\": \"this attribute without id is also extracted\"\n }\n },\n \"ordinary-div\": \"text 1\"\n}",
"/simple-attribute-element/text-attribute-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"span_4\": \"text\"\n}",
"/simple-text-dom-bind.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"third-level-div\": \"great grandchild text within div\",\n \"second-level-div:div_1\": \"great grandchild text within div without id\",\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items:li\": \"line item with id 1\",\n \"line-items:li_1\": \"line item with id 2\",\n \"line-items:li_2\": \"line item with id 3\",\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/simple-text-element/locales/simple-text-element.fr.json": "{\n \"model\": {},\n \"text\": \"fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \"fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"div_9:span\": \"fr simple text within div\",\n \"div_9:span_1\": \"fr simple text within div 2\",\n \"div_9:div_2:div\": \"fr great grandchild text within div\",\n \"div_10:text\": \"fr simple text as the first element in div \",\n \"div_10:span_1\": \"fr simple text within div\",\n \"div_10:text_2\": \"fr simple text in the middle of div \",\n \"div_10:span_3\": \"fr simple text within div 2\",\n \"div_10:div_4:div\": \"fr great grandchild text within div\",\n \"div_10:text_5\": \"fr simple text at the last element in div \",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"third-level-div\": \"fr great grandchild text within div\",\n \"second-level-div:div_1\": \"fr great grandchild text within div without id\",\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items:li\": \"fr line item with id 1\",\n \"line-items:li_1\": \"fr line item with id 2\",\n \"line-items:li_2\": \"fr line item with id 3\",\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \"fr outermost text at the end \"\n}\n",
"/simple-text-element/locales/simple-text-element.ru.json": "{\n \"model\": {},\n \"text\": \"ru outermost text at the beginning \",\n \"h1_3\": \"ru outermost header 1\",\n \"text_4\": \"ru outermost text in the middle \",\n \"span_5\": \"ru simple text without id\",\n \"span_6\": \"ru simple text without id 2\",\n \"label-1\": \"ru simple text with id\",\n \"label-2\": \"ru simple text with id 2\",\n \"div_9:span\": \"ru simple text within div\",\n \"div_9:span_1\": \"ru simple text within div 2\",\n \"div_9:div_2:div\": \"ru great grandchild text within div\",\n \"div_10:text\": \"ru simple text as the first element in div \",\n \"div_10:span_1\": \"ru simple text within div\",\n \"div_10:text_2\": \"ru simple text in the middle of div \",\n \"div_10:span_3\": \"ru simple text within div 2\",\n \"div_10:div_4:div\": \"ru great grandchild text within div\",\n \"div_10:text_5\": \"ru simple text at the last element in div \",\n \"toplevel-div:span\": \"ru simple text within div\",\n \"toplevel-div:span_1\": \"ru simple text within div 2\",\n \"third-level-div\": \"ru great grandchild text within div\",\n \"second-level-div:div_1\": \"ru great grandchild text within div without id\",\n \"div_12:ul:li\": \"ru line item without id 1\",\n \"div_12:ul:li_1\": \"ru line item without id 2\",\n \"div_12:ul:li_2\": \"ru line item without id 3\",\n \"line-items:li\": \"ru line item with id 1\",\n \"line-items:li_1\": \"ru line item with id 2\",\n \"line-items:li_2\": \"ru line item with id 3\",\n \"p_13\": [\n \"ru A paragraph with {1} is converted to {2}.\",\n \"ru parameters\",\n \"ru <i18n-format>\"\n ],\n \"paragraph\": [\n \"ru A paragraph with {1} is converted to {2}.\",\n \"ru id\",\n \"ru <i18n-format>\"\n ],\n \"text_15\": \"ru outermost text at the end \"\n}\n",
"/simple-text-element/simple-text-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"third-level-div\": \"great grandchild text within div\",\n \"second-level-div:div_1\": \"great grandchild text within div without id\",\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items:li\": \"line item with id 1\",\n \"line-items:li_1\": \"line item with id 2\",\n \"line-items:li_2\": \"line item with id 3\",\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/simple-text-id-element/locales/simple-text-id-element.fr.json": "{\n \"model\": {},\n \"text\": \"fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \"fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"div_9:span\": \"fr simple text within div\",\n \"div_9:span_1\": \"fr simple text within div 2\",\n \"div_9:div_2:div\": \"fr great grandchild text within div\",\n \"div_10:text\": \"fr simple text as the first element in div \",\n \"div_10:span_1\": \"fr simple text within div\",\n \"div_10:text_2\": \"fr simple text in the middle of div \",\n \"div_10:span_3\": \"fr simple text within div 2\",\n \"div_10:div_4:div\": \"fr great grandchild text within div\",\n \"div_10:text_5\": \"fr simple text at the last element in div \",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"second-level-div\": [\n \"fr {1}\\n {2} \",\n \"fr great grandchild text within div\",\n \"fr great grandchild text within div without id\"\n ],\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items\": [\n \"fr {1}\\n {2}\\n {3} \",\n \"fr line item with id 1\",\n \"fr line item with id 2\",\n \"fr line item with id 3\"\n ],\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \"fr outermost text at the end \"\n}\n",
"/simple-text-id-element/simple-text-id-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"second-level-div\": [\n \" {1}\\n {2} \",\n \"great grandchild text within div\",\n \"great grandchild text within div without id\"\n ],\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items\": [\n \" {1}\\n {2}\\n {3} \",\n \"line item with id 1\",\n \"line item with id 2\",\n \"line item with id 3\"\n ],\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/template-default-lang/locales/null-template-default-lang-element.ja.json": "",
"/template-default-lang/locales/null-template-default-lang-element.zh-Hans-CN.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \"zh-Hans-CN outermost text at the beginning \",\n \"h1_3\": \"zh-Hans-CN outermost header 1\",\n \"text_4\": \"zh-Hans-CN outermost text in the middle \",\n \"span_5\": \"zh-Hans-CN simple text without id\",\n \"span_6\": \"zh-Hans-CN simple text without id 2\",\n \"label-1\": \"zh-Hans-CN simple text with id\",\n \"label-2\": \"zh-Hans-CN simple text with id 2\",\n \"div_9:span\": \"zh-Hans-CN simple text within div\",\n \"div_9:span_1\": \"zh-Hans-CN simple text within div 2\",\n \"div_9:div_2:div\": \"zh-Hans-CN great grandchild text within div\",\n \"div_10:text\": \"zh-Hans-CN simple text as the first element in div \",\n \"div_10:span_1\": \"zh-Hans-CN simple text within div\",\n \"div_10:text_2\": \"zh-Hans-CN simple text in the middle of div \",\n \"div_10:span_3\": \"zh-Hans-CN simple text within div 2\",\n \"div_10:div_4:div\": \"zh-Hans-CN great grandchild text within div\",\n \"div_10:text_5\": \"zh-Hans-CN simple text at the last element in div \",\n \"toplevel-div:span\": \"zh-Hans-CN simple text within div\",\n \"toplevel-div:span_1\": \"zh-Hans-CN simple text within div 2\",\n \"third-level-div\": \"zh-Hans-CN great grandchild text within div\",\n \"second-level-div:div_1\": \"zh-Hans-CN great grandchild text within div without id\",\n \"div_12:ul:li\": \"zh-Hans-CN line item without id 1\",\n \"div_12:ul:li_1\": \"zh-Hans-CN line item without id 2\",\n \"div_12:ul:li_2\": \"zh-Hans-CN line item without id 3\",\n \"line-items:li\": \"zh-Hans-CN line item with id 1\",\n \"line-items:li_1\": \"zh-Hans-CN line item with id 2\",\n \"line-items:li_2\": \"zh-Hans-CN line item with id 3\",\n \"p_13\": [\n \"zh-Hans-CN A paragraph with {1} is converted to {2}.\",\n \"zh-Hans-CN parameters\",\n \"zh-Hans-CN <i18n-format>\"\n ],\n \"paragraph\": [\n \"zh-Hans-CN A paragraph with {1} is converted to {2}.\",\n \"zh-Hans-CN id\",\n \"zh-Hans-CN <i18n-format>\"\n ],\n \"text_15\": \"zh-Hans-CN outermost text at the end \"\n}",
"/template-default-lang/locales/template-default-lang-element.zh-Hans-CN.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" zh-Hans-CN outermost text at the beginning \",\n \"h1_3\": \"zh-Hans-CN outermost header 1\",\n \"text_4\": \" zh-Hans-CN outermost text in the middle \",\n \"span_5\": \"zh-Hans-CN simple text without id\",\n \"span_6\": \"zh-Hans-CN simple text without id 2\",\n \"label-1\": \"zh-Hans-CN simple text with id\",\n \"label-2\": \"zh-Hans-CN simple text with id 2\",\n \"div_9:span\": \"zh-Hans-CN simple text within div\",\n \"div_9:span_1\": \"zh-Hans-CN simple text within div 2\",\n \"div_9:div_2:div\": \"zh-Hans-CN great grandchild text within div\",\n \"div_10:text\": \" zh-Hans-CN simple text as the first element in div \",\n \"div_10:span_1\": \"zh-Hans-CN simple text within div\",\n \"div_10:text_2\": \" zh-Hans-CN simple text in the middle of div \",\n \"div_10:span_3\": \"zh-Hans-CN simple text within div 2\",\n \"div_10:div_4:div\": \"zh-Hans-CN great grandchild text within div\",\n \"div_10:text_5\": \" zh-Hans-CN simple text at the last element in div \",\n \"toplevel-div:span\": \"zh-Hans-CN simple text within div\",\n \"toplevel-div:span_1\": \"zh-Hans-CN simple text within div 2\",\n \"third-level-div\": \"zh-Hans-CN great grandchild text within div\",\n \"second-level-div:div_1\": \"zh-Hans-CN great grandchild text within div without id\",\n \"div_12:ul:li\": \"zh-Hans-CN line item without id 1\",\n \"div_12:ul:li_1\": \"zh-Hans-CN line item without id 2\",\n \"div_12:ul:li_2\": \"zh-Hans-CN line item without id 3\",\n \"line-items:li\": \"zh-Hans-CN line item with id 1\",\n \"line-items:li_1\": \"zh-Hans-CN line item with id 2\",\n \"line-items:li_2\": \"zh-Hans-CN line item with id 3\",\n \"p_13\": [\n \"zh-Hans-CN A paragraph with {1} is converted to {2}.\",\n \"zh-Hans-CN parameters\",\n \"zh-Hans-CN <i18n-format>\"\n ],\n \"paragraph\": [\n \"zh-Hans-CN A paragraph with {1} is converted to {2}.\",\n \"zh-Hans-CN id\",\n \"zh-Hans-CN <i18n-format>\"\n ],\n \"text_15\": \" zh-Hans-CN outermost text at the end \"\n}",
"/template-default-lang/null-template-default-lang-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" outermost text at the beginning \",\n \"h1_3\": \"outermost header 1\",\n \"text_4\": \" outermost text in the middle \",\n \"span_5\": \"simple text without id\",\n \"span_6\": \"simple text without id 2\",\n \"label-1\": \"simple text with id\",\n \"label-2\": \"simple text with id 2\",\n \"div_9:span\": \"simple text within div\",\n \"div_9:span_1\": \"simple text within div 2\",\n \"div_9:div_2:div\": \"great grandchild text within div\",\n \"div_10:text\": \" simple text as the first element in div \",\n \"div_10:span_1\": \"simple text within div\",\n \"div_10:text_2\": \" simple text in the middle of div \",\n \"div_10:span_3\": \"simple text within div 2\",\n \"div_10:div_4:div\": \"great grandchild text within div\",\n \"div_10:text_5\": \" simple text at the last element in div \",\n \"toplevel-div:span\": \"simple text within div\",\n \"toplevel-div:span_1\": \"simple text within div 2\",\n \"third-level-div\": \"great grandchild text within div\",\n \"second-level-div:div_1\": \"great grandchild text within div without id\",\n \"div_12:ul:li\": \"line item without id 1\",\n \"div_12:ul:li_1\": \"line item without id 2\",\n \"div_12:ul:li_2\": \"line item without id 3\",\n \"line-items:li\": \"line item with id 1\",\n \"line-items:li_1\": \"line item with id 2\",\n \"line-items:li_2\": \"line item with id 3\",\n \"p_13\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"parameters\",\n \"<i18n-format>\"\n ],\n \"paragraph\": [\n \"A paragraph with {1} is converted to {2}.\",\n \"id\",\n \"<i18n-format>\"\n ],\n \"text_15\": \" outermost text at the end \"\n}",
"/template-default-lang/template-default-lang-element.json": "{\n \"meta\": {},\n \"model\": {},\n \"text\": \" fr outermost text at the beginning \",\n \"h1_3\": \"fr outermost header 1\",\n \"text_4\": \" fr outermost text in the middle \",\n \"span_5\": \"fr simple text without id\",\n \"span_6\": \"fr simple text without id 2\",\n \"label-1\": \"fr simple text with id\",\n \"label-2\": \"fr simple text with id 2\",\n \"div_9:span\": \"fr simple text within div\",\n \"div_9:span_1\": \"fr simple text within div 2\",\n \"div_9:div_2:div\": \"fr great grandchild text within div\",\n \"div_10:text\": \" fr simple text as the first element in div \",\n \"div_10:span_1\": \"fr simple text within div\",\n \"div_10:text_2\": \" fr simple text in the middle of div \",\n \"div_10:span_3\": \"fr simple text within div 2\",\n \"div_10:div_4:div\": \"fr great grandchild text within div\",\n \"div_10:text_5\": \" fr simple text at the last element in div \",\n \"toplevel-div:span\": \"fr simple text within div\",\n \"toplevel-div:span_1\": \"fr simple text within div 2\",\n \"third-level-div\": \"fr great grandchild text within div\",\n \"second-level-div:div_1\": \"fr great grandchild text within div without id\",\n \"div_12:ul:li\": \"fr line item without id 1\",\n \"div_12:ul:li_1\": \"fr line item without id 2\",\n \"div_12:ul:li_2\": \"fr line item without id 3\",\n \"line-items:li\": \"fr line item with id 1\",\n \"line-items:li_1\": \"fr line item with id 2\",\n \"line-items:li_2\": \"fr line item with id 3\",\n \"p_13\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr parameters\",\n \"fr <i18n-format>\"\n ],\n \"paragraph\": [\n \"fr A paragraph with {1} is converted to {2}.\",\n \"fr id\",\n \"fr <i18n-format>\"\n ],\n \"text_15\": \" fr outermost text at the end \"\n}"
};
</script>
<script type="module">
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
/*!
* @license https://github.com/t2ym/i18n-behavior/blob/master/LICENSE.md
* Copyright (c) 2016, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
*/
if (!Number.isNaN) {
// polyfill Number.isNaN for IE11
Number.isNaN = function (value) {
return typeof value === 'number' && isNaN(value);
};
}
// Inheritance of test parameters
var p = Object.setPrototypeOf || function (target, base) {
var obj = Object.create(base);
for (var p in target) {
obj[p] = target[p];
}
return obj;
};
var g = Object.getPrototypeOf;
var _name = 'suite';
var suiteMap = { null: {} };
var s = function (name, baseName, extension) {
if (suiteMap[name]) {
throw new Error('duplicate suite name ' + name);
}
if (!suiteMap[baseName]) {
throw new Error('inexistent base suite name ' + baseName);
}
extension[_name] = name;
extension = p(extension, suiteMap[baseName]);
suiteMap[name] = extension;
return extension;
};
// Utility functions
function updateProperty (element, properties) {
for (var name in properties) {
var path = name.split(/[.]/);
if (path.length === 1) {
element[name] = properties[name];
}
else {
var cursor = element;
var p = path.shift();
while (p) {
if (path.length < 1) {
cursor[p] = properties[name];
element.notifyPath(name, properties[name], true);
break;
}
else if (p === 'PolymerDom') {
cursor = dom(cursor);
}
else if (p === 'html') {
cursor = document.querySelector('html');
}
else {
cursor = cursor[p];
}
p = path.shift();
}
}
}
}
function getProperty (target, name) {
var path = name.split(/[.]/);
if (path.length === 1) {
return target[name];
}
else {
var cursor = target;
var p = path.shift();
while (p) {
//console.log(p, cursor);
if (path.length < 1) {
if (p === 'raw' ||
p === 'text') {
return cursor;
}
else if (p === 'trim') {
return cursor.trim();
}
if (p === 'data') {
cursor = cursor[p];
cursor = cursor.replace(/^[\s]{1,}/g, ' ').replace(/[\s]{1,}$/g, ' ');
return cursor;
}
else {
return cursor[p];
}
}
else if (p === 'PolymerDom') {
cursor = dom(cursor);
}
else if (p === 'previousTextSibling') {
do {
cursor = cursor.previousSibling;
} while (cursor.nodeType === cursor.COMMENT_NODE ||
(cursor.nodeType === cursor.TEXT_NODE && cursor.data.match(/^[\s]*$/)));
}
else if (p === 'nextTextSibling') {
do {
cursor = cursor.nextSibling;
} while (cursor.nodeType === cursor.COMMENT_NODE ||
(cursor.nodeType === cursor.TEXT_NODE && cursor.data.match(/^[\s]*$/)));
}
else if (p === 'effectiveChildNodes') {
cursor = cursor.getEffectiveChildNodes();
}
else if (p === 'nonWS') {
cursor = Array.prototype.filter.call(cursor, function (item) {
return (item.nodeType !== item.TEXT_NODE &&
item.nodeType !== item.COMMENT_NODE) ||
(item.nodeType === item.TEXT_NODE &&
!item.data.match(/^[\s]*$/));
});
}
else {
cursor = cursor[p];
}
p = path.shift();
}
}
}
function deepMap (target, source, map) {
var value;
for (var prop in source) {
value = source[prop];
switch (typeof value) {
case 'string':
case 'number':
case 'boolean':
if (typeof target === 'object') {
target[prop] = map(value, prop);
}
break;
case 'object':
if (typeof target === 'object') {
if (Array.isArray(value)) {
target[prop] = target[prop] || [];
deepMap(target[prop], value, map);
}
else {
target[prop] = target[prop] || {};
deepMap(target[prop], value, map);
}
}
break;
case 'function':
case 'symbol':
case 'undefined':
if (typeof target === 'object') {
target[prop] = value;
}
break;
default:
if (typeof target === 'object') {
target[prop] = value;
}
break;
}
}
}
function translate (lang, path, text) {
var result;
switch (lang) {
case '':
case 'en':
case null:
case undefined:
result = text;
break;
default:
if (!path || path.match(/(textContent|[.]data|[.]text|[.]trim)$/)) {
result = {};
deepMap(result, { text: text }, function (value, prop) {
if (typeof value === 'string' &&
!value.match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/) &&
!value.match(/^[0-9]{1,}$/) &&
prop !== 'type') {
return path && path.match(/[.]trim$/) ? (lang + ' ' + value).trim() : lang + ' ' + value;
}
return value;
});
result = result.text;
}
else {
result = text;
}
}
//console.log('translate (' + lang + ', ' + path + ', ' + JSON.stringify(text, null, 2) + ') = ' + JSON.stringify(result, null, 2));
return result;
}
function minifyText (text) {
if (text && typeof text === 'string') {
text = text.replace(/[\s]{1,}/g, ' ');
}
return text;
}
var isFakeServer = typeof window === 'object' &&
typeof window.location.href === 'string' &&
window.location.href.indexOf('xhr=fake') > 0 &&
typeof window.fakeServerContents === 'object';
var isSuppressingSuiteParams = typeof window === 'object' &&
typeof window.location.href === 'string' &&
window.location.href.indexOf('suppress=true') > 0;
function setupFakeServer (e) {
if (isFakeServer) {
e.server = sinon.fakeServer.create();
e.server.autoRespond = true;
//e.server.autoRespondAfter = 100;
e.server.respondImmediately = true;
e.server.respondWith(/\/test\/[-\w]+(\/.*[.]json)$/, function (xhr, urlPath) {
if (fakeServerContents.hasOwnProperty(urlPath)) {
//console.log('fake-server: 200 ' + urlPath);
xhr.respond(200, { 'Content-Type': 'application/json' }, fakeServerContents[urlPath])
}
else {
//console.log('fake-server: 404 ' + urlPath);
xhr.respond(404, {}, '');
}
});
}
}
function teardownFakeServer (e) {
if (isFakeServer) {
e.server.restore();
}
}
function setupFixture (params, fixtureModel) {
var fixtureName = params.fixture;
var e = document.querySelector('#' + fixtureName);
var runningTest = document.querySelectorAll('.running-test');
var title = document.querySelector('#test-name');
var currentPath = window.location.pathname.split('/');
if (!e) {
throw new Error('Fixture element with id = ' + fixtureName + ' not found');
}
if (title) {
title.textContent =
(currentPath.length >= 2 ? currentPath[currentPath.length - 2] : '') +
(currentPath.length >= 1 ? '/' + currentPath[currentPath.length - 1].replace(/-test[.]html$/, '') + '/': '') +
params.suite;
}
//console.log('setupFixture: suite = ' + params.suite);
if (e.is === 'i18n-dom-bind') {
e.parentElement.classList.add('running-test');
Array.prototype.forEach.call(runningTest, function (node) {
if (node !== e.parentElement) {
node.classList.remove('running-test');
}
});
return new Promise(function (resolve, reject) {
e.addEventListener('dom-change', function setupFixtureDomChange (ev) {
if (dom(ev).rootTarget === e) {
//console.log('setupFixture dom-change');
e.removeEventListener('dom-change', setupFixtureDomChange);
try {
if (fixtureModel &&
typeof fixtureModel.lang === 'string' &&
fixtureModel.lang !== 'en') {
//console.log('setupFixture: waiting for lang-updated');
e.addEventListener('lang-updated', function setupFixtureLangDomChange (event) {
//console.log('setupFixtureLangDomChange');
if (event.target === e &&
e.effectiveLang === fixtureModel.lang) {
//console.log('setupFixtureLangDomChange lang = ' + event.detail.lang + ' effectiveLang = ' + e.effectiveLang);
e.removeEventListener('lang-updated', setupFixtureLangDomChange);
e.render();
resolve(e);
}
});
for (var p in fixtureModel) {
e[p] = fixtureModel[p];
}
e.params = params;
}
else {
for (var p in fixtureModel) {
e[p] = fixtureModel[p];
}
e.params = params;
//console.log('setupFixture: resolving');
e.render();
resolve(e);
}
}
catch (ex) {
reject(ex);
}
}
});
if (e._children) {
e.render();
}
});
}
else {
e.classList.add('running-test');
Array.prototype.forEach.call(runningTest, function (node) {
if (node !== e) {
node.classList.remove('running-test');
}
});
setupFakeServer(e);
return new Promise(function (resolve, reject) {
//console.log('setupFixture: name = ' + fixtureName + ' model = ' + JSON.stringify(fixtureModel, null, 2));
var element = fixture(fixtureName, fixtureModel);
//console.log('setupFixture: name = ' + fixtureName +
// ' element.lang = ' + element.lang +
// ' getAttribute("lang") = ' + element.getAttribute('lang') +
// ' element._lang = ' + element._lang);
if (element) {
if (fixtureModel &&
typeof fixtureModel.lang === 'string' &&
fixtureModel.lang !== 'en' &&
fixtureModel.lang !== element.effectiveLang) {
//console.log('setupFixture: waiting for lang-updated');
element.addEventListener('lang-updated', function setupFixtureLangUpdated (event) {
//console.log('setupFixtureLangUpdated');
if (event.target === element &&
element.effectiveLang === fixtureModel.lang) {
//console.log('setupFixtureLangUpdated lang = ' + event.detail.lang + ' effectiveLang = ' + element.effectiveLang);
element.removeEventListener('lang-updated', setupFixtureLangUpdated);
resolve(element);
}
});
}
else {
//console.log('setupFixture: element ready without lang-updated');
resolve(element);
}
}
else {
reject(new Error('setupFixture returns null for ' +
fixtureName + ' ' + JSON.stringify(fixtureModel,null,2)));
}
});
}
}
function restoreFixture (fixtureName) {
var e = document.querySelector('#' + fixtureName);
if (!e) {
throw new Error('Fixture element with id = ' + fixtureName + ' not found');
}
if (e.is === 'i18n-dom-bind') {
if (e._intervalId) {
clearInterval(e._intervalId);
}
Array.prototype.forEach.call(document.querySelectorAll('[is="i18n-dom-bind"]'),
function (node) {
node.observeHtmlLang = true;
}
);
}
else {
teardownFakeServer(e);
e.restore();
}
}
function getLocalDomRoot (e) {
if (e.is === 'i18n-dom-bind') {
return e.parentElement;
}
else if (e) {
return e.root;
}
else {
return null;
}
}
function suitesRunner (suites) {
suites.forEach(function (params) {
suite(params.suite, function () {
var el;
var p;
var n;
var i, j;
var expected;
var results;
var node;
var rawValue = params.rawValue;
var fixtureElement;
var noProperties;
var lang = params.assign && params.assign.lang ? params.assign.lang : 'en';
var event = params.event ? params.event : 'lang-updated';
var defTimeout = 300000;
var timeout = params.timeout ? (params.timeout < defTimeout ? defTimeout : params.timeout) : defTimeout;
this.timeout(timeout);
(params.setup ? setup : suiteSetup)(function () {
return setupFixture(params, params.fixtureModel)
.then(function (element) {
el = element;
//console.log('setup: element.lang = ' + element.lang);
return new Promise(function (resolve, reject) {
//console.log(params.suite, 'waiting for ' + event);
if (params &&
(params.event ||
params.assign && (params.assign.lang || params.assign['html.lang']))) {
el.addEventListener(event, function fixtureSetup (e) {
if (el === dom(e).rootTarget &&
el.lang === params.lang &&
el.effectiveLang === params.effectiveLang) {
el.removeEventListener(event, fixtureSetup);
//console.log('setup: updateProperty resolving on ' + event);
resolve(el);
}
else {
console.log(params.suite + ' skipping uninteresting event ' + event +
' "' + el.lang + '" "' + params.lang + '" "' + el.effectiveLang + '" "' + params.effectiveLang + '"');
}
});
//console.log('setup: updateProperty ' + JSON.stringify(params.assign, null, 2));
updateProperty(el, params.assign);
}
else {
//console.log('setup: updateProperty ' + JSON.stringify(params.assign, null, 2));
//console.log('setup: updateProperty resolving without ' + event);
updateProperty(el, params.assign);
resolve(el);
}
});
}, function (error) {
throw new Error(error);
});
});
test('{lang, effectiveLang, templateDefaultLang, observeHtmlLang' +
(params.text ? ', text' : '') +
(params.model ? ', model' : '') +
(params.localDOM ? ', local DOM' : '') +
'} properties are set as {' +
(isSuppressingSuiteParams ? '' :
[ params.lang, params.effectiveLang, params.templateDefaultLang, params.observeHtmlLang].join(', ') +
(params.text ? ', ' + JSON.stringify(params.text, null, 2) : '') +
(params.model ? ', ' + JSON.stringify(params.model, null, 2) : '') +
(!params.setup && params.localDOM ? ', ' + JSON.stringify(params.localDOM, null, 2) : '')) +
'}' +
(params.assign && params.assign.lang ? ' for ' + params.assign.lang : ''), function () {
assert.isString(el.lang, 'lang property is a string');
assert.equal(el.lang, params.lang, 'lang property is set');
assert.isString(el.effectiveLang, 'effectiveLang property is a string');
assert.equal(el.effectiveLang, params.effectiveLang, 'effectiveLang property is set');
assert.isString(el.templateDefaultLang, 'templateDefaultLang property is a string');
assert.equal(el.templateDefaultLang, params.templateDefaultLang, 'templateDefaultLang property is set');
assert.isBoolean(el.observeHtmlLang, 'observeHtmlLang property is a Boolean');
assert.equal(el.observeHtmlLang, params.observeHtmlLang, 'observeHtmlLang property is set');
if (params.text) {
expected = deepMap(deepcopy(params.text), params.text, minifyText);
noProperties = true;
assert.isObject(el.text, 'text property is an object');
//console.log(JSON.stringify(e.detail, null, 2));
//console.log(JSON.stringify(el.text, null, 2));
for (p in expected) {
noProperties = false;
assert.deepEqual(deepMap(deepcopy(el.text[p]), el.text[p], minifyText),
params.rawText ? expected[p] : translate(params.effectiveLang, null, expected[p]),
'text.' + p + ' property is set for ' + params.effectiveLang);
}
if (noProperties) {
assert.deepEqual(deepMap(deepcopy(el.text), el.text, minifyText),
expected,
'text property is set');
}
}
if (params.model) {
noProperties = true;
assert.isObject(el.model, 'model property is an object');
for (p in params.model) {
noProperties = false;
//console.log('model.' + p + ' = ' + JSON.stringify(el.model[p]));
//console.log('expected model.' + p + ' = ' + JSON.stringify(translate(el.effectiveLang, null, params.model[p])));
assert.deepEqual(el.model[p],
params.rawText ? params.model[p] : translate(params.effectiveLang, null, params.model[p]),
'model.' + p + ' property is set for ' + params.effectiveLang);
}
if (noProperties) {
assert.deepEqual(el.model, params.model, 'model property is set');
}
}
if (!params.setup && params.localDOM) {
params.localDOM.forEach(function (childPath) {
var completeStatus;
var nodes = dom(getLocalDomRoot(el)).querySelectorAll(childPath.select);
assert.ok(nodes.length > 0, childPath.select + ' is defined');
for (var p in childPath) {
if (p === 'select') {
continue;
}
//console.log(p + ' is set as ' + childPath[p]);
if (Array.isArray(childPath[p])) {
//console.log(nodes);
Array.prototype.forEach.call(childPath[p], function (path, i, a) {
assert.equal(minifyText(getProperty(nodes[i], p)),
minifyText(params.rawText ? path : translate(params.effectiveLang, p, path)),
p + ' is set as ' + minifyText(params.rawText ? path : translate(params.effectiveLang, p, path)));
});
}
else {
//console.log(nodes[0]);
assert.equal(minifyText(getProperty(nodes[0], p)),
minifyText(params.rawText ? childPath[p] : translate(params.effectiveLang, p, childPath[p])),
p + ' is set as ' + translate(params.rawText ? childPath[p] : params.effectiveLang, p, childPath[p]));
}
}
//console.log(childPath);
});
}
});
/*
if (params.text) {
test('text' + ' property is set as ' + JSON.stringify(params.text,null,2) +
(params.assign && params.assign.lang ? ' for ' + params.assign.lang : ''), function () {
expected = deepMap(deepcopy(params.text), params.text, minifyText);
noProperties = true;
assert.isObject(el.text, 'text property is an object');
//console.log(JSON.stringify(e.detail, null, 2));
//console.log(JSON.stringify(el.text, null, 2));
for (p in expected) {
noProperties = false;
assert.deepEqual(deepMap(deepcopy(el.text[p]), el.text[p], minifyText),
params.rawText ? expected[p] : translate(params.effectiveLang, null, expected[p]),
'text.' + p + ' property is set for ' + params.effectiveLang);
}
if (noProperties) {
assert.deepEqual(deepMap(deepcopy(el.text), el.text, minifyText),
expected,
'text property is set');
}
});
}
if (params.model) {
test('model' + ' property is set as ' + JSON.stringify(params.model,null,2) +
(params.assign && params.assign.lang ? ' for ' + params.assign.lang : ''), function () {
noProperties = true;
assert.isObject(el.model, 'model property is an object');
for (p in params.model) {
noProperties = false;
//console.log('model.' + p + ' = ' + JSON.stringify(el.model[p]));
//console.log('expected model.' + p + ' = ' + JSON.stringify(translate(el.effectiveLang, null, params.model[p])));
assert.deepEqual(el.model[p],
params.rawText ? params.model[p] : translate(params.effectiveLang, null, params.model[p]),
'model.' + p + ' property is set for ' + params.effectiveLang);
}
if (noProperties) {
assert.deepEqual(el.model, params.model, 'model property is set');
}
});
}
*/
if (params.setup && params.localDOM) {
test('local DOM ' + (isSuppressingSuiteParams ? '{}' : JSON.stringify(params.localDOM, null, 2)) + ' is set' +
(params.assign && params.assign.lang ? ' for ' + params.assign.lang : ''), function () {
params.localDOM.forEach(function (childPath) {
var completeStatus;
var nodes = dom(getLocalDomRoot(el)).querySelectorAll(childPath.select);
assert.ok(nodes.length > 0, childPath.select + ' is defined');
for (var p in childPath) {
if (p === 'select') {
continue;
}
//console.log(p + ' is set as ' + childPath[p]);
if (Array.isArray(childPath[p])) {
//console.log(nodes);
Array.prototype.forEach.call(childPath[p], function (path, i, a) {
assert.equal(minifyText(getProperty(nodes[i], p)),
minifyText(params.rawText ? path : translate(params.effectiveLang, p, path)),
p + ' is set as ' + minifyText(params.rawText ? path : translate(params.effectiveLang, p, path)));
});
}
else {
//console.log(nodes[0]);
assert.equal(minifyText(getProperty(nodes[0], p)),
minifyText(params.rawText ? childPath[p] : translate(params.effectiveLang, p, childPath[p])),
p + ' is set as ' + translate(params.rawText ? childPath[p] : params.effectiveLang, p, childPath[p]));
}
}
//console.log(childPath);
});
});
}
if (params.lightDOM) {
test('light DOM ' + (isSuppressingSuiteParams ? '{}' : JSON.stringify(params.lightDOM, null, 2)) + ' is set' +
(params.assign && params.assign.lang ? ' for ' + params.assign.lang : ''), function () {
params.lightDOM.forEach(function (childPath) {
var completeStatus;
var nodes = dom(el).querySelectorAll(childPath.select);
assert.ok(nodes.length > 0, childPath.select + ' is defined');
for (var p in childPath) {
if (p === 'select') {
continue;
}
//console.log(p + ' is set as ' + childPath[p]);
if (Array.isArray(childPath[p])) {
//console.log(nodes);
Array.prototype.forEach.call(childPath[p], function (path, i, a) {
assert.equal(getProperty(nodes[i], p), translate(params.effectiveLang, p, path), p + ' is set as ' + translate(params.effectiveLang, p, path));
});
}
else {
//console.log(nodes[0]);
assert.equal(getProperty(nodes[0], p), translate(params.effectiveLang, p, childPath[p]), p + ' is set as ' + translate(params.effectiveLang, p, childPath[p]));
}
}
//console.log(childPath);
});
});
}
(params.setup ? teardown : suiteTeardown)(function () {
restoreFixture(params.fixture);
});
});
});
}
</script>
<style>
.test-container.running-test {
display: block;
}
.test-container:not(.running-test) {
display: none;
}
</style>
</head>
<body><div hidden="" by-vulcanize=""><script>(function () {
function resolve() {
document.body.removeAttribute('unresolved');
}
if (window.WebComponents) {
addEventListener('WebComponentsReady', resolve);
} else {
if (document.readyState === 'interactive' || document.readyState === 'complete') {
resolve();
} else {
addEventListener('DOMContentLoaded', resolve);
}
}
}());window.Polymer = {
Settings: function () {
var settings = window.Polymer || {};
if (!settings.noUrlSettings) {
var parts = location.search.slice(1).split('&');
for (var i = 0, o; i < parts.length && (o = parts[i]); i++) {
o = o.split('=');
o[0] && (settings[o[0]] = o[1] || true);
}
}
settings.wantShadow = settings.dom === 'shadow';
settings.hasShadow = Boolean(Element.prototype.createShadowRoot);
settings.nativeShadow = settings.hasShadow && !window.ShadowDOMPolyfill;
settings.useShadow = settings.wantShadow && settings.hasShadow;
settings.hasNativeImports = Boolean('import' in document.createElement('link'));
settings.useNativeImports = settings.hasNativeImports;
settings.useNativeCustomElements = !window.CustomElements || window.CustomElements.useNative;
settings.useNativeShadow = settings.useShadow && settings.nativeShadow;
settings.usePolyfillProto = !settings.useNativeCustomElements && !Object.__proto__;
settings.hasNativeCSSProperties = !navigator.userAgent.match('AppleWebKit/601') && window.CSS && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)');
settings.useNativeCSSProperties = settings.hasNativeCSSProperties && settings.lazyRegister && settings.useNativeCSSProperties;
return settings;
}()
};(function () {
var userPolymer = window.Polymer;
window.Polymer = function (prototype) {
if (typeof prototype === 'function') {
prototype = prototype.prototype;
}
if (!prototype) {
prototype = {};
}
var factory = desugar(prototype);
prototype = factory.prototype;
var options = { prototype: prototype };
if (prototype.extends) {
options.extends = prototype.extends;
}
Polymer.telemetry._registrate(prototype);
document.registerElement(prototype.is, options);
return factory;
};
var desugar = function (prototype) {
var base = Polymer.Base;
if (prototype.extends) {
base = Polymer.Base._getExtendedPrototype(prototype.extends);
}
prototype = Polymer.Base.chainObject(prototype, base);
prototype.registerCallback();
return prototype.constructor;
};
if (userPolymer) {
for (var i in userPolymer) {
Polymer[i] = userPolymer[i];
}
}
Polymer.Class = desugar;
}());
Polymer.telemetry = {
registrations: [],
_regLog: function (prototype) {
console.log('[' + prototype.is + ']: registered');
},
_registrate: function (prototype) {
this.registrations.push(prototype);
Polymer.log && this._regLog(prototype);
},
dumpRegistrations: function () {
this.registrations.forEach(this._regLog);
}
};Object.defineProperty(window, 'currentImport', {
enumerable: true,
configurable: true,
get: function () {
return (document._currentScript || document.currentScript).ownerDocument;
}
});Polymer.RenderStatus = {
_ready: false,
_callbacks: [],
whenReady: function (cb) {
if (this._ready) {
cb();
} else {
this._callbacks.push(cb);
}
},
_makeReady: function () {
this._ready = true;
for (var i = 0; i < this._callbacks.length; i++) {
this._callbacks[i]();
}
this._callbacks = [];
},
_catchFirstRender: function () {
requestAnimationFrame(function () {
Polymer.RenderStatus._makeReady();
});
},
_afterNextRenderQueue: [],
_waitingNextRender: false,
afterNextRender: function (element, fn, args) {
this._watchNextRender();
this._afterNextRenderQueue.push([
element,
fn,
args
]);
},
hasRendered: function () {
return this._ready;
},
_watchNextRender: function () {
if (!this._waitingNextRender) {
this._waitingNextRender = true;
var fn = function () {
Polymer.RenderStatus._flushNextRender();
};
if (!this._ready) {
this.whenReady(fn);
} else {
requestAnimationFrame(fn);
}
}
},
_flushNextRender: function () {
var self = this;
setTimeout(function () {
self._flushRenderCallbacks(self._afterNextRenderQueue);
self._afterNextRenderQueue = [];
self._waitingNextRender = false;
});
},
_flushRenderCallbacks: function (callbacks) {
for (var i = 0, h; i < callbacks.length; i++) {
h = callbacks[i];
h[1].apply(h[0], h[2] || Polymer.nar);
}
}
};
if (window.HTMLImports) {
HTMLImports.whenReady(function () {
Polymer.RenderStatus._catchFirstRender();
});
} else {
Polymer.RenderStatus._catchFirstRender();
}
Polymer.ImportStatus = Polymer.RenderStatus;
Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady;(function () {
'use strict';
var settings = Polymer.Settings;
Polymer.Base = {
__isPolymerInstance__: true,
_addFeature: function (feature) {
this.extend(this, feature);
},
registerCallback: function () {
if (settings.lazyRegister === 'max') {
if (this.beforeRegister) {
this.beforeRegister();
}
} else {
this._desugarBehaviors();
this._doBehavior('beforeRegister');
}
this._registerFeatures();
if (!settings.lazyRegister) {
this.ensureRegisterFinished();
}
},
createdCallback: function () {
if (!this.__hasRegisterFinished) {
this._ensureRegisterFinished(this.__proto__);
}
Polymer.telemetry.instanceCount++;
this.root = this;
this._doBehavior('created');
this._initFeatures();
},
ensureRegisterFinished: function () {
this._ensureRegisterFinished(this);
},
_ensureRegisterFinished: function (proto) {
if (proto.__hasRegisterFinished !== proto.is || !proto.is) {
if (settings.lazyRegister === 'max') {
proto._desugarBehaviors();
proto._doBehaviorOnly('beforeRegister');
}
proto.__hasRegisterFinished = proto.is;
if (proto._finishRegisterFeatures) {
proto._finishRegisterFeatures();
}
proto._doBehavior('registered');
if (settings.usePolyfillProto && proto !== this) {
proto.extend(this, proto);
}
}
},
attachedCallback: function () {
var self = this;
Polymer.RenderStatus.whenReady(function () {
self.isAttached = true;
self._doBehavior('attached');
});
},
detachedCallback: function () {
var self = this;
Polymer.RenderStatus.whenReady(function () {
self.isAttached = false;
self._doBehavior('detached');
});
},
attributeChangedCallback: function (name, oldValue, newValue) {
this._attributeChangedImpl(name);
this._doBehavior('attributeChanged', [
name,
oldValue,
newValue
]);
},
_attributeChangedImpl: function (name) {
this._setAttributeToProperty(this, name);
},
extend: function (target, source) {
if (target && source) {
var n$ = Object.getOwnPropertyNames(source);
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
this.copyOwnProperty(n, source, target);
}
}
return target || source;
},
mixin: function (target, source) {
for (var i in source) {
target[i] = source[i];
}
return target;
},
copyOwnProperty: function (name, source, target) {
var pd = Object.getOwnPropertyDescriptor(source, name);
if (pd) {
Object.defineProperty(target, name, pd);
}
},
_logger: function (level, args) {
if (args.length === 1 && Array.isArray(args[0])) {
args = args[0];
}
switch (level) {
case 'log':
case 'warn':
case 'error':
console[level].apply(console, args);
break;
}
},
_log: function () {
var args = Array.prototype.slice.call(arguments, 0);
this._logger('log', args);
},
_warn: function () {
var args = Array.prototype.slice.call(arguments, 0);
this._logger('warn', args);
},
_error: function () {
var args = Array.prototype.slice.call(arguments, 0);
this._logger('error', args);
},
_logf: function () {
return this._logPrefix.concat(this.is).concat(Array.prototype.slice.call(arguments, 0));
}
};
Polymer.Base._logPrefix = function () {
var color = window.chrome && !/edge/i.test(navigator.userAgent) || /firefox/i.test(navigator.userAgent);
return color ? [
'%c[%s::%s]:',
'font-weight: bold; background-color:#EEEE00;'
] : ['[%s::%s]:'];
}();
Polymer.Base.chainObject = function (object, inherited) {
if (object && inherited && object !== inherited) {
if (!Object.__proto__) {
object = Polymer.Base.extend(Object.create(inherited), object);
}
object.__proto__ = inherited;
}
return object;
};
Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype);
if (window.CustomElements) {
Polymer.instanceof = CustomElements.instanceof;
} else {
Polymer.instanceof = function (obj, ctor) {
return obj instanceof ctor;
};
}
Polymer.isInstance = function (obj) {
return Boolean(obj && obj.__isPolymerInstance__);
};
Polymer.telemetry.instanceCount = 0;
}());(function () {
var modules = {};
var lcModules = {};
var findModule = function (id) {
return modules[id] || lcModules[id.toLowerCase()];
};
var DomModule = function () {
return document.createElement('dom-module');
};
DomModule.prototype = Object.create(HTMLElement.prototype);
Polymer.Base.extend(DomModule.prototype, {
constructor: DomModule,
createdCallback: function () {
this.register();
},
register: function (id) {
id = id || this.id || this.getAttribute('name') || this.getAttribute('is');
if (id) {
this.id = id;
modules[id] = this;
lcModules[id.toLowerCase()] = this;
}
},
import: function (id, selector) {
if (id) {
var m = findModule(id);
if (!m) {
forceDomModulesUpgrade();
m = findModule(id);
}
if (m && selector) {
m = m.querySelector(selector);
}
return m;
}
}
});
var cePolyfill = window.CustomElements && !CustomElements.useNative;
document.registerElement('dom-module', DomModule);
function forceDomModulesUpgrade() {
if (cePolyfill) {
var script = document._currentScript || document.currentScript;
var doc = script && script.ownerDocument || document;
var modules = doc.querySelectorAll('dom-module');
for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) {
if (m.__upgraded__) {
return;
} else {
CustomElements.upgrade(m);
}
}
}
}
}());Polymer.Base._addFeature({
_prepIs: function () {
if (!this.is) {
var module = (document._currentScript || document.currentScript).parentNode;
if (module.localName === 'dom-module') {
var id = module.id || module.getAttribute('name') || module.getAttribute('is');
this.is = id;
}
}
if (this.is) {
this.is = this.is.toLowerCase();
}
}
});Polymer.Base._addFeature({
behaviors: [],
_desugarBehaviors: function () {
if (this.behaviors.length) {
this.behaviors = this._desugarSomeBehaviors(this.behaviors);
}
},
_desugarSomeBehaviors: function (behaviors) {
var behaviorSet = [];
behaviors = this._flattenBehaviorsList(behaviors);
for (var i = behaviors.length - 1; i >= 0; i--) {
var b = behaviors[i];
if (behaviorSet.indexOf(b) === -1) {
this._mixinBehavior(b);
behaviorSet.unshift(b);
}
}
return behaviorSet;
},
_flattenBehaviorsList: function (behaviors) {
var flat = [];
for (var i = 0; i < behaviors.length; i++) {
var b = behaviors[i];
if (b instanceof Array) {
flat = flat.concat(this._flattenBehaviorsList(b));
} else if (b) {
flat.push(b);
} else {
this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import'));
}
}
return flat;
},
_mixinBehavior: function (b) {
var n$ = Object.getOwnPropertyNames(b);
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) {
this.copyOwnProperty(n, b, this);
}
}
},
_prepBehaviors: function () {
this._prepFlattenedBehaviors(this.behaviors);
},
_prepFlattenedBehaviors: function (behaviors) {
for (var i = 0, l = behaviors.length; i < l; i++) {
this._prepBehavior(behaviors[i]);
}
this._prepBehavior(this);
},
_doBehavior: function (name, args) {
for (var i = 0; i < this.behaviors.length; i++) {
this._invokeBehavior(this.behaviors[i], name, args);
}
this._invokeBehavior(this, name, args);
},
_doBehaviorOnly: function (name, args) {
for (var i = 0; i < this.behaviors.length; i++) {
this._invokeBehavior(this.behaviors[i], name, args);
}
},
_invokeBehavior: function (b, name, args) {
var fn = b[name];
if (fn) {
fn.apply(this, args || Polymer.nar);
}
},
_marshalBehaviors: function () {
for (var i = 0; i < this.behaviors.length; i++) {
this._marshalBehavior(this.behaviors[i]);
}
this._marshalBehavior(this);
}
});
Polymer.Base._behaviorProperties = {
hostAttributes: true,
beforeRegister: true,
registered: true,
properties: true,
observers: true,
listeners: true,
created: true,
attached: true,
detached: true,
attributeChanged: true,
ready: true
};Polymer.Base._addFeature({
_getExtendedPrototype: function (tag) {
return this._getExtendedNativePrototype(tag);
},
_nativePrototypes: {},
_getExtendedNativePrototype: function (tag) {
var p = this._nativePrototypes[tag];
if (!p) {
var np = this.getNativePrototype(tag);
p = this.extend(Object.create(np), Polymer.Base);
this._nativePrototypes[tag] = p;
}
return p;
},
getNativePrototype: function (tag) {
return Object.getPrototypeOf(document.createElement(tag));
}
});Polymer.Base._addFeature({
_prepConstructor: function () {
this._factoryArgs = this.extends ? [
this.extends,
this.is
] : [this.is];
var ctor = function () {
return this._factory(arguments);
};
if (this.hasOwnProperty('extends')) {
ctor.extends = this.extends;
}
Object.defineProperty(this, 'constructor', {
value: ctor,
writable: true,
configurable: true
});
ctor.prototype = this;
},
_factory: function (args) {
var elt = document.createElement.apply(document, this._factoryArgs);
if (this.factoryImpl) {
this.factoryImpl.apply(elt, args);
}
return elt;
}
});Polymer.nob = Object.create(null);
Polymer.Base._addFeature({
properties: {},
getPropertyInfo: function (property) {
var info = this._getPropertyInfo(property, this.properties);
if (!info) {
for (var i = 0; i < this.behaviors.length; i++) {
info = this._getPropertyInfo(property, this.behaviors[i].properties);
if (info) {
return info;
}
}
}
return info || Polymer.nob;
},
_getPropertyInfo: function (property, properties) {
var p = properties && properties[property];
if (typeof p === 'function') {
p = properties[property] = { type: p };
}
if (p) {
p.defined = true;
}
return p;
},
_prepPropertyInfo: function () {
this._propertyInfo = {};
for (var i = 0; i < this.behaviors.length; i++) {
this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties);
}
this._addPropertyInfo(this._propertyInfo, this.properties);
this._addPropertyInfo(this._propertyInfo, this._propertyEffects);
},
_addPropertyInfo: function (target, source) {
if (source) {
var t, s;
for (var i in source) {
t = target[i];
s = source[i];
if (i[0] === '_' && !s.readOnly) {
continue;
}
if (!target[i]) {
target[i] = {
type: typeof s === 'function' ? s : s.type,
readOnly: s.readOnly,
attribute: Polymer.CaseMap.camelToDashCase(i)
};
} else {
if (!t.type) {
t.type = s.type;
}
if (!t.readOnly) {
t.readOnly = s.readOnly;
}
}
}
}
}
});Polymer.CaseMap = {
_caseMap: {},
_rx: {
dashToCamel: /-[a-z]/g,
camelToDash: /([A-Z])/g
},
dashToCamelCase: function (dash) {
return this._caseMap[dash] || (this._caseMap[dash] = dash.indexOf('-') < 0 ? dash : dash.replace(this._rx.dashToCamel, function (m) {
return m[1].toUpperCase();
}));
},
camelToDashCase: function (camel) {
return this._caseMap[camel] || (this._caseMap[camel] = camel.replace(this._rx.camelToDash, '-$1').toLowerCase());
}
};Polymer.Base._addFeature({
_addHostAttributes: function (attributes) {
if (!this._aggregatedAttributes) {
this._aggregatedAttributes = {};
}
if (attributes) {
this.mixin(this._aggregatedAttributes, attributes);
}
},
_marshalHostAttributes: function () {
if (this._aggregatedAttributes) {
this._applyAttributes(this, this._aggregatedAttributes);
}
},
_applyAttributes: function (node, attr$) {
for (var n in attr$) {
if (!this.hasAttribute(n) && n !== 'class') {
var v = attr$[n];
this.serializeValueToAttribute(v, n, this);
}
}
},
_marshalAttributes: function () {
this._takeAttributesToModel(this);
},
_takeAttributesToModel: function (model) {
if (this.hasAttributes()) {
for (var i in this._propertyInfo) {
var info = this._propertyInfo[i];
if (this.hasAttribute(info.attribute)) {
this._setAttributeToProperty(model, info.attribute, i, info);
}
}
}
},
_setAttributeToProperty: function (model, attribute, property, info) {
if (!this._serializing) {
property = property || Polymer.CaseMap.dashToCamelCase(attribute);
info = info || this._propertyInfo && this._propertyInfo[property];
if (info && !info.readOnly) {
var v = this.getAttribute(attribute);
model[property] = this.deserialize(v, info.type);
}
}
},
_serializing: false,
reflectPropertyToAttribute: function (property, attribute, value) {
this._serializing = true;
value = value === undefined ? this[property] : value;
this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCase(property));
this._serializing = false;
},
serializeValueToAttribute: function (value, attribute, node) {
var str = this.serialize(value);
node = node || this;
if (str === undefined) {
node.removeAttribute(attribute);
} else {
node.setAttribute(attribute, str);
}
},
deserialize: function (value, type) {
switch (type) {
case Number:
value = Number(value);
break;
case Boolean:
value = value != null;
break;
case Object:
try {
value = JSON.parse(value);
} catch (x) {
}
break;
case Array:
try {
value = JSON.parse(value);
} catch (x) {
value = null;
console.warn('Polymer::Attributes: couldn`t decode Array as JSON');
}
break;
case Date:
value = new Date(value);
break;
case String:
default:
break;
}
return value;
},
serialize: function (value) {
switch (typeof value) {
case 'boolean':
return value ? '' : undefined;
case 'object':
if (value instanceof Date) {
return value.toString();
} else if (value) {
try {
return JSON.stringify(value);
} catch (x) {
return '';
}
}
default:
return value != null ? value : undefined;
}
}
});Polymer.version = "1.6.1";Polymer.Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepBehaviors();
this._prepConstructor();
this._prepPropertyInfo();
},
_prepBehavior: function (b) {
this._addHostAttributes(b.hostAttributes);
},
_marshalBehavior: function (b) {
},
_initFeatures: function () {
this._marshalHostAttributes();
this._marshalBehaviors();
}
});</script>
<script type="module">
import { Base } from '@polymer/polymer/polymer-legacy.js';
import { DomModule as DomModule$0 } from '@polymer/polymer/lib/elements/dom-module.js';
import { dom as dom$0, flush as flush$0, DomApi as DomApi$0, addDebouncer as addDebouncer$0 } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { useNativeCustomElements, useShadow as useShadow$0 } from '@polymer/polymer/lib/utils/settings.js';
import { calculateSplices as calculateSplices$0 } from '@polymer/polymer/lib/utils/array-splice.js';
import * as async from '@polymer/polymer/lib/utils/async.js';
Base._addFeature({
_prepTemplate: function () {
if (this._template === undefined) {
this._template = DomModule$0.import(this.is, 'template');
}
if (this._template && this._template.hasAttribute('is')) {
this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.'));
}
if (this._template && !this._template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) {
HTMLTemplateElement.decorate(this._template);
}
},
_stampTemplate: function () {
if (this._template) {
this.root = this.instanceTemplate(this._template);
}
},
instanceTemplate: function (template) {
var dom = document.importNode(template._content || template.content, true);
return dom;
}
});
var baseAttachedCallback = Base.attachedCallback;
Base._addFeature({
_hostStack: [],
ready: function () {
},
_registerHost: function (host) {
this.dataHost = host = host || Base._hostStack[Base._hostStack.length - 1];
if (host && host._clients) {
host._clients.push(this);
}
this._clients = null;
this._clientsReadied = false;
},
_beginHosting: function () {
Base._hostStack.push(this);
if (!this._clients) {
this._clients = [];
}
},
_endHosting: function () {
Base._hostStack.pop();
},
_tryReady: function () {
this._readied = false;
if (this._canReady()) {
this._ready();
}
},
_canReady: function () {
return !this.dataHost || this.dataHost._clientsReadied;
},
_ready: function () {
this._beforeClientsReady();
if (this._template) {
this._setupRoot();
this._readyClients();
}
this._clientsReadied = true;
this._clients = null;
this._afterClientsReady();
this._readySelf();
},
_readyClients: function () {
this._beginDistribute();
var c$ = this._clients;
if (c$) {
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
c._ready();
}
}
this._finishDistribute();
},
_readySelf: function () {
this._doBehavior('ready');
this._readied = true;
if (this._attachedPending) {
this._attachedPending = false;
this.attachedCallback();
}
},
_beforeClientsReady: function () {
},
_afterClientsReady: function () {
},
_beforeAttached: function () {
},
attachedCallback: function () {
if (this._readied) {
this._beforeAttached();
baseAttachedCallback.call(this);
} else {
this._attachedPending = true;
}
}
});
export const ArraySplice = function () {
function newSplice(index, removed, addedCount) {
return {
index: index,
removed: removed,
addedCount: addedCount
};
}
var EDIT_LEAVE = 0;
var EDIT_UPDATE = 1;
var EDIT_ADD = 2;
var EDIT_DELETE = 3;
function ArraySplice() {
}
ArraySplice.prototype = {
calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
var rowCount = oldEnd - oldStart + 1;
var columnCount = currentEnd - currentStart + 1;
var distances = new Array(rowCount);
for (var i = 0; i < rowCount; i++) {
distances[i] = new Array(columnCount);
distances[i][0] = i;
}
for (var j = 0; j < columnCount; j++)
distances[0][j] = j;
for (i = 1; i < rowCount; i++) {
for (j = 1; j < columnCount; j++) {
if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
distances[i][j] = distances[i - 1][j - 1];
else {
var north = distances[i - 1][j] + 1;
var west = distances[i][j - 1] + 1;
distances[i][j] = north < west ? north : west;
}
}
}
return distances;
},
spliceOperationsFromEditDistances: function (distances) {
var i = distances.length - 1;
var j = distances[0].length - 1;
var current = distances[i][j];
var edits = [];
while (i > 0 || j > 0) {
if (i == 0) {
edits.push(EDIT_ADD);
j--;
continue;
}
if (j == 0) {
edits.push(EDIT_DELETE);
i--;
continue;
}
var northWest = distances[i - 1][j - 1];
var west = distances[i - 1][j];
var north = distances[i][j - 1];
var min;
if (west < north)
min = west < northWest ? west : northWest;
else
min = north < northWest ? north : northWest;
if (min == northWest) {
if (northWest == current) {
edits.push(EDIT_LEAVE);
} else {
edits.push(EDIT_UPDATE);
current = northWest;
}
i--;
j--;
} else if (min == west) {
edits.push(EDIT_DELETE);
i--;
current = west;
} else {
edits.push(EDIT_ADD);
j--;
current = north;
}
}
edits.reverse();
return edits;
},
calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
var prefixCount = 0;
var suffixCount = 0;
var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
if (currentStart == 0 && oldStart == 0)
prefixCount = this.sharedPrefix(current, old, minLength);
if (currentEnd == current.length && oldEnd == old.length)
suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
currentStart += prefixCount;
oldStart += prefixCount;
currentEnd -= suffixCount;
oldEnd -= suffixCount;
if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
return [];
if (currentStart == currentEnd) {
var splice = newSplice(currentStart, [], 0);
while (oldStart < oldEnd)
splice.removed.push(old[oldStart++]);
return [splice];
} else if (oldStart == oldEnd)
return [newSplice(currentStart, [], currentEnd - currentStart)];
var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
splice = undefined;
var splices = [];
var index = currentStart;
var oldIndex = oldStart;
for (var i = 0; i < ops.length; i++) {
switch (ops[i]) {
case EDIT_LEAVE:
if (splice) {
splices.push(splice);
splice = undefined;
}
index++;
oldIndex++;
break;
case EDIT_UPDATE:
if (!splice)
splice = newSplice(index, [], 0);
splice.addedCount++;
index++;
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
case EDIT_ADD:
if (!splice)
splice = newSplice(index, [], 0);
splice.addedCount++;
index++;
break;
case EDIT_DELETE:
if (!splice)
splice = newSplice(index, [], 0);
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
}
}
if (splice) {
splices.push(splice);
}
return splices;
},
sharedPrefix: function (current, old, searchLength) {
for (var i = 0; i < searchLength; i++)
if (!this.equals(current[i], old[i]))
return i;
return searchLength;
},
sharedSuffix: function (current, old, searchLength) {
var index1 = current.length;
var index2 = old.length;
var count = 0;
while (count < searchLength && this.equals(current[--index1], old[--index2]))
count++;
return count;
},
calculateSplices: function (current, previous) {
return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
},
equals: function (currentValue, previousValue) {
return currentValue === previousValue;
}
};
return new ArraySplice();
}();
export const domInnerHTML = function () {
var escapeAttrRegExp = /[&\u00A0"]/g;
var escapeDataRegExp = /[&\u00A0<>]/g;
function escapeReplace(c) {
switch (c) {
case '&':
return '&';
case '<':
return '<';
case '>':
return '>';
case '"':
return '"';
case '\xA0':
return ' ';
}
}
function escapeAttr(s) {
return s.replace(escapeAttrRegExp, escapeReplace);
}
function escapeData(s) {
return s.replace(escapeDataRegExp, escapeReplace);
}
function makeSet(arr) {
var set = {};
for (var i = 0; i < arr.length; i++) {
set[arr[i]] = true;
}
return set;
}
var voidElements = makeSet([
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
]);
var plaintextParents = makeSet([
'style',
'script',
'xmp',
'iframe',
'noembed',
'noframes',
'plaintext',
'noscript'
]);
function getOuterHTML(node, parentNode, composed) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
var tagName = node.localName;
var s = '<' + tagName;
var attrs = node.attributes;
for (var i = 0, attr; attr = attrs[i]; i++) {
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
}
s += '>';
if (voidElements[tagName]) {
return s;
}
return s + getInnerHTML(node, composed) + '</' + tagName + '>';
case Node.TEXT_NODE:
var data = node.data;
if (parentNode && plaintextParents[parentNode.localName]) {
return data;
}
return escapeData(data);
case Node.COMMENT_NODE:
return '<!--' + node.data + '-->';
default:
console.error(node);
throw new Error('not implemented');
}
}
function getInnerHTML(node, composed) {
if (node instanceof HTMLTemplateElement)
node = node.content;
var s = '';
var c$ = dom$0(node).childNodes;
for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) {
s += getOuterHTML(child, node, composed);
}
return s;
}
return { getInnerHTML: getInnerHTML };
}();
var nativeInsertBefore = Element.prototype.insertBefore;
var nativeAppendChild = Element.prototype.appendChild;
var nativeRemoveChild = Element.prototype.removeChild;
export const TreeApi = {
arrayCopyChildNodes: function (parent) {
var copy = [], i = 0;
for (var n = parent.firstChild; n; n = n.nextSibling) {
copy[i++] = n;
}
return copy;
},
arrayCopyChildren: function (parent) {
var copy = [], i = 0;
for (var n = parent.firstElementChild; n; n = n.nextElementSibling) {
copy[i++] = n;
}
return copy;
},
arrayCopy: function (a$) {
var l = a$.length;
var copy = new Array(l);
for (var i = 0; i < l; i++) {
copy[i] = a$[i];
}
return copy;
}
};
TreeApi.Logical = {
hasParentNode: function (node) {
return Boolean(node.__dom && node.__dom.parentNode);
},
hasChildNodes: function (node) {
return Boolean(node.__dom && node.__dom.childNodes !== undefined);
},
getChildNodes: function (node) {
return this.hasChildNodes(node) ? this._getChildNodes(node) : node.childNodes;
},
_getChildNodes: function (node) {
if (!node.__dom.childNodes) {
node.__dom.childNodes = [];
for (var n = node.__dom.firstChild; n; n = n.__dom.nextSibling) {
node.__dom.childNodes.push(n);
}
}
return node.__dom.childNodes;
},
getParentNode: function (node) {
return node.__dom && node.__dom.parentNode !== undefined ? node.__dom.parentNode : node.parentNode;
},
getFirstChild: function (node) {
return node.__dom && node.__dom.firstChild !== undefined ? node.__dom.firstChild : node.firstChild;
},
getLastChild: function (node) {
return node.__dom && node.__dom.lastChild !== undefined ? node.__dom.lastChild : node.lastChild;
},
getNextSibling: function (node) {
return node.__dom && node.__dom.nextSibling !== undefined ? node.__dom.nextSibling : node.nextSibling;
},
getPreviousSibling: function (node) {
return node.__dom && node.__dom.previousSibling !== undefined ? node.__dom.previousSibling : node.previousSibling;
},
getFirstElementChild: function (node) {
return node.__dom && node.__dom.firstChild !== undefined ? this._getFirstElementChild(node) : node.firstElementChild;
},
_getFirstElementChild: function (node) {
var n = node.__dom.firstChild;
while (n && n.nodeType !== Node.ELEMENT_NODE) {
n = n.__dom.nextSibling;
}
return n;
},
getLastElementChild: function (node) {
return node.__dom && node.__dom.lastChild !== undefined ? this._getLastElementChild(node) : node.lastElementChild;
},
_getLastElementChild: function (node) {
var n = node.__dom.lastChild;
while (n && n.nodeType !== Node.ELEMENT_NODE) {
n = n.__dom.previousSibling;
}
return n;
},
getNextElementSibling: function (node) {
return node.__dom && node.__dom.nextSibling !== undefined ? this._getNextElementSibling(node) : node.nextElementSibling;
},
_getNextElementSibling: function (node) {
var n = node.__dom.nextSibling;
while (n && n.nodeType !== Node.ELEMENT_NODE) {
n = n.__dom.nextSibling;
}
return n;
},
getPreviousElementSibling: function (node) {
return node.__dom && node.__dom.previousSibling !== undefined ? this._getPreviousElementSibling(node) : node.previousElementSibling;
},
_getPreviousElementSibling: function (node) {
var n = node.__dom.previousSibling;
while (n && n.nodeType !== Node.ELEMENT_NODE) {
n = n.__dom.previousSibling;
}
return n;
},
saveChildNodes: function (node) {
if (!this.hasChildNodes(node)) {
node.__dom = node.__dom || {};
node.__dom.firstChild = node.firstChild;
node.__dom.lastChild = node.lastChild;
node.__dom.childNodes = [];
for (var n = node.firstChild; n; n = n.nextSibling) {
n.__dom = n.__dom || {};
n.__dom.parentNode = node;
node.__dom.childNodes.push(n);
n.__dom.nextSibling = n.nextSibling;
n.__dom.previousSibling = n.previousSibling;
}
}
},
recordInsertBefore: function (node, container, ref_node) {
container.__dom.childNodes = null;
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
for (var n = node.firstChild; n; n = n.nextSibling) {
this._linkNode(n, container, ref_node);
}
} else {
this._linkNode(node, container, ref_node);
}
},
_linkNode: function (node, container, ref_node) {
node.__dom = node.__dom || {};
container.__dom = container.__dom || {};
if (ref_node) {
ref_node.__dom = ref_node.__dom || {};
}
node.__dom.previousSibling = ref_node ? ref_node.__dom.previousSibling : container.__dom.lastChild;
if (node.__dom.previousSibling) {
node.__dom.previousSibling.__dom.nextSibling = node;
}
node.__dom.nextSibling = ref_node || null;
if (node.__dom.nextSibling) {
node.__dom.nextSibling.__dom.previousSibling = node;
}
node.__dom.parentNode = container;
if (ref_node) {
if (ref_node === container.__dom.firstChild) {
container.__dom.firstChild = node;
}
} else {
container.__dom.lastChild = node;
if (!container.__dom.firstChild) {
container.__dom.firstChild = node;
}
}
container.__dom.childNodes = null;
},
recordRemoveChild: function (node, container) {
node.__dom = node.__dom || {};
container.__dom = container.__dom || {};
if (node === container.__dom.firstChild) {
container.__dom.firstChild = node.__dom.nextSibling;
}
if (node === container.__dom.lastChild) {
container.__dom.lastChild = node.__dom.previousSibling;
}
var p = node.__dom.previousSibling;
var n = node.__dom.nextSibling;
if (p) {
p.__dom.nextSibling = n;
}
if (n) {
n.__dom.previousSibling = p;
}
node.__dom.parentNode = node.__dom.previousSibling = node.__dom.nextSibling = undefined;
container.__dom.childNodes = null;
}
};
TreeApi.Composed = {
getChildNodes: function (node) {
return TreeApi.arrayCopyChildNodes(node);
},
getParentNode: function (node) {
return node.parentNode;
},
clearChildNodes: function (node) {
node.textContent = '';
},
insertBefore: function (parentNode, newChild, refChild) {
return nativeInsertBefore.call(parentNode, newChild, refChild || null);
},
appendChild: function (parentNode, newChild) {
return nativeAppendChild.call(parentNode, newChild);
},
removeChild: function (parentNode, node) {
return nativeRemoveChild.call(parentNode, node);
}
};
export const DomApi = function () {
'use strict';
var Settings = undefined;
var TreeApi = TreeApi;
var DomApi = function (node) {
this.node = needsToWrap ? DomApi.wrap(node) : node;
};
var needsToWrap = Settings.hasShadow && !Settings.nativeShadow;
DomApi.wrap = window.wrap ? window.wrap : function (node) {
return node;
};
DomApi.prototype = {
flush: function () {
flush$0();
},
deepContains: function (node) {
if (this.node.contains(node)) {
return true;
}
var n = node;
var doc = node.ownerDocument;
while (n && n !== doc && n !== this.node) {
n = dom$0(n).parentNode || n.host;
}
return n === this.node;
},
queryDistributedElements: function (selector) {
var c$ = this.getEffectiveChildNodes();
var list = [];
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
if (c.nodeType === Node.ELEMENT_NODE && DomApi.matchesSelector.call(c, selector)) {
list.push(c);
}
}
return list;
},
getEffectiveChildNodes: function () {
var list = [];
var c$ = this.childNodes;
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
if (c.localName === CONTENT) {
var d$ = dom(c).getDistributedNodes();
for (var j = 0; j < d$.length; j++) {
list.push(d$[j]);
}
} else {
list.push(c);
}
}
return list;
},
observeNodes: function (callback) {
if (callback) {
if (!this.observer) {
this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObserver(this) : new DomApi.EffectiveNodesObserver(this);
}
return this.observer.addListener(callback);
}
},
unobserveNodes: function (handle) {
if (this.observer) {
this.observer.removeListener(handle);
}
},
notifyObserver: function () {
if (this.observer) {
this.observer.notify();
}
},
_query: function (matcher, node, halter) {
node = node || this.node;
var list = [];
this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
return list;
},
_queryElements: function (elements, matcher, halter, list) {
for (var i = 0, l = elements.length, c; i < l && (c = elements[i]); i++) {
if (c.nodeType === Node.ELEMENT_NODE) {
if (this._queryElement(c, matcher, halter, list)) {
return true;
}
}
}
},
_queryElement: function (node, matcher, halter, list) {
var result = matcher(node);
if (result) {
list.push(node);
}
if (halter && halter(result)) {
return result;
}
this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
}
};
var CONTENT = DomApi.CONTENT = 'content';
var dom = DomApi.factory = function (node) {
node = node || document;
if (!node.__domApi) {
node.__domApi = new DomApi.ctor(node);
}
return node.__domApi;
};
DomApi.hasApi = function (node) {
return Boolean(node.__domApi);
};
DomApi.ctor = DomApi;
Polymer.dom = function (obj, patch) {
if (obj instanceof Event) {
return EventApi.factory(obj);
} else {
return DomApi.factory(obj, patch);
}
};
var p = Element.prototype;
DomApi.matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector;
return DomApi;
}();
var Settings = undefined;
var DomApi = DomApi$0;
var dom = DomApi.factory;
var TreeApi = TreeApi;
var getInnerHTML = domInnerHTML.getInnerHTML;
var CONTENT = DomApi.CONTENT;
if (Settings.useShadow) {
return;
}
var nativeCloneNode = Element.prototype.cloneNode;
var nativeImportNode = Document.prototype.importNode;
Base.extend(DomApi.prototype, {
_lazyDistribute: function (host) {
if (host.shadyRoot && host.shadyRoot._distributionClean) {
host.shadyRoot._distributionClean = false;
addDebouncer$0(host.debounce('_distribute', host._distributeContent));
}
},
appendChild: function (node) {
return this.insertBefore(node);
},
insertBefore: function (node, ref_node) {
if (ref_node && TreeApi.Logical.getParentNode(ref_node) !== this.node) {
throw Error('The ref_node to be inserted before is not a child ' + 'of this node');
}
if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
var parent = TreeApi.Logical.getParentNode(node);
if (parent) {
if (DomApi.hasApi(parent)) {
dom(parent).notifyObserver();
}
this._removeNode(node);
} else {
this._removeOwnerShadyRoot(node);
}
}
if (!this._addNode(node, ref_node)) {
if (ref_node) {
ref_node = ref_node.localName === CONTENT ? this._firstComposedNode(ref_node) : ref_node;
}
var container = this.node._isShadyRoot ? this.node.host : this.node;
if (ref_node) {
TreeApi.Composed.insertBefore(container, node, ref_node);
} else {
TreeApi.Composed.appendChild(container, node);
}
}
this.notifyObserver();
return node;
},
_addNode: function (node, ref_node) {
var root = this.getOwnerRoot();
if (root) {
var ipAdded = this._maybeAddInsertionPoint(node, this.node);
if (!root._invalidInsertionPoints) {
root._invalidInsertionPoints = ipAdded;
}
this._addNodeToHost(root.host, node);
}
if (TreeApi.Logical.hasChildNodes(this.node)) {
TreeApi.Logical.recordInsertBefore(node, this.node, ref_node);
}
var handled = this._maybeDistribute(node) || this.node.shadyRoot;
if (handled) {
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
while (node.firstChild) {
TreeApi.Composed.removeChild(node, node.firstChild);
}
} else {
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
TreeApi.Composed.removeChild(parent, node);
}
}
}
return handled;
},
removeChild: function (node) {
if (TreeApi.Logical.getParentNode(node) !== this.node) {
throw Error('The node to be removed is not a child of this node: ' + node);
}
if (!this._removeNode(node)) {
var container = this.node._isShadyRoot ? this.node.host : this.node;
var parent = TreeApi.Composed.getParentNode(node);
if (container === parent) {
TreeApi.Composed.removeChild(container, node);
}
}
this.notifyObserver();
return node;
},
_removeNode: function (node) {
var logicalParent = TreeApi.Logical.hasParentNode(node) && TreeApi.Logical.getParentNode(node);
var distributed;
var root = this._ownerShadyRootForNode(node);
if (logicalParent) {
distributed = dom(node)._maybeDistributeParent();
TreeApi.Logical.recordRemoveChild(node, logicalParent);
if (root && this._removeDistributedChildren(root, node)) {
root._invalidInsertionPoints = true;
this._lazyDistribute(root.host);
}
}
this._removeOwnerShadyRoot(node);
if (root) {
this._removeNodeFromHost(root.host, node);
}
return distributed;
},
replaceChild: function (node, ref_node) {
this.insertBefore(node, ref_node);
this.removeChild(ref_node);
return node;
},
_hasCachedOwnerRoot: function (node) {
return Boolean(node._ownerShadyRoot !== undefined);
},
getOwnerRoot: function () {
return this._ownerShadyRootForNode(this.node);
},
_ownerShadyRootForNode: function (node) {
if (!node) {
return;
}
var root = node._ownerShadyRoot;
if (root === undefined) {
if (node._isShadyRoot) {
root = node;
} else {
var parent = TreeApi.Logical.getParentNode(node);
if (parent) {
root = parent._isShadyRoot ? parent : this._ownerShadyRootForNode(parent);
} else {
root = null;
}
}
if (root || document.documentElement.contains(node)) {
node._ownerShadyRoot = root;
}
}
return root;
},
_maybeDistribute: function (node) {
var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent && dom(node).querySelector(CONTENT);
var wrappedContent = fragContent && TreeApi.Logical.getParentNode(fragContent).nodeType !== Node.DOCUMENT_FRAGMENT_NODE;
var hasContent = fragContent || node.localName === CONTENT;
if (hasContent) {
var root = this.getOwnerRoot();
if (root) {
this._lazyDistribute(root.host);
}
}
var needsDist = this._nodeNeedsDistribution(this.node);
if (needsDist) {
this._lazyDistribute(this.node);
}
return needsDist || hasContent && !wrappedContent;
},
_maybeAddInsertionPoint: function (node, parent) {
var added;
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent) {
var c$ = dom(node).querySelectorAll(CONTENT);
for (var i = 0, n, np, na; i < c$.length && (n = c$[i]); i++) {
np = TreeApi.Logical.getParentNode(n);
if (np === node) {
np = parent;
}
na = this._maybeAddInsertionPoint(n, np);
added = added || na;
}
} else if (node.localName === CONTENT) {
TreeApi.Logical.saveChildNodes(parent);
TreeApi.Logical.saveChildNodes(node);
added = true;
}
return added;
},
_updateInsertionPoints: function (host) {
var i$ = host.shadyRoot._insertionPoints = dom(host.shadyRoot).querySelectorAll(CONTENT);
for (var i = 0, c; i < i$.length; i++) {
c = i$[i];
TreeApi.Logical.saveChildNodes(c);
TreeApi.Logical.saveChildNodes(TreeApi.Logical.getParentNode(c));
}
},
_nodeNeedsDistribution: function (node) {
return node && node.shadyRoot && DomApi.hasInsertionPoint(node.shadyRoot);
},
_addNodeToHost: function (host, node) {
if (host._elementAdd) {
host._elementAdd(node);
}
},
_removeNodeFromHost: function (host, node) {
if (host._elementRemove) {
host._elementRemove(node);
}
},
_removeDistributedChildren: function (root, container) {
var hostNeedsDist;
var ip$ = root._insertionPoints;
for (var i = 0; i < ip$.length; i++) {
var content = ip$[i];
if (this._contains(container, content)) {
var dc$ = dom(content).getDistributedNodes();
for (var j = 0; j < dc$.length; j++) {
hostNeedsDist = true;
var node = dc$[j];
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
TreeApi.Composed.removeChild(parent, node);
}
}
}
}
return hostNeedsDist;
},
_contains: function (container, node) {
while (node) {
if (node == container) {
return true;
}
node = TreeApi.Logical.getParentNode(node);
}
},
_removeOwnerShadyRoot: function (node) {
if (this._hasCachedOwnerRoot(node)) {
var c$ = TreeApi.Logical.getChildNodes(node);
for (var i = 0, l = c$.length, n; i < l && (n = c$[i]); i++) {
this._removeOwnerShadyRoot(n);
}
}
node._ownerShadyRoot = undefined;
},
_firstComposedNode: function (content) {
var n$ = dom(content).getDistributedNodes();
for (var i = 0, l = n$.length, n, p$; i < l && (n = n$[i]); i++) {
p$ = dom(n).getDestinationInsertionPoints();
if (p$[p$.length - 1] === content) {
return n;
}
}
},
querySelector: function (selector) {
var result = this._query(function (n) {
return DomApi.matchesSelector.call(n, selector);
}, this.node, function (n) {
return Boolean(n);
})[0];
return result || null;
},
querySelectorAll: function (selector) {
return this._query(function (n) {
return DomApi.matchesSelector.call(n, selector);
}, this.node);
},
getDestinationInsertionPoints: function () {
return this.node._destinationInsertionPoints || [];
},
getDistributedNodes: function () {
return this.node._distributedNodes || [];
},
_clear: function () {
while (this.childNodes.length) {
this.removeChild(this.childNodes[0]);
}
},
setAttribute: function (name, value) {
this.node.setAttribute(name, value);
this._maybeDistributeParent();
},
removeAttribute: function (name) {
this.node.removeAttribute(name);
this._maybeDistributeParent();
},
_maybeDistributeParent: function () {
if (this._nodeNeedsDistribution(this.parentNode)) {
this._lazyDistribute(this.parentNode);
return true;
}
},
cloneNode: function (deep) {
var n = nativeCloneNode.call(this.node, false);
if (deep) {
var c$ = this.childNodes;
var d = dom(n);
for (var i = 0, nc; i < c$.length; i++) {
nc = dom(c$[i]).cloneNode(true);
d.appendChild(nc);
}
}
return n;
},
importNode: function (externalNode, deep) {
var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
var n = nativeImportNode.call(doc, externalNode, false);
if (deep) {
var c$ = TreeApi.Logical.getChildNodes(externalNode);
var d = dom(n);
for (var i = 0, nc; i < c$.length; i++) {
nc = dom(doc).importNode(c$[i], true);
d.appendChild(nc);
}
}
return n;
},
_getComposedInnerHTML: function () {
return getInnerHTML(this.node, true);
}
});
Object.defineProperties(DomApi.prototype, {
activeElement: {
get: function () {
var active = document.activeElement;
if (!active) {
return null;
}
var isShadyRoot = !!this.node._isShadyRoot;
if (this.node !== document) {
if (!isShadyRoot) {
return null;
}
if (this.node.host === active || !this.node.host.contains(active)) {
return null;
}
}
var activeRoot = dom(active).getOwnerRoot();
while (activeRoot && activeRoot !== this.node) {
active = activeRoot.host;
activeRoot = dom(active).getOwnerRoot();
}
if (this.node === document) {
return activeRoot ? null : active;
} else {
return activeRoot === this.node ? active : null;
}
},
configurable: true
},
childNodes: {
get: function () {
var c$ = TreeApi.Logical.getChildNodes(this.node);
return Array.isArray(c$) ? c$ : TreeApi.arrayCopyChildNodes(this.node);
},
configurable: true
},
children: {
get: function () {
if (TreeApi.Logical.hasChildNodes(this.node)) {
return Array.prototype.filter.call(this.childNodes, function (n) {
return n.nodeType === Node.ELEMENT_NODE;
});
} else {
return TreeApi.arrayCopyChildren(this.node);
}
},
configurable: true
},
parentNode: {
get: function () {
return TreeApi.Logical.getParentNode(this.node);
},
configurable: true
},
firstChild: {
get: function () {
return TreeApi.Logical.getFirstChild(this.node);
},
configurable: true
},
lastChild: {
get: function () {
return TreeApi.Logical.getLastChild(this.node);
},
configurable: true
},
nextSibling: {
get: function () {
return TreeApi.Logical.getNextSibling(this.node);
},
configurable: true
},
previousSibling: {
get: function () {
return TreeApi.Logical.getPreviousSibling(this.node);
},
configurable: true
},
firstElementChild: {
get: function () {
return TreeApi.Logical.getFirstElementChild(this.node);
},
configurable: true
},
lastElementChild: {
get: function () {
return TreeApi.Logical.getLastElementChild(this.node);
},
configurable: true
},
nextElementSibling: {
get: function () {
return TreeApi.Logical.getNextElementSibling(this.node);
},
configurable: true
},
previousElementSibling: {
get: function () {
return TreeApi.Logical.getPreviousElementSibling(this.node);
},
configurable: true
},
textContent: {
get: function () {
var nt = this.node.nodeType;
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
return this.node.textContent;
} else {
var tc = [];
for (var i = 0, cn = this.childNodes, c; c = cn[i]; i++) {
if (c.nodeType !== Node.COMMENT_NODE) {
tc.push(c.textContent);
}
}
return tc.join('');
}
},
set: function (text) {
var nt = this.node.nodeType;
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
this.node.textContent = text;
} else {
this._clear();
if (text) {
this.appendChild(document.createTextNode(text));
}
}
},
configurable: true
},
innerHTML: {
get: function () {
var nt = this.node.nodeType;
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
return null;
} else {
return getInnerHTML(this.node);
}
},
set: function (text) {
var nt = this.node.nodeType;
if (nt !== Node.TEXT_NODE || nt !== Node.COMMENT_NODE) {
this._clear();
var d = document.createElement('div');
d.innerHTML = text;
var c$ = TreeApi.arrayCopyChildNodes(d);
for (var i = 0; i < c$.length; i++) {
this.appendChild(c$[i]);
}
}
},
configurable: true
}
});
DomApi.hasInsertionPoint = function (root) {
return Boolean(root && root._insertionPoints.length);
};
forwardProperties([
'parentNode',
'firstChild',
'lastChild',
'nextSibling',
'previousSibling',
'firstElementChild',
'lastElementChild',
'nextElementSibling',
'previousElementSibling'
]);
var forwardProperty = function (name) {
Object.defineProperty(DomApi.prototype, name, {
get: function () {
return this.node[name];
},
configurable: true
});
};
var forwardProperties = function (f$) {
for (var i = 0; i < f$.length; i++) {
forwardProperty(f$[i]);
}
};
forwardMethods([
'cloneNode',
'appendChild',
'insertBefore',
'removeChild',
'replaceChild',
'setAttribute',
'removeAttribute',
'querySelector'
]);
var forwardMethod = function (method) {
DomApi.prototype[method] = function () {
return this.node[method].apply(this.node, arguments);
};
};
var forwardMethods = function (m$) {
for (var i = 0; i < m$.length; i++) {
forwardMethod(m$[i]);
}
};
Object.defineProperties(DomApi.prototype, {
activeElement: {
get: function () {
var node = DomApi.wrap(this.node);
var activeElement = node.activeElement;
return node.contains(activeElement) ? activeElement : null;
},
configurable: true
},
childNodes: {
get: function () {
return TreeApi.arrayCopyChildNodes(this.node);
},
configurable: true
},
children: {
get: function () {
return TreeApi.arrayCopyChildren(this.node);
},
configurable: true
},
textContent: {
get: function () {
return this.node.textContent;
},
set: function (value) {
return this.node.textContent = value;
},
configurable: true
},
innerHTML: {
get: function () {
return this.node.innerHTML;
},
set: function (value) {
return this.node.innerHTML = value;
},
configurable: true
}
});
Base.extend(DomApi.prototype, {
querySelectorAll: function (selector) {
return TreeApi.arrayCopy(this.node.querySelectorAll(selector));
},
getOwnerRoot: function () {
var n = this.node;
while (n) {
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
return n;
}
n = n.parentNode;
}
},
importNode: function (externalNode, deep) {
var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
return doc.importNode(externalNode, deep);
},
getDestinationInsertionPoints: function () {
var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInsertionPoints();
return n$ ? TreeApi.arrayCopy(n$) : [];
},
getDistributedNodes: function () {
var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes();
return n$ ? TreeApi.arrayCopy(n$) : [];
}
});
if (!Settings.useShadow) {
return;
}
var DomApi = DomApi$0;
var TreeApi = TreeApi;
var Settings = undefined;
Base.extend(dom$0, {
_flushGuard: 0,
_FLUSH_MAX: 100,
_needsTakeRecords: !useNativeCustomElements,
_debouncers: [],
_staticFlushList: [],
_finishDebouncer: null,
flush: function () {
this._flushGuard = 0;
this._prepareFlush();
while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
while (this._debouncers.length) {
this._debouncers.shift().complete();
}
if (this._finishDebouncer) {
this._finishDebouncer.complete();
}
this._prepareFlush();
this._flushGuard++;
}
if (this._flushGuard >= this._FLUSH_MAX) {
console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
}
},
_prepareFlush: function () {
if (this._needsTakeRecords) {
CustomElements.takeRecords();
}
for (var i = 0; i < this._staticFlushList.length; i++) {
this._staticFlushList[i]();
}
},
addStaticFlush: function (fn) {
this._staticFlushList.push(fn);
},
removeStaticFlush: function (fn) {
var i = this._staticFlushList.indexOf(fn);
if (i >= 0) {
this._staticFlushList.splice(i, 1);
}
},
addDebouncer: function (debouncer) {
this._debouncers.push(debouncer);
this._finishDebouncer = Debounce(this._finishDebouncer, this._finishFlush);
},
_finishFlush: function () {
dom$0._debouncers = [];
}
});
export const EventApi = function () {
'use strict';
var DomApi = DomApi$0.ctor;
var Settings = undefined;
DomApi.Event = function (event) {
this.event = event;
};
if (Settings.useShadow) {
DomApi.Event.prototype = {
get rootTarget() {
return this.event.path[0];
},
get localTarget() {
return this.event.target;
},
get path() {
var path = this.event.path;
if (!Array.isArray(path)) {
path = Array.prototype.slice.call(path);
}
return path;
}
};
} else {
DomApi.Event.prototype = {
get rootTarget() {
return this.event.target;
},
get localTarget() {
var current = this.event.currentTarget;
var currentRoot = current && dom$0(current).getOwnerRoot();
var p$ = this.path;
for (var i = 0; i < p$.length; i++) {
if (dom$0(p$[i]).getOwnerRoot() === currentRoot) {
return p$[i];
}
}
},
get path() {
if (!this.event._path) {
var path = [];
var current = this.rootTarget;
while (current) {
path.push(current);
var insertionPoints = dom$0(current).getDestinationInsertionPoints();
if (insertionPoints.length) {
for (var i = 0; i < insertionPoints.length - 1; i++) {
path.push(insertionPoints[i]);
}
current = insertionPoints[insertionPoints.length - 1];
} else {
current = dom$0(current).parentNode || current.host;
}
}
path.push(window);
this.event._path = path;
}
return this.event._path;
}
};
}
var factory = function (event) {
if (!event.__eventApi) {
event.__eventApi = new DomApi.Event(event);
}
return event.__eventApi;
};
return { factory: factory };
}();
var DomApi = DomApi$0.ctor;
var useShadow = useShadow$0;
Object.defineProperty(DomApi.prototype, 'classList', {
get: function () {
if (!this._classList) {
this._classList = new DomApi.ClassList(this);
}
return this._classList;
},
configurable: true
});
DomApi.ClassList = function (host) {
this.domApi = host;
this.node = host.node;
};
DomApi.ClassList.prototype = {
add: function () {
this.node.classList.add.apply(this.node.classList, arguments);
this._distributeParent();
},
remove: function () {
this.node.classList.remove.apply(this.node.classList, arguments);
this._distributeParent();
},
toggle: function () {
this.node.classList.toggle.apply(this.node.classList, arguments);
this._distributeParent();
},
_distributeParent: function () {
if (!useShadow) {
this.domApi._maybeDistributeParent();
}
},
contains: function () {
return this.node.classList.contains.apply(this.node.classList, arguments);
}
};
if (Settings.useShadow) {
var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
Base.extend(DomApi.EffectiveNodesObserver.prototype, {
_setup: function () {
if (!this._observer) {
var self = this;
this._mutationHandler = function (mxns) {
if (mxns && mxns.length) {
self._scheduleNotify();
}
};
this._observer = new MutationObserver(this._mutationHandler);
this._boundFlush = function () {
self._flush();
};
dom$0.addStaticFlush(this._boundFlush);
this._observer.observe(this.node, { childList: true });
}
baseSetup.call(this);
},
_cleanup: function () {
this._observer.disconnect();
this._observer = null;
this._mutationHandler = null;
dom$0.removeStaticFlush(this._boundFlush);
baseCleanup.call(this);
},
_flush: function () {
if (this._observer) {
this._mutationHandler(this._observer.takeRecords());
}
},
enableShadowAttributeTracking: function () {
if (this._observer) {
this._makeContentListenersAlwaysNotify();
this._observer.disconnect();
this._observer.observe(this.node, {
childList: true,
attributes: true,
subtree: true
});
var root = this.domApi.getOwnerRoot();
var host = root && root.host;
if (host && dom$0(host).observer) {
dom$0(host).observer.enableShadowAttributeTracking();
}
}
},
_makeContentListenersAlwaysNotify: function () {
for (var i = 0, h; i < this._listeners.length; i++) {
h = this._listeners[i];
h._alwaysNotify = h._isContentListener;
}
}
});
}
DomApi.EffectiveNodesObserver.prototype = {
addListener: function (callback) {
if (!this._isSetup) {
this._setup();
this._isSetup = true;
}
var listener = {
fn: callback,
_nodes: []
};
this._listeners.push(listener);
this._scheduleNotify();
return listener;
},
removeListener: function (handle) {
var i = this._listeners.indexOf(handle);
if (i >= 0) {
this._listeners.splice(i, 1);
handle._nodes = [];
}
if (!this._hasListeners()) {
this._cleanup();
this._isSetup = false;
}
},
_setup: function () {
this._observeContentElements(this.domApi.childNodes);
},
_cleanup: function () {
this._unobserveContentElements(this.domApi.childNodes);
},
_hasListeners: function () {
return Boolean(this._listeners.length);
},
_scheduleNotify: function () {
if (this._debouncer) {
this._debouncer.stop();
}
this._debouncer = Debounce(this._debouncer, this._notify);
this._debouncer.context = this;
addDebouncer$0(this._debouncer);
},
notify: function () {
if (this._hasListeners()) {
this._scheduleNotify();
}
},
_notify: function () {
this._beforeCallListeners();
this._callListeners();
},
_beforeCallListeners: function () {
this._updateContentElements();
},
_updateContentElements: function () {
this._observeContentElements(this.domApi.childNodes);
},
_observeContentElements: function (elements) {
for (var i = 0, n; i < elements.length && (n = elements[i]); i++) {
if (this._isContent(n)) {
n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
if (!n.__observeNodesMap.has(this)) {
n.__observeNodesMap.set(this, this._observeContent(n));
}
}
}
},
_observeContent: function (content) {
var self = this;
var h = dom$0(content).observeNodes(function () {
self._scheduleNotify();
});
h._avoidChangeCalculation = true;
return h;
},
_unobserveContentElements: function (elements) {
for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) {
if (this._isContent(n)) {
h = n.__observeNodesMap.get(this);
if (h) {
dom$0(n).unobserveNodes(h);
n.__observeNodesMap.delete(this);
}
}
}
},
_isContent: function (node) {
return node.localName === 'content';
},
_callListeners: function () {
var o$ = this._listeners;
var nodes = this._getEffectiveNodes();
for (var i = 0, o; i < o$.length && (o = o$[i]); i++) {
var info = this._generateListenerInfo(o, nodes);
if (info || o._alwaysNotify) {
this._callListener(o, info);
}
}
},
_getEffectiveNodes: function () {
return this.domApi.getEffectiveChildNodes();
},
_generateListenerInfo: function (listener, newNodes) {
if (listener._avoidChangeCalculation) {
return true;
}
var oldNodes = listener._nodes;
var info = {
target: this.node,
addedNodes: [],
removedNodes: []
};
var splices = calculateSplices$0(newNodes, oldNodes);
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
info.removedNodes.push(n);
}
}
for (i = 0, s; i < splices.length && (s = splices[i]); i++) {
for (j = s.index; j < s.index + s.addedCount; j++) {
info.addedNodes.push(newNodes[j]);
}
}
listener._nodes = newNodes;
if (info.addedNodes.length || info.removedNodes.length) {
return info;
}
},
_callListener: function (listener, info) {
return listener.fn.call(this.node, info);
},
enableShadowAttributeTracking: function () {
}
};
DomApi.EffectiveNodesObserver = function (domApi) {
this.domApi = domApi;
this.node = this.domApi.node;
this._listeners = [];
};
var Settings = undefined;
var DomApi = DomApi$0.ctor;
if (Settings.useShadow) {
Base.extend(DomApi.DistributedNodesObserver.prototype, {
_setup: function () {
if (!this._observer) {
var root = this.domApi.getOwnerRoot();
var host = root && root.host;
if (host) {
var self = this;
this._observer = dom$0(host).observeNodes(function () {
self._scheduleNotify();
});
this._observer._isContentListener = true;
if (this._hasAttrSelect()) {
dom$0(host).observer.enableShadowAttributeTracking();
}
}
}
},
_hasAttrSelect: function () {
var select = this.node.getAttribute('select');
return select && select.match(/[[.]+/);
},
_cleanup: function () {
var root = this.domApi.getOwnerRoot();
var host = root && root.host;
if (host) {
dom$0(host).unobserveNodes(this._observer);
}
this._observer = null;
}
});
}
Base.extend(DomApi.DistributedNodesObserver.prototype, {
_setup: function () {
},
_cleanup: function () {
},
_beforeCallListeners: function () {
},
_getEffectiveNodes: function () {
return this.domApi.getDistributedNodes();
}
});
DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesObserver.prototype);
DomApi.DistributedNodesObserver = function (domApi) {
DomApi.EffectiveNodesObserver.call(this, domApi);
};
var Settings = undefined;
var DomApi = DomApi$0.ctor;
function upgradeLogicalChildren(children) {
if (needsUpgrade && children) {
for (var i = 0; i < children.length; i++) {
CustomElements.upgrade(children[i]);
}
}
}
var needsUpgrade = window.CustomElements && !CustomElements.useNative;
function notifyInitialDistribution(host) {
if (DomApi.hasApi(host)) {
dom$0(host).notifyObserver();
}
}
function notifyContentObservers(root) {
for (var i = 0, c; i < root._insertionPoints.length; i++) {
c = root._insertionPoints[i];
if (DomApi.hasApi(c)) {
dom$0(c).notifyObserver();
}
}
}
function hostNeedsRedistribution(host) {
var c$ = TreeApi.Logical.getChildNodes(host);
for (var i = 0, c; i < c$.length; i++) {
c = c$[i];
if (c.localName && c.localName === 'content') {
return host.domHost;
}
}
}
function getTopDistributingHost(host) {
while (host && hostNeedsRedistribution(host)) {
host = host.domHost;
}
return host;
}
function isInsertionPoint(node) {
return node.localName == 'content';
}
function isFinalDestination(insertionPoint, node) {
var points = node._destinationInsertionPoints;
return points && points[points.length - 1] === insertionPoint;
}
function maybeRedistributeParent(content, host) {
var parent = TreeApi.Logical.getParentNode(content);
if (parent && parent.shadyRoot && DomApi.hasInsertionPoint(parent.shadyRoot) && parent.shadyRoot._distributionClean) {
parent.shadyRoot._distributionClean = false;
host.shadyRoot._dirtyRoots.push(parent);
}
}
function clearDistributedDestinationInsertionPoints(content) {
var e$ = content._distributedNodes;
if (e$) {
for (var i = 0; i < e$.length; i++) {
var d = e$[i]._destinationInsertionPoints;
if (d) {
d.splice(d.indexOf(content) + 1, d.length);
}
}
}
}
function distributeNodeInto(child, insertionPoint) {
insertionPoint._distributedNodes.push(child);
var points = child._destinationInsertionPoints;
if (!points) {
child._destinationInsertionPoints = [insertionPoint];
} else {
points.push(insertionPoint);
}
}
Base._addFeature({
_prepShady: function () {
this._useContent = this._useContent || Boolean(this._template);
},
_setupShady: function () {
this.shadyRoot = null;
if (!this.__domApi) {
this.__domApi = null;
}
if (!this.__dom) {
this.__dom = null;
}
if (!this._ownerShadyRoot) {
this._ownerShadyRoot = undefined;
}
},
_poolContent: function () {
if (this._useContent) {
TreeApi.Logical.saveChildNodes(this);
}
},
_setupRoot: function () {
if (this._useContent) {
this._createLocalRoot();
if (!this.dataHost) {
upgradeLogicalChildren(TreeApi.Logical.getChildNodes(this));
}
}
},
_createLocalRoot: function () {
this.shadyRoot = this.root;
this.shadyRoot._distributionClean = false;
this.shadyRoot._hasDistributed = false;
this.shadyRoot._isShadyRoot = true;
this.shadyRoot._dirtyRoots = [];
var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : [];
TreeApi.Logical.saveChildNodes(this.shadyRoot);
for (var i = 0, c; i < i$.length; i++) {
c = i$[i];
TreeApi.Logical.saveChildNodes(c);
TreeApi.Logical.saveChildNodes(c.parentNode);
}
this.shadyRoot.host = this;
},
get domHost() {
var root = dom$0(this).getOwnerRoot();
return root && root.host;
},
distributeContent: function (updateInsertionPoints) {
if (this.shadyRoot) {
this.shadyRoot._invalidInsertionPoints = this.shadyRoot._invalidInsertionPoints || updateInsertionPoints;
var host = getTopDistributingHost(this);
dom$0(this)._lazyDistribute(host);
}
},
_distributeContent: function () {
if (this._useContent && !this.shadyRoot._distributionClean) {
if (this.shadyRoot._invalidInsertionPoints) {
dom$0(this)._updateInsertionPoints(this);
this.shadyRoot._invalidInsertionPoints = false;
}
this._beginDistribute();
this._distributeDirtyRoots();
this._finishDistribute();
}
},
_beginDistribute: function () {
if (this._useContent && DomApi.hasInsertionPoint(this.shadyRoot)) {
this._resetDistribution();
this._distributePool(this.shadyRoot, this._collectPool());
}
},
_distributeDirtyRoots: function () {
var c$ = this.shadyRoot._dirtyRoots;
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
c._distributeContent();
}
this.shadyRoot._dirtyRoots = [];
},
_finishDistribute: function () {
if (this._useContent) {
this.shadyRoot._distributionClean = true;
if (DomApi.hasInsertionPoint(this.shadyRoot)) {
this._composeTree();
notifyContentObservers(this.shadyRoot);
} else {
if (!this.shadyRoot._hasDistributed) {
TreeApi.Composed.clearChildNodes(this);
this.appendChild(this.shadyRoot);
} else {
var children = this._composeNode(this);
this._updateChildNodes(this, children);
}
}
if (!this.shadyRoot._hasDistributed) {
notifyInitialDistribution(this);
}
this.shadyRoot._hasDistributed = true;
}
},
elementMatches: function (selector, node) {
node = node || this;
return DomApi.matchesSelector.call(node, selector);
},
_resetDistribution: function () {
var children = TreeApi.Logical.getChildNodes(this);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child._destinationInsertionPoints) {
child._destinationInsertionPoints = undefined;
}
if (isInsertionPoint(child)) {
clearDistributedDestinationInsertionPoints(child);
}
}
var root = this.shadyRoot;
var p$ = root._insertionPoints;
for (var j = 0; j < p$.length; j++) {
p$[j]._distributedNodes = [];
}
},
_collectPool: function () {
var pool = [];
var children = TreeApi.Logical.getChildNodes(this);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (isInsertionPoint(child)) {
pool.push.apply(pool, child._distributedNodes);
} else {
pool.push(child);
}
}
return pool;
},
_distributePool: function (node, pool) {
var p$ = node._insertionPoints;
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
this._distributeInsertionPoint(p, pool);
maybeRedistributeParent(p, this);
}
},
_distributeInsertionPoint: function (content, pool) {
var anyDistributed = false;
for (var i = 0, l = pool.length, node; i < l; i++) {
node = pool[i];
if (!node) {
continue;
}
if (this._matchesContentSelect(node, content)) {
distributeNodeInto(node, content);
pool[i] = undefined;
anyDistributed = true;
}
}
if (!anyDistributed) {
var children = TreeApi.Logical.getChildNodes(content);
for (var j = 0; j < children.length; j++) {
distributeNodeInto(children[j], content);
}
}
},
_composeTree: function () {
this._updateChildNodes(this, this._composeNode(this));
var p$ = this.shadyRoot._insertionPoints;
for (var i = 0, l = p$.length, p, parent; i < l && (p = p$[i]); i++) {
parent = TreeApi.Logical.getParentNode(p);
if (!parent._useContent && parent !== this && parent !== this.shadyRoot) {
this._updateChildNodes(parent, this._composeNode(parent));
}
}
},
_composeNode: function (node) {
var children = [];
var c$ = TreeApi.Logical.getChildNodes(node.shadyRoot || node);
for (var i = 0; i < c$.length; i++) {
var child = c$[i];
if (isInsertionPoint(child)) {
var distributedNodes = child._distributedNodes;
for (var j = 0; j < distributedNodes.length; j++) {
var distributedNode = distributedNodes[j];
if (isFinalDestination(child, distributedNode)) {
children.push(distributedNode);
}
}
} else {
children.push(child);
}
}
return children;
},
_updateChildNodes: function (container, children) {
var composed = TreeApi.Composed.getChildNodes(container);
var splices = calculateSplices$0(children, composed);
for (var i = 0, d = 0, s; i < splices.length && (s = splices[i]); i++) {
for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
if (TreeApi.Composed.getParentNode(n) === container) {
TreeApi.Composed.removeChild(container, n);
}
composed.splice(s.index + d, 1);
}
d -= s.addedCount;
}
for (var i = 0, s, next; i < splices.length && (s = splices[i]); i++) {
next = composed[s.index];
for (j = s.index, n; j < s.index + s.addedCount; j++) {
n = children[j];
TreeApi.Composed.insertBefore(container, n, next);
composed.splice(j, 0, n);
}
}
},
_matchesContentSelect: function (node, contentElement) {
var select = contentElement.getAttribute('select');
if (!select) {
return true;
}
select = select.trim();
if (!select) {
return true;
}
if (!(node instanceof Element)) {
return false;
}
var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
if (!validSelectors.test(select)) {
return false;
}
return this.elementMatches(select, node);
},
_elementAdd: function () {
},
_elementRemove: function () {
}
});
var TreeApi = TreeApi;
var DomApi = DomApi$0;
if (useShadow$0) {
Base._addFeature({
_poolContent: function () {
},
_beginDistribute: function () {
},
distributeContent: function () {
},
_distributeContent: function () {
},
_finishDistribute: function () {
},
_createLocalRoot: function () {
this.createShadowRoot();
this.shadowRoot.appendChild(this.root);
this.root = this.shadowRoot;
}
});
}
export const Async = {
_currVal: 0,
_lastVal: 0,
_callbacks: [],
_twiddleContent: 0,
_twiddle: document.createTextNode(''),
run: function (callback, waitTime) {
if (waitTime > 0) {
return ~setTimeout(callback, waitTime);
} else {
this._twiddle.textContent = this._twiddleContent++;
this._callbacks.push(callback);
return this._currVal++;
}
},
cancel: function (handle) {
if (handle < 0) {
clearTimeout(~handle);
} else {
var idx = handle - this._lastVal;
if (idx >= 0) {
if (!this._callbacks[idx]) {
throw 'invalid async handle: ' + handle;
}
this._callbacks[idx] = null;
}
}
},
_atEndOfMicrotask: function () {
var len = this._callbacks.length;
for (var i = 0; i < len; i++) {
var cb = this._callbacks[i];
if (cb) {
try {
cb();
} catch (e) {
i++;
this._callbacks.splice(0, i);
this._lastVal += i;
this._twiddle.textContent = this._twiddleContent++;
throw e;
}
}
}
this._callbacks.splice(0, len);
this._lastVal += len;
}
};
new window.MutationObserver(function () {
async._atEndOfMicrotask();
}).observe(async._twiddle, { characterData: true });
export const Debounce = function () {
var Async = async;
var Debouncer = function (context) {
this.context = context;
var self = this;
this.boundComplete = function () {
self.complete();
};
};
Debouncer.prototype = {
go: function (callback, wait) {
var h;
this.finish = function () {
Async.cancel(h);
};
h = Async.run(this.boundComplete, wait);
this.callback = callback;
},
stop: function () {
if (this.finish) {
this.finish();
this.finish = null;
this.callback = null;
}
},
complete: function () {
if (this.finish) {
var callback = this.callback;
this.stop();
callback.call(this.context);
}
}
};
function debounce(debouncer, callback, wait) {
if (debouncer) {
debouncer.stop();
} else {
debouncer = new Debouncer(this);
}
debouncer.go(callback, wait);
return debouncer;
}
return debounce;
}();
Base._addFeature({
_setupDebouncers: function () {
this._debouncers = {};
},
debounce: function (jobName, callback, wait) {
return this._debouncers[jobName] = Debounce.call(this, this._debouncers[jobName], callback, wait);
},
isDebouncerActive: function (jobName) {
var debouncer = this._debouncers[jobName];
return !!(debouncer && debouncer.finish);
},
flushDebouncer: function (jobName) {
var debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.complete();
}
},
cancelDebouncer: function (jobName) {
var debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.stop();
}
}
});
export const DomModule = document.createElement('dom-module');
Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepBehaviors();
this._prepConstructor();
this._prepTemplate();
this._prepShady();
this._prepPropertyInfo();
},
_prepBehavior: function (b) {
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function () {
this._registerHost();
if (this._template) {
this._poolContent();
this._beginHosting();
this._stampTemplate();
this._endHosting();
}
this._marshalHostAttributes();
this._setupDebouncers();
this._marshalBehaviors();
this._tryReady();
},
_marshalBehavior: function (b) {
}
});
</script>
<script type="module">
import { dashToCamelCase, camelToDashCase } from '@polymer/polymer/lib/utils/case-map.js';
import { Base } from '@polymer/polymer/polymer-legacy.js';
import * as resolveUrl$1 from '@polymer/polymer/lib/utils/resolve-url.js';
import { resolveUrl as resolveUrl$0, resolveCss as resolveCss$0 } from '@polymer/polymer/lib/utils/resolve-url.js';
import { DomApi, dom as dom$0, addDebouncer, flush } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { findOriginalTarget as findOriginalTarget$0, add as add$0, remove as remove$0 } from '@polymer/polymer/lib/utils/gestures.js';
import { useNativeCustomElements, useNativeCSSProperties as useNativeCSSProperties$0 } from '@polymer/polymer/lib/utils/settings.js';
import * as async$0 from '@polymer/polymer/lib/utils/async.js';
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js';
import { Polymer as Polymer$0 } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { updateStyles as updateStyles$0 } from '@polymer/polymer/lib/mixins/element-mixin.js';
import * as renderStatus from '@polymer/polymer/lib/utils/render-status.js';
import { Templatizer as Templatizer$0 } from '@polymer/polymer/lib/legacy/templatizer-behavior.js';
export const nar = [];
export const Annotations = {
parseAnnotations: function (template) {
var list = [];
var content = template._content || template.content;
this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace'));
return list;
},
_parseNodeAnnotations: function (node, list, stripWhiteSpace) {
return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace);
},
_bindingRegex: function () {
var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$\\-*]*' + ')';
var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
var ARGUMENT_LIST = '(?:' + '\\(\\s*' + '(?:' + ARGUMENTS + '?' + ')' + '\\)\\s*' + ')';
var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')';
var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
var CLOSE_BRACKET = '(?:]]|}})';
var NEGATE = '(?:(!)\\s*)?';
var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
return new RegExp(EXPRESSION, 'g');
}(),
_parseBindings: function (text) {
var re = this._bindingRegex;
var parts = [];
var lastIndex = 0;
var m;
while ((m = re.exec(text)) !== null) {
if (m.index > lastIndex) {
parts.push({ literal: text.slice(lastIndex, m.index) });
}
var mode = m[1][0];
var negate = Boolean(m[2]);
var value = m[3].trim();
var customEvent, notifyEvent, colon;
if (mode == '{' && (colon = value.indexOf('::')) > 0) {
notifyEvent = value.substring(colon + 2);
value = value.substring(0, colon);
customEvent = true;
}
parts.push({
compoundIndex: parts.length,
value: value,
mode: mode,
negate: negate,
event: notifyEvent,
customEvent: customEvent
});
lastIndex = re.lastIndex;
}
if (lastIndex && lastIndex < text.length) {
var literal = text.substring(lastIndex);
if (literal) {
parts.push({ literal: literal });
}
}
if (parts.length) {
return parts;
}
},
_literalFromParts: function (parts) {
var s = '';
for (var i = 0; i < parts.length; i++) {
var literal = parts[i].literal;
s += literal || '';
}
return s;
},
_parseTextNodeAnnotation: function (node, list) {
var parts = this._parseBindings(node.textContent);
if (parts) {
node.textContent = this._literalFromParts(parts) || ' ';
var annote = {
bindings: [{
kind: 'text',
name: 'textContent',
parts: parts,
isCompound: parts.length !== 1
}]
};
list.push(annote);
return annote;
}
},
_parseElementAnnotations: function (element, list, stripWhiteSpace) {
var annote = {
bindings: [],
events: []
};
if (element.localName === 'content') {
list._hasContent = true;
}
this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace);
if (element.attributes) {
this._parseNodeAttributeAnnotations(element, annote, list);
if (this.prepElement) {
this.prepElement(element);
}
}
if (annote.bindings.length || annote.events.length || annote.id) {
list.push(annote);
}
return annote;
},
_parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) {
if (root.firstChild) {
var node = root.firstChild;
var i = 0;
while (node) {
var next = node.nextSibling;
if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
this._parseTemplate(node, i, list, annote);
}
if (node.nodeType === Node.TEXT_NODE) {
var n = next;
while (n && n.nodeType === Node.TEXT_NODE) {
node.textContent += n.textContent;
next = n.nextSibling;
root.removeChild(n);
n = next;
}
if (stripWhiteSpace && !node.textContent.trim()) {
root.removeChild(node);
i--;
}
}
if (node.parentNode) {
var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace);
if (childAnnotation) {
childAnnotation.parent = annote;
childAnnotation.index = i;
}
}
node = next;
i++;
}
}
},
_parseTemplate: function (node, index, list, parent) {
var content = document.createDocumentFragment();
content._notes = this.parseAnnotations(node);
content.appendChild(node.content);
list.push({
bindings: nar,
events: nar,
templateContent: content,
parent: parent,
index: index
});
},
_parseNodeAttributeAnnotations: function (node, annotation) {
var attrs = Array.prototype.slice.call(node.attributes);
for (var i = attrs.length - 1, a; a = attrs[i]; i--) {
var n = a.name;
var v = a.value;
var b;
if (n.slice(0, 3) === 'on-') {
node.removeAttribute(n);
annotation.events.push({
name: n.slice(3),
value: v
});
} else if (b = this._parseNodeAttributeAnnotation(node, n, v)) {
annotation.bindings.push(b);
} else if (n === 'id') {
annotation.id = v;
}
}
},
_parseNodeAttributeAnnotation: function (node, name, value) {
var parts = this._parseBindings(value);
if (parts) {
var origName = name;
var kind = 'property';
if (name[name.length - 1] == '$') {
name = name.slice(0, -1);
kind = 'attribute';
}
var literal = this._literalFromParts(parts);
if (literal && kind == 'attribute') {
node.setAttribute(name, literal);
}
if (node.localName === 'input' && origName === 'value') {
node.setAttribute(origName, '');
}
node.removeAttribute(origName);
var propertyName = dashToCamelCase(name);
if (kind === 'property') {
name = propertyName;
}
return {
kind: kind,
name: name,
propertyName: propertyName,
parts: parts,
literal: literal,
isCompound: parts.length !== 1
};
}
},
findAnnotatedNode: function (root, annote) {
var parent = annote.parent && Annotations.findAnnotatedNode(root, annote.parent);
if (parent) {
for (var n = parent.firstChild, i = 0; n; n = n.nextSibling) {
if (annote.index === i++) {
return n;
}
}
} else {
return root;
}
}
};
function resolveCss(cssText, ownerDocument) {
return cssText.replace(CSS_URL_RX, function (m, pre, url, post) {
return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + post;
});
}
function resolveAttrs(element, ownerDocument) {
for (var name in URL_ATTRS) {
var a$ = URL_ATTRS[name];
for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) {
if (name === '*' || element.localName === name) {
at = element.attributes[a];
v = at && at.value;
if (v && v.search(BINDING_RX) < 0) {
at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocument);
}
}
}
}
}
function resolve(url, ownerDocument) {
if (url && ABS_URL.test(url)) {
return url;
}
var resolver = getUrlResolver(ownerDocument);
resolver.href = url;
return resolver.href || url;
}
var tempDoc;
var tempDocBase;
function resolveUrl(url, baseUri) {
if (!tempDoc) {
tempDoc = document.implementation.createHTMLDocument('temp');
tempDocBase = tempDoc.createElement('base');
tempDoc.head.appendChild(tempDocBase);
}
tempDocBase.href = baseUri;
return resolve(url, tempDoc);
}
function getUrlResolver(ownerDocument) {
return ownerDocument.__urlResolver || (ownerDocument.__urlResolver = ownerDocument.createElement('a'));
}
var CSS_URL_RX = /(url\()([^)]*)(\))/g;
var URL_ATTRS = {
'*': [
'href',
'src',
'style',
'url'
],
form: ['action']
};
var ABS_URL = /(^\/)|(^#)|(^[\w-\d]*:)/;
var BINDING_RX = /\{\{|\[\[/;
export const ResolveUrl = {
resolveCss: resolveCss,
resolveAttrs: resolveAttrs,
resolveUrl: resolveUrl
};
Base._addFeature({
_prepAnnotations: function () {
if (!this._template) {
this._notes = [];
} else {
var self = this;
Annotations.prepElement = function (element) {
self._prepElement(element);
};
if (this._template._content && this._template._content._notes) {
this._notes = this._template._content._notes;
} else {
this._notes = Annotations.parseAnnotations(this._template);
this._processAnnotations(this._notes);
}
Annotations.prepElement = null;
}
},
_processAnnotations: function (notes) {
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
for (var j = 0; j < note.bindings.length; j++) {
var b = note.bindings[j];
for (var k = 0; k < b.parts.length; k++) {
var p = b.parts[k];
if (!p.literal) {
var signature = this._parseMethod(p.value);
if (signature) {
p.signature = signature;
} else {
p.model = this._modelForPath(p.value);
}
}
}
}
if (note.templateContent) {
this._processAnnotations(note.templateContent._notes);
var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(note.templateContent._notes);
var bindings = [];
for (var prop in pp) {
var name = '_parent_' + prop;
bindings.push({
index: note.index,
kind: 'property',
name: name,
propertyName: name,
parts: [{
mode: '{',
model: prop,
value: prop
}]
});
}
note.bindings = note.bindings.concat(bindings);
}
}
},
_discoverTemplateParentProps: function (notes) {
var pp = {};
for (var i = 0, n; i < notes.length && (n = notes[i]); i++) {
for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) {
for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) {
if (p.signature) {
var args = p.signature.args;
for (var kk = 0; kk < args.length; kk++) {
var model = args[kk].model;
if (model) {
pp[model] = true;
}
}
if (p.signature.dynamicFn) {
pp[p.signature.method] = true;
}
} else {
if (p.model) {
pp[p.model] = true;
}
}
}
}
if (n.templateContent) {
var tpp = n.templateContent._parentProps;
Base.mixin(pp, tpp);
}
}
return pp;
},
_prepElement: function (element) {
resolveUrl$1.resolveAttrs(element, this._template.ownerDocument);
},
_findAnnotatedNode: Annotations.findAnnotatedNode,
_marshalAnnotationReferences: function () {
if (this._template) {
this._marshalIdNodes();
this._marshalAnnotatedNodes();
this._marshalAnnotatedListeners();
}
},
_configureAnnotationReferences: function () {
var notes = this._notes;
var nodes = this._nodes;
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
var node = nodes[i];
this._configureTemplateContent(note, node);
this._configureCompoundBindings(note, node);
}
},
_configureTemplateContent: function (note, node) {
if (note.templateContent) {
node._content = note.templateContent;
}
},
_configureCompoundBindings: function (note, node) {
var bindings = note.bindings;
for (var i = 0; i < bindings.length; i++) {
var binding = bindings[i];
if (binding.isCompound) {
var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {});
var parts = binding.parts;
var literals = new Array(parts.length);
for (var j = 0; j < parts.length; j++) {
literals[j] = parts[j].literal;
}
var name = binding.name;
storage[name] = literals;
if (binding.literal && binding.kind == 'property') {
if (node._configValue) {
node._configValue(name, binding.literal);
} else {
node[name] = binding.literal;
}
}
}
}
},
_marshalIdNodes: function () {
this.$ = {};
for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
if (a.id) {
this.$[a.id] = this._findAnnotatedNode(this.root, a);
}
}
},
_marshalAnnotatedNodes: function () {
if (this._notes && this._notes.length) {
var r = new Array(this._notes.length);
for (var i = 0; i < this._notes.length; i++) {
r[i] = this._findAnnotatedNode(this.root, this._notes[i]);
}
this._nodes = r;
}
},
_marshalAnnotatedListeners: function () {
for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
if (a.events && a.events.length) {
var node = this._findAnnotatedNode(this.root, a);
for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) {
this.listen(node, e.name, e.value);
}
}
}
}
});Base._addFeature({
listeners: {},
_listenListeners: function (listeners) {
var node, name, eventName;
for (eventName in listeners) {
if (eventName.indexOf('.') < 0) {
node = this;
name = eventName;
} else {
name = eventName.split('.');
node = this.$[name[0]];
name = name[1];
}
this.listen(node, name, listeners[eventName]);
}
},
listen: function (node, eventName, methodName) {
var handler = this._recallEventHandler(this, eventName, node, methodName);
if (!handler) {
handler = this._createEventHandler(node, eventName, methodName);
}
if (handler._listening) {
return;
}
this._listen(node, eventName, handler);
handler._listening = true;
},
_boundListenerKey: function (eventName, methodName) {
return eventName + ':' + methodName;
},
_recordEventHandler: function (host, eventName, target, methodName, handler) {
var hbl = host.__boundListeners;
if (!hbl) {
hbl = host.__boundListeners = new WeakMap();
}
var bl = hbl.get(target);
if (!bl) {
bl = {};
hbl.set(target, bl);
}
var key = this._boundListenerKey(eventName, methodName);
bl[key] = handler;
},
_recallEventHandler: function (host, eventName, target, methodName) {
var hbl = host.__boundListeners;
if (!hbl) {
return;
}
var bl = hbl.get(target);
if (!bl) {
return;
}
var key = this._boundListenerKey(eventName, methodName);
return bl[key];
},
_createEventHandler: function (node, eventName, methodName) {
var host = this;
var handler = function (e) {
if (host[methodName]) {
host[methodName](e, e.detail);
} else {
host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined'));
}
};
handler._listening = false;
this._recordEventHandler(host, eventName, node, methodName, handler);
return handler;
},
unlisten: function (node, eventName, methodName) {
var handler = this._recallEventHandler(this, eventName, node, methodName);
if (handler) {
this._unlisten(node, eventName, handler);
handler._listening = false;
}
},
_listen: function (node, eventName, handler) {
node.addEventListener(eventName, handler);
},
_unlisten: function (node, eventName, handler) {
node.removeEventListener(eventName, handler);
}
});
var wrap = DomApi.wrap;
var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
var GESTURE_KEY = '__polymerGestures';
var HANDLED_OBJ = '__polymerGesturesHandled';
var TOUCH_ACTION = '__polymerGesturesTouchAction';
var TAP_DISTANCE = 25;
var TRACK_DISTANCE = 5;
var TRACK_LENGTH = 2;
var MOUSE_TIMEOUT = 2500;
var MOUSE_EVENTS = [
'mousedown',
'mousemove',
'mouseup',
'click'
];
var MOUSE_WHICH_TO_BUTTONS = [
0,
1,
4,
2
];
var MOUSE_HAS_BUTTONS = function () {
try {
return new MouseEvent('test', { buttons: 1 }).buttons === 1;
} catch (e) {
return false;
}
}();
var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
var mouseCanceller = function (mouseEvent) {
var sc = mouseEvent.sourceCapabilities;
if (sc && !sc.firesTouchEvents) {
return;
}
mouseEvent[HANDLED_OBJ] = { skip: true };
if (mouseEvent.type === 'click') {
var path = dom$0(mouseEvent).path;
for (var i = 0; i < path.length; i++) {
if (path[i] === POINTERSTATE.mouse.target) {
return;
}
}
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
}
};
function setupTeardownMouseCanceller(setup) {
for (var i = 0, en; i < MOUSE_EVENTS.length; i++) {
en = MOUSE_EVENTS[i];
if (setup) {
document.addEventListener(en, mouseCanceller, true);
} else {
document.removeEventListener(en, mouseCanceller, true);
}
}
}
function ignoreMouse() {
if (IS_TOUCH_ONLY) {
return;
}
if (!POINTERSTATE.mouse.mouseIgnoreJob) {
setupTeardownMouseCanceller(true);
}
var unset = function () {
setupTeardownMouseCanceller();
POINTERSTATE.mouse.target = null;
POINTERSTATE.mouse.mouseIgnoreJob = null;
};
POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT);
}
function hasLeftMouseButton(ev) {
var type = ev.type;
if (MOUSE_EVENTS.indexOf(type) === -1) {
return false;
}
if (type === 'mousemove') {
var buttons = ev.buttons === undefined ? 1 : ev.buttons;
if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
}
return Boolean(buttons & 1);
} else {
var button = ev.button === undefined ? 0 : ev.button;
return button === 0;
}
}
function isSyntheticClick(ev) {
if (ev.type === 'click') {
if (ev.detail === 0) {
return true;
}
var t = findOriginalTarget$0(ev);
var bcr = t.getBoundingClientRect();
var x = ev.pageX, y = ev.pageY;
return !(x >= bcr.left && x <= bcr.right && (y >= bcr.top && y <= bcr.bottom));
}
return false;
}
var POINTERSTATE = {
mouse: {
target: null,
mouseIgnoreJob: null
},
touch: {
x: 0,
y: 0,
id: -1,
scrollDecided: false
}
};
function firstTouchAction(ev) {
var path = dom$0(ev).path;
var ta = 'auto';
for (var i = 0, n; i < path.length; i++) {
n = path[i];
if (n[TOUCH_ACTION]) {
ta = n[TOUCH_ACTION];
break;
}
}
return ta;
}
function trackDocument(stateObj, movefn, upfn) {
stateObj.movefn = movefn;
stateObj.upfn = upfn;
document.addEventListener('mousemove', movefn);
document.addEventListener('mouseup', upfn);
}
function untrackDocument(stateObj) {
document.removeEventListener('mousemove', stateObj.movefn);
document.removeEventListener('mouseup', stateObj.upfn);
stateObj.movefn = null;
stateObj.upfn = null;
}
var Gestures = {
gestures: {},
recognizers: [],
deepTargetFind: function (x, y) {
var node = document.elementFromPoint(x, y);
var next = node;
while (next && next.shadowRoot) {
next = next.shadowRoot.elementFromPoint(x, y);
if (next) {
node = next;
}
}
return node;
},
findOriginalTarget: function (ev) {
if (ev.path) {
return ev.path[0];
}
return ev.target;
},
handleNative: function (ev) {
var handled;
var type = ev.type;
var node = wrap(ev.currentTarget);
var gobj = node[GESTURE_KEY];
if (!gobj) {
return;
}
var gs = gobj[type];
if (!gs) {
return;
}
if (!ev[HANDLED_OBJ]) {
ev[HANDLED_OBJ] = {};
if (type.slice(0, 5) === 'touch') {
var t = ev.changedTouches[0];
if (type === 'touchstart') {
if (ev.touches.length === 1) {
POINTERSTATE.touch.id = t.identifier;
}
}
if (POINTERSTATE.touch.id !== t.identifier) {
return;
}
if (!HAS_NATIVE_TA) {
if (type === 'touchstart' || type === 'touchmove') {
Gestures.handleTouchAction(ev);
}
}
if (type === 'touchend') {
POINTERSTATE.mouse.target = dom$0(ev).rootTarget;
ignoreMouse();
}
}
}
handled = ev[HANDLED_OBJ];
if (handled.skip) {
return;
}
var recognizers = Gestures.recognizers;
for (var i = 0, r; i < recognizers.length; i++) {
r = recognizers[i];
if (gs[r.name] && !handled[r.name]) {
if (r.flow && r.flow.start.indexOf(ev.type) > -1 && r.reset) {
r.reset();
}
}
}
for (i = 0, r; i < recognizers.length; i++) {
r = recognizers[i];
if (gs[r.name] && !handled[r.name]) {
handled[r.name] = true;
r[type](ev);
}
}
},
handleTouchAction: function (ev) {
var t = ev.changedTouches[0];
var type = ev.type;
if (type === 'touchstart') {
POINTERSTATE.touch.x = t.clientX;
POINTERSTATE.touch.y = t.clientY;
POINTERSTATE.touch.scrollDecided = false;
} else if (type === 'touchmove') {
if (POINTERSTATE.touch.scrollDecided) {
return;
}
POINTERSTATE.touch.scrollDecided = true;
var ta = firstTouchAction(ev);
var prevent = false;
var dx = Math.abs(POINTERSTATE.touch.x - t.clientX);
var dy = Math.abs(POINTERSTATE.touch.y - t.clientY);
if (!ev.cancelable) {
} else if (ta === 'none') {
prevent = true;
} else if (ta === 'pan-x') {
prevent = dy > dx;
} else if (ta === 'pan-y') {
prevent = dx > dy;
}
if (prevent) {
ev.preventDefault();
} else {
Gestures.prevent('track');
}
}
},
add: function (node, evType, handler) {
node = wrap(node);
var recognizer = this.gestures[evType];
var deps = recognizer.deps;
var name = recognizer.name;
var gobj = node[GESTURE_KEY];
if (!gobj) {
node[GESTURE_KEY] = gobj = {};
}
for (var i = 0, dep, gd; i < deps.length; i++) {
dep = deps[i];
if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) {
continue;
}
gd = gobj[dep];
if (!gd) {
gobj[dep] = gd = { _count: 0 };
}
if (gd._count === 0) {
node.addEventListener(dep, this.handleNative);
}
gd[name] = (gd[name] || 0) + 1;
gd._count = (gd._count || 0) + 1;
}
node.addEventListener(evType, handler);
if (recognizer.touchAction) {
this.setTouchAction(node, recognizer.touchAction);
}
},
remove: function (node, evType, handler) {
node = wrap(node);
var recognizer = this.gestures[evType];
var deps = recognizer.deps;
var name = recognizer.name;
var gobj = node[GESTURE_KEY];
if (gobj) {
for (var i = 0, dep, gd; i < deps.length; i++) {
dep = deps[i];
gd = gobj[dep];
if (gd && gd[name]) {
gd[name] = (gd[name] || 1) - 1;
gd._count = (gd._count || 1) - 1;
if (gd._count === 0) {
node.removeEventListener(dep, this.handleNative);
}
}
}
}
node.removeEventListener(evType, handler);
},
register: function (recog) {
this.recognizers.push(recog);
for (var i = 0; i < recog.emits.length; i++) {
this.gestures[recog.emits[i]] = recog;
}
},
findRecognizerByEvent: function (evName) {
for (var i = 0, r; i < this.recognizers.length; i++) {
r = this.recognizers[i];
for (var j = 0, n; j < r.emits.length; j++) {
n = r.emits[j];
if (n === evName) {
return r;
}
}
}
return null;
},
setTouchAction: function (node, value) {
if (HAS_NATIVE_TA) {
node.style.touchAction = value;
}
node[TOUCH_ACTION] = value;
},
fire: function (target, type, detail) {
var ev = Base.fire(type, detail, {
node: target,
bubbles: true,
cancelable: true
});
if (ev.defaultPrevented) {
var preventer = detail.preventer || detail.sourceEvent;
if (preventer && preventer.preventDefault) {
preventer.preventDefault();
}
}
},
prevent: function (evName) {
var recognizer = this.findRecognizerByEvent(evName);
if (recognizer.info) {
recognizer.info.prevent = true;
}
},
resetMouseCanceller: function () {
if (POINTERSTATE.mouse.mouseIgnoreJob) {
POINTERSTATE.mouse.mouseIgnoreJob.complete();
}
}
};
Gestures.register({
name: 'downup',
deps: [
'mousedown',
'touchstart',
'touchend'
],
flow: {
start: [
'mousedown',
'touchstart'
],
end: [
'mouseup',
'touchend'
]
},
emits: [
'down',
'up'
],
info: {
movefn: null,
upfn: null
},
reset: function () {
untrackDocument(this.info);
},
mousedown: function (e) {
if (!hasLeftMouseButton(e)) {
return;
}
var t = findOriginalTarget$0(e);
var self = this;
var movefn = function movefn(e) {
if (!hasLeftMouseButton(e)) {
self.fire('up', t, e);
untrackDocument(self.info);
}
};
var upfn = function upfn(e) {
if (hasLeftMouseButton(e)) {
self.fire('up', t, e);
}
untrackDocument(self.info);
};
trackDocument(this.info, movefn, upfn);
this.fire('down', t, e);
},
touchstart: function (e) {
this.fire('down', findOriginalTarget$0(e), e.changedTouches[0], e);
},
touchend: function (e) {
this.fire('up', findOriginalTarget$0(e), e.changedTouches[0], e);
},
fire: function (type, target, event, preventer) {
Gestures.fire(target, type, {
x: event.clientX,
y: event.clientY,
sourceEvent: event,
preventer: preventer,
prevent: function (e) {
return Gestures.prevent(e);
}
});
}
});
Gestures.register({
name: 'track',
touchAction: 'none',
deps: [
'mousedown',
'touchstart',
'touchmove',
'touchend'
],
flow: {
start: [
'mousedown',
'touchstart'
],
end: [
'mouseup',
'touchend'
]
},
emits: ['track'],
info: {
x: 0,
y: 0,
state: 'start',
started: false,
moves: [],
addMove: function (move) {
if (this.moves.length > TRACK_LENGTH) {
this.moves.shift();
}
this.moves.push(move);
},
movefn: null,
upfn: null,
prevent: false
},
reset: function () {
this.info.state = 'start';
this.info.started = false;
this.info.moves = [];
this.info.x = 0;
this.info.y = 0;
this.info.prevent = false;
untrackDocument(this.info);
},
hasMovedEnough: function (x, y) {
if (this.info.prevent) {
return false;
}
if (this.info.started) {
return true;
}
var dx = Math.abs(this.info.x - x);
var dy = Math.abs(this.info.y - y);
return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE;
},
mousedown: function (e) {
if (!hasLeftMouseButton(e)) {
return;
}
var t = findOriginalTarget$0(e);
var self = this;
var movefn = function movefn(e) {
var x = e.clientX, y = e.clientY;
if (self.hasMovedEnough(x, y)) {
self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : 'start';
if (self.info.state === 'start') {
Gestures.prevent('tap');
}
self.info.addMove({
x: x,
y: y
});
if (!hasLeftMouseButton(e)) {
self.info.state = 'end';
untrackDocument(self.info);
}
self.fire(t, e);
self.info.started = true;
}
};
var upfn = function upfn(e) {
if (self.info.started) {
movefn(e);
}
untrackDocument(self.info);
};
trackDocument(this.info, movefn, upfn);
this.info.x = e.clientX;
this.info.y = e.clientY;
},
touchstart: function (e) {
var ct = e.changedTouches[0];
this.info.x = ct.clientX;
this.info.y = ct.clientY;
},
touchmove: function (e) {
var t = findOriginalTarget$0(e);
var ct = e.changedTouches[0];
var x = ct.clientX, y = ct.clientY;
if (this.hasMovedEnough(x, y)) {
if (this.info.state === 'start') {
Gestures.prevent('tap');
}
this.info.addMove({
x: x,
y: y
});
this.fire(t, ct);
this.info.state = 'track';
this.info.started = true;
}
},
touchend: function (e) {
var t = findOriginalTarget$0(e);
var ct = e.changedTouches[0];
if (this.info.started) {
this.info.state = 'end';
this.info.addMove({
x: ct.clientX,
y: ct.clientY
});
this.fire(t, ct, e);
}
},
fire: function (target, touch, preventer) {
var secondlast = this.info.moves[this.info.moves.length - 2];
var lastmove = this.info.moves[this.info.moves.length - 1];
var dx = lastmove.x - this.info.x;
var dy = lastmove.y - this.info.y;
var ddx, ddy = 0;
if (secondlast) {
ddx = lastmove.x - secondlast.x;
ddy = lastmove.y - secondlast.y;
}
return Gestures.fire(target, 'track', {
state: this.info.state,
x: touch.clientX,
y: touch.clientY,
dx: dx,
dy: dy,
ddx: ddx,
ddy: ddy,
sourceEvent: touch,
preventer: preventer,
hover: function () {
return Gestures.deepTargetFind(touch.clientX, touch.clientY);
}
});
}
});
Gestures.register({
name: 'tap',
deps: [
'mousedown',
'click',
'touchstart',
'touchend'
],
flow: {
start: [
'mousedown',
'touchstart'
],
end: [
'click',
'touchend'
]
},
emits: ['tap'],
info: {
x: NaN,
y: NaN,
prevent: false
},
reset: function () {
this.info.x = NaN;
this.info.y = NaN;
this.info.prevent = false;
},
save: function (e) {
this.info.x = e.clientX;
this.info.y = e.clientY;
},
mousedown: function (e) {
if (hasLeftMouseButton(e)) {
this.save(e);
}
},
click: function (e) {
if (hasLeftMouseButton(e)) {
this.forward(e);
}
},
touchstart: function (e) {
this.save(e.changedTouches[0], e);
},
touchend: function (e) {
this.forward(e.changedTouches[0], e);
},
forward: function (e, preventer) {
var dx = Math.abs(e.clientX - this.info.x);
var dy = Math.abs(e.clientY - this.info.y);
var t = findOriginalTarget$0(e);
if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE || isSyntheticClick(e)) {
if (!this.info.prevent) {
Gestures.fire(t, 'tap', {
x: e.clientX,
y: e.clientY,
sourceEvent: e,
preventer: preventer
});
}
}
}
});
var DIRECTION_MAP = {
x: 'pan-x',
y: 'pan-y',
none: 'none',
all: 'auto'
};
Base._addFeature({
_setupGestures: function () {
this.__polymerGestures = null;
},
_listen: function (node, eventName, handler) {
if (Gestures.gestures[eventName]) {
add$0(node, eventName, handler);
} else {
node.addEventListener(eventName, handler);
}
},
_unlisten: function (node, eventName, handler) {
if (Gestures.gestures[eventName]) {
remove$0(node, eventName, handler);
} else {
node.removeEventListener(eventName, handler);
}
},
setScrollDirection: function (direction, node) {
node = node || this;
Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto');
}
});
export { Gestures };
if (!useNativeCustomElements) {
var importHref = Base.importHref;
Base.importHref = function (href, onload, onerror, optAsync) {
CustomElements.ready = false;
var loadFn = function (e) {
CustomElements.upgradeDocumentTree(document);
CustomElements.ready = true;
if (onload) {
return onload.call(this, e);
}
};
return importHref.call(this, href, loadFn, onerror, optAsync);
};
}
Base._addFeature({
$$: function (slctr) {
return dom$0(this.root).querySelector(slctr);
},
toggleClass: function (name, bool, node) {
node = node || this;
if (arguments.length == 1) {
bool = !node.classList.contains(name);
}
if (bool) {
dom$0(node).classList.add(name);
} else {
dom$0(node).classList.remove(name);
}
},
toggleAttribute: function (name, bool, node) {
node = node || this;
if (arguments.length == 1) {
bool = !node.hasAttribute(name);
}
if (bool) {
dom$0(node).setAttribute(name, '');
} else {
dom$0(node).removeAttribute(name);
}
},
classFollows: function (name, toElement, fromElement) {
if (fromElement) {
dom$0(fromElement).classList.remove(name);
}
if (toElement) {
dom$0(toElement).classList.add(name);
}
},
attributeFollows: function (name, toElement, fromElement) {
if (fromElement) {
dom$0(fromElement).removeAttribute(name);
}
if (toElement) {
dom$0(toElement).setAttribute(name, '');
}
},
getEffectiveChildNodes: function () {
return dom$0(this).getEffectiveChildNodes();
},
getEffectiveChildren: function () {
var list = dom$0(this).getEffectiveChildNodes();
return list.filter(function (n) {
return n.nodeType === Node.ELEMENT_NODE;
});
},
getEffectiveTextContent: function () {
var cn = this.getEffectiveChildNodes();
var tc = [];
for (var i = 0, c; c = cn[i]; i++) {
if (c.nodeType !== Node.COMMENT_NODE) {
tc.push(dom$0(c).textContent);
}
}
return tc.join('');
},
queryEffectiveChildren: function (slctr) {
var e$ = dom$0(this).queryDistributedElements(slctr);
return e$ && e$[0];
},
queryAllEffectiveChildren: function (slctr) {
return dom$0(this).queryDistributedElements(slctr);
},
getContentChildNodes: function (slctr) {
var content = dom$0(this.root).querySelector(slctr || 'content');
return content ? dom$0(content).getDistributedNodes() : [];
},
getContentChildren: function (slctr) {
return this.getContentChildNodes(slctr).filter(function (n) {
return n.nodeType === Node.ELEMENT_NODE;
});
},
fire: function (type, detail, options) {
options = options || Polymer.nob;
var node = options.node || this;
detail = detail === null || detail === undefined ? {} : detail;
var bubbles = options.bubbles === undefined ? true : options.bubbles;
var cancelable = Boolean(options.cancelable);
var useCache = options._useCache;
var event = this._getEvent(type, bubbles, cancelable, useCache);
event.detail = detail;
if (useCache) {
this.__eventCache[type] = null;
}
node.dispatchEvent(event);
if (useCache) {
this.__eventCache[type] = event;
}
return event;
},
__eventCache: {},
_getEvent: function (type, bubbles, cancelable, useCache) {
var event = useCache && this.__eventCache[type];
if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) {
event = new Event(type, {
bubbles: Boolean(bubbles),
cancelable: cancelable
});
}
return event;
},
async: function (callback, waitTime) {
var self = this;
return async$0.run(function () {
callback.call(self);
}, waitTime);
},
cancelAsync: function (handle) {
async$0.cancel(handle);
},
arrayDelete: function (path, item) {
var index;
if (Array.isArray(path)) {
index = path.indexOf(item);
if (index >= 0) {
return path.splice(index, 1);
}
} else {
var arr = this._get(path);
index = arr.indexOf(item);
if (index >= 0) {
return this.splice(path, index, 1);
}
}
},
transform: function (transform, node) {
node = node || this;
node.style.webkitTransform = transform;
node.style.transform = transform;
},
translate3d: function (x, y, z, node) {
node = node || this;
this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
},
importHref: function (href, onload, onerror, optAsync) {
var link = document.createElement('link');
link.rel = 'import';
link.href = href;
var list = Base.importHref.imported = Base.importHref.imported || {};
var cached = list[link.href];
var imprt = cached || link;
var self = this;
if (onload) {
var loadListener = function (e) {
e.target.__firedLoad = true;
e.target.removeEventListener('load', loadListener);
return onload.call(self, e);
};
imprt.addEventListener('load', loadListener);
}
if (onerror) {
var errorListener = function (e) {
e.target.__firedError = true;
e.target.removeEventListener('error', errorListener);
return onerror.call(self, e);
};
imprt.addEventListener('error', errorListener);
}
if (cached) {
if (cached.__firedLoad) {
cached.dispatchEvent(new Event('load'));
}
if (cached.__firedError) {
cached.dispatchEvent(new Event('error'));
}
} else {
list[link.href] = link;
optAsync = Boolean(optAsync);
if (optAsync) {
link.setAttribute('async', '');
}
document.head.appendChild(link);
}
return imprt;
},
create: function (tag, props) {
var elt = document.createElement(tag);
if (props) {
for (var n in props) {
elt[n] = props[n];
}
}
return elt;
},
isLightDescendant: function (node) {
return this !== node && this.contains(node) && dom$0(this).getOwnerRoot() === dom$0(node).getOwnerRoot();
},
isLocalDescendant: function (node) {
return this.root === dom$0(node).getOwnerRoot();
}
});
export const Bind = {
prepareModel: function (model) {
Base.mixin(model, this._modelApi);
},
_modelApi: {
_notifyChange: function (source, event, value) {
value = value === undefined ? this[source] : value;
event = event || camelToDashCase(source) + '-changed';
this.fire(event, { value: value }, {
bubbles: false,
cancelable: false,
_useCache: true
});
},
_propertySetter: function (property, value, effects, fromAbove) {
var old = this.__data__[property];
if (old !== value && (old === old || value === value)) {
this.__data__[property] = value;
if (typeof value == 'object') {
this._clearPath(property);
}
if (this._propertyChanged) {
this._propertyChanged(property, value, old);
}
if (effects) {
this._effectEffects(property, value, effects, old, fromAbove);
}
}
return old;
},
__setProperty: function (property, value, quiet, node) {
node = node || this;
var effects = node._propertyEffects && node._propertyEffects[property];
if (effects) {
node._propertySetter(property, value, effects, quiet);
} else if (node[property] !== value) {
node[property] = value;
}
},
_effectEffects: function (property, value, effects, old, fromAbove) {
for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) {
fx.fn.call(this, property, this[property], fx.effect, old, fromAbove);
}
},
_clearPath: function (path) {
for (var prop in this.__data__) {
if (prop.indexOf(path + '.') === 0) {
this.__data__[prop] = undefined;
}
}
}
},
ensurePropertyEffects: function (model, property) {
if (!model._propertyEffects) {
model._propertyEffects = {};
}
var fx = model._propertyEffects[property];
if (!fx) {
fx = model._propertyEffects[property] = [];
}
return fx;
},
addPropertyEffect: function (model, property, kind, effect) {
var fx = this.ensurePropertyEffects(model, property);
var propEffect = {
kind: kind,
effect: effect,
fn: Bind['_' + kind + 'Effect']
};
fx.push(propEffect);
return propEffect;
},
createBindings: function (model) {
var fx$ = model._propertyEffects;
if (fx$) {
for (var n in fx$) {
var fx = fx$[n];
fx.sort(this._sortPropertyEffects);
this._createAccessors(model, n, fx);
}
}
},
_sortPropertyEffects: function () {
var EFFECT_ORDER = {
'compute': 0,
'annotation': 1,
'annotatedComputation': 2,
'reflect': 3,
'notify': 4,
'observer': 5,
'complexObserver': 6,
'function': 7
};
return function (a, b) {
return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind];
};
}(),
_createAccessors: function (model, property, effects) {
var defun = {
get: function () {
return this.__data__[property];
}
};
var setter = function (value) {
this._propertySetter(property, value, effects);
};
var info = model.getPropertyInfo && model.getPropertyInfo(property);
if (info && info.readOnly) {
if (!info.computed) {
model['_set' + this.upper(property)] = setter;
}
} else {
defun.set = setter;
}
Object.defineProperty(model, property, defun);
},
upper: function (name) {
return name[0].toUpperCase() + name.substring(1);
},
_addAnnotatedListener: function (model, index, property, path, event, negated) {
if (!model._bindListeners) {
model._bindListeners = [];
}
var fn = this._notedListenerFactory(property, path, this._isStructured(path), negated);
var eventName = event || camelToDashCase(property) + '-changed';
model._bindListeners.push({
index: index,
property: property,
path: path,
changedFn: fn,
event: eventName
});
},
_isStructured: function (path) {
return path.indexOf('.') > 0;
},
_isEventBogus: function (e, target) {
return e.path && e.path[0] !== target;
},
_notedListenerFactory: function (property, path, isStructured, negated) {
return function (target, value, targetPath) {
if (targetPath) {
this._notifyPath(this._fixPath(path, property, targetPath), value);
} else {
value = target[property];
if (negated) {
value = !value;
}
if (!isStructured) {
this[path] = value;
} else {
if (this.__data__[path] != value) {
this.set(path, value);
}
}
}
};
},
prepareInstance: function (inst) {
inst.__data__ = Object.create(null);
},
setupBindListeners: function (inst) {
var b$ = inst._bindListeners;
for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) {
var node = inst._nodes[info.index];
this._addNotifyListener(node, inst, info.event, info.changedFn);
}
},
_addNotifyListener: function (element, context, event, changedFn) {
element.addEventListener(event, function (e) {
return context._notifyListener(changedFn, e);
});
}
};
Base.extend(Bind, {
_shouldAddListener: function (effect) {
return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{';
},
_annotationEffect: function (source, value, effect) {
if (source != effect.value) {
value = this._get(effect.value);
this.__data__[effect.value] = value;
}
this._applyEffectValue(effect, value);
},
_reflectEffect: function (source, value, effect) {
this.reflectPropertyToAttribute(source, effect.attribute, value);
},
_notifyEffect: function (source, value, effect, old, fromAbove) {
if (!fromAbove) {
this._notifyChange(source, effect.event, value);
}
},
_functionEffect: function (source, value, fn, old, fromAbove) {
fn.call(this, source, value, old, fromAbove);
},
_observerEffect: function (source, value, effect, old) {
var fn = this[effect.method];
if (fn) {
fn.call(this, value, old);
} else {
this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + '` not defined'));
}
},
_complexObserverEffect: function (source, value, effect) {
var fn = this[effect.method];
if (fn) {
var args = Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
fn.apply(this, args);
}
} else if (effect.dynamicFn) {
} else {
this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.method + '` not defined'));
}
},
_computeEffect: function (source, value, effect) {
var fn = this[effect.method];
if (fn) {
var args = Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var computedvalue = fn.apply(this, args);
this.__setProperty(effect.name, computedvalue);
}
} else if (effect.dynamicFn) {
} else {
this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
}
},
_annotatedComputationEffect: function (source, value, effect) {
var computedHost = this._rootDataHost || this;
var fn = computedHost[effect.method];
if (fn) {
var args = Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var computedvalue = fn.apply(computedHost, args);
this._applyEffectValue(effect, computedvalue);
}
} else if (effect.dynamicFn) {
} else {
computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined'));
}
},
_marshalArgs: function (model, effect, path, value) {
var values = [];
var args = effect.args;
var bailoutEarly = args.length > 1 || effect.dynamicFn;
for (var i = 0, l = args.length; i < l; i++) {
var arg = args[i];
var name = arg.name;
var v;
if (arg.literal) {
v = arg.value;
} else if (path === name) {
v = value;
} else {
v = model[name];
if (v === undefined && arg.structured) {
v = Base._get(name, model);
}
}
if (bailoutEarly && v === undefined) {
return;
}
if (arg.wildcard) {
var matches = path.indexOf(name + '.') === 0;
values[i] = {
path: matches ? path : name,
value: matches ? value : v,
base: v
};
} else {
values[i] = v;
}
}
return values;
}
});Base._addFeature({
_addPropertyEffect: function (property, kind, effect) {
var prop = Bind.addPropertyEffect(this, property, kind, effect);
prop.pathFn = this['_' + prop.kind + 'PathEffect'];
},
_prepEffects: function () {
Bind.prepareModel(this);
this._addAnnotationEffects(this._notes);
},
_prepBindings: function () {
Bind.createBindings(this);
},
_addPropertyEffects: function (properties) {
if (properties) {
for (var p in properties) {
var prop = properties[p];
if (prop.observer) {
this._addObserverEffect(p, prop.observer);
}
if (prop.computed) {
prop.readOnly = true;
this._addComputedEffect(p, prop.computed);
}
if (prop.notify) {
this._addPropertyEffect(p, 'notify', { event: camelToDashCase(p) + '-changed' });
}
if (prop.reflectToAttribute) {
var attr = camelToDashCase(p);
if (attr[0] === '-') {
this._warn(this._logf('_addPropertyEffects', 'Property ' + p + ' cannot be reflected to attribute ' + attr + ' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.'));
} else {
this._addPropertyEffect(p, 'reflect', { attribute: attr });
}
}
if (prop.readOnly) {
Bind.ensurePropertyEffects(this, p);
}
}
}
},
_addComputedEffect: function (name, expression) {
var sig = this._parseMethod(expression);
var dynamicFn = sig.dynamicFn;
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
this._addPropertyEffect(arg.model, 'compute', {
method: sig.method,
args: sig.args,
trigger: arg,
name: name,
dynamicFn: dynamicFn
});
}
if (dynamicFn) {
this._addPropertyEffect(sig.method, 'compute', {
method: sig.method,
args: sig.args,
trigger: null,
name: name,
dynamicFn: dynamicFn
});
}
},
_addObserverEffect: function (property, observer) {
this._addPropertyEffect(property, 'observer', {
method: observer,
property: property
});
},
_addComplexObserverEffects: function (observers) {
if (observers) {
for (var i = 0, o; i < observers.length && (o = observers[i]); i++) {
this._addComplexObserverEffect(o);
}
}
},
_addComplexObserverEffect: function (observer) {
var sig = this._parseMethod(observer);
if (!sig) {
throw new Error('Malformed observer expression \'' + observer + '\'');
}
var dynamicFn = sig.dynamicFn;
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
this._addPropertyEffect(arg.model, 'complexObserver', {
method: sig.method,
args: sig.args,
trigger: arg,
dynamicFn: dynamicFn
});
}
if (dynamicFn) {
this._addPropertyEffect(sig.method, 'complexObserver', {
method: sig.method,
args: sig.args,
trigger: null,
dynamicFn: dynamicFn
});
}
},
_addAnnotationEffects: function (notes) {
for (var i = 0, note; i < notes.length && (note = notes[i]); i++) {
var b$ = note.bindings;
for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) {
this._addAnnotationEffect(binding, i);
}
}
},
_addAnnotationEffect: function (note, index) {
if (Bind._shouldAddListener(note)) {
Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event, note.parts[0].negate);
}
for (var i = 0; i < note.parts.length; i++) {
var part = note.parts[i];
if (part.signature) {
this._addAnnotatedComputationEffect(note, part, index);
} else if (!part.literal) {
if (note.kind === 'attribute' && note.name[0] === '-') {
this._warn(this._logf('_addAnnotationEffect', 'Cannot set attribute ' + note.name + ' because "-" is not a valid attribute starting character'));
} else {
this._addPropertyEffect(part.model, 'annotation', {
kind: note.kind,
index: index,
name: note.name,
propertyName: note.propertyName,
value: part.value,
isCompound: note.isCompound,
compoundIndex: part.compoundIndex,
event: part.event,
customEvent: part.customEvent,
negate: part.negate
});
}
}
}
},
_addAnnotatedComputationEffect: function (note, part, index) {
var sig = part.signature;
if (sig.static) {
this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
} else {
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
if (!arg.literal) {
this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
}
}
if (sig.dynamicFn) {
this.__addAnnotatedComputationEffect(sig.method, index, note, part, null);
}
}
},
__addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
this._addPropertyEffect(property, 'annotatedComputation', {
index: index,
isCompound: note.isCompound,
compoundIndex: part.compoundIndex,
kind: note.kind,
name: note.name,
negate: part.negate,
method: part.signature.method,
args: part.signature.args,
trigger: trigger,
dynamicFn: part.signature.dynamicFn
});
},
_parseMethod: function (expression) {
var m = expression.match(/([^\s]+?)\(([\s\S]*)\)/);
if (m) {
var sig = {
method: m[1],
static: true
};
if (this.getPropertyInfo(sig.method) !== Polymer.nob) {
sig.static = false;
sig.dynamicFn = true;
}
if (m[2].trim()) {
var args = m[2].replace(/\\,/g, ',').split(',');
return this._parseArgs(args, sig);
} else {
sig.args = nar;
return sig;
}
}
},
_parseArgs: function (argList, sig) {
sig.args = argList.map(function (rawArg) {
var arg = this._parseArg(rawArg);
if (!arg.literal) {
sig.static = false;
}
return arg;
}, this);
return sig;
},
_parseArg: function (rawArg) {
var arg = rawArg.trim().replace(/,/g, ',').replace(/\\(.)/g, '$1');
var a = { name: arg };
var fc = arg[0];
if (fc === '-') {
fc = arg[1];
}
if (fc >= '0' && fc <= '9') {
fc = '#';
}
switch (fc) {
case '\'':
case '"':
a.value = arg.slice(1, -1);
a.literal = true;
break;
case '#':
a.value = Number(arg);
a.literal = true;
break;
}
if (!a.literal) {
a.model = this._modelForPath(arg);
a.structured = arg.indexOf('.') > 0;
if (a.structured) {
a.wildcard = arg.slice(-2) == '.*';
if (a.wildcard) {
a.name = arg.slice(0, -2);
}
}
}
return a;
},
_marshalInstanceEffects: function () {
Bind.prepareInstance(this);
if (this._bindListeners) {
Bind.setupBindListeners(this);
}
},
_applyEffectValue: function (info, value) {
var node = this._nodes[info.index];
var property = info.name;
value = this._computeFinalAnnotationValue(node, property, value, info);
if (info.kind == 'attribute') {
this.serializeValueToAttribute(value, property, node);
} else {
var pinfo = node._propertyInfo && node._propertyInfo[property];
if (pinfo && pinfo.readOnly) {
return;
}
this.__setProperty(property, value, false, node);
}
},
_computeFinalAnnotationValue: function (node, property, value, info) {
if (info.negate) {
value = !value;
}
if (info.isCompound) {
var storage = node.__compoundStorage__[property];
storage[info.compoundIndex] = value;
value = storage.join('');
}
if (info.kind !== 'attribute') {
if (property === 'className') {
value = this._scopeElementClass(node, value);
}
if (property === 'textContent' || node.localName == 'input' && property == 'value') {
value = value == undefined ? '' : value;
}
}
return value;
},
_executeStaticEffects: function () {
if (this._propertyEffects && this._propertyEffects.__static__) {
this._effectEffects('__static__', null, this._propertyEffects.__static__);
}
}
});
var usePolyfillProto = undefined.usePolyfillProto;
Base._addFeature({
_setupConfigure: function (initialConfig) {
this._config = {};
this._handlers = [];
this._aboveConfig = null;
if (initialConfig) {
for (var i in initialConfig) {
if (initialConfig[i] !== undefined) {
this._config[i] = initialConfig[i];
}
}
}
},
_marshalAttributes: function () {
this._takeAttributesToModel(this._config);
},
_attributeChangedImpl: function (name) {
var model = this._clientsReadied ? this : this._config;
this._setAttributeToProperty(model, name);
},
_configValue: function (name, value) {
var info = this._propertyInfo[name];
if (!info || !info.readOnly) {
this._config[name] = value;
}
},
_beforeClientsReady: function () {
this._configure();
},
_configure: function () {
this._configureAnnotationReferences();
this._configureInstanceProperties();
this._aboveConfig = this.mixin({}, this._config);
var config = {};
for (var i = 0; i < this.behaviors.length; i++) {
this._configureProperties(this.behaviors[i].properties, config);
}
this._configureProperties(this.properties, config);
this.mixin(config, this._aboveConfig);
this._config = config;
if (this._clients && this._clients.length) {
this._distributeConfig(this._config);
}
},
_configureInstanceProperties: function () {
for (var i in this._propertyEffects) {
if (!usePolyfillProto && this.hasOwnProperty(i)) {
this._configValue(i, this[i]);
delete this[i];
}
}
},
_configureProperties: function (properties, config) {
for (var i in properties) {
var c = properties[i];
if (c.value !== undefined) {
var value = c.value;
if (typeof value == 'function') {
value = value.call(this, this._config);
}
config[i] = value;
}
}
},
_distributeConfig: function (config) {
var fx$ = this._propertyEffects;
if (fx$) {
for (var p in config) {
var fx = fx$[p];
if (fx) {
for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
if (x.kind === 'annotation') {
var node = this._nodes[x.effect.index];
var name = x.effect.propertyName;
var isAttr = x.effect.kind == 'attribute';
var hasEffect = node._propertyEffects && node._propertyEffects[name];
if (node._configValue && (hasEffect || !isAttr)) {
var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config);
value = this._computeFinalAnnotationValue(node, name, value, x.effect);
if (isAttr) {
value = node.deserialize(this.serialize(value), node._propertyInfo[name].type);
}
node._configValue(name, value);
}
}
}
}
}
}
},
_afterClientsReady: function () {
this._executeStaticEffects();
this._applyConfig(this._config, this._aboveConfig);
this._flushHandlers();
},
_applyConfig: function (config, aboveConfig) {
for (var n in config) {
if (this[n] === undefined) {
this.__setProperty(n, config[n], n in aboveConfig);
}
}
},
_notifyListener: function (fn, e) {
if (!Bind._isEventBogus(e, e.target)) {
var value, path;
if (e.detail) {
value = e.detail.value;
path = e.detail.path;
}
if (!this._clientsReadied) {
this._queueHandler([
fn,
e.target,
value,
path
]);
} else {
return fn.call(this, e.target, value, path);
}
}
},
_queueHandler: function (args) {
this._handlers.push(args);
},
_flushHandlers: function () {
var h$ = this._handlers;
for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
h[0].call(this, h[1], h[2], h[3]);
}
this._handlers = [];
}
});
Base._addFeature({
notifyPath: function (path, value, fromAbove) {
var info = {};
var v = this._get(path, this, info);
if (arguments.length === 1) {
value = v;
}
if (info.path) {
this._notifyPath(info.path, value, fromAbove);
}
},
_notifyPath: function (path, value, fromAbove) {
var old = this._propertySetter(path, value);
if (old !== value && (old === old || value === value)) {
this._pathEffector(path, value);
if (!fromAbove) {
this._notifyPathUp(path, value);
}
return true;
}
},
_getPathParts: function (path) {
if (Array.isArray(path)) {
var parts = [];
for (var i = 0; i < path.length; i++) {
var args = path[i].toString().split('.');
for (var j = 0; j < args.length; j++) {
parts.push(args[j]);
}
}
return parts;
} else {
return path.toString().split('.');
}
},
set: function (path, value, root) {
var prop = root || this;
var parts = this._getPathParts(path);
var array;
var last = parts[parts.length - 1];
if (parts.length > 1) {
for (var i = 0; i < parts.length - 1; i++) {
var part = parts[i];
if (array && part[0] == '#') {
prop = undefined.get(array).getItem(part);
} else {
prop = prop[part];
if (array && parseInt(part, 10) == part) {
parts[i] = undefined.get(array).getKey(prop);
}
}
if (!prop) {
return;
}
array = Array.isArray(prop) ? prop : null;
}
if (array) {
var coll = undefined.get(array);
var old, key;
if (last[0] == '#') {
key = last;
old = coll.getItem(key);
last = array.indexOf(old);
coll.setItem(key, value);
} else if (parseInt(last, 10) == last) {
old = prop[last];
key = coll.getKey(old);
parts[i] = key;
coll.setItem(key, value);
}
}
prop[last] = value;
if (!root) {
this._notifyPath(parts.join('.'), value);
}
} else {
prop[path] = value;
}
},
get: function (path, root) {
return this._get(path, root);
},
_get: function (path, root, info) {
var prop = root || this;
var parts = this._getPathParts(path);
var array;
for (var i = 0; i < parts.length; i++) {
if (!prop) {
return;
}
var part = parts[i];
if (array && part[0] == '#') {
prop = undefined.get(array).getItem(part);
} else {
prop = prop[part];
if (info && array && parseInt(part, 10) == part) {
parts[i] = undefined.get(array).getKey(prop);
}
}
array = Array.isArray(prop) ? prop : null;
}
if (info) {
info.path = parts.join('.');
}
return prop;
},
_pathEffector: function (path, value) {
var model = this._modelForPath(path);
var fx$ = this._propertyEffects && this._propertyEffects[model];
if (fx$) {
for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) {
var fxFn = fx.pathFn;
if (fxFn) {
fxFn.call(this, path, value, fx.effect);
}
}
}
if (this._boundPaths) {
this._notifyBoundPaths(path, value);
}
},
_annotationPathEffect: function (path, value, effect) {
if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
Bind._annotationEffect.call(this, path, value, effect);
} else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
var node = this._nodes[effect.index];
if (node && node._notifyPath) {
var p = this._fixPath(effect.name, effect.value, path);
node._notifyPath(p, value, true);
}
}
},
_complexObserverPathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Bind._complexObserverEffect.call(this, path, value, effect);
}
},
_computePathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Bind._computeEffect.call(this, path, value, effect);
}
},
_annotatedComputationPathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Bind._annotatedComputationEffect.call(this, path, value, effect);
}
},
_pathMatchesEffect: function (path, effect) {
var effectArg = effect.trigger.name;
return effectArg == path || effectArg.indexOf(path + '.') === 0 || effect.trigger.wildcard && path.indexOf(effectArg + '.') === 0;
},
linkPaths: function (to, from) {
this._boundPaths = this._boundPaths || {};
if (from) {
this._boundPaths[to] = from;
} else {
this.unlinkPaths(to);
}
},
unlinkPaths: function (path) {
if (this._boundPaths) {
delete this._boundPaths[path];
}
},
_notifyBoundPaths: function (path, value) {
for (var a in this._boundPaths) {
var b = this._boundPaths[a];
if (path.indexOf(a + '.') == 0) {
this._notifyPath(this._fixPath(b, a, path), value);
} else if (path.indexOf(b + '.') == 0) {
this._notifyPath(this._fixPath(a, b, path), value);
}
}
},
_fixPath: function (property, root, path) {
return property + path.slice(root.length);
},
_notifyPathUp: function (path, value) {
var rootName = this._modelForPath(path);
var dashCaseName = camelToDashCase(rootName);
var eventName = dashCaseName + this._EVENT_CHANGED;
this.fire(eventName, {
path: path,
value: value
}, {
bubbles: false,
_useCache: true
});
},
_modelForPath: function (path) {
var dot = path.indexOf('.');
return dot < 0 ? path : path.slice(0, dot);
},
_EVENT_CHANGED: '-changed',
notifySplices: function (path, splices) {
var info = {};
var array = this._get(path, this, info);
this._notifySplices(array, info.path, splices);
},
_notifySplices: function (array, path, splices) {
var change = {
keySplices: undefined.applySplices(array, splices),
indexSplices: splices
};
var splicesPath = path + '.splices';
this._notifyPath(splicesPath, change);
this._notifyPath(path + '.length', array.length);
this.__data__[splicesPath] = {
keySplices: null,
indexSplices: null
};
},
_notifySplice: function (array, path, index, added, removed) {
this._notifySplices(array, path, [{
index: index,
addedCount: added,
removed: removed,
object: array,
type: 'splice'
}]);
},
push: function (path) {
var info = {};
var array = this._get(path, this, info);
var args = Array.prototype.slice.call(arguments, 1);
var len = array.length;
var ret = array.push.apply(array, args);
if (args.length) {
this._notifySplice(array, info.path, len, args.length, []);
}
return ret;
},
pop: function (path) {
var info = {};
var array = this._get(path, this, info);
var hadLength = Boolean(array.length);
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.pop.apply(array, args);
if (hadLength) {
this._notifySplice(array, info.path, array.length, 0, [ret]);
}
return ret;
},
splice: function (path, start) {
var info = {};
var array = this._get(path, this, info);
if (start < 0) {
start = array.length - Math.floor(-start);
} else {
start = Math.floor(start);
}
if (!start) {
start = 0;
}
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.splice.apply(array, args);
var addedCount = Math.max(args.length - 2, 0);
if (addedCount || ret.length) {
this._notifySplice(array, info.path, start, addedCount, ret);
}
return ret;
},
shift: function (path) {
var info = {};
var array = this._get(path, this, info);
var hadLength = Boolean(array.length);
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.shift.apply(array, args);
if (hadLength) {
this._notifySplice(array, info.path, 0, 0, [ret]);
}
return ret;
},
unshift: function (path) {
var info = {};
var array = this._get(path, this, info);
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.unshift.apply(array, args);
if (args.length) {
this._notifySplice(array, info.path, 0, args.length, []);
}
return ret;
},
prepareModelNotifyPath: function (model) {
this.mixin(model, {
fire: Base.fire,
_getEvent: Base._getEvent,
__eventCache: Base.__eventCache,
notifyPath: Base.notifyPath,
_get: Base._get,
_EVENT_CHANGED: Base._EVENT_CHANGED,
_notifyPath: Base._notifyPath,
_notifyPathUp: Base._notifyPathUp,
_pathEffector: Base._pathEffector,
_annotationPathEffect: Base._annotationPathEffect,
_complexObserverPathEffect: Base._complexObserverPathEffect,
_annotatedComputationPathEffect: Base._annotatedComputationPathEffect,
_computePathEffect: Base._computePathEffect,
_modelForPath: Base._modelForPath,
_pathMatchesEffect: Base._pathMatchesEffect,
_notifyBoundPaths: Base._notifyBoundPaths,
_getPathParts: Base._getPathParts
});
}
});
Base._addFeature({
resolveUrl: function (url) {
var module = DomModule.import(this.is);
var root = '';
if (module) {
var assetPath = module.getAttribute('assetpath') || '';
root = resolveUrl$0(assetPath, module.ownerDocument.baseURI);
}
return resolveUrl$0(url, root);
}
});
export const CssParse = function () {
return {
parse: function (text) {
text = this._clean(text);
return this._parseCss(this._lex(text), text);
},
_clean: function (cssText) {
return cssText.replace(this._rx.comments, '').replace(this._rx.port, '');
},
_lex: function (text) {
var root = {
start: 0,
end: text.length
};
var n = root;
for (var i = 0, l = text.length; i < l; i++) {
switch (text[i]) {
case this.OPEN_BRACE:
if (!n.rules) {
n.rules = [];
}
var p = n;
var previous = p.rules[p.rules.length - 1];
n = {
start: i + 1,
parent: p,
previous: previous
};
p.rules.push(n);
break;
case this.CLOSE_BRACE:
n.end = i + 1;
n = n.parent || root;
break;
}
}
return root;
},
_parseCss: function (node, text) {
var t = text.substring(node.start, node.end - 1);
node.parsedCssText = node.cssText = t.trim();
if (node.parent) {
var ss = node.previous ? node.previous.end : node.parent.start;
t = text.substring(ss, node.start - 1);
t = this._expandUnicodeEscapes(t);
t = t.replace(this._rx.multipleSpaces, ' ');
t = t.substring(t.lastIndexOf(';') + 1);
var s = node.parsedSelector = node.selector = t.trim();
node.atRule = s.indexOf(this.AT_START) === 0;
if (node.atRule) {
if (s.indexOf(this.MEDIA_START) === 0) {
node.type = this.types.MEDIA_RULE;
} else if (s.match(this._rx.keyframesRule)) {
node.type = this.types.KEYFRAMES_RULE;
node.keyframesName = node.selector.split(this._rx.multipleSpaces).pop();
}
} else {
if (s.indexOf(this.VAR_START) === 0) {
node.type = this.types.MIXIN_RULE;
} else {
node.type = this.types.STYLE_RULE;
}
}
}
var r$ = node.rules;
if (r$) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
this._parseCss(r, text);
}
}
return node;
},
_expandUnicodeEscapes: function (s) {
return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () {
var code = arguments[1], repeat = 6 - code.length;
while (repeat--) {
code = '0' + code;
}
return '\\' + code;
});
},
stringify: function (node, preserveProperties, text) {
text = text || '';
var cssText = '';
if (node.cssText || node.rules) {
var r$ = node.rules;
if (r$ && !this._hasMixinRules(r$)) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
cssText = this.stringify(r, preserveProperties, cssText);
}
} else {
cssText = preserveProperties ? node.cssText : this.removeCustomProps(node.cssText);
cssText = cssText.trim();
if (cssText) {
cssText = ' ' + cssText + '\n';
}
}
}
if (cssText) {
if (node.selector) {
text += node.selector + ' ' + this.OPEN_BRACE + '\n';
}
text += cssText;
if (node.selector) {
text += this.CLOSE_BRACE + '\n\n';
}
}
return text;
},
_hasMixinRules: function (rules) {
return rules[0].selector.indexOf(this.VAR_START) === 0;
},
removeCustomProps: function (cssText) {
cssText = this.removeCustomPropAssignment(cssText);
return this.removeCustomPropApply(cssText);
},
removeCustomPropAssignment: function (cssText) {
return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, '');
},
removeCustomPropApply: function (cssText) {
return cssText.replace(this._rx.mixinApply, '').replace(this._rx.varApply, '');
},
types: {
STYLE_RULE: 1,
KEYFRAMES_RULE: 7,
MEDIA_RULE: 4,
MIXIN_RULE: 1000
},
OPEN_BRACE: '{',
CLOSE_BRACE: '}',
_rx: {
comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
port: /@import[^;]*;/gim,
customProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,
mixinProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,
mixinApply: /@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,
varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,
keyframesRule: /^@[^\s]*keyframes/,
multipleSpaces: /\s+/g
},
VAR_START: '--',
MEDIA_START: '@media',
AT_START: '@'
};
}();
export const StyleUtil = function () {
var settings = undefined;
return {
NATIVE_VARIABLES: useNativeCSSProperties$0,
MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template',
INCLUDE_ATTR: 'include',
toCssText: function (rules, callback) {
if (typeof rules === 'string') {
rules = this.parser.parse(rules);
}
if (callback) {
this.forEachRule(rules, callback);
}
return this.parser.stringify(rules, this.NATIVE_VARIABLES);
},
forRulesInStyles: function (styles, styleRuleCallback, keyframesRuleCallback) {
if (styles) {
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
this.forEachRuleInStyle(s, styleRuleCallback, keyframesRuleCallback);
}
}
},
forActiveRulesInStyles: function (styles, styleRuleCallback, keyframesRuleCallback) {
if (styles) {
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
this.forEachRuleInStyle(s, styleRuleCallback, keyframesRuleCallback, true);
}
}
},
rulesForStyle: function (style) {
if (!style.__cssRules && style.textContent) {
style.__cssRules = this.parser.parse(style.textContent);
}
return style.__cssRules;
},
isKeyframesSelector: function (rule) {
return rule.parent && rule.parent.type === this.ruleTypes.KEYFRAMES_RULE;
},
forEachRuleInStyle: function (style, styleRuleCallback, keyframesRuleCallback, onlyActiveRules) {
var rules = this.rulesForStyle(style);
var styleCallback, keyframeCallback;
if (styleRuleCallback) {
styleCallback = function (rule) {
styleRuleCallback(rule, style);
};
}
if (keyframesRuleCallback) {
keyframeCallback = function (rule) {
keyframesRuleCallback(rule, style);
};
}
this.forEachRule(rules, styleCallback, keyframeCallback, onlyActiveRules);
},
forEachRule: function (node, styleRuleCallback, keyframesRuleCallback, onlyActiveRules) {
if (!node) {
return;
}
var skipRules = false;
if (onlyActiveRules) {
if (node.type === this.ruleTypes.MEDIA_RULE) {
var matchMedia = node.selector.match(this.rx.MEDIA_MATCH);
if (matchMedia) {
if (!window.matchMedia(matchMedia[1]).matches) {
skipRules = true;
}
}
}
}
if (node.type === this.ruleTypes.STYLE_RULE) {
styleRuleCallback(node);
} else if (keyframesRuleCallback && node.type === this.ruleTypes.KEYFRAMES_RULE) {
keyframesRuleCallback(node);
} else if (node.type === this.ruleTypes.MIXIN_RULE) {
skipRules = true;
}
var r$ = node.rules;
if (r$ && !skipRules) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
this.forEachRule(r, styleRuleCallback, keyframesRuleCallback, onlyActiveRules);
}
}
},
applyCss: function (cssText, moniker, target, contextNode) {
var style = this.createScopeStyle(cssText, moniker);
return this.applyStyle(style, target, contextNode);
},
applyStyle: function (style, target, contextNode) {
target = target || document.head;
var after = contextNode && contextNode.nextSibling || target.firstChild;
this.__lastHeadApplyNode = style;
return target.insertBefore(style, after);
},
createScopeStyle: function (cssText, moniker) {
var style = document.createElement('style');
if (moniker) {
style.setAttribute('scope', moniker);
}
style.textContent = cssText;
return style;
},
__lastHeadApplyNode: null,
applyStylePlaceHolder: function (moniker) {
var placeHolder = document.createComment(' Shady DOM styles for ' + moniker + ' ');
var after = this.__lastHeadApplyNode ? this.__lastHeadApplyNode.nextSibling : null;
var scope = document.head;
scope.insertBefore(placeHolder, after || scope.firstChild);
this.__lastHeadApplyNode = placeHolder;
return placeHolder;
},
cssFromModules: function (moduleIds, warnIfNotFound) {
var modules = moduleIds.trim().split(' ');
var cssText = '';
for (var i = 0; i < modules.length; i++) {
cssText += this.cssFromModule(modules[i], warnIfNotFound);
}
return cssText;
},
cssFromModule: function (moduleId, warnIfNotFound) {
var m = DomModule.import(moduleId);
if (m && !m._cssText) {
m._cssText = this.cssFromElement(m);
}
if (!m && warnIfNotFound) {
console.warn('Could not find style data in module named', moduleId);
}
return m && m._cssText || '';
},
cssFromElement: function (element) {
var cssText = '';
var content = element.content || element;
var e$ = Polymer.TreeApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));
for (var i = 0, e; i < e$.length; i++) {
e = e$[i];
if (e.localName === 'template') {
cssText += this.cssFromElement(e);
} else {
if (e.localName === 'style') {
var include = e.getAttribute(this.INCLUDE_ATTR);
if (include) {
cssText += this.cssFromModules(include, true);
}
e = e.__appliedElement || e;
e.parentNode.removeChild(e);
cssText += this.resolveCss(e.textContent, element.ownerDocument);
} else if (e.import && e.import.body) {
cssText += this.resolveCss(e.import.body.textContent, e.import);
}
}
}
return cssText;
},
isTargetedBuild: function (buildType) {
return settings.useNativeShadow ? buildType === 'shadow' : buildType === 'shady';
},
cssBuildTypeForModule: function (module) {
var dm = DomModule.import(module);
if (dm) {
return this.getCssBuildType(dm);
}
},
getCssBuildType: function (element) {
return element.getAttribute('css-build');
},
_findMatchingParen: function (text, start) {
var level = 0;
for (var i = start, l = text.length; i < l; i++) {
switch (text[i]) {
case '(':
level++;
break;
case ')':
if (--level === 0) {
return i;
}
break;
}
}
return -1;
},
processVariableAndFallback: function (str, callback) {
var start = str.indexOf('var(');
if (start === -1) {
return callback(str, '', '', '');
}
var end = this._findMatchingParen(str, start + 3);
var inner = str.substring(start + 4, end);
var prefix = str.substring(0, start);
var suffix = this.processVariableAndFallback(str.substring(end + 1), callback);
var comma = inner.indexOf(',');
if (comma === -1) {
return callback(prefix, inner.trim(), '', suffix);
}
var value = inner.substring(0, comma).trim();
var fallback = inner.substring(comma + 1).trim();
return callback(prefix, value, fallback, suffix);
},
rx: {
VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi,
MIXIN_MATCH: /(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,
VAR_CONSUMED: /(--[\w-]+)\s*([:,;)]|$)/gi,
ANIMATION_MATCH: /(animation\s*:)|(animation-name\s*:)/,
MEDIA_MATCH: /@media[^(]*(\([^)]*\))/,
IS_VAR: /^--/,
BRACKETED: /\{[^}]*\}/g,
HOST_PREFIX: '(?:^|[^.#[:])',
HOST_SUFFIX: '($|[.:[\\s>+~])'
},
resolveCss: resolveCss$0,
parser: CssParse,
ruleTypes: CssParse.types
};
}();
export const StyleTransformer = function () {
var styleUtil = StyleUtil;
var settings = undefined;
var api = {
dom: function (node, scope, useAttr, shouldRemoveScope) {
this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
},
_transformDom: function (node, selector, useAttr, shouldRemoveScope) {
if (node.setAttribute) {
this.element(node, selector, useAttr, shouldRemoveScope);
}
var c$ = dom$0(node).childNodes;
for (var i = 0; i < c$.length; i++) {
this._transformDom(c$[i], selector, useAttr, shouldRemoveScope);
}
},
element: function (element, scope, useAttr, shouldRemoveScope) {
if (useAttr) {
if (shouldRemoveScope) {
element.removeAttribute(SCOPE_NAME);
} else {
element.setAttribute(SCOPE_NAME, scope);
}
} else {
if (scope) {
if (element.classList) {
if (shouldRemoveScope) {
element.classList.remove(SCOPE_NAME);
element.classList.remove(scope);
} else {
element.classList.add(SCOPE_NAME);
element.classList.add(scope);
}
} else if (element.getAttribute) {
var c = element.getAttribute(CLASS);
if (shouldRemoveScope) {
if (c) {
element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, ''));
}
} else {
element.setAttribute(CLASS, (c ? c + ' ' : '') + SCOPE_NAME + ' ' + scope);
}
}
}
}
},
elementStyles: function (element, callback) {
var styles = element._styles;
var cssText = '';
var cssBuildType = element.__cssBuild;
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
var rules = styleUtil.rulesForStyle(s);
cssText += settings.useNativeShadow || cssBuildType === 'shady' ? styleUtil.toCssText(rules, callback) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n';
}
return cssText.trim();
},
css: function (rules, scope, ext, callback, useAttr) {
var hostScope = this._calcHostScope(scope, ext);
scope = this._calcElementScope(scope, useAttr);
var self = this;
return styleUtil.toCssText(rules, function (rule) {
if (!rule.isScoped) {
self.rule(rule, scope, hostScope);
rule.isScoped = true;
}
if (callback) {
callback(rule, scope, hostScope);
}
});
},
_calcElementScope: function (scope, useAttr) {
if (scope) {
return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope;
} else {
return '';
}
},
_calcHostScope: function (scope, ext) {
return ext ? '[is=' + scope + ']' : scope;
},
rule: function (rule, scope, hostScope) {
this._transformRule(rule, this._transformComplexSelector, scope, hostScope);
},
_transformRule: function (rule, transformer, scope, hostScope) {
rule.selector = rule.transformedSelector = this._transformRuleCss(rule, transformer, scope, hostScope);
},
_transformRuleCss: function (rule, transformer, scope, hostScope) {
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
if (!styleUtil.isKeyframesSelector(rule)) {
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
p$[i] = transformer.call(this, p, scope, hostScope);
}
}
return p$.join(COMPLEX_SELECTOR_SEP);
},
_transformComplexSelector: function (selector, scope, hostScope) {
var stop = false;
var hostContext = false;
var self = this;
selector = selector.trim();
selector = selector.replace(CONTENT_START, HOST + ' $1');
selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) {
if (!stop) {
var info = self._transformCompoundSelector(s, c, scope, hostScope);
stop = stop || info.stop;
hostContext = hostContext || info.hostContext;
c = info.combinator;
s = info.value;
} else {
s = s.replace(SCOPE_JUMP, ' ');
}
return c + s;
});
if (hostContext) {
selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) {
return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
});
}
return selector;
},
_transformCompoundSelector: function (selector, combinator, scope, hostScope) {
var jumpIndex = selector.search(SCOPE_JUMP);
var hostContext = false;
if (selector.indexOf(HOST_CONTEXT) >= 0) {
hostContext = true;
} else if (selector.indexOf(HOST) >= 0) {
selector = this._transformHostSelector(selector, hostScope);
} else if (jumpIndex !== 0) {
selector = scope ? this._transformSimpleSelector(selector, scope) : selector;
}
if (selector.indexOf(CONTENT) >= 0) {
combinator = '';
}
var stop;
if (jumpIndex >= 0) {
selector = selector.replace(SCOPE_JUMP, ' ');
stop = true;
}
return {
value: selector,
combinator: combinator,
stop: stop,
hostContext: hostContext
};
},
_transformSimpleSelector: function (selector, scope) {
var p$ = selector.split(PSEUDO_PREFIX);
p$[0] += scope;
return p$.join(PSEUDO_PREFIX);
},
_transformHostSelector: function (selector, hostScope) {
var m = selector.match(HOST_PAREN);
var paren = m && m[2].trim() || '';
if (paren) {
if (!paren[0].match(SIMPLE_SELECTOR_PREFIX)) {
var typeSelector = paren.split(SIMPLE_SELECTOR_PREFIX)[0];
if (typeSelector === hostScope) {
return paren;
} else {
return SELECTOR_NO_MATCH;
}
} else {
return selector.replace(HOST_PAREN, function (m, host, paren) {
return hostScope + paren;
});
}
} else {
return selector.replace(HOST, hostScope);
}
},
documentRule: function (rule) {
rule.selector = rule.parsedSelector;
this.normalizeRootSelector(rule);
if (!settings.useNativeShadow) {
this._transformRule(rule, this._transformDocumentSelector);
}
},
normalizeRootSelector: function (rule) {
if (rule.selector === ROOT) {
rule.selector = 'html';
}
},
_transformDocumentSelector: function (selector) {
return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELECTOR);
},
SCOPE_NAME: 'style-scope'
};
var SCOPE_NAME = api.SCOPE_NAME;
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')';
var COMPLEX_SELECTOR_SEP = ',';
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;
var SIMPLE_SELECTOR_PREFIX = /[[.:#*]/;
var HOST = ':host';
var ROOT = ':root';
var HOST_PAREN = /(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;
var HOST_CONTEXT = ':host-context';
var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var CONTENT = '::content';
var SCOPE_JUMP = /::content|::shadow|\/deep\//;
var CSS_CLASS_PREFIX = '.';
var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
var CSS_ATTR_SUFFIX = ']';
var PSEUDO_PREFIX = ':';
var CLASS = 'class';
var CONTENT_START = new RegExp('^(' + CONTENT + ')');
var SELECTOR_NO_MATCH = 'should_not_match';
return api;
}();
export const StyleExtends = function () {
var styleUtil = StyleUtil;
return {
hasExtends: function (cssText) {
return Boolean(cssText.match(this.rx.EXTEND));
},
transform: function (style) {
var rules = styleUtil.rulesForStyle(style);
var self = this;
styleUtil.forEachRule(rules, function (rule) {
self._mapRuleOntoParent(rule);
if (rule.parent) {
var m;
while (m = self.rx.EXTEND.exec(rule.cssText)) {
var extend = m[1];
var extendor = self._findExtendor(extend, rule);
if (extendor) {
self._extendRule(rule, extendor);
}
}
}
rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
});
return styleUtil.toCssText(rules, function (rule) {
if (rule.selector.match(self.rx.STRIP)) {
rule.cssText = '';
}
}, true);
},
_mapRuleOntoParent: function (rule) {
if (rule.parent) {
var map = rule.parent.map || (rule.parent.map = {});
var parts = rule.selector.split(',');
for (var i = 0, p; i < parts.length; i++) {
p = parts[i];
map[p.trim()] = rule;
}
return map;
}
},
_findExtendor: function (extend, rule) {
return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findExtendor(extend, rule.parent);
},
_extendRule: function (target, source) {
if (target.parent !== source.parent) {
this._cloneAndAddRuleToParent(source, target.parent);
}
target.extends = target.extends || [];
target.extends.push(source);
source.selector = source.selector.replace(this.rx.STRIP, '');
source.selector = (source.selector && source.selector + ',\n') + target.selector;
if (source.extends) {
source.extends.forEach(function (e) {
this._extendRule(target, e);
}, this);
}
},
_cloneAndAddRuleToParent: function (rule, parent) {
rule = Object.create(rule);
rule.parent = parent;
if (rule.extends) {
rule.extends = rule.extends.slice();
}
parent.rules.push(rule);
},
rx: {
EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
STRIP: /%[^,]*$/
}
};
}();
export const ApplyShim = function () {
'use strict';
var styleUtil = StyleUtil;
var MIXIN_MATCH = styleUtil.rx.MIXIN_MATCH;
var VAR_ASSIGN = styleUtil.rx.VAR_ASSIGN;
var BAD_VAR = /var\(\s*(--[^,]*),\s*(--[^)]*)\)/g;
var APPLY_NAME_CLEAN = /;\s*/m;
var INITIAL_INHERIT = /^\s*(initial)|(inherit)\s*$/;
var MIXIN_VAR_SEP = '_-_';
var mixinMap = {};
function mapSet(name, props) {
name = name.trim();
mixinMap[name] = {
properties: props,
dependants: {}
};
}
function mapGet(name) {
name = name.trim();
return mixinMap[name];
}
function replaceInitialOrInherit(property, value) {
var match = INITIAL_INHERIT.exec(value);
if (match) {
if (match[1]) {
value = ApplyShim._getInitialValueForProperty(property);
} else {
value = 'apply-shim-inherit';
}
}
return value;
}
function cssTextToMap(text) {
var props = text.split(';');
var property, value;
var out = {};
for (var i = 0, p, sp; i < props.length; i++) {
p = props[i];
if (p) {
sp = p.split(':');
if (sp.length > 1) {
property = sp[0].trim();
value = replaceInitialOrInherit(property, sp.slice(1).join(':'));
out[property] = value;
}
}
}
return out;
}
function invalidateMixinEntry(mixinEntry) {
var currentProto = ApplyShim.__currentElementProto;
var currentElementName = currentProto && currentProto.is;
for (var elementName in mixinEntry.dependants) {
if (elementName !== currentElementName) {
mixinEntry.dependants[elementName].__applyShimInvalid = true;
}
}
}
function produceCssProperties(matchText, propertyName, valueProperty, valueMixin) {
if (valueProperty) {
styleUtil.processVariableAndFallback(valueProperty, function (prefix, value) {
if (value && mapGet(value)) {
valueMixin = '@apply ' + value + ';';
}
});
}
if (!valueMixin) {
return matchText;
}
var mixinAsProperties = consumeCssProperties(valueMixin);
var prefix = matchText.slice(0, matchText.indexOf('--'));
var mixinValues = cssTextToMap(mixinAsProperties);
var combinedProps = mixinValues;
var mixinEntry = mapGet(propertyName);
var oldProps = mixinEntry && mixinEntry.properties;
if (oldProps) {
combinedProps = Object.create(oldProps);
combinedProps = Base.mixin(combinedProps, mixinValues);
} else {
mapSet(propertyName, combinedProps);
}
var out = [];
var p, v;
var needToInvalidate = false;
for (p in combinedProps) {
v = mixinValues[p];
if (v === undefined) {
v = 'initial';
}
if (oldProps && !(p in oldProps)) {
needToInvalidate = true;
}
out.push(propertyName + MIXIN_VAR_SEP + p + ': ' + v);
}
if (needToInvalidate) {
invalidateMixinEntry(mixinEntry);
}
if (mixinEntry) {
mixinEntry.properties = combinedProps;
}
if (valueProperty) {
prefix = matchText + ';' + prefix;
}
return prefix + out.join('; ') + ';';
}
function fixVars(matchText, varA, varB) {
return 'var(' + varA + ',' + 'var(' + varB + '));';
}
function atApplyToCssProperties(mixinName, fallbacks) {
mixinName = mixinName.replace(APPLY_NAME_CLEAN, '');
var vars = [];
var mixinEntry = mapGet(mixinName);
if (!mixinEntry) {
mapSet(mixinName, {});
mixinEntry = mapGet(mixinName);
}
if (mixinEntry) {
var currentProto = ApplyShim.__currentElementProto;
if (currentProto) {
mixinEntry.dependants[currentProto.is] = currentProto;
}
var p, parts, f;
for (p in mixinEntry.properties) {
f = fallbacks && fallbacks[p];
parts = [
p,
': var(',
mixinName,
MIXIN_VAR_SEP,
p
];
if (f) {
parts.push(',', f);
}
parts.push(')');
vars.push(parts.join(''));
}
}
return vars.join('; ');
}
function consumeCssProperties(text) {
var m;
while (m = MIXIN_MATCH.exec(text)) {
var matchText = m[0];
var mixinName = m[1];
var idx = m.index;
var applyPos = idx + matchText.indexOf('@apply');
var afterApplyPos = idx + matchText.length;
var textBeforeApply = text.slice(0, applyPos);
var textAfterApply = text.slice(afterApplyPos);
var defaults = cssTextToMap(textBeforeApply);
var replacement = atApplyToCssProperties(mixinName, defaults);
text = [
textBeforeApply,
replacement,
textAfterApply
].join('');
MIXIN_MATCH.lastIndex = idx + replacement.length;
}
return text;
}
var ApplyShim = {
_measureElement: null,
_map: mixinMap,
_separator: MIXIN_VAR_SEP,
transform: function (styles, elementProto) {
this.__currentElementProto = elementProto;
styleUtil.forRulesInStyles(styles, this._boundTransformRule);
elementProto.__applyShimInvalid = false;
this.__currentElementProto = null;
},
transformRule: function (rule) {
rule.cssText = this.transformCssText(rule.parsedCssText);
if (rule.selector === ':root') {
rule.selector = ':host > *';
}
},
transformCssText: function (cssText) {
cssText = cssText.replace(BAD_VAR, fixVars);
cssText = cssText.replace(VAR_ASSIGN, produceCssProperties);
return consumeCssProperties(cssText);
},
_getInitialValueForProperty: function (property) {
if (!this._measureElement) {
this._measureElement = document.createElement('meta');
this._measureElement.style.all = 'initial';
document.head.appendChild(this._measureElement);
}
return window.getComputedStyle(this._measureElement).getPropertyValue(property);
}
};
ApplyShim._boundTransformRule = ApplyShim.transformRule.bind(ApplyShim);
return ApplyShim;
}();
var prepElement = Base._prepElement;
var nativeShadow = undefined.useNativeShadow;
var styleUtil = StyleUtil;
var styleTransformer = StyleTransformer;
var styleExtends = StyleExtends;
var applyShim = ApplyShim;
var settings = undefined;
Base._addFeature({
_prepElement: function (element) {
if (this._encapsulateStyle && this.__cssBuild !== 'shady') {
styleTransformer.element(element, this.is, this._scopeCssViaAttr);
}
prepElement.call(this, element);
},
_prepStyles: function () {
if (this._encapsulateStyle === undefined) {
this._encapsulateStyle = !nativeShadow;
}
if (!nativeShadow) {
this._scopeStyle = styleUtil.applyStylePlaceHolder(this.is);
}
this.__cssBuild = styleUtil.cssBuildTypeForModule(this.is);
},
_prepShimStyles: function () {
if (this._template) {
var hasTargetedCssBuild = styleUtil.isTargetedBuild(this.__cssBuild);
if (settings.useNativeCSSProperties && this.__cssBuild === 'shadow' && hasTargetedCssBuild) {
return;
}
this._styles = this._styles || this._collectStyles();
if (settings.useNativeCSSProperties && !this.__cssBuild) {
applyShim.transform(this._styles, this);
}
var cssText = settings.useNativeCSSProperties && hasTargetedCssBuild ? this._styles.length && this._styles[0].textContent.trim() : styleTransformer.elementStyles(this);
this._prepStyleProperties();
if (!this._needsStyleProperties() && cssText) {
styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null, this._scopeStyle);
}
} else {
this._styles = [];
}
},
_collectStyles: function () {
var styles = [];
var cssText = '', m$ = this.styleModules;
if (m$) {
for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) {
cssText += styleUtil.cssFromModule(m);
}
}
cssText += styleUtil.cssFromModule(this.is);
var p = this._template && this._template.parentNode;
if (this._template && (!p || p.id.toLowerCase() !== this.is)) {
cssText += styleUtil.cssFromElement(this._template);
}
if (cssText) {
var style = document.createElement('style');
style.textContent = cssText;
if (styleExtends.hasExtends(style.textContent)) {
cssText = styleExtends.transform(style);
}
styles.push(style);
}
return styles;
},
_elementAdd: function (node) {
if (this._encapsulateStyle) {
if (node.__styleScoped) {
node.__styleScoped = false;
} else {
styleTransformer.dom(node, this.is, this._scopeCssViaAttr);
}
}
},
_elementRemove: function (node) {
if (this._encapsulateStyle) {
styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
}
},
scopeSubtree: function (container, shouldObserve) {
if (nativeShadow) {
return;
}
var self = this;
var scopify = function (node) {
if (node.nodeType === Node.ELEMENT_NODE) {
var className = node.getAttribute('class');
node.setAttribute('class', self._scopeElementClass(node, className));
var n$ = node.querySelectorAll('*');
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
className = n.getAttribute('class');
n.setAttribute('class', self._scopeElementClass(n, className));
}
}
};
scopify(container);
if (shouldObserve) {
var mo = new MutationObserver(function (mxns) {
for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) {
if (m.addedNodes) {
for (var j = 0; j < m.addedNodes.length; j++) {
scopify(m.addedNodes[j]);
}
}
}
});
mo.observe(container, {
childList: true,
subtree: true
});
return mo;
}
}
});
export const StyleProperties = function () {
'use strict';
var matchesSelector = DomApi.matchesSelector;
var styleUtil = StyleUtil;
var styleTransformer = StyleTransformer;
var IS_IE = navigator.userAgent.match('Trident');
var settings = undefined;
return {
decorateStyles: function (styles, scope) {
var self = this, props = {}, keyframes = [], ruleIndex = 0;
var scopeSelector = styleTransformer._calcHostScope(scope.is, scope.extends);
styleUtil.forRulesInStyles(styles, function (rule, style) {
self.decorateRule(rule);
rule.index = ruleIndex++;
self.whenHostOrRootRule(scope, rule, style, function (info) {
if (rule.parent.type === styleUtil.ruleTypes.MEDIA_RULE) {
scope.__notStyleScopeCacheable = true;
}
if (info.isHost) {
var hostContextOrFunction = info.selector.split(' ').some(function (s) {
return s.indexOf(scopeSelector) === 0 && s.length !== scopeSelector.length;
});
scope.__notStyleScopeCacheable = scope.__notStyleScopeCacheable || hostContextOrFunction;
}
});
self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
}, function onKeyframesRule(rule) {
keyframes.push(rule);
});
styles._keyframes = keyframes;
var names = [];
for (var i in props) {
names.push(i);
}
return names;
},
decorateRule: function (rule) {
if (rule.propertyInfo) {
return rule.propertyInfo;
}
var info = {}, properties = {};
var hasProperties = this.collectProperties(rule, properties);
if (hasProperties) {
info.properties = properties;
rule.rules = null;
}
info.cssText = this.collectCssText(rule);
rule.propertyInfo = info;
return info;
},
collectProperties: function (rule, properties) {
var info = rule.propertyInfo;
if (info) {
if (info.properties) {
Base.mixin(properties, info.properties);
return true;
}
} else {
var m, rx = this.rx.VAR_ASSIGN;
var cssText = rule.parsedCssText;
var value;
var any;
while (m = rx.exec(cssText)) {
value = (m[2] || m[3]).trim();
if (value !== 'inherit') {
properties[m[1].trim()] = value;
}
any = true;
}
return any;
}
},
collectCssText: function (rule) {
return this.collectConsumingCssText(rule.parsedCssText);
},
collectConsumingCssText: function (cssText) {
return cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, '');
},
collectPropertiesInCssText: function (cssText, props) {
var m;
while (m = this.rx.VAR_CONSUMED.exec(cssText)) {
var name = m[1];
if (m[2] !== ':') {
props[name] = true;
}
}
},
reify: function (props) {
var names = Object.getOwnPropertyNames(props);
for (var i = 0, n; i < names.length; i++) {
n = names[i];
props[n] = this.valueForProperty(props[n], props);
}
},
valueForProperty: function (property, props) {
if (property) {
if (property.indexOf(';') >= 0) {
property = this.valueForProperties(property, props);
} else {
var self = this;
var fn = function (prefix, value, fallback, suffix) {
var propertyValue = self.valueForProperty(props[value], props);
if (!propertyValue || propertyValue === 'initial') {
propertyValue = self.valueForProperty(props[fallback] || fallback, props) || fallback;
} else if (propertyValue === 'apply-shim-inherit') {
propertyValue = 'inherit';
}
return prefix + (propertyValue || '') + suffix;
};
property = styleUtil.processVariableAndFallback(property, fn);
}
}
return property && property.trim() || '';
},
valueForProperties: function (property, props) {
var parts = property.split(';');
for (var i = 0, p, m; i < parts.length; i++) {
if (p = parts[i]) {
this.rx.MIXIN_MATCH.lastIndex = 0;
m = this.rx.MIXIN_MATCH.exec(p);
if (m) {
p = this.valueForProperty(props[m[1]], props);
} else {
var colon = p.indexOf(':');
if (colon !== -1) {
var pp = p.substring(colon);
pp = pp.trim();
pp = this.valueForProperty(pp, props) || pp;
p = p.substring(0, colon) + pp;
}
}
parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
}
}
return parts.join(';');
},
applyProperties: function (rule, props) {
var output = '';
if (!rule.propertyInfo) {
this.decorateRule(rule);
}
if (rule.propertyInfo.cssText) {
output = this.valueForProperties(rule.propertyInfo.cssText, props);
}
rule.cssText = output;
},
applyKeyframeTransforms: function (rule, keyframeTransforms) {
var input = rule.cssText;
var output = rule.cssText;
if (rule.hasAnimations == null) {
rule.hasAnimations = this.rx.ANIMATION_MATCH.test(input);
}
if (rule.hasAnimations) {
var transform;
if (rule.keyframeNamesToTransform == null) {
rule.keyframeNamesToTransform = [];
for (var keyframe in keyframeTransforms) {
transform = keyframeTransforms[keyframe];
output = transform(input);
if (input !== output) {
input = output;
rule.keyframeNamesToTransform.push(keyframe);
}
}
} else {
for (var i = 0; i < rule.keyframeNamesToTransform.length; ++i) {
transform = keyframeTransforms[rule.keyframeNamesToTransform[i]];
input = transform(input);
}
output = input;
}
}
rule.cssText = output;
},
propertyDataFromStyles: function (styles, element) {
var props = {}, self = this;
var o = [];
styleUtil.forActiveRulesInStyles(styles, function (rule) {
if (!rule.propertyInfo) {
self.decorateRule(rule);
}
var selectorToMatch = rule.transformedSelector || rule.parsedSelector;
if (element && rule.propertyInfo.properties && selectorToMatch) {
if (matchesSelector.call(element, selectorToMatch)) {
self.collectProperties(rule, props);
addToBitMask(rule.index, o);
}
}
});
return {
properties: props,
key: o
};
},
whenHostOrRootRule: function (scope, rule, style, callback) {
if (!rule.propertyInfo) {
self.decorateRule(rule);
}
if (!rule.propertyInfo.properties) {
return;
}
var hostScope = scope.is ? styleTransformer._calcHostScope(scope.is, scope.extends) : 'html';
var parsedSelector = rule.parsedSelector;
var isRoot = parsedSelector === ':root';
var isHost = parsedSelector.indexOf(':host') === 0;
var cssBuild = scope.__cssBuild || style.__cssBuild;
if (cssBuild === 'shady') {
isRoot = parsedSelector === hostScope + ' > *.' + hostScope || parsedSelector.indexOf('html') !== -1;
isHost = !isRoot && parsedSelector.indexOf(hostScope) === 0;
}
if (cssBuild === 'shadow') {
isRoot = parsedSelector === ':host > *' || parsedSelector === 'html';
isHost = isHost && !isRoot;
}
if (!isRoot && !isHost) {
return;
}
var selectorToMatch = hostScope;
if (isHost) {
if (settings.useNativeShadow && !rule.transformedSelector) {
rule.transformedSelector = styleTransformer._transformRuleCss(rule, styleTransformer._transformComplexSelector, scope.is, hostScope);
}
selectorToMatch = rule.transformedSelector || rule.parsedSelector;
}
callback({
selector: selectorToMatch,
isHost: isHost,
isRoot: isRoot
});
},
hostAndRootPropertiesForScope: function (scope) {
var hostProps = {}, rootProps = {}, self = this;
styleUtil.forActiveRulesInStyles(scope._styles, function (rule, style) {
self.whenHostOrRootRule(scope, rule, style, function (info) {
var element = scope._element || scope;
if (matchesSelector.call(element, info.selector)) {
if (info.isHost) {
self.collectProperties(rule, hostProps);
} else {
self.collectProperties(rule, rootProps);
}
}
});
});
return {
rootProps: rootProps,
hostProps: hostProps
};
},
transformStyles: function (element, properties, scopeSelector) {
var self = this;
var hostSelector = styleTransformer._calcHostScope(element.is, element.extends);
var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector;
var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFFIX);
var keyframeTransforms = this._elementKeyframeTransforms(element, scopeSelector);
return styleTransformer.elementStyles(element, function (rule) {
self.applyProperties(rule, properties);
if (!settings.useNativeShadow && !StyleUtil.isKeyframesSelector(rule) && rule.cssText) {
self.applyKeyframeTransforms(rule, keyframeTransforms);
self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeSelector);
}
});
},
_elementKeyframeTransforms: function (element, scopeSelector) {
var keyframesRules = element._styles._keyframes;
var keyframeTransforms = {};
if (!settings.useNativeShadow && keyframesRules) {
for (var i = 0, keyframesRule = keyframesRules[i]; i < keyframesRules.length; keyframesRule = keyframesRules[++i]) {
this._scopeKeyframes(keyframesRule, scopeSelector);
keyframeTransforms[keyframesRule.keyframesName] = this._keyframesRuleTransformer(keyframesRule);
}
}
return keyframeTransforms;
},
_keyframesRuleTransformer: function (keyframesRule) {
return function (cssText) {
return cssText.replace(keyframesRule.keyframesNameRx, keyframesRule.transformedKeyframesName);
};
},
_scopeKeyframes: function (rule, scopeId) {
rule.keyframesNameRx = new RegExp(rule.keyframesName, 'g');
rule.transformedKeyframesName = rule.keyframesName + '-' + scopeId;
rule.transformedSelector = rule.transformedSelector || rule.selector;
rule.selector = rule.transformedSelector.replace(rule.keyframesName, rule.transformedKeyframesName);
},
_scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) {
rule.transformedSelector = rule.transformedSelector || rule.selector;
var selector = rule.transformedSelector;
var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId;
var parts = selector.split(',');
for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
parts[i] = p.match(hostRx) ? p.replace(hostSelector, scope) : scope + ' ' + p;
}
rule.selector = parts.join(',');
},
applyElementScopeSelector: function (element, selector, old, viaAttr) {
var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.getAttribute('class') || '';
var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector;
if (c !== v) {
if (viaAttr) {
element.setAttribute(styleTransformer.SCOPE_NAME, v);
} else {
element.setAttribute('class', v);
}
}
},
applyElementStyle: function (element, properties, selector, style) {
var cssText = style ? style.textContent || '' : this.transformStyles(element, properties, selector);
var s = element._customStyle;
if (s && !settings.useNativeShadow && s !== style) {
s._useCount--;
if (s._useCount <= 0 && s.parentNode) {
s.parentNode.removeChild(s);
}
}
if (settings.useNativeShadow) {
if (element._customStyle) {
element._customStyle.textContent = cssText;
style = element._customStyle;
} else if (cssText) {
style = styleUtil.applyCss(cssText, selector, element.root, element._scopeStyle);
}
} else {
if (!style) {
if (cssText) {
style = styleUtil.applyCss(cssText, selector, null, element._scopeStyle);
}
} else if (!style.parentNode) {
styleUtil.applyStyle(style, null, element._scopeStyle);
}
}
if (style) {
style._useCount = style._useCount || 0;
if (element._customStyle != style) {
style._useCount++;
}
element._customStyle = style;
}
if (IS_IE) {
style.textContent = style.textContent;
}
return style;
},
mixinCustomStyle: function (props, customStyle) {
var v;
for (var i in customStyle) {
v = customStyle[i];
if (v || v === 0) {
props[i] = v;
}
}
},
updateNativeStyleProperties: function (element, properties) {
var oldPropertyNames = element.__customStyleProperties;
if (oldPropertyNames) {
for (var i = 0; i < oldPropertyNames.length; i++) {
element.style.removeProperty(oldPropertyNames[i]);
}
}
var propertyNames = [];
for (var p in properties) {
if (properties[p] !== null) {
element.style.setProperty(p, properties[p]);
propertyNames.push(p);
}
}
element.__customStyleProperties = propertyNames;
},
rx: styleUtil.rx,
XSCOPE_NAME: 'x-scope'
};
function addToBitMask(n, bits) {
var o = parseInt(n / 32);
var v = 1 << n % 32;
bits[o] = (bits[o] || 0) | v;
}
}();
export const StyleCache = function () {
this.cache = {};
};
StyleCache.prototype = {
MAX: 100,
store: function (is, data, keyValues, keyStyles) {
data.keyValues = keyValues;
data.styles = keyStyles;
var s$ = this.cache[is] = this.cache[is] || [];
s$.push(data);
if (s$.length > this.MAX) {
s$.shift();
}
},
retrieve: function (is, keyValues, keyStyles) {
var cache = this.cache[is];
if (cache) {
for (var i = cache.length - 1, data; i >= 0; i--) {
data = cache[i];
if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) {
return data;
}
}
}
},
clear: function () {
this.cache = {};
},
_objectsEqual: function (target, source) {
var t, s;
for (var i in target) {
t = target[i], s = source[i];
if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) {
return false;
}
}
if (Array.isArray(target)) {
return target.length === source.length;
}
return true;
},
_objectsStrictlyEqual: function (target, source) {
return this._objectsEqual(target, source) && this._objectsEqual(source, target);
}
};
export const StyleDefaults = function () {
var styleProperties = StyleProperties;
var StyleCache = StyleCache;
var nativeVariables = useNativeCSSProperties$0;
var api = {
_styles: [],
_properties: null,
customStyle: {},
_styleCache: new StyleCache(),
_element: DomApi.wrap(document.documentElement),
addStyle: function (style) {
this._styles.push(style);
this._properties = null;
},
get _styleProperties() {
if (!this._properties) {
styleProperties.decorateStyles(this._styles, this);
this._styles._scopeStyleProperties = null;
this._properties = styleProperties.hostAndRootPropertiesForScope(this).rootProps;
styleProperties.mixinCustomStyle(this._properties, this.customStyle);
styleProperties.reify(this._properties);
}
return this._properties;
},
hasStyleProperties: function () {
return Boolean(this._properties);
},
_needsStyleProperties: function () {
},
_computeStyleProperties: function () {
return this._styleProperties;
},
updateStyles: function (properties) {
this._properties = null;
if (properties) {
Base.mixin(this.customStyle, properties);
}
this._styleCache.clear();
for (var i = 0, s; i < this._styles.length; i++) {
s = this._styles[i];
s = s.__importElement || s;
s._apply();
}
if (nativeVariables) {
styleProperties.updateNativeStyleProperties(document.documentElement, this.customStyle);
}
}
};
return api;
}();
var serializeValueToAttribute = Base.serializeValueToAttribute;
var propertyUtils = StyleProperties;
var styleTransformer = StyleTransformer;
var styleDefaults = StyleDefaults;
var nativeShadow = undefined.useNativeShadow;
var nativeVariables = useNativeCSSProperties$0;
Base._addFeature({
_prepStyleProperties: function () {
if (!nativeVariables) {
this._ownStylePropertyNames = this._styles && this._styles.length ? propertyUtils.decorateStyles(this._styles, this) : null;
}
},
customStyle: null,
getComputedStyleValue: function (property) {
return !nativeVariables && this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property);
},
_setupStyleProperties: function () {
this.customStyle = {};
this._styleCache = null;
this._styleProperties = null;
this._scopeSelector = null;
this._ownStyleProperties = null;
this._customStyle = null;
},
_needsStyleProperties: function () {
return Boolean(!nativeVariables && this._ownStylePropertyNames && this._ownStylePropertyNames.length);
},
_validateApplyShim: function () {
if (this.__applyShimInvalid) {
ApplyShim.transform(this._styles, this.__proto__);
var cssText = styleTransformer.elementStyles(this);
if (nativeShadow) {
var templateStyle = this._template.content.querySelector('style');
if (templateStyle) {
templateStyle.textContent = cssText;
}
} else {
var shadyStyle = this._scopeStyle && this._scopeStyle.nextSibling;
if (shadyStyle) {
shadyStyle.textContent = cssText;
}
}
}
},
_beforeAttached: function () {
if ((!this._scopeSelector || this.__stylePropertiesInvalid) && this._needsStyleProperties()) {
this.__stylePropertiesInvalid = false;
this._updateStyleProperties();
}
},
_findStyleHost: function () {
var e = this, root;
while (root = dom$0(e).getOwnerRoot()) {
if (Polymer.isInstance(root.host)) {
return root.host;
}
e = root.host;
}
return styleDefaults;
},
_updateStyleProperties: function () {
var info, scope = this._findStyleHost();
if (!scope._styleProperties) {
scope._computeStyleProperties();
}
if (!scope._styleCache) {
scope._styleCache = new StyleCache();
}
var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this);
var scopeCacheable = !this.__notStyleScopeCacheable;
if (scopeCacheable) {
scopeData.key.customStyle = this.customStyle;
info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles);
}
var scopeCached = Boolean(info);
if (scopeCached) {
this._styleProperties = info._styleProperties;
} else {
this._computeStyleProperties(scopeData.properties);
}
this._computeOwnStyleProperties();
if (!scopeCached) {
info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles);
}
var globalCached = Boolean(info) && !scopeCached;
var style = this._applyStyleProperties(info);
if (!scopeCached) {
style = style && nativeShadow ? style.cloneNode(true) : style;
info = {
style: style,
_scopeSelector: this._scopeSelector,
_styleProperties: this._styleProperties
};
if (scopeCacheable) {
scopeData.key.customStyle = {};
this.mixin(scopeData.key.customStyle, this.customStyle);
scope._styleCache.store(this.is, info, scopeData.key, this._styles);
}
if (!globalCached) {
styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._styles);
}
}
},
_computeStyleProperties: function (scopeProps) {
var scope = this._findStyleHost();
if (!scope._styleProperties) {
scope._computeStyleProperties();
}
var props = Object.create(scope._styleProperties);
var hostAndRootProps = propertyUtils.hostAndRootPropertiesForScope(this);
this.mixin(props, hostAndRootProps.hostProps);
scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, this).properties;
this.mixin(props, scopeProps);
this.mixin(props, hostAndRootProps.rootProps);
propertyUtils.mixinCustomStyle(props, this.customStyle);
propertyUtils.reify(props);
this._styleProperties = props;
},
_computeOwnStyleProperties: function () {
var props = {};
for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) {
n = this._ownStylePropertyNames[i];
props[n] = this._styleProperties[n];
}
this._ownStyleProperties = props;
},
_scopeCount: 0,
_applyStyleProperties: function (info) {
var oldScopeSelector = this._scopeSelector;
this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++;
var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style);
if (!nativeShadow) {
propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr);
}
return style;
},
serializeValueToAttribute: function (value, attribute, node) {
node = node || this;
if (attribute === 'class' && !nativeShadow) {
var host = node === this ? this.domHost || this.dataHost : this;
if (host) {
value = host._scopeElementClass(node, value);
}
}
node = this.shadyRoot && this.shadyRoot._hasDistributed ? dom$0(node) : node;
serializeValueToAttribute.call(this, value, attribute, node);
},
_scopeElementClass: function (element, selector) {
if (!nativeShadow && !this._scopeCssViaAttr) {
selector = (selector ? selector + ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scopeSelector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : '');
}
return selector;
},
updateStyles: function (properties) {
if (properties) {
this.mixin(this.customStyle, properties);
}
if (nativeVariables) {
propertyUtils.updateNativeStyleProperties(this, this.customStyle);
} else {
if (this.isAttached) {
if (this._needsStyleProperties()) {
this._updateStyleProperties();
} else {
this._styleProperties = null;
}
} else {
this.__stylePropertiesInvalid = true;
}
if (this._styleCache) {
this._styleCache.clear();
}
this._updateRootStyles();
}
},
_updateRootStyles: function (root) {
root = root || this.root;
var c$ = dom$0(root)._query(function (e) {
return e.shadyRoot || e.shadowRoot;
});
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
if (c.updateStyles) {
c.updateStyles();
}
}
}
});
export const updateStyles = function (properties) {
styleDefaults.updateStyles(properties);
Base._updateRootStyles(document);
};
var styleCache = new StyleCache();
export { styleCache as customStyleCache };
var SCOPE_NAME = styleTransformer.SCOPE_NAME;
var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepConstructor();
this._prepStyles();
},
_finishRegisterFeatures: function () {
this._prepTemplate();
this._prepShimStyles();
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepPropertyInfo();
this._prepBindings();
this._prepShady();
},
_prepBehavior: function (b) {
this._addPropertyEffects(b.properties);
this._addComplexObserverEffects(b.observers);
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function () {
this._setupGestures();
this._setupConfigure();
this._setupStyleProperties();
this._setupDebouncers();
this._setupShady();
this._registerHost();
if (this._template) {
this._validateApplyShim();
this._poolContent();
this._beginHosting();
this._stampTemplate();
this._endHosting();
this._marshalAnnotationReferences();
}
this._marshalInstanceEffects();
this._marshalBehaviors();
this._marshalHostAttributes();
this._marshalAttributes();
this._tryReady();
},
_marshalBehavior: function (b) {
if (b.listeners) {
this._listenListeners(b.listeners);
}
}
});
var propertyUtils = StyleProperties;
var styleUtil = StyleUtil;
var cssParse = CssParse;
var styleDefaults = StyleDefaults;
var styleTransformer = StyleTransformer;
var applyShim = ApplyShim;
var debounce = Polymer.Debounce;
var settings = undefined;
var updateDebouncer;
Polymer$0({
is: 'custom-style',
extends: 'style',
_template: null,
properties: { include: String },
ready: function () {
this.__appliedElement = this.__appliedElement || this;
this.__cssBuild = styleUtil.getCssBuildType(this);
if (this.__appliedElement !== this) {
this.__appliedElement.__cssBuild = this.__cssBuild;
}
this._tryApply();
},
attached: function () {
this._tryApply();
},
_tryApply: function () {
if (!this._appliesToDocument) {
if (this.parentNode && this.parentNode.localName !== 'dom-module') {
this._appliesToDocument = true;
var e = this.__appliedElement;
if (!settings.useNativeCSSProperties) {
this.__needsUpdateStyles = styleDefaults.hasStyleProperties();
styleDefaults.addStyle(e);
}
if (e.textContent || this.include) {
this._apply(true);
} else {
var self = this;
var observer = new MutationObserver(function () {
observer.disconnect();
self._apply(true);
});
observer.observe(e, { childList: true });
}
}
}
},
_updateStyles: function () {
updateStyles$0();
},
_apply: function (initialApply) {
var e = this.__appliedElement;
if (this.include) {
e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent;
}
if (!e.textContent) {
return;
}
var buildType = this.__cssBuild;
var targetedBuild = styleUtil.isTargetedBuild(buildType);
if (settings.useNativeCSSProperties && targetedBuild) {
return;
}
var styleRules = styleUtil.rulesForStyle(e);
if (!targetedBuild) {
styleUtil.forEachRule(styleRules, function (rule) {
styleTransformer.documentRule(rule);
if (settings.useNativeCSSProperties && !buildType) {
applyShim.transformRule(rule);
}
});
}
if (settings.useNativeCSSProperties) {
e.textContent = styleUtil.toCssText(styleRules);
} else {
var self = this;
var fn = function fn() {
self._flushCustomProperties();
};
if (initialApply) {
renderStatus.whenReady(fn);
} else {
fn();
}
}
},
_flushCustomProperties: function () {
if (this.__needsUpdateStyles) {
this.__needsUpdateStyles = false;
updateDebouncer = debounce(updateDebouncer, this._updateStyles);
} else {
this._applyCustomProperties();
}
},
_applyCustomProperties: function () {
var element = this.__appliedElement;
this._computeStyleProperties();
var props = this._styleProperties;
var rules = styleUtil.rulesForStyle(element);
if (!rules) {
return;
}
element.textContent = styleUtil.toCssText(rules, function (rule) {
var css = rule.cssText = rule.parsedCssText;
if (rule.propertyInfo && rule.propertyInfo.cssText) {
css = cssParse.removeCustomPropAssignment(css);
rule.cssText = propertyUtils.valueForProperties(css, props);
}
});
}
});
export const Templatizer = {
properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } },
_instanceProps: Polymer.nob,
_parentPropPrefix: '_parent_',
templatize: function (template) {
this._templatized = template;
if (!template._content) {
template._content = template.content;
}
if (template._content._ctor) {
this.ctor = template._content._ctor;
this._prepParentProperties(this.ctor.prototype, template);
return;
}
var archetype = Object.create(Base);
this._customPrepAnnotations(archetype, template);
this._prepParentProperties(archetype, template);
archetype._prepEffects();
this._customPrepEffects(archetype);
archetype._prepBehaviors();
archetype._prepPropertyInfo();
archetype._prepBindings();
archetype._notifyPathUp = this._notifyPathUpImpl;
archetype._scopeElementClass = this._scopeElementClassImpl;
archetype.listen = this._listenImpl;
archetype._showHideChildren = this._showHideChildrenImpl;
archetype.__setPropertyOrig = this.__setProperty;
archetype.__setProperty = this.__setPropertyImpl;
var _constructor = this._constructorImpl;
var ctor = function TemplateInstance(model, host) {
_constructor.call(this, model, host);
};
ctor.prototype = archetype;
archetype.constructor = ctor;
template._content._ctor = ctor;
this.ctor = ctor;
},
_getRootDataHost: function () {
return this.dataHost && this.dataHost._rootDataHost || this.dataHost;
},
_showHideChildrenImpl: function (hide) {
var c = this._children;
for (var i = 0; i < c.length; i++) {
var n = c[i];
if (Boolean(hide) != Boolean(n.__hideTemplateChildren__)) {
if (n.nodeType === Node.TEXT_NODE) {
if (hide) {
n.__polymerTextContent__ = n.textContent;
n.textContent = '';
} else {
n.textContent = n.__polymerTextContent__;
}
} else if (n.style) {
if (hide) {
n.__polymerDisplay__ = n.style.display;
n.style.display = 'none';
} else {
n.style.display = n.__polymerDisplay__;
}
}
}
n.__hideTemplateChildren__ = hide;
}
},
__setPropertyImpl: function (property, value, fromAbove, node) {
if (node && node.__hideTemplateChildren__ && property == 'textContent') {
property = '__polymerTextContent__';
}
this.__setPropertyOrig(property, value, fromAbove, node);
},
_debounceTemplate: function (fn) {
addDebouncer(this.debounce('_debounceTemplate', fn));
},
_flushTemplates: function () {
flush();
},
_customPrepEffects: function (archetype) {
var parentProps = archetype._parentProps;
for (var prop in parentProps) {
archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop));
}
for (prop in this._instanceProps) {
archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector(prop));
}
},
_customPrepAnnotations: function (archetype, template) {
archetype._template = template;
var c = template._content;
if (!c._notes) {
var rootDataHost = archetype._rootDataHost;
if (rootDataHost) {
Annotations.prepElement = function () {
rootDataHost._prepElement();
};
}
c._notes = Annotations.parseAnnotations(template);
Annotations.prepElement = null;
this._processAnnotations(c._notes);
}
archetype._notes = c._notes;
archetype._parentProps = c._parentProps;
},
_prepParentProperties: function (archetype, template) {
var parentProps = this._parentProps = archetype._parentProps;
if (this._forwardParentProp && parentProps) {
var proto = archetype._parentPropProto;
var prop;
if (!proto) {
for (prop in this._instanceProps) {
delete parentProps[prop];
}
proto = archetype._parentPropProto = Object.create(null);
if (template != this) {
Bind.prepareModel(proto);
Base.prepareModelNotifyPath(proto);
}
for (prop in parentProps) {
var parentProp = this._parentPropPrefix + prop;
var effects = [
{
kind: 'function',
effect: this._createForwardPropEffector(prop),
fn: Bind._functionEffect
},
{
kind: 'notify',
fn: Bind._notifyEffect,
effect: { event: camelToDashCase(parentProp) + '-changed' }
}
];
Bind._createAccessors(proto, parentProp, effects);
}
}
var self = this;
if (template != this) {
Bind.prepareInstance(template);
template._forwardParentProp = function (source, value) {
self._forwardParentProp(source, value);
};
}
this._extendTemplate(template, proto);
template._pathEffector = function (path, value, fromAbove) {
return self._pathEffectorImpl(path, value, fromAbove);
};
}
},
_createForwardPropEffector: function (prop) {
return function (source, value) {
this._forwardParentProp(prop, value);
};
},
_createHostPropEffector: function (prop) {
var prefix = this._parentPropPrefix;
return function (source, value) {
this.dataHost._templatized[prefix + prop] = value;
};
},
_createInstancePropEffector: function (prop) {
return function (source, value, old, fromAbove) {
if (!fromAbove) {
this.dataHost._forwardInstanceProp(this, prop, value);
}
};
},
_extendTemplate: function (template, proto) {
var n$ = Object.getOwnPropertyNames(proto);
if (proto._propertySetter) {
template._propertySetter = proto._propertySetter;
}
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
var val = template[n];
var pd = Object.getOwnPropertyDescriptor(proto, n);
Object.defineProperty(template, n, pd);
if (val !== undefined) {
template._propertySetter(n, val);
}
}
},
_showHideChildren: function (hidden) {
},
_forwardInstancePath: function (inst, path, value) {
},
_forwardInstanceProp: function (inst, prop, value) {
},
_notifyPathUpImpl: function (path, value) {
var dataHost = this.dataHost;
var dot = path.indexOf('.');
var root = dot < 0 ? path : path.slice(0, dot);
dataHost._forwardInstancePath.call(dataHost, this, path, value);
if (root in dataHost._parentProps) {
dataHost._templatized._notifyPath(dataHost._parentPropPrefix + path, value);
}
},
_pathEffectorImpl: function (path, value, fromAbove) {
if (this._forwardParentPath) {
if (path.indexOf(this._parentPropPrefix) === 0) {
var subPath = path.substring(this._parentPropPrefix.length);
var model = this._modelForPath(subPath);
if (model in this._parentProps) {
this._forwardParentPath(subPath, value);
}
}
}
Base._pathEffector.call(this._templatized, path, value, fromAbove);
},
_constructorImpl: function (model, host) {
this._rootDataHost = host._getRootDataHost();
this._setupConfigure(model);
this._registerHost(host);
this._beginHosting();
this.root = this.instanceTemplate(this._template);
this.root.__noContent = !this._notes._hasContent;
this.root.__styleScoped = true;
this._endHosting();
this._marshalAnnotatedNodes();
this._marshalInstanceEffects();
this._marshalAnnotatedListeners();
var children = [];
for (var n = this.root.firstChild; n; n = n.nextSibling) {
children.push(n);
n._templateInstance = this;
}
this._children = children;
if (host.__hideTemplateChildren__) {
this._showHideChildren(true);
}
this._tryReady();
},
_listenImpl: function (node, eventName, methodName) {
var model = this;
var host = this._rootDataHost;
var handler = host._createEventHandler(node, eventName, methodName);
var decorated = function (e) {
e.model = model;
handler(e);
};
host._listen(node, eventName, decorated);
},
_scopeElementClassImpl: function (node, value) {
var host = this._rootDataHost;
if (host) {
return host._scopeElementClass(node, value);
}
return value;
},
stamp: function (model) {
model = model || {};
if (this._parentProps) {
var templatized = this._templatized;
for (var prop in this._parentProps) {
if (model[prop] === undefined) {
model[prop] = templatized[this._parentPropPrefix + prop];
}
}
}
return new this.ctor(model, this);
},
modelForElement: function (el) {
var model;
while (el) {
if (model = el._templateInstance) {
if (model.dataHost != this) {
el = model.dataHost;
} else {
return model;
}
} else {
el = el.parentNode;
}
}
}
};
Polymer$0({
is: 'dom-template',
extends: 'template',
_template: null,
behaviors: [Templatizer$0],
ready: function () {
this.templatize(this);
}
});
export const _collections = new WeakMap();
export const Collection = function (userArray) {
_collections.set(userArray, this);
this.userArray = userArray;
this.store = userArray.slice();
this.initMap();
};
undefined.prototype = {
constructor: undefined,
initMap: function () {
var omap = this.omap = new WeakMap();
var pmap = this.pmap = {};
var s = this.store;
for (var i = 0; i < s.length; i++) {
var item = s[i];
if (item && typeof item == 'object') {
omap.set(item, i);
} else {
pmap[item] = i;
}
}
},
add: function (item) {
var key = this.store.push(item) - 1;
if (item && typeof item == 'object') {
this.omap.set(item, key);
} else {
this.pmap[item] = key;
}
return '#' + key;
},
removeKey: function (key) {
if (key = this._parseKey(key)) {
this._removeFromMap(this.store[key]);
delete this.store[key];
}
},
_removeFromMap: function (item) {
if (item && typeof item == 'object') {
this.omap.delete(item);
} else {
delete this.pmap[item];
}
},
remove: function (item) {
var key = this.getKey(item);
this.removeKey(key);
return key;
},
getKey: function (item) {
var key;
if (item && typeof item == 'object') {
key = this.omap.get(item);
} else {
key = this.pmap[item];
}
if (key != undefined) {
return '#' + key;
}
},
getKeys: function () {
return Object.keys(this.store).map(function (key) {
return '#' + key;
});
},
_parseKey: function (key) {
if (key && key[0] == '#') {
return key.slice(1);
}
},
setItem: function (key, item) {
if (key = this._parseKey(key)) {
var old = this.store[key];
if (old) {
this._removeFromMap(old);
}
if (item && typeof item == 'object') {
this.omap.set(item, key);
} else {
this.pmap[item] = key;
}
this.store[key] = item;
}
},
getItem: function (key) {
if (key = this._parseKey(key)) {
return this.store[key];
}
},
getItems: function () {
var items = [], store = this.store;
for (var key in store) {
items.push(store[key]);
}
return items;
},
_applySplices: function (splices) {
var keyMap = {}, key;
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
s.addedKeys = [];
for (var j = 0; j < s.removed.length; j++) {
key = this.getKey(s.removed[j]);
keyMap[key] = keyMap[key] ? null : -1;
}
for (j = 0; j < s.addedCount; j++) {
var item = this.userArray[s.index + j];
key = this.getKey(item);
key = key === undefined ? this.add(item) : key;
keyMap[key] = keyMap[key] ? null : 1;
s.addedKeys.push(key);
}
}
var removed = [];
var added = [];
for (key in keyMap) {
if (keyMap[key] < 0) {
this.removeKey(key);
removed.push(key);
}
if (keyMap[key] > 0) {
added.push(key);
}
}
return [{
removed: removed,
added: added
}];
}
};
undefined.get = function (userArray) {
return _collections.get(userArray) || new undefined(userArray);
};
undefined.applySplices = function (userArray, splices) {
var coll = _collections.get(userArray);
return coll ? coll._applySplices(splices) : null;
};Polymer$0({
is: 'dom-repeat',
extends: 'template',
_template: null,
properties: {
items: { type: Array },
as: {
type: String,
value: 'item'
},
indexAs: {
type: String,
value: 'index'
},
sort: {
type: Function,
observer: '_sortChanged'
},
filter: {
type: Function,
observer: '_filterChanged'
},
observe: {
type: String,
observer: '_observeChanged'
},
delay: Number,
renderedItemCount: {
type: Number,
notify: true,
readOnly: true
},
initialCount: {
type: Number,
observer: '_initializeChunking'
},
targetFramerate: {
type: Number,
value: 20
},
_targetFrameTime: {
type: Number,
computed: '_computeFrameTime(targetFramerate)'
}
},
behaviors: [Templatizer$0],
observers: ['_itemsChanged(items.*)'],
created: function () {
this._instances = [];
this._pool = [];
this._limit = Infinity;
var self = this;
this._boundRenderChunk = function () {
self._renderChunk();
};
},
detached: function () {
this.__isDetached = true;
for (var i = 0; i < this._instances.length; i++) {
this._detachInstance(i);
}
},
attached: function () {
if (this.__isDetached) {
this.__isDetached = false;
var parent = dom$0(dom$0(this).parentNode);
for (var i = 0; i < this._instances.length; i++) {
this._attachInstance(i, parent);
}
}
},
ready: function () {
this._instanceProps = { __key__: true };
this._instanceProps[this.as] = true;
this._instanceProps[this.indexAs] = true;
if (!this.ctor) {
this.templatize(this);
}
},
_sortChanged: function (sort) {
var dataHost = this._getRootDataHost();
this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
return dataHost[sort].apply(dataHost, arguments);
});
this._needFullRefresh = true;
if (this.items) {
this._debounceTemplate(this._render);
}
},
_filterChanged: function (filter) {
var dataHost = this._getRootDataHost();
this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
return dataHost[filter].apply(dataHost, arguments);
});
this._needFullRefresh = true;
if (this.items) {
this._debounceTemplate(this._render);
}
},
_computeFrameTime: function (rate) {
return Math.ceil(1000 / rate);
},
_initializeChunking: function () {
if (this.initialCount) {
this._limit = this.initialCount;
this._chunkCount = this.initialCount;
this._lastChunkTime = performance.now();
}
},
_tryRenderChunk: function () {
if (this.items && this._limit < this.items.length) {
this.debounce('renderChunk', this._requestRenderChunk);
}
},
_requestRenderChunk: function () {
requestAnimationFrame(this._boundRenderChunk);
},
_renderChunk: function () {
var currChunkTime = performance.now();
var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime);
this._chunkCount = Math.round(this._chunkCount * ratio) || 1;
this._limit += this._chunkCount;
this._lastChunkTime = currChunkTime;
this._debounceTemplate(this._render);
},
_observeChanged: function () {
this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
},
_itemsChanged: function (change) {
if (change.path == 'items') {
if (Array.isArray(this.items)) {
this.collection = undefined.get(this.items);
} else if (!this.items) {
this.collection = null;
} else {
this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', this.items));
}
this._keySplices = [];
this._indexSplices = [];
this._needFullRefresh = true;
this._initializeChunking();
this._debounceTemplate(this._render);
} else if (change.path == 'items.splices') {
this._keySplices = this._keySplices.concat(change.value.keySplices);
this._indexSplices = this._indexSplices.concat(change.value.indexSplices);
this._debounceTemplate(this._render);
} else {
var subpath = change.path.slice(6);
this._forwardItemPath(subpath, change.value);
this._checkObservedPaths(subpath);
}
},
_checkObservedPaths: function (path) {
if (this._observePaths) {
path = path.substring(path.indexOf('.') + 1);
var paths = this._observePaths;
for (var i = 0; i < paths.length; i++) {
if (path.indexOf(paths[i]) === 0) {
this._needFullRefresh = true;
if (this.delay) {
this.debounce('render', this._render, this.delay);
} else {
this._debounceTemplate(this._render);
}
return;
}
}
}
},
render: function () {
this._needFullRefresh = true;
this._debounceTemplate(this._render);
this._flushTemplates();
},
_render: function () {
if (this._needFullRefresh) {
this._applyFullRefresh();
this._needFullRefresh = false;
} else if (this._keySplices.length) {
if (this._sortFn) {
this._applySplicesUserSort(this._keySplices);
} else {
if (this._filterFn) {
this._applyFullRefresh();
} else {
this._applySplicesArrayOrder(this._indexSplices);
}
}
} else {
}
this._keySplices = [];
this._indexSplices = [];
var keyToIdx = this._keyToInstIdx = {};
for (var i = this._instances.length - 1; i >= 0; i--) {
var inst = this._instances[i];
if (inst.isPlaceholder && i < this._limit) {
inst = this._insertInstance(i, inst.__key__);
} else if (!inst.isPlaceholder && i >= this._limit) {
inst = this._downgradeInstance(i, inst.__key__);
}
keyToIdx[inst.__key__] = i;
if (!inst.isPlaceholder) {
inst.__setProperty(this.indexAs, i, true);
}
}
this._pool.length = 0;
this._setRenderedItemCount(this._instances.length);
this.fire('dom-change');
this._tryRenderChunk();
},
_applyFullRefresh: function () {
var c = this.collection;
var keys;
if (this._sortFn) {
keys = c ? c.getKeys() : [];
} else {
keys = [];
var items = this.items;
if (items) {
for (var i = 0; i < items.length; i++) {
keys.push(c.getKey(items[i]));
}
}
}
var self = this;
if (this._filterFn) {
keys = keys.filter(function (a) {
return self._filterFn(c.getItem(a));
});
}
if (this._sortFn) {
keys.sort(function (a, b) {
return self._sortFn(c.getItem(a), c.getItem(b));
});
}
for (i = 0; i < keys.length; i++) {
var key = keys[i];
var inst = this._instances[i];
if (inst) {
inst.__key__ = key;
if (!inst.isPlaceholder && i < this._limit) {
inst.__setProperty(this.as, c.getItem(key), true);
}
} else if (i < this._limit) {
this._insertInstance(i, key);
} else {
this._insertPlaceholder(i, key);
}
}
for (var j = this._instances.length - 1; j >= i; j--) {
this._detachAndRemoveInstance(j);
}
},
_numericSort: function (a, b) {
return a - b;
},
_applySplicesUserSort: function (splices) {
var c = this.collection;
var keyMap = {};
var key;
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
for (var j = 0; j < s.removed.length; j++) {
key = s.removed[j];
keyMap[key] = keyMap[key] ? null : -1;
}
for (j = 0; j < s.added.length; j++) {
key = s.added[j];
keyMap[key] = keyMap[key] ? null : 1;
}
}
var removedIdxs = [];
var addedKeys = [];
for (key in keyMap) {
if (keyMap[key] === -1) {
removedIdxs.push(this._keyToInstIdx[key]);
}
if (keyMap[key] === 1) {
addedKeys.push(key);
}
}
if (removedIdxs.length) {
removedIdxs.sort(this._numericSort);
for (i = removedIdxs.length - 1; i >= 0; i--) {
var idx = removedIdxs[i];
if (idx !== undefined) {
this._detachAndRemoveInstance(idx);
}
}
}
var self = this;
if (addedKeys.length) {
if (this._filterFn) {
addedKeys = addedKeys.filter(function (a) {
return self._filterFn(c.getItem(a));
});
}
addedKeys.sort(function (a, b) {
return self._sortFn(c.getItem(a), c.getItem(b));
});
var start = 0;
for (i = 0; i < addedKeys.length; i++) {
start = this._insertRowUserSort(start, addedKeys[i]);
}
}
},
_insertRowUserSort: function (start, key) {
var c = this.collection;
var item = c.getItem(key);
var end = this._instances.length - 1;
var idx = -1;
while (start <= end) {
var mid = start + end >> 1;
var midKey = this._instances[mid].__key__;
var cmp = this._sortFn(c.getItem(midKey), item);
if (cmp < 0) {
start = mid + 1;
} else if (cmp > 0) {
end = mid - 1;
} else {
idx = mid;
break;
}
}
if (idx < 0) {
idx = end + 1;
}
this._insertPlaceholder(idx, key);
return idx;
},
_applySplicesArrayOrder: function (splices) {
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
for (var j = 0; j < s.removed.length; j++) {
this._detachAndRemoveInstance(s.index);
}
for (j = 0; j < s.addedKeys.length; j++) {
this._insertPlaceholder(s.index + j, s.addedKeys[j]);
}
}
},
_detachInstance: function (idx) {
var inst = this._instances[idx];
if (!inst.isPlaceholder) {
for (var i = 0; i < inst._children.length; i++) {
var el = inst._children[i];
dom$0(inst.root).appendChild(el);
}
return inst;
}
},
_attachInstance: function (idx, parent) {
var inst = this._instances[idx];
if (!inst.isPlaceholder) {
parent.insertBefore(inst.root, this);
}
},
_detachAndRemoveInstance: function (idx) {
var inst = this._detachInstance(idx);
if (inst) {
this._pool.push(inst);
}
this._instances.splice(idx, 1);
},
_insertPlaceholder: function (idx, key) {
this._instances.splice(idx, 0, {
isPlaceholder: true,
__key__: key
});
},
_stampInstance: function (idx, key) {
var model = { __key__: key };
model[this.as] = this.collection.getItem(key);
model[this.indexAs] = idx;
return this.stamp(model);
},
_insertInstance: function (idx, key) {
var inst = this._pool.pop();
if (inst) {
inst.__setProperty(this.as, this.collection.getItem(key), true);
inst.__setProperty('__key__', key, true);
} else {
inst = this._stampInstance(idx, key);
}
var beforeRow = this._instances[idx + 1];
var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
var parentNode = dom$0(this).parentNode;
dom$0(parentNode).insertBefore(inst.root, beforeNode);
this._instances[idx] = inst;
return inst;
},
_downgradeInstance: function (idx, key) {
var inst = this._detachInstance(idx);
if (inst) {
this._pool.push(inst);
}
inst = {
isPlaceholder: true,
__key__: key
};
this._instances[idx] = inst;
return inst;
},
_showHideChildren: function (hidden) {
for (var i = 0; i < this._instances.length; i++) {
this._instances[i]._showHideChildren(hidden);
}
},
_forwardInstanceProp: function (inst, prop, value) {
if (prop == this.as) {
var idx;
if (this._sortFn || this._filterFn) {
idx = this.items.indexOf(this.collection.getItem(inst.__key__));
} else {
idx = inst[this.indexAs];
}
this.set('items.' + idx, value);
}
},
_forwardInstancePath: function (inst, path, value) {
if (path.indexOf(this.as + '.') === 0) {
this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
}
},
_forwardParentProp: function (prop, value) {
var i$ = this._instances;
for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
if (!inst.isPlaceholder) {
inst.__setProperty(prop, value, true);
}
}
},
_forwardParentPath: function (path, value) {
var i$ = this._instances;
for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
if (!inst.isPlaceholder) {
inst._notifyPath(path, value, true);
}
}
},
_forwardItemPath: function (path, value) {
if (this._keyToInstIdx) {
var dot = path.indexOf('.');
var key = path.substring(0, dot < 0 ? path.length : dot);
var idx = this._keyToInstIdx[key];
var inst = this._instances[idx];
if (inst && !inst.isPlaceholder) {
if (dot >= 0) {
path = this.as + '.' + path.substring(dot + 1);
inst._notifyPath(path, value, true);
} else {
inst.__setProperty(this.as, value, true);
}
}
}
},
itemForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance[this.as];
},
keyForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance.__key__;
},
indexForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance[this.indexAs];
}
});Polymer$0({
is: 'array-selector',
_template: null,
properties: {
items: {
type: Array,
observer: 'clearSelection'
},
multi: {
type: Boolean,
value: false,
observer: 'clearSelection'
},
selected: {
type: Object,
notify: true
},
selectedItem: {
type: Object,
notify: true
},
toggle: {
type: Boolean,
value: false
}
},
clearSelection: function () {
if (Array.isArray(this.selected)) {
for (var i = 0; i < this.selected.length; i++) {
this.unlinkPaths('selected.' + i);
}
} else {
this.unlinkPaths('selected');
this.unlinkPaths('selectedItem');
}
if (this.multi) {
if (!this.selected || this.selected.length) {
this.selected = [];
this._selectedColl = undefined.get(this.selected);
}
} else {
this.selected = null;
this._selectedColl = null;
}
this.selectedItem = null;
},
isSelected: function (item) {
if (this.multi) {
return this._selectedColl.getKey(item) !== undefined;
} else {
return this.selected == item;
}
},
deselect: function (item) {
if (this.multi) {
if (this.isSelected(item)) {
var skey = this._selectedColl.getKey(item);
this.arrayDelete('selected', item);
this.unlinkPaths('selected.' + skey);
}
} else {
this.selected = null;
this.selectedItem = null;
this.unlinkPaths('selected');
this.unlinkPaths('selectedItem');
}
},
select: function (item) {
var icol = undefined.get(this.items);
var key = icol.getKey(item);
if (this.multi) {
if (this.isSelected(item)) {
if (this.toggle) {
this.deselect(item);
}
} else {
this.push('selected', item);
var skey = this._selectedColl.getKey(item);
this.linkPaths('selected.' + skey, 'items.' + key);
}
} else {
if (this.toggle && item == this.selected) {
this.deselect();
} else {
this.selected = item;
this.selectedItem = item;
this.linkPaths('selected', 'items.' + key);
this.linkPaths('selectedItem', 'items.' + key);
}
}
}
});Polymer$0({
is: 'dom-if',
extends: 'template',
_template: null,
properties: {
'if': {
type: Boolean,
value: false,
observer: '_queueRender'
},
restamp: {
type: Boolean,
value: false,
observer: '_queueRender'
}
},
behaviors: [Templatizer$0],
_queueRender: function () {
this._debounceTemplate(this._render);
},
detached: function () {
if (!this.parentNode || this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (!undefined.hasShadow || !(this.parentNode instanceof ShadowRoot))) {
this._teardownInstance();
}
},
attached: function () {
if (this.if && this.ctor) {
this.async(this._ensureInstance);
}
},
render: function () {
this._flushTemplates();
},
_render: function () {
if (this.if) {
if (!this.ctor) {
this.templatize(this);
}
this._ensureInstance();
this._showHideChildren();
} else if (this.restamp) {
this._teardownInstance();
}
if (!this.restamp && this._instance) {
this._showHideChildren();
}
if (this.if != this._lastIf) {
this.fire('dom-change');
this._lastIf = this.if;
}
},
_ensureInstance: function () {
var parentNode = dom$0(this).parentNode;
if (parentNode) {
var parent = dom$0(parentNode);
if (!this._instance) {
this._instance = this.stamp();
var root = this._instance.root;
parent.insertBefore(root, this);
} else {
var c$ = this._instance._children;
if (c$ && c$.length) {
var lastChild = dom$0(this).previousSibling;
if (lastChild !== c$[c$.length - 1]) {
for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
parent.insertBefore(n, this);
}
}
}
}
}
},
_teardownInstance: function () {
if (this._instance) {
var c$ = this._instance._children;
if (c$ && c$.length) {
var parent = dom$0(dom$0(c$[0]).parentNode);
for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
parent.removeChild(n);
}
}
this._instance = null;
}
},
_showHideChildren: function () {
var hidden = this.__hideTemplateChildren__ || !this.if;
if (this._instance) {
this._instance._showHideChildren(hidden);
}
},
_forwardParentProp: function (prop, value) {
if (this._instance) {
this._instance.__setProperty(prop, value, true);
}
},
_forwardParentPath: function (path, value) {
if (this._instance) {
this._instance._notifyPath(path, value, true);
}
}
});Polymer$0({
is: 'dom-bind',
extends: 'template',
_template: null,
created: function () {
var self = this;
renderStatus.whenReady(function () {
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', function () {
self._markImportsReady();
});
} else {
self._markImportsReady();
}
});
},
_ensureReady: function () {
if (!this._readied) {
this._readySelf();
}
},
_markImportsReady: function () {
this._importsReady = true;
this._ensureReady();
},
_registerFeatures: function () {
this._prepConstructor();
},
_insertChildren: function () {
var parentDom = dom$0(dom$0(this).parentNode);
parentDom.insertBefore(this.root, this);
},
_removeChildren: function () {
if (this._children) {
for (var i = 0; i < this._children.length; i++) {
this.root.appendChild(this._children[i]);
}
}
},
_initFeatures: function () {
},
_scopeElementClass: function (element, selector) {
if (this.dataHost) {
return this.dataHost._scopeElementClass(element, selector);
} else {
return selector;
}
},
_configureInstanceProperties: function () {
},
_prepConfigure: function () {
var config = {};
for (var prop in this._propertyEffects) {
config[prop] = this[prop];
}
var setupConfigure = this._setupConfigure;
this._setupConfigure = function () {
setupConfigure.call(this, config);
};
},
attached: function () {
if (this._importsReady) {
this.render();
}
},
detached: function () {
this._removeChildren();
},
render: function () {
this._ensureReady();
if (!this._children) {
this._template = this;
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepConfigure();
this._prepBindings();
this._prepPropertyInfo();
Base._initFeatures.call(this);
this._children = Polymer.TreeApi.arrayCopyChildNodes(this.root);
}
this._insertChildren();
this.fire('dom-change');
}
});
</script>
<script>/**
@license
Copyright (c) 2016 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
*/
function MakePromise (asap) {
function Promise(fn) {
if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError();
this._state = null;
this._value = null;
this._deferreds = []
doResolve(fn, resolve.bind(this), reject.bind(this));
}
function handle(deferred) {
var me = this;
if (this._state === null) {
this._deferreds.push(deferred);
return
}
asap(function() {
var cb = me._state ? deferred.onFulfilled : deferred.onRejected
if (typeof cb !== 'function') {
(me._state ? deferred.resolve : deferred.reject)(me._value);
return;
}
var ret;
try {
ret = cb(me._value);
}
catch (e) {
deferred.reject(e);
return;
}
deferred.resolve(ret);
})
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === this) throw new TypeError();
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
doResolve(then.bind(newValue), resolve.bind(this), reject.bind(this));
return;
}
}
this._state = true;
this._value = newValue;
finale.call(this);
} catch (e) { reject.call(this, e); }
}
function reject(newValue) {
this._state = false;
this._value = newValue;
finale.call(this);
}
function finale() {
for (var i = 0, len = this._deferreds.length; i < len; i++) {
handle.call(this, this._deferreds[i]);
}
this._deferreds = null;
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return;
done = true;
onFulfilled(value);
}, function (reason) {
if (done) return;
done = true;
onRejected(reason);
})
} catch (ex) {
if (done) return;
done = true;
onRejected(ex);
}
}
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function(onFulfilled, onRejected) {
var me = this;
return new Promise(function(resolve, reject) {
handle.call(me, {
onFulfilled: onFulfilled,
onRejected: onRejected,
resolve: resolve,
reject: reject
});
})
};
Promise.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
};
return Promise;
}
if (typeof module !== 'undefined') {
module.exports = MakePromise;
}
</script><script type="module">
import { Base } from '@polymer/polymer/polymer-legacy.js';
if (!window.Promise) {
window.Promise = MakePromise(Base.async);
}
</script>
<script>
(function () {
var _bindingRegex_patch = {
// Issue with https://github.com/Polymer/polymer/issues/3349
_bindingRegex_1_2_4: (function() {
var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$-*]*' + ')';
var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
var ARGUMENT_LIST = '(?:' + '\\(\\s*' +
'(?:' + ARGUMENTS + '?' + ')' +
'\\)\\s*' + ')';
var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')'; // Group 3
var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
var CLOSE_BRACKET = '(?:]]|}})';
var NEGATE = '(?:(!)\\s*)?'; // Group 2
var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
return new RegExp(EXPRESSION, "g");
})(),
// Fix from https://github.com/TimvdLippe/polymer/blob/fix-binding-with-dash/src/lib/annotations/annotations.html
_bindingRegex_1_2_4_patched: (function() {
var IDENT = '(?:' + '[a-zA-Z_\\$][\\w\\.:\\$\\-\\*]*' + ')';
var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
var ARGUMENT_LIST = '(?:' + '\\(\\s*' +
'(?:' + ARGUMENTS + '?' + ')' +
'\\)\\s*' + ')';
var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')'; // Group 3
var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
var CLOSE_BRACKET = '(?:]]|}})';
var NEGATE = '(?:(!)\\s*)?'; // Group 2
var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
return new RegExp(EXPRESSION, "g");
})()
};
if (Polymer.Annotations._bindingRegex.toString() ===
_bindingRegex_patch._bindingRegex_1_2_4.toString()) {
console.log('Fixing Polymer issue#3349 by patching Polymer.Annotations._bindingRegex for Polymer 1.2.4');
Polymer.Annotations._bindingRegex = _bindingRegex_patch._bindingRegex_1_2_4_patched;
}
})();
</script>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { Base } from '@polymer/polymer/polymer-legacy.js';
Polymer({
is: 'iron-request',
hostAttributes: {
hidden: true
},
properties: {
/**
* A reference to the XMLHttpRequest instance used to generate the
* network request.
*
* @type {XMLHttpRequest}
*/
xhr: {
type: Object,
notify: true,
readOnly: true,
value: function() {
return new XMLHttpRequest();
}
},
/**
* A reference to the parsed response body, if the `xhr` has completely
* resolved.
*
* @type {*}
* @default null
*/
response: {
type: Object,
notify: true,
readOnly: true,
value: function() {
return null;
}
},
/**
* A reference to the status code, if the `xhr` has completely resolved.
*/
status: {
type: Number,
notify: true,
readOnly: true,
value: 0
},
/**
* A reference to the status text, if the `xhr` has completely resolved.
*/
statusText: {
type: String,
notify: true,
readOnly: true,
value: ''
},
/**
* A promise that resolves when the `xhr` response comes back, or rejects
* if there is an error before the `xhr` completes.
*
* @type {Promise}
*/
completes: {
type: Object,
readOnly: true,
notify: true,
value: function() {
return new Promise(function (resolve, reject) {
this.resolveCompletes = resolve;
this.rejectCompletes = reject;
}.bind(this));
}
},
/**
* An object that contains progress information emitted by the XHR if
* available.
*
* @default {}
*/
progress: {
type: Object,
notify: true,
readOnly: true,
value: function() {
return {};
}
},
/**
* Aborted will be true if an abort of the request is attempted.
*/
aborted: {
type: Boolean,
notify: true,
readOnly: true,
value: false,
},
/**
* Errored will be true if the browser fired an error event from the
* XHR object (mainly network errors).
*/
errored: {
type: Boolean,
notify: true,
readOnly: true,
value: false
},
/**
* TimedOut will be true if the XHR threw a timeout event.
*/
timedOut: {
type: Boolean,
notify: true,
readOnly: true,
value: false
}
},
/**
* Succeeded is true if the request succeeded. The request succeeded if it
* loaded without error, wasn't aborted, and the status code is ≥ 200, and
* < 300, or if the status code is 0.
*
* The status code 0 is accepted as a success because some schemes - e.g.
* file:// - don't provide status codes.
*
* @return {boolean}
*/
get succeeded() {
if (this.errored || this.aborted || this.timedOut) {
return false;
}
var status = this.xhr.status || 0;
// Note: if we are using the file:// protocol, the status code will be 0
// for all outcomes (successful or otherwise).
return status === 0 ||
(status >= 200 && status < 300);
},
/**
* Sends an HTTP request to the server and returns the XHR object.
*
* The handling of the `body` parameter will vary based on the Content-Type
* header. See the docs for iron-ajax's `body` param for details.
*
* @param {{
* url: string,
* method: (string|undefined),
* async: (boolean|undefined),
* body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object),
* headers: (Object|undefined),
* handleAs: (string|undefined),
* jsonPrefix: (string|undefined),
* withCredentials: (boolean|undefined)}} options -
* url The url to which the request is sent.
* method The HTTP method to use, default is GET.
* async By default, all requests are sent asynchronously. To send synchronous requests,
* set to false.
* body The content for the request body for POST method.
* headers HTTP request headers.
* handleAs The response type. Default is 'text'.
* withCredentials Whether or not to send credentials on the request. Default is false.
* timeout: (Number|undefined)
* @return {Promise}
*/
send: function (options) {
var xhr = this.xhr;
if (xhr.readyState > 0) {
return null;
}
xhr.addEventListener('progress', function (progress) {
this._setProgress({
lengthComputable: progress.lengthComputable,
loaded: progress.loaded,
total: progress.total
});
}.bind(this))
xhr.addEventListener('error', function (error) {
this._setErrored(true);
this._updateStatus();
this.rejectCompletes(error);
}.bind(this));
xhr.addEventListener('timeout', function (error) {
this._setTimedOut(true);
this._updateStatus();
this.rejectCompletes(error);
}.bind(this));
xhr.addEventListener('abort', function () {
this._updateStatus();
this.rejectCompletes(new Error('Request aborted.'));
}.bind(this));
// Called after all of the above.
xhr.addEventListener('loadend', function () {
this._updateStatus();
this._setResponse(this.parseResponse());
if (!this.succeeded) {
this.rejectCompletes(new Error('The request failed with status code: ' + this.xhr.status));
return;
}
this.resolveCompletes(this);
}.bind(this));
this.url = options.url;
xhr.open(
options.method || 'GET',
options.url,
options.async !== false
);
var acceptType = {
'json': 'application/json',
'text': 'text/plain',
'html': 'text/html',
'xml': 'application/xml',
'arraybuffer': 'application/octet-stream'
}[options.handleAs];
var headers = options.headers || Object.create(null);
var newHeaders = Object.create(null);
for (var key in headers) {
newHeaders[key.toLowerCase()] = headers[key];
}
headers = newHeaders;
if (acceptType && !headers['accept']) {
headers['accept'] = acceptType;
}
Object.keys(headers).forEach(function (requestHeader) {
if (/[A-Z]/.test(requestHeader)) {
Base._error('Headers must be lower case, got', requestHeader);
}
xhr.setRequestHeader(
requestHeader,
headers[requestHeader]
);
}, this);
if (options.async !== false) {
if (options.async) {
xhr.timeout = options.timeout;
}
var handleAs = options.handleAs;
// If a JSON prefix is present, the responseType must be 'text' or the
// browser won’t be able to parse the response.
if (!!options.jsonPrefix || !handleAs) {
handleAs = 'text';
}
// In IE, `xhr.responseType` is an empty string when the response
// returns. Hence, caching it as `xhr._responseType`.
xhr.responseType = xhr._responseType = handleAs;
// Cache the JSON prefix, if it exists.
if (!!options.jsonPrefix) {
xhr._jsonPrefix = options.jsonPrefix;
}
}
xhr.withCredentials = !!options.withCredentials;
var body = this._encodeBodyObject(options.body, headers['content-type']);
xhr.send(
/** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|
null|string|undefined} */
(body));
return this.completes;
},
/**
* Attempts to parse the response body of the XHR. If parsing succeeds,
* the value returned will be deserialized based on the `responseType`
* set on the XHR.
*
* @return {*} The parsed response,
* or undefined if there was an empty response or parsing failed.
*/
parseResponse: function () {
var xhr = this.xhr;
var responseType = xhr.responseType || xhr._responseType;
var preferResponseText = !this.xhr.responseType;
var prefixLen = (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0;
try {
switch (responseType) {
case 'json':
// If the xhr object doesn't have a natural `xhr.responseType`,
// we can assume that the browser hasn't parsed the response for us,
// and so parsing is our responsibility. Likewise if response is
// undefined, as there's no way to encode undefined in JSON.
if (preferResponseText || xhr.response === undefined) {
// Try to emulate the JSON section of the response body section of
// the spec: https://xhr.spec.whatwg.org/#response-body
// That is to say, we try to parse as JSON, but if anything goes
// wrong return null.
try {
return JSON.parse(xhr.responseText);
} catch (_) {
return null;
}
}
return xhr.response;
case 'xml':
return xhr.responseXML;
case 'blob':
case 'document':
case 'arraybuffer':
return xhr.response;
case 'text':
default: {
// If `prefixLen` is set, it implies the response should be parsed
// as JSON once the prefix of length `prefixLen` is stripped from
// it. Emulate the behavior above where null is returned on failure
// to parse.
if (prefixLen) {
try {
return JSON.parse(xhr.responseText.substring(prefixLen));
} catch (_) {
return null;
}
}
return xhr.responseText;
}
}
} catch (e) {
this.rejectCompletes(new Error('Could not parse response. ' + e.message));
}
},
/**
* Aborts the request.
*/
abort: function () {
this._setAborted(true);
this.xhr.abort();
},
/**
* @param {*} body The given body of the request to try and encode.
* @param {?string} contentType The given content type, to infer an encoding
* from.
* @return {*} Either the encoded body as a string, if successful,
* or the unaltered body object if no encoding could be inferred.
*/
_encodeBodyObject: function(body, contentType) {
if (typeof body == 'string') {
return body; // Already encoded.
}
var bodyObj = /** @type {Object} */ (body);
switch(contentType) {
case('application/json'):
return JSON.stringify(bodyObj);
case('application/x-www-form-urlencoded'):
return this._wwwFormUrlEncode(bodyObj);
}
return body;
},
/**
* @param {Object} object The object to encode as x-www-form-urlencoded.
* @return {string} .
*/
_wwwFormUrlEncode: function(object) {
if (!object) {
return '';
}
var pieces = [];
Object.keys(object).forEach(function(key) {
// TODO(rictic): handle array values here, in a consistent way with
// iron-ajax params.
pieces.push(
this._wwwFormUrlEncodePiece(key) + '=' +
this._wwwFormUrlEncodePiece(object[key]));
}, this);
return pieces.join('&');
},
/**
* @param {*} str A key or value to encode as x-www-form-urlencoded.
* @return {string} .
*/
_wwwFormUrlEncodePiece: function(str) {
// Spec says to normalize newlines to \r\n and replace %20 spaces with +.
// jQuery does this as well, so this is likely to be widely compatible.
if (str === null) {
return '';
}
return encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n'))
.replace(/%20/g, '+');
},
/**
* Updates the status code and status text.
*/
_updateStatus: function() {
this._setStatus(this.xhr.status);
this._setStatusText((this.xhr.statusText === undefined) ? '' : this.xhr.statusText);
}
});
</script>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { Base } from '@polymer/polymer/polymer-legacy.js';
Polymer({
is: 'iron-ajax',
/**
* Fired when a request is sent.
*
* @event request
* @event iron-ajax-request
*/
/**
* Fired when a response is received.
*
* @event response
* @event iron-ajax-response
*/
/**
* Fired when an error is received.
*
* @event error
* @event iron-ajax-error
*/
hostAttributes: {
hidden: true
},
properties: {
/**
* The URL target of the request.
*/
url: {
type: String
},
/**
* An object that contains query parameters to be appended to the
* specified `url` when generating a request. If you wish to set the body
* content when making a POST request, you should use the `body` property
* instead.
*/
params: {
type: Object,
value: function() {
return {};
}
},
/**
* The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
* Default is 'GET'.
*/
method: {
type: String,
value: 'GET'
},
/**
* HTTP request headers to send.
*
* Example:
*
* <iron-ajax
* auto
* url="http://somesite.com"
* headers='{"X-Requested-With": "XMLHttpRequest"}'
* handle-as="json"></iron-ajax>
*
* Note: setting a `Content-Type` header here will override the value
* specified by the `contentType` property of this element.
*/
headers: {
type: Object,
value: function() {
return {};
}
},
/**
* Content type to use when sending data. If the `contentType` property
* is set and a `Content-Type` header is specified in the `headers`
* property, the `headers` property value will take precedence.
*
* Varies the handling of the `body` param.
*/
contentType: {
type: String,
value: null
},
/**
* Body content to send with the request, typically used with "POST"
* requests.
*
* If body is a string it will be sent unmodified.
*
* If Content-Type is set to a value listed below, then
* the body will be encoded accordingly.
*
* * `content-type="application/json"`
* * body is encoded like `{"foo":"bar baz","x":1}`
* * `content-type="application/x-www-form-urlencoded"`
* * body is encoded like `foo=bar+baz&x=1`
*
* Otherwise the body will be passed to the browser unmodified, and it
* will handle any encoding (e.g. for FormData, Blob, ArrayBuffer).
*
* @type (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object)
*/
body: {
type: Object,
value: null
},
/**
* Toggle whether XHR is synchronous or asynchronous. Don't change this
* to true unless You Know What You Are Doing™.
*/
sync: {
type: Boolean,
value: false
},
/**
* Specifies what data to store in the `response` property, and
* to deliver as `event.detail.response` in `response` events.
*
* One of:
*
* `text`: uses `XHR.responseText`.
*
* `xml`: uses `XHR.responseXML`.
*
* `json`: uses `XHR.responseText` parsed as JSON.
*
* `arraybuffer`: uses `XHR.response`.
*
* `blob`: uses `XHR.response`.
*
* `document`: uses `XHR.response`.
*/
handleAs: {
type: String,
value: 'json'
},
/**
* Set the withCredentials flag on the request.
*/
withCredentials: {
type: Boolean,
value: false
},
/**
* Set the timeout flag on the request.
*/
timeout: {
type: Number,
value: 0
},
/**
* If true, automatically performs an Ajax request when either `url` or
* `params` changes.
*/
auto: {
type: Boolean,
value: false
},
/**
* If true, error messages will automatically be logged to the console.
*/
verbose: {
type: Boolean,
value: false
},
/**
* The most recent request made by this iron-ajax element.
*/
lastRequest: {
type: Object,
notify: true,
readOnly: true
},
/**
* True while lastRequest is in flight.
*/
loading: {
type: Boolean,
notify: true,
readOnly: true
},
/**
* lastRequest's response.
*
* Note that lastResponse and lastError are set when lastRequest finishes,
* so if loading is true, then lastResponse and lastError will correspond
* to the result of the previous request.
*
* The type of the response is determined by the value of `handleAs` at
* the time that the request was generated.
*
* @type {Object}
*/
lastResponse: {
type: Object,
notify: true,
readOnly: true
},
/**
* lastRequest's error, if any.
*
* @type {Object}
*/
lastError: {
type: Object,
notify: true,
readOnly: true
},
/**
* An Array of all in-flight requests originating from this iron-ajax
* element.
*/
activeRequests: {
type: Array,
notify: true,
readOnly: true,
value: function() {
return [];
}
},
/**
* Length of time in milliseconds to debounce multiple automatically generated requests.
*/
debounceDuration: {
type: Number,
value: 0,
notify: true
},
/**
* Prefix to be stripped from a JSON response before parsing it.
*
* In order to prevent an attack using CSRF with Array responses
* (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/)
* many backends will mitigate this by prefixing all JSON response bodies
* with a string that would be nonsensical to a JavaScript parser.
*
*/
jsonPrefix: {
type: String,
value: ''
},
/**
* By default, iron-ajax's events do not bubble. Setting this attribute will cause its
* request and response events as well as its iron-ajax-request, -response, and -error
* events to bubble to the window object. The vanilla error event never bubbles when
* using shadow dom even if this.bubbles is true because a scoped flag is not passed with
* it (first link) and because the shadow dom spec did not used to allow certain events,
* including events named error, to leak outside of shadow trees (second link).
* https://www.w3.org/TR/shadow-dom/#scoped-flag
* https://www.w3.org/TR/2015/WD-shadow-dom-20151215/#events-that-are-not-leaked-into-ancestor-trees
*/
bubbles: {
type: Boolean,
value: false
},
_boundHandleResponse: {
type: Function,
value: function() {
return this._handleResponse.bind(this);
}
}
},
observers: [
'_requestOptionsChanged(url, method, params.*, headers, contentType, ' +
'body, sync, handleAs, jsonPrefix, withCredentials, timeout, auto)'
],
/**
* The query string that should be appended to the `url`, serialized from
* the current value of `params`.
*
* @return {string}
*/
get queryString () {
var queryParts = [];
var param;
var value;
for (param in this.params) {
value = this.params[param];
param = window.encodeURIComponent(param);
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
queryParts.push(param + '=' + window.encodeURIComponent(value[i]));
}
} else if (value !== null) {
queryParts.push(param + '=' + window.encodeURIComponent(value));
} else {
queryParts.push(param);
}
}
return queryParts.join('&');
},
/**
* The `url` with query string (if `params` are specified), suitable for
* providing to an `iron-request` instance.
*
* @return {string}
*/
get requestUrl() {
var queryString = this.queryString;
var url = this.url || '';
if (queryString) {
var bindingChar = url.indexOf('?') >= 0 ? '&' : '?';
return url + bindingChar + queryString;
}
return url;
},
/**
* An object that maps header names to header values, first applying the
* the value of `Content-Type` and then overlaying the headers specified
* in the `headers` property.
*
* @return {Object}
*/
get requestHeaders() {
var headers = {};
var contentType = this.contentType;
if (contentType == null && (typeof this.body === 'string')) {
contentType = 'application/x-www-form-urlencoded';
}
if (contentType) {
headers['content-type'] = contentType;
}
var header;
if (this.headers instanceof Object) {
for (header in this.headers) {
headers[header] = this.headers[header].toString();
}
}
return headers;
},
/**
* Request options suitable for generating an `iron-request` instance based
* on the current state of the `iron-ajax` instance's properties.
*
* @return {{
* url: string,
* method: (string|undefined),
* async: (boolean|undefined),
* body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object),
* headers: (Object|undefined),
* handleAs: (string|undefined),
* jsonPrefix: (string|undefined),
* withCredentials: (boolean|undefined)}}
*/
toRequestOptions: function() {
return {
url: this.requestUrl || '',
method: this.method,
headers: this.requestHeaders,
body: this.body,
async: !this.sync,
handleAs: this.handleAs,
jsonPrefix: this.jsonPrefix,
withCredentials: this.withCredentials,
timeout: this.timeout
};
},
/**
* Performs an AJAX request to the specified URL.
*
* @return {!IronRequestElement}
*/
generateRequest: function() {
var request = /** @type {!IronRequestElement} */ (document.createElement('iron-request'));
var requestOptions = this.toRequestOptions();
this.push('activeRequests', request);
request.completes.then(
this._boundHandleResponse
).catch(
this._handleError.bind(this, request)
).then(
this._discardRequest.bind(this, request)
);
request.send(requestOptions);
this._setLastRequest(request);
this._setLoading(true);
this.fire('request', {
request: request,
options: requestOptions
}, {bubbles: this.bubbles});
this.fire('iron-ajax-request', {
request: request,
options: requestOptions
}, {bubbles: this.bubbles});
return request;
},
_handleResponse: function(request) {
if (request === this.lastRequest) {
this._setLastResponse(request.response);
this._setLastError(null);
this._setLoading(false);
}
this.fire('response', request, {bubbles: this.bubbles});
this.fire('iron-ajax-response', request, {bubbles: this.bubbles});
},
_handleError: function(request, error) {
if (this.verbose) {
Base._error(error);
}
if (request === this.lastRequest) {
this._setLastError({
request: request,
error: error,
status: request.xhr.status,
statusText: request.xhr.statusText,
response: request.xhr.response
});
this._setLastResponse(null);
this._setLoading(false);
}
// Tests fail if this goes after the normal this.fire('error', ...)
this.fire('iron-ajax-error', {
request: request,
error: error
}, {bubbles: this.bubbles});
this.fire('error', {
request: request,
error: error
}, {bubbles: this.bubbles});
},
_discardRequest: function(request) {
var requestIndex = this.activeRequests.indexOf(request);
if (requestIndex > -1) {
this.splice('activeRequests', requestIndex, 1);
}
},
_requestOptionsChanged: function() {
this.debounce('generate-request', function() {
if (this.url == null) {
return;
}
if (this.auto) {
this.generateRequest();
}
}, this.debounceDuration);
},
});
</script>
<dom-module id="i18n-number" assetpath="../../../i18n-number/">
<template strip-whitespace="">
<span id="number"></span>
</template>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
var intlLibraryScript;
var intlLibraryLoadingStatus = 'initializing';
/**
* Set up Intl polyfill if required
*/
function _setupIntlPolyfill () {
// Polyfill Intl if required
var intlLibraryUrl = this.resolveUrl('../intl/dist/Intl.min.js');
if (window.Intl) {
if (window.IntlPolyfill && window.Intl === window.IntlPolyfill) {
intlLibraryLoadingStatus = 'loaded';
}
else {
intlLibraryLoadingStatus = 'native';
}
}
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);
}
}
/**
* 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':
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');
}
break;
// impossible cases
case 'initializing':
case 'loaded':
case 'native':
default:
/* istanbul ignore next: these cases are impossible */
break;
}
}
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'));
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;
if (!lang || lang.length === 0) {
result.push('');
}
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
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({
is: 'i18n-number',
/**
* Fired whenever the formatted text is rendered.
*
* @event rendered
*/
properties: {
/**
* The locale for the formatted number.
* The typical value is bound to `{{effectiveLang}}` when the containing element has
* `BehaviorsStore.I18nBehavior`.
*/
lang: {
type: String,
value: 'en',
observer: '_langChanged',
reflectToAttribute: true
},
/**
* Options object for Intl.NumberFormat
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat)
*/
options: {
type: Object,
observer: '_optionsChanged',
notify: true
},
/**
* Raw string synchronized with textContent
*/
raw: {
type: String,
observer: '_rawChanged'
},
/**
* Offset for number
*
* Note: number = rawNumber - offset
*/
offset: {
type: Number,
value: 0,
observer: '_offsetChanged'
},
/**
* Raw number parsed from raw
*/
rawNumber: {
type: Number,
notify: true
},
/**
* Number calculated from rawNumber and offset
*/
number: {
type: Number,
notify: true
},
/**
* 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
}
},
observers: [
'_onOptionsPropertyChanged(options.*)'
],
/**
* Default locale constant 'en'
*/
DEFAULT_LANG: 'en',
/**
* Start loading Intl polyfill before its registration
*/
beforeRegister: function () {
_setupIntlPolyfill.call(this);
},
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;
}
},
attached: function () {
this.raw = this.textNode.data;
},
/**
* Set up observers of textContent mutations
*/
_setupObservers: function () {
this.textNode = dom(this).childNodes[0];
if (!this.textNode) {
dom(this).appendChild(document.createTextNode(''));
this.textNode = dom(this).childNodes[0];
}
this.observer = new MutationObserver(this._textMutated.bind(this));
this.observer.observe(this.textNode, { characterData: true });
var desc = Object.getOwnPropertyDescriptor(this, 'lang');
if (desc && typeof desc.set !== 'function') {
// Fix #3. Emulate lang's observer since Safari 7 overrides lang property
this.observer.observe(this, { attributes: true, attributeFilter: [ 'lang' ] });
}
this.nodeObserver = dom(this).observeNodes(function (info) {
if (info.addedNodes[0] &&
info.addedNodes[0].nodeType === info.addedNodes[0].TEXT_NODE) {
this.textNode = info.addedNodes[0];
this.raw = this.textNode.data;
//console.log('i18n-number: text node added with ' + this.raw);
this.observer.observe(this.textNode, { characterData: true });
}
}.bind(this));
},
/**
* MutationObserver callback of the child text node to re-render on text mutations.
*
* @param {Array} mutations Array of MutationRecord (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
*/
_textMutated: function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'characterData':
//console.log('i18n-number: _textMutated: raw = ' + mutation.target.data);
if (this.raw !== mutation.target.data) {
this.raw = mutation.target.data;
}
break;
case 'attributes':
if (mutation.attributeName === 'lang') {
this._langChanged(this.lang);
}
break;
default:
/* istanbul ignore next: mutation.type is characterData or attributes */
break;
}
}, this);
},
/**
* Observer of `raw` property to re-render the formatted number.
*
* @param {string} raw New raw number string.
*/
_rawChanged: function (raw) {
if (this.textNode) {
if (raw !== this.textNode.data) {
this.textNode.data = raw;
}
//console.log('i18n-number: _rawChanged: raw = ' + raw);
this._render(this.lang, this.options, raw, this.offset);
}
},
/**
* Observer of `lang` property to re-render the formatted number.
*
* @param {string} lang New locale.
*/
_langChanged: function (lang) {
if (!lang) {
this.lang = this.DEFAULT_LANG;
lang = this.lang;
}
if (this.textNode) {
//console.log('i18n-number: _langChanged: lang = ' + lang);
this._render(lang, this.options, this.raw, this.offset);
}
},
/**
* Observer of `options` property to re-render the formatted number.
*
* @param {Object} options New options for Intl.NumberFormat.
*/
_optionsChanged: function (options) {
if (this.textNode) {
//console.log('i18n-number: _optionsChanged: options = ' + JSON.stringify(options));
this._render(this.lang, options, this.raw, this.offset);
}
},
/**
* Observer of `options` sub-properties to re-render the formatted number.
*/
_onOptionsPropertyChanged: function (/* changeRecord */) {
if (this.textNode) {
//console.log('_onOptionsPropertyChanged: path = ' + changeRecord.path + ' value = ' + JSON.stringify(changeRecord.value));
this._render(this.lang, this.options, this.raw, this.offset);
}
},
/**
* Observer of `offset` property to re-render the formatted number.
*
* @param {number} offset New offset.
*/
_offsetChanged: function (offset) {
if (this.textNode) {
//console.log('i18n-number: _offsetChanged: offset = ' + offset);
this._render(this.lang, this.options, this.raw, offset);
}
},
/**
* Formats the number
*
* @param {string} lang Locale for formatting.
* @param {Object} options Options for Intl.NumberFormat.
* @param {number} number Number to format.
* @return {string} Formatted number string.
*/
_formatNumber: function (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 new Intl.NumberFormat(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 new Intl.NumberFormat(lang, options).format(number);
}
catch (e) {
return number.toString();
}
/* istanbul ignore next: unreachable code due to returns in the same case */
break;
}
},
/**
* Renders the formatted number
*
* @param {string} lang Locale for formatting.
* @param {Object} options Options for Intl.NumberFormat.
* @param {string} raw Raw number string.
* @param {number} offset Offset for number.
*/
_render: function (lang, options, raw, offset) {
// TODO: rendering may be done redundantly on property initializations
raw = raw.trim();
if (!raw && !this.formatted) {
//console.log('i18n-number: skipping _render as raw is null');
return;
}
if (raw) {
this.rawNumber = Number(raw);
this.number = this.rawNumber - offset;
this.formatted = this._formatNumber(lang, options, this.number);
}
else {
this.rawNumber = undefined;
this.number = undefined;
this.formatted = '';
}
this.$.number.textContent = this.formatted ? this.formatted : '';
//console.log('i18n-number: _render ' + this.formatted);
if (typeof this.formatted !== 'undefined') {
this.fire('rendered');
}
},
/**
* Renders the formatted number with the current parameters
*
* Note: (As of Polymer 1.2.3)
* Explicit render() call is needed whenever the observer
* `_onOptionsPropertyChanged(options.*)` is NOT invoked
* after a property of `options` is changed. An explicit call
* `this.notifyPath('options', this.options, true)` can also
* trigger re-rendering.
*
* If the changed property of `options` is bound in an annotation
* like `{{options.currency}}`, the observer `_onOptionsPropertyChanged(options.*)`
* is automatically called whenever the property value is changed
* and thus no explicit call of `render()` or `notifyPath()` is
* required.
*/
render: function () {
this._render(this.lang, this.options, this.raw, this.offset);
}
});
</script>
</dom-module><script>var _cp=[function(e,t){return"other"},function(e,t){return t?"other":1==e?"one":"other"},function(e,t){return t?"other":0==e||1==e?"one":"other"},function(e,t){var r=String(e).split("."),n=!r[1];return t?"other":1==e&&n?"one":"other"}];!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t:e.plurals=t}(this,{af:_cp[1],ak:_cp[2],am:function(e,t){return t?"other":e>=0&&1>=e?"one":"other"},ar:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-2);return t?"other":0==e?"zero":1==e?"one":2==e?"two":o>=3&&10>=o?"few":o>=11&&99>=o?"many":"other"},as:function(e,t){return t?1==e||5==e||7==e||8==e||9==e||10==e?"one":2==e||3==e?"two":4==e?"few":6==e?"many":"other":e>=0&&1>=e?"one":"other"},asa:_cp[1],ast:_cp[3],az:function(e,t){var r=String(e).split("."),n=r[0],o=n.slice(-1),c=n.slice(-2),i=n.slice(-3);return t?1==o||2==o||5==o||7==o||8==o||20==c||50==c||70==c||80==c?"one":3==o||4==o||100==i||200==i||300==i||400==i||500==i||600==i||700==i||800==i||900==i?"few":0==n||6==o||40==c||60==c||90==c?"many":"other":1==e?"one":"other"},be:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-1),c=n&&r[0].slice(-2);return t?2!=o&&3!=o||12==c||13==c?"other":"few":1==o&&11!=c?"one":o>=2&&4>=o&&(12>c||c>14)?"few":n&&0==o||o>=5&&9>=o||c>=11&&14>=c?"many":"other"},bem:_cp[1],bez:_cp[1],bg:_cp[1],bh:_cp[2],bm:_cp[0],bn:function(e,t){return t?1==e||5==e||7==e||8==e||9==e||10==e?"one":2==e||3==e?"two":4==e?"few":6==e?"many":"other":e>=0&&1>=e?"one":"other"},bo:_cp[0],br:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-1),c=n&&r[0].slice(-2),i=n&&r[0].slice(-6);return t?"other":1==o&&11!=c&&71!=c&&91!=c?"one":2==o&&12!=c&&72!=c&&92!=c?"two":(3==o||4==o||9==o)&&(10>c||c>19)&&(70>c||c>79)&&(90>c||c>99)?"few":0!=e&&n&&0==i?"many":"other"},brx:_cp[1],bs:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=n.slice(-2),p=o.slice(-1),h=o.slice(-2);return t?"other":c&&1==i&&11!=u||1==p&&11!=h?"one":c&&i>=2&&4>=i&&(12>u||u>14)||p>=2&&4>=p&&(12>h||h>14)?"few":"other"},ca:function(e,t){var r=String(e).split("."),n=!r[1];return t?1==e||3==e?"one":2==e?"two":4==e?"few":"other":1==e&&n?"one":"other"},ce:_cp[1],cgg:_cp[1],chr:_cp[1],ckb:_cp[1],cs:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1];return t?"other":1==e&&o?"one":n>=2&&4>=n&&o?"few":o?"other":"many"},cy:function(e,t){return t?0==e||7==e||8==e||9==e?"zero":1==e?"one":2==e?"two":3==e||4==e?"few":5==e||6==e?"many":"other":0==e?"zero":1==e?"one":2==e?"two":3==e?"few":6==e?"many":"other"},da:function(e,t){var r=String(e).split("."),n=r[0],o=Number(r[0])==e;return t?"other":1!=e&&(o||0!=n&&1!=n)?"other":"one"},de:_cp[3],dsb:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-2),u=o.slice(-2);return t?"other":c&&1==i||1==u?"one":c&&2==i||2==u?"two":c&&(3==i||4==i)||3==u||4==u?"few":"other"},dv:_cp[1],dz:_cp[0],ee:_cp[1],el:_cp[1],en:function(e,t){var r=String(e).split("."),n=!r[1],o=Number(r[0])==e,c=o&&r[0].slice(-1),i=o&&r[0].slice(-2);return t?1==c&&11!=i?"one":2==c&&12!=i?"two":3==c&&13!=i?"few":"other":1==e&&n?"one":"other"},eo:_cp[1],es:_cp[1],et:_cp[3],eu:_cp[1],fa:function(e,t){return t?"other":e>=0&&1>=e?"one":"other"},ff:function(e,t){return t?"other":e>=0&&2>e?"one":"other"},fi:_cp[3],fil:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=o.slice(-1);return t?1==e?"one":"other":c&&(1==n||2==n||3==n)||c&&4!=i&&6!=i&&9!=i||!c&&4!=u&&6!=u&&9!=u?"one":"other"},fo:_cp[1],fr:function(e,t){return t?1==e?"one":"other":e>=0&&2>e?"one":"other"},fur:_cp[1],fy:_cp[3],ga:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?1==e?"one":"other":1==e?"one":2==e?"two":n&&e>=3&&6>=e?"few":n&&e>=7&&10>=e?"many":"other"},gd:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?"other":1==e||11==e?"one":2==e||12==e?"two":n&&e>=3&&10>=e||n&&e>=13&&19>=e?"few":"other"},gl:_cp[3],gsw:_cp[1],gu:function(e,t){return t?1==e?"one":2==e||3==e?"two":4==e?"few":6==e?"many":"other":e>=0&&1>=e?"one":"other"},guw:_cp[2],gv:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=n.slice(-1),i=n.slice(-2);return t?"other":o&&1==c?"one":o&&2==c?"two":!o||0!=i&&20!=i&&40!=i&&60!=i&&80!=i?o?"other":"many":"few"},ha:_cp[1],haw:_cp[1],he:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=Number(r[0])==e,i=c&&r[0].slice(-1);return t?"other":1==e&&o?"one":2==n&&o?"two":o&&(0>e||e>10)&&c&&0==i?"many":"other"},hi:function(e,t){return t?1==e?"one":2==e||3==e?"two":4==e?"few":6==e?"many":"other":e>=0&&1>=e?"one":"other"},hr:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=n.slice(-2),p=o.slice(-1),h=o.slice(-2);return t?"other":c&&1==i&&11!=u||1==p&&11!=h?"one":c&&i>=2&&4>=i&&(12>u||u>14)||p>=2&&4>=p&&(12>h||h>14)?"few":"other"},hsb:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-2),u=o.slice(-2);return t?"other":c&&1==i||1==u?"one":c&&2==i||2==u?"two":c&&(3==i||4==i)||3==u||4==u?"few":"other"},hu:function(e,t){return t?1==e||5==e?"one":"other":1==e?"one":"other"},hy:function(e,t){return t?1==e?"one":"other":e>=0&&2>e?"one":"other"},id:_cp[0],ig:_cp[0],ii:_cp[0],"in":_cp[0],is:function(e,t){var r=String(e).split("."),n=r[0],o=Number(r[0])==e,c=n.slice(-1),i=n.slice(-2);return t?"other":o&&1==c&&11!=i||!o?"one":"other"},it:function(e,t){var r=String(e).split("."),n=!r[1];return t?11==e||8==e||80==e||800==e?"many":"other":1==e&&n?"one":"other"},iu:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},iw:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=Number(r[0])==e,i=c&&r[0].slice(-1);return t?"other":1==e&&o?"one":2==n&&o?"two":o&&(0>e||e>10)&&c&&0==i?"many":"other"},ja:_cp[0],jbo:_cp[0],jgo:_cp[1],ji:_cp[3],jmc:_cp[1],jv:_cp[0],jw:_cp[0],ka:function(e,t){var r=String(e).split("."),n=r[0],o=n.slice(-2);return t?1==n?"one":0==n||o>=2&&20>=o||40==o||60==o||80==o?"many":"other":1==e?"one":"other"},kab:function(e,t){return t?"other":e>=0&&2>e?"one":"other"},kaj:_cp[1],kcg:_cp[1],kde:_cp[0],kea:_cp[0],kk:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-1);return t?6==o||9==o||n&&0==o&&0!=e?"many":"other":1==e?"one":"other"},kkj:_cp[1],kl:_cp[1],km:_cp[0],kn:function(e,t){return t?"other":e>=0&&1>=e?"one":"other"},ko:_cp[0],ks:_cp[1],ksb:_cp[1],ksh:function(e,t){return t?"other":0==e?"zero":1==e?"one":"other"},ku:_cp[1],kw:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},ky:_cp[1],lag:function(e,t){var r=String(e).split("."),n=r[0];return t?"other":0==e?"zero":0!=n&&1!=n||0==e?"other":"one"},lb:_cp[1],lg:_cp[1],lkt:_cp[0],ln:_cp[2],lo:function(e,t){return t&&1==e?"one":"other"},lt:function(e,t){var r=String(e).split("."),n=r[1]||"",o=Number(r[0])==e,c=o&&r[0].slice(-1),i=o&&r[0].slice(-2);return t?"other":1==c&&(11>i||i>19)?"one":c>=2&&9>=c&&(11>i||i>19)?"few":0!=n?"many":"other"},lv:function(e,t){var r=String(e).split("."),n=r[1]||"",o=n.length,c=Number(r[0])==e,i=c&&r[0].slice(-1),u=c&&r[0].slice(-2),p=n.slice(-2),h=n.slice(-1);return t?"other":c&&0==i||u>=11&&19>=u||2==o&&p>=11&&19>=p?"zero":1==i&&11!=u||2==o&&1==h&&11!=p||2!=o&&1==h?"one":"other"},mas:_cp[1],mg:_cp[2],mgo:_cp[1],mk:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=n.slice(-2),p=o.slice(-1);return t?1==i&&11!=u?"one":2==i&&12!=u?"two":7!=i&&8!=i||17==u||18==u?"other":"many":c&&1==i||1==p?"one":"other"},ml:_cp[1],mn:_cp[1],mo:function(e,t){var r=String(e).split("."),n=!r[1],o=Number(r[0])==e,c=o&&r[0].slice(-2);return t?1==e?"one":"other":1==e&&n?"one":!n||0==e||1!=e&&c>=1&&19>=c?"few":"other"},mr:function(e,t){return t?1==e?"one":2==e||3==e?"two":4==e?"few":"other":e>=0&&1>=e?"one":"other"},ms:function(e,t){return t&&1==e?"one":"other"},mt:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-2);return t?"other":1==e?"one":0==e||o>=2&&10>=o?"few":o>=11&&19>=o?"many":"other"},my:_cp[0],nah:_cp[1],naq:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},nb:_cp[1],nd:_cp[1],ne:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?n&&e>=1&&4>=e?"one":"other":1==e?"one":"other"},nl:_cp[3],nn:_cp[1],nnh:_cp[1],no:_cp[1],nqo:_cp[0],nr:_cp[1],nso:_cp[2],ny:_cp[1],nyn:_cp[1],om:_cp[1],or:_cp[1],os:_cp[1],pa:_cp[2],pap:_cp[1],pl:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=n.slice(-1),i=n.slice(-2);return t?"other":1==e&&o?"one":o&&c>=2&&4>=c&&(12>i||i>14)?"few":o&&1!=n&&(0==c||1==c)||o&&c>=5&&9>=c||o&&i>=12&&14>=i?"many":"other"},prg:function(e,t){var r=String(e).split("."),n=r[1]||"",o=n.length,c=Number(r[0])==e,i=c&&r[0].slice(-1),u=c&&r[0].slice(-2),p=n.slice(-2),h=n.slice(-1);return t?"other":c&&0==i||u>=11&&19>=u||2==o&&p>=11&&19>=p?"zero":1==i&&11!=u||2==o&&1==h&&11!=p||2!=o&&1==h?"one":"other"},ps:_cp[1],pt:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?"other":n&&e>=0&&2>=e&&2!=e?"one":"other"},"pt-PT":_cp[3],rm:_cp[1],ro:function(e,t){var r=String(e).split("."),n=!r[1],o=Number(r[0])==e,c=o&&r[0].slice(-2);return t?1==e?"one":"other":1==e&&n?"one":!n||0==e||1!=e&&c>=1&&19>=c?"few":"other"},rof:_cp[1],root:_cp[0],ru:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=n.slice(-1),i=n.slice(-2);return t?"other":o&&1==c&&11!=i?"one":o&&c>=2&&4>=c&&(12>i||i>14)?"few":o&&0==c||o&&c>=5&&9>=c||o&&i>=11&&14>=i?"many":"other"},rwk:_cp[1],sah:_cp[0],saq:_cp[1],sdh:_cp[1],se:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},seh:_cp[1],ses:_cp[0],sg:_cp[0],sh:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=n.slice(-2),p=o.slice(-1),h=o.slice(-2);return t?"other":c&&1==i&&11!=u||1==p&&11!=h?"one":c&&i>=2&&4>=i&&(12>u||u>14)||p>=2&&4>=p&&(12>h||h>14)?"few":"other"},shi:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?"other":e>=0&&1>=e?"one":n&&e>=2&&10>=e?"few":"other"},si:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"";return t?"other":0==e||1==e||0==n&&1==o?"one":"other"},sk:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1];return t?"other":1==e&&o?"one":n>=2&&4>=n&&o?"few":o?"other":"many"},sl:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=n.slice(-2);return t?"other":o&&1==c?"one":o&&2==c?"two":o&&(3==c||4==c)||!o?"few":"other"},sma:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},smi:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},smj:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},smn:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},sms:function(e,t){return t?"other":1==e?"one":2==e?"two":"other"},sn:_cp[1],so:_cp[1],sq:function(e,t){var r=String(e).split("."),n=Number(r[0])==e,o=n&&r[0].slice(-1),c=n&&r[0].slice(-2);return t?1==e?"one":4==o&&14!=c?"many":"other":1==e?"one":"other"},sr:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=n.slice(-2),p=o.slice(-1),h=o.slice(-2);return t?"other":c&&1==i&&11!=u||1==p&&11!=h?"one":c&&i>=2&&4>=i&&(12>u||u>14)||p>=2&&4>=p&&(12>h||h>14)?"few":"other"},ss:_cp[1],ssy:_cp[1],st:_cp[1],sv:function(e,t){var r=String(e).split("."),n=!r[1],o=Number(r[0])==e,c=o&&r[0].slice(-1),i=o&&r[0].slice(-2);return t?1!=c&&2!=c||11==i||12==i?"other":"one":1==e&&n?"one":"other"},sw:_cp[3],syr:_cp[1],ta:_cp[1],te:_cp[1],teo:_cp[1],th:_cp[0],ti:_cp[2],tig:_cp[1],tk:_cp[1],tl:function(e,t){var r=String(e).split("."),n=r[0],o=r[1]||"",c=!r[1],i=n.slice(-1),u=o.slice(-1);return t?1==e?"one":"other":c&&(1==n||2==n||3==n)||c&&4!=i&&6!=i&&9!=i||!c&&4!=u&&6!=u&&9!=u?"one":"other"},tn:_cp[1],to:_cp[0],tr:_cp[1],ts:_cp[1],tzm:function(e,t){var r=String(e).split("."),n=Number(r[0])==e;return t?"other":0==e||1==e||n&&e>=11&&99>=e?"one":"other"},ug:_cp[1],uk:function(e,t){var r=String(e).split("."),n=r[0],o=!r[1],c=Number(r[0])==e,i=c&&r[0].slice(-1),u=c&&r[0].slice(-2),p=n.slice(-1),h=n.slice(-2);return t?3==i&&13!=u?"few":"other":o&&1==p&&11!=h?"one":o&&p>=2&&4>=p&&(12>h||h>14)?"few":o&&0==p||o&&p>=5&&9>=p||o&&h>=11&&14>=h?"many":"other"},ur:_cp[3],uz:_cp[1],ve:_cp[1],vi:function(e,t){return t&&1==e?"one":"other"},vo:_cp[1],vun:_cp[1],wa:_cp[2],wae:_cp[1],wo:_cp[0],xh:_cp[1],xog:_cp[1],yi:_cp[3],yo:_cp[0],zh:_cp[0],zu:function(e,t){return t?"other":e>=0&&1>=e?"one":"other"}});</script>
<dom-module id="i18n-format" assetpath="../../../i18n-format/">
<template>
</template>
</dom-module>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
Polymer({
is: 'i18n-format',
/**
* Fired whenever the formatted text is rendered.
*
* @event rendered
*/
properties: {
/**
* The locale for the template text.
* The typical value is bound to `{{effectiveLang}}` when the containing element has
* `BehaviorsStore.I18nBehavior`.
*/
lang: {
type: String,
value: 'en',
reflectToAttribute: true,
observer: '_langChanged'
},
/**
* The parameter attribute name to identify parameters.
* No need to change in a normal usage.
*/
paramAttribute: {
type: String,
value: 'param',
observer: '_paramAttributeChanged'
},
/**
* The parameter format in the template text.
* The `'n'` in the format means n-th parameter.
* No need to change in a normal usage.
*/
paramFormat: {
type: String,
value: '{n}',
observer: '_paramFormatChanged'
},
/**
* When the boolean attribute `observe-params` is specified,
* the template is re-rendered on every parameter mutation.
* If not specified, the template is re-rendered only on `lang` changes and template text changes.
*
* Note: If true, re-rendering may be performed muiltiple times redundantly on a locale change.
*/
observeParams: {
type: Boolean,
value: true // TODO: optimize re-rendering
}
},
/**
* Default locale constant 'en'
*/
DEFAULT_LANG: 'en',
ready: function () {
this._setupParams();
if (!this.lang) {
// Polyfill non-functional default value for lang property in Safari 7
this.lang = this.DEFAULT_LANG;
}
},
attached: function () {
this.render();
},
/**
* Traverse the local DOM and set up parameters and observers.
*/
_setupParams: function () {
var n;
this.elements = Array.prototype.filter.call(
dom(this).childNodes,
function (node) {
return node.nodeType === node.ELEMENT_NODE;
}
);
var needParamObservation = this.observeParams &&
this.elements.length > 0 &&
this.elements[0].tagName.toLowerCase() === 'json-data';
this.observer = new MutationObserver(this._templateMutated.bind(this));
var desc = Object.getOwnPropertyDescriptor(this, 'lang');
if (desc && typeof desc.set !== 'function') {
// Fix #1. Emulate lang's observer since Safari 7 overrides lang property
this.observer.observe(this, { attributes: true, attributeFilter: [ 'lang' ] });
}
for (n = 0; n < this.elements.length; n++) {
if (n === 0) {
this.templateElement = this.elements[n];
this.templateTextNode = dom(this.templateElement).childNodes[0];
this.observer.observe(this.templateTextNode, { characterData: true });
}
else {
if (!this.elements[n].hasAttribute(this.paramAttribute)) {
this.elements[n].setAttribute(this.paramAttribute, '' + n);
}
if (needParamObservation) {
// TODO: childNodes[0] may not be a text node
this.observer.observe(dom(this.elements[n]).childNodes[0], { characterData: true });
if (this.elements[n].tagName.toLowerCase() === 'i18n-number') {
this.listen(this.elements[n], 'rendered', 'render');
}
}
}
}
//console.log('i18n-format: _setupParams: elements = ' + this.elements);
},
/**
* MutationObserver callback of child text nodes to re-render on template text or parameter mutations.
*
* @param {Array} mutations Array of MutationRecord (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
*/
_templateMutated: function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'characterData':
//console.log('i18n-format: ' + this.id + '._templateMutated(): characterData: tag = ' +
// Polymer.dom(mutation.target).parentNode.tagName.toLowerCase() +
// ' data = ' + mutation.target.data);
if (dom(mutation.target).parentNode.tagName.toLowerCase() !== 'i18n-number') {
this.render();
}
else if (typeof dom(mutation.target).parentNode.formatted !== 'undefined') {
this.render();
}
break;
case 'attributes':
if (mutation.attributeName === 'lang') {
this._langChanged(this.lang);
}
break;
default:
/* istanbul ignore next: mutation.type is always characterData or attributes */
break;
}
}, this);
},
/**
* Observer of `lang` property to re-render the template text.
*
* @param {string} lang New locale.
*/
_langChanged: function (lang /*, oldLang */) {
//console.log('i18n-format: ' + this.id + '._langChanged() lang = ' + lang + ' oldLang = ' + oldLang);
if (this.elements &&
lang !== undefined &&
lang !== null &&
!lang.match(/^{{.*}}$/) &&
!lang.match(/^\[\[.*\]\]$/)) {
this.render();
}
//else {
// console.log('i18n-format: skipping render()');
//}
},
/**
* Observer of `paramFormat` property to re-render the template text.
*
* @param {string} paramFormat New paramFormat.
* @param {string} oldParamFormat Old paramFormat.
*/
_paramFormatChanged: function (paramFormat, oldParamFormat) {
//console.log('i18n-format: ' + this.id + '._paramFormatChanged() new = ' + paramFormat + ' old = ' + oldParamFormat);
if (this.elements &&
oldParamFormat !== undefined &&
paramFormat &&
this.lang !== undefined &&
this.lang !== null &&
!this.lang.match(/^{{.*}}$/) &&
!this.lang.match(/^\[\[.*\]\]$/)) {
this.lastTemplateText = undefined;
this.render();
}
},
/**
* Observer of `paramAttribute` property to reset parameter attributes.
*
* @param {string} paramAttribute New paramAttribute.
* @param {string} oldParamAttribute Old paramAttribute.
*/
_paramAttributeChanged: function (paramAttribute, oldParamAttribute) {
//console.log('i18n-format: ' + this.id + '._paramAttributeChanged() new = ' + paramAttribute + ' old = ' + oldParamAttribute);
var n;
if (this.elements &&
oldParamAttribute !== undefined &&
paramAttribute &&
this.lang !== undefined &&
this.lang !== null &&
!this.lang.match(/^{{.*}}$/) &&
!this.lang.match(/^\[\[.*\]\]$/)) {
for (n = 1; n < this.elements.length; n++) {
this.elements[n].removeAttribute(oldParamAttribute);
if (!this.elements[n].hasAttribute(paramAttribute)) {
this.elements[n].setAttribute(paramAttribute, '' + n);
}
}
this.lastTemplateText = undefined;
this.render();
}
},
/**
* Detect the CLDR plural category of a number
* with [`make-plural` library](https://github.com/eemeli/make-plural.js).
*
* @param {number} n The number to get the plural category for.
* @return {string} Plural category of the number.
*/
_getPluralCategory: function (n) {
var category = 'other';
var lang = this.lang || this.DEFAULT_LANG;
lang = lang.split(/[-_]/)[0];
if (window.plurals[lang]) {
category = window.plurals[lang](n);
}
else {
category = window.plurals.en(n);
}
//console.log('i18n-format: _getPluralCategory(' + n + ') = ' + category);
return category;
},
/**
* Select a template text by parameters.
*
* @return {string} Selected template text.
*/
_selectTemplateText: function () {
var templateText = '';
if (!this.templateElement) {
return templateText;
}
else if (this.templateElement.tagName.toLowerCase() === 'json-data') {
var templateObject;
try {
templateObject = JSON.parse(this.templateTextNode.data);
}
catch (ex) {
if (this.templateTextNode.data) {
console.warn('i18n-format: parse error in json-data');
}
return templateText;
}
var n;
for (n = 1;
typeof templateObject === 'object' && n < this.elements.length;
n++) {
var param = this.elements[n];
if (param.tagName.toLowerCase() === 'i18n-number') {
// plural selector
var category = this._getPluralCategory(param.number);
if (typeof param.number === 'undefined' ||
typeof param.formatted === 'undefined') {
// i18n-number is not ready
//console.log('i18n-format: i18n-number is not ready');
templateObject = undefined;
}
else if (templateObject[param.rawNumber]) {
templateObject = templateObject[param.rawNumber];
}
else if (templateObject[category]) {
// plural category matched
templateObject = templateObject[category];
}
else if (templateObject.other) {
// other
templateObject = templateObject.other;
}
else {
// default
templateObject = '';
console.warn('i18n-format: cannot find a template');
}
}
else {
// string selector
if (templateObject[param.textContent]) {
// template found
templateObject = templateObject[param.textContent];
}
else if (templateObject.other) {
// other
templateObject = templateObject.other;
}
else {
// default
templateObject = '';
console.warn('i18n-format: cannot find a template');
}
}
}
if (typeof templateObject === 'string') {
templateText = templateObject;
}
else if (typeof templateObject === 'undefined') {
templateText = undefined;
}
else {
templateText = '';
console.warn('i18n-format: cannot find a template');
}
}
else {
templateText = this.templateTextNode.data;
}
return templateText;
},
/**
* Render the template text.
*/
render: function () {
var templateText = this._selectTemplateText();
var tmpNode = document.createElement('span');
var paramPlaceholder;
var childNodes = [];
var i;
if (templateText === this.lastTemplateText) {
//console.log('i18n-format: skipping rendering as the templateText has not changed');
return;
}
else if (typeof templateText === 'undefined') {
return;
}
else {
this.lastTemplateText = templateText;
//console.log('i18n-format: ' + this.id + '.render() templateText = ' + templateText);
}
i = 1;
while (i < this.elements.length) {
paramPlaceholder = this.paramFormat.replace('n', i);
templateText = templateText.replace(paramPlaceholder,
'<content select="[' + this.paramAttribute + '=\'' + i + '\']"></content>');
i++;
}
tmpNode.innerHTML = templateText;
dom(this.root).innerHTML = '';
// References of childNodes have to be copied for Shady DOM compatibility
for (i = 0; i < tmpNode.childNodes.length; i++) {
childNodes[i] = tmpNode.childNodes[i];
}
for (i = 0; i < childNodes.length; i++) {
// each node has to be appended via Polymer.dom()
dom(this.root).appendChild(childNodes[i]);
}
this.fire('rendered');
}
});
</script>
<dom-module id="iron-localstorage" assetpath="../../../iron-localstorage/"></dom-module>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { Base } from '@polymer/polymer/polymer-legacy.js';
Polymer({
is: 'iron-localstorage',
properties: {
/**
* localStorage item key
*/
name: {
type: String,
value: ''
},
/**
* The data associated with this storage.
* If set to null item will be deleted.
* @type {*}
*/
value: {
type: Object,
notify: true
},
/**
* If true: do not convert value to JSON on save/load
*/
useRaw: {
type: Boolean,
value: false
},
/**
* Value will not be saved automatically if true. You'll have to do it manually with `save()`
*/
autoSaveDisabled: {
type: Boolean,
value: false
},
/**
* Last error encountered while saving/loading items
*/
errorMessage: {
type: String,
notify: true
},
/** True if value has been loaded */
_loaded: {
type: Boolean,
value: false
}
},
observers: [
'_debounceReload(name,useRaw)',
'_trySaveValue(autoSaveDisabled)',
'_trySaveValue(value.*)'
],
ready: function() {
this._boundHandleStorage = this._handleStorage.bind(this);
},
attached: function() {
window.addEventListener('storage', this._boundHandleStorage);
},
detached: function() {
window.removeEventListener('storage', this._boundHandleStorage);
},
_handleStorage: function(ev) {
if (ev.key == this.name) {
this._load(true);
}
},
_trySaveValue: function() {
if (this._doNotSave) {
return;
}
if (this._loaded && !this.autoSaveDisabled) {
this.debounce('save', this.save);
}
},
_debounceReload: function() {
this.debounce('reload', this.reload);
},
/**
* Loads the value again. Use if you modify
* localStorage using DOM calls, and want to
* keep this element in sync.
*/
reload: function() {
this._loaded = false;
this._load();
},
/**
* loads value from local storage
* @param {boolean=} externalChange true if loading changes from a different window
*/
_load: function(externalChange) {
try {
var v = window.localStorage.getItem(this.name);
} catch (ex) {
this.errorMessage = ex.message;
this._error("Could not save to localStorage. Try enabling cookies for this page.", ex);
};
if (v === null) {
this._loaded = true;
this._doNotSave = true; // guard for save watchers
this.value = null;
this._doNotSave = false;
this.fire('iron-localstorage-load-empty', { externalChange: externalChange});
} else {
if (!this.useRaw) {
try { // parse value as JSON
v = JSON.parse(v);
} catch(x) {
this.errorMessage = "Could not parse local storage value";
Base._error("could not parse local storage value", v);
v = null;
}
}
this._loaded = true;
this._doNotSave = true;
this.value = v;
this._doNotSave = false;
this.fire('iron-localstorage-load', { externalChange: externalChange});
}
},
/**
* Saves the value to localStorage. Call to save if autoSaveDisabled is set.
* If `value` is null or undefined, deletes localStorage.
*/
save: function() {
var v = this.useRaw ? this.value : JSON.stringify(this.value);
try {
if (this.value === null || this.value === undefined) {
window.localStorage.removeItem(this.name);
} else {
window.localStorage.setItem(this.name, /** @type {string} */ (v));
}
}
catch(ex) {
// Happens in Safari incognito mode,
this.errorMessage = ex.message;
Base._error("Could not save to localStorage. Incognito mode may be blocking this action", ex);
}
}
/**
* Fired when value loads from localStorage.
*
* @event iron-localstorage-load
* @param {{externalChange:boolean}} detail -
* externalChange: true if change occured in different window.
*/
/**
* Fired when loaded value does not exist.
* Event handler can be used to initialize default value.
*
* @event iron-localstorage-load-empty
* @param {{externalChange:boolean}} detail -
* externalChange: true if change occured in different window.
*/
});
</script>
<dom-module id="i18n-preference" assetpath="../../">
<template>
<iron-localstorage id="storage" name="i18n-behavior-preference">
</iron-localstorage>
</template>
</dom-module>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
(function(document) {
'use strict';
// html element of this document
var html = document.querySelector('html');
// app global default language
var defaultLang = html.hasAttribute('lang') ? html.getAttribute('lang') : '';
Polymer({
is: 'i18n-preference',
properties: {
/**
* Persistence of preference
*/
persist: {
type: Boolean,
value: false,
reflectToAttribute: true,
notify: true,
observer: '_onPersistChange'
}
},
listeners: {
'storage.iron-localstorage-load-empty': '_onLoadEmptyStorage',
'storage.iron-localstorage-load': '_onLoadStorage',
'storage.value-changed': '_onStorageValueChange'
},
/**
* Ready callback to initialize this.lang
*/
ready: function () {
if (this.persist) {
// delay this.lang update
}
else {
//this.$.storage.value = undefined;
}
this.isReady = true;
},
/**
* Attached callback to initialize html.lang and its observation
*/
attached: function () {
this._observe();
if (this.persist) {
// delay html.lang update
}
else {
if (!html.hasAttribute('preferred')) {
html.setAttribute('lang', navigator.language || navigator.browserLanguage);
}
}
},
/**
* Detached callback to diconnect html.lang observation
*/
detached: function () {
this._disconnect();
},
/**
* Initialize an empty localstorage
*/
_onLoadEmptyStorage: function () {
if (this.isReady) {
if (this.persist) {
if (this.isInitialized) {
// store html.lang value
this.$.storage.value = html.getAttribute('lang');
}
else {
if (html.hasAttribute('preferred')) {
this.$.storage.value = html.getAttribute('lang');
}
else {
this.$.storage.value = navigator.language || navigator.browserLanguage;
if (html.getAttribute('lang') !== this.$.storage.value) {
html.setAttribute('lang', this.$.storage.value);
}
}
this.isInitialized = true;
}
}
else {
// leave the empty storage as it is
}
}
},
/**
* Handle the loaded storage value
*/
_onLoadStorage: function () {
if (this.isReady) {
if (this.persist) {
// preferred attribute in html to put higher priority
// in the default html language than navigator.language
if (html.hasAttribute('preferred')) {
if (this.$.storage.value !== defaultLang) {
// overwrite the storage by the app default language
this.$.storage.value = defaultLang;
}
}
else {
// load the value from the storage
html.setAttribute('lang', this.$.storage.value);
}
}
else {
// empty the storage
this.$.storage.value = undefined;
}
}
},
/**
* Handle persist changes
*
* @param {Boolean} value new this.persist value
*/
_onPersistChange: function (value) {
if (this.isReady) {
if (value) {
if (this.$.storage.value !== html.getAttribute('lang')) {
// save to the storage
this.$.storage.value = html.getAttribute('lang');
}
}
else {
// empty the storage
this.$.storage.value = undefined;
}
}
},
/**
* Handle storage value changes
*
* @param {Event} e value-changed event on the storage
*/
_onStorageValueChange: function (e) {
var value = e.detail.value;
if (this.isReady) {
if (this.persist) {
if (value) {
if (value !== html.getAttribute('lang')) {
// save to the lang
html.setAttribute('lang', value);
}
}
else {
// update the storage
this.$.storage.value = html.getAttribute('lang');
}
}
else {
if (value) {
// empty the storage
this.$.storage.value = undefined;
}
}
}
},
/**
* Handle value changes on localstorage
*
* @param {MutationRecord[]} mutations Array of MutationRecords for html.lang
*
* Note:
* - Bound to this element
*/
_htmlLangMutationObserverCallback: function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'attributes':
if (mutation.attributeName === 'lang') {
if (this.$.storage.value !== mutation.target.getAttribute('lang')) {
this.$.storage.value = mutation.target.getAttribute('lang');
}
}
break;
default:
break;
}
}.bind(this));
},
/**
* Set up html.lang mutation observer
*/
_observe: function () {
// observe html lang mutations
if (!this._htmlLangMutationObserver) {
this._htmlLangMutationObserverCallbackBindThis =
this._htmlLangMutationObserverCallback.bind(this);
this._htmlLangMutationObserver =
new MutationObserver(this._htmlLangMutationObserverCallbackBindThis);
}
this._htmlLangMutationObserver.observe(html, { attributes: true });
},
/**
* Disconnect html.lang mutation observer
*/
_disconnect: function () {
if (this._htmlLangMutationObserver) {
this._htmlLangMutationObserver.disconnect();
}
}
});
})(document);
</script>
<dom-module id="i18n-attr-repo" assetpath="../../">
<template>
<template id="standard">
<input placeholder="" value="type=button|submit">
<any-elements title="" aria-label="$" aria-valuetext="$"></any-elements>
<paper-input label="" error-message="" placeholder=""></paper-input>
<paper-textarea label="" error-message="" placeholder=""></paper-textarea>
<paper-dropdown-menu label=""></paper-dropdown-menu>
<paper-toast text=""></paper-toast>
<paper-badge label=""></paper-badge>
<google-chart options="" cols="" rows="" data=""></google-chart>
<google-signin label-signin="" label-signout="" label-additional=""></google-signin>
<platinum-push-messaging title="" message=""></platinum-push-messaging>
<json-data any-attributes=""></json-data>
</template>
</template>
</dom-module>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
// shared data
var sharedData = {};
Polymer({
is: 'i18n-attr-repo',
ready: function () {
this.data = sharedData;
var customAttributes = dom(this).querySelector('template#custom');
// traverse custom attributes repository
if (customAttributes) {
this._traverseTemplateTree(customAttributes._content || customAttributes.content);
}
if (this.data.__ready__) {
return; // traverse standard attributes only once
}
this.data.__ready__ = true;
this._traverseTemplateTree(this.$.standard._content || this.$.standard.content);
},
/**
* Judge if a specific attribute of an element requires localization.
*
* @param {HTMLElement} element Target element.
* @param {string} attr Target attribute name.
* @return {string or boolean} true - property, '$' - attribute, false - not targeted, 'type-name' - type name
*/
isLocalizableAttribute: function (element, attr) {
var tagName = element.tagName.toLowerCase();
attr = attr.replace(/\$$/, '');
if (this.data['any-elements'] &&
this.data['any-elements'][attr]) {
return this.data['any-elements'][attr];
}
else if (this.data[tagName]) {
return this.data[tagName]['any-attributes'] ||
this._getType(element, this.data[tagName][attr]);
}
else {
return false;
}
},
/**
* Get the type name or '$' for a specific attribute of an element from the attributes repository
*
* @param {HTMLElement} element Target element.
* @param {object} value this.data[tagName][attr]
* @return {string or boolean} true - property, '$' - attribute, false - not targeted, 'type-name' - type name
*/
_getType: function (element, value) {
var selector;
var result;
if (typeof value === 'object') {
for (selector in value) {
if (selector) {
if (this._matchAttribute(element, selector)) {
result = this._getType(element, value[selector]);
if (result) {
return result;
}
}
}
}
if (value['']) {
if (this._matchAttribute(element, '')) {
result = this._getType(element, value['']);
if (result) {
return result;
}
}
}
return false;
}
else {
return value;
}
},
/**
* Get the type name or '$' for a specific attribute of an element from the attributes repository
*
* Format for selectors:
* - `attr=value` - Value of `attr` matches Regex `^value$`
* - `!boolean-attr` - Boolean attribute does not exist
* - `boolean-attr` - Boolean attribute exists with empty value
* - empty string `''` - Always matches
*
* @param {HTMLElement} element Target element.
* @param {string} selector Matching condition for target attribute.
* @return {boolean} true - matching, false - not matching
*/
_matchAttribute: function (element, selector) {
var value;
var match;
// default ''
if (selector === '') {
return true;
}
// attr=value Regex ^value$
match = selector.match(/^([^!=]*)=(.*)$/);
if (match) {
if (element.hasAttribute(match[1])) {
value = element.getAttribute(match[1]);
return !!value.match(new RegExp('^' + match[2] + '$'));
}
else {
return false;
}
}
// !boolean-attr
match = selector.match(/^!([^!=]*)$/);
if (match) {
return !element.hasAttribute(match[1]);
}
// boolean-attr or empty-attr
match = selector.match(/^([^!=]*)$/);
if (match) {
if (element.hasAttribute(match[1])) {
value = element.getAttribute(match[1]);
return !value;
}
else {
return false;
}
}
// no matching
return false;
},
/**
* Comparator for attribute selectors
*
* @param {string} s1 selector 1
* @param {string} s2 selector 2
* @return {number} comparison result as -1, 0, or 1
*/
_compareSelectors: function (s1, s2) {
var name1 = s1.replace(/^!/, '').replace(/=.*$/, '').toLowerCase();
var name2 = s2.replace(/^!/, '').replace(/=.*$/, '').toLowerCase();
return name1.localeCompare(name2);
},
/**
* Add a new localizable attribute of an element to the repository.
*
* Format for selector values for defining I18N-target attributes:
* - `attr1=value1,attr2=value2,boolean-attr,!boolean-attr` - Attribute value matching condition for property
* - `attr1=value1,attr2=value2,$` - Attribute value matching condition for attribute
* - `boolean-attr=` - Boolean attribute condition
* - `attr1=value1,type` - Attribute value condition with type name (type is currently ineffective)
*
* @param {string} element Target element name.
* @param {string} attr Target attribute name.
* @param {?*} value Selector value
*/
setLocalizableAttribute: function (element, attr, value) {
this.data[element] = this.data[element] || {};
var cursor = this.data[element];
var prev = attr;
var type = true;
var selectors = [];
if (typeof value === 'string' && value) {
selectors = value.split(',');
if (selectors[selectors.length - 1].match(/^[^!=][^=]*$/)) {
type = selectors.pop();
}
selectors = selectors.map(function (selector) {
return selector.replace(/=$/, '');
});
selectors.sort(this._compareSelectors);
while (selectors[0] === '') {
selectors.shift();
}
}
selectors.forEach(function (selector, index) {
if (typeof cursor[prev] !== 'object') {
cursor[prev] = cursor[prev] ? { '': cursor[prev] } : {};
}
cursor[prev][selector] = cursor[prev][selector] || {};
cursor = cursor[prev];
prev = selector;
});
if (typeof cursor[prev] === 'object' &&
cursor[prev] &&
Object.keys(cursor[prev]).length) {
cursor = cursor[prev];
prev = '';
}
cursor[prev] = type;
},
/**
* Pick up localizable attributes description for a custom element
* from `text-attr` attribute and register them to the repository.
* The `text-attr` attribute is used in the template of a custom
* element to declare localizable attributes of its own element.
*
* Format:
*
* Type 1: `<template text-attr="localizable-attr1 attr2">`
*
* Type 2: `<template text-attr localizable-attr1 attr2="value2">`
*
* @param {string} element Target element name.
* @param {HTMLTemplateElement} template Template of the element.
*/
registerLocalizableAttributes: function (element, template) {
if (!element) {
element = template.getAttribute('id');
}
if (element) {
var attrs = (template.getAttribute('text-attr') || '').split(' ');
var textAttr = false;
attrs.forEach(function (attr) {
if (attr) {
this.setLocalizableAttribute(element, attr, true);
}
}, this);
Array.prototype.forEach.call(template.attributes, function (attr) {
switch (attr.name) {
case 'id':
case 'lang':
case 'localizable-text':
case 'assetpath':
break;
case 'text-attr':
textAttr = true;
break;
default:
if (textAttr) {
this.setLocalizableAttribute(element, attr.name, attr.value);
}
break;
}
}.bind(this));
}
},
/**
* Traverse the template of `i18n-attr-repo` in the ready() callback
* and construct the localizable attributes repository object. The method calls itself
* recursively for traversal.
*
* @param {HTMLElement} node The target HTML node for traversing.
*/
_traverseTemplateTree: function (node) {
var name;
if (node.nodeType === node.ELEMENT_NODE) {
name = node.nodeName.toLowerCase();
Array.prototype.forEach.call(node.attributes, function (attribute) {
this.data[name] = this.data[name] || {};
this.setLocalizableAttribute(name, attribute.name, attribute.value);
}, this);
}
if (node.childNodes.length > 0) {
for (var i = 0; i < node.childNodes.length; i++) {
this._traverseTemplateTree(node.childNodes[i]);
}
}
}
});
</script><script>/*!
* @license deepcopy.js Copyright(c) 2013 sasa+1
* https://github.com/sasaplus1/deepcopy.js
* Released under the MIT license.
*/
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.deepcopy=e():t.deepcopy=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return t[o].call(r.exports,r,r.exports,e),r.loaded=!0,r.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports=n(3)},function(t,e){"use strict";function n(t,e){if("[object Array]"!==o.call(t))throw new TypeError("array must be an Array");var n=void 0,r=void 0,u=void 0;for(n=0,r=t.length;r>n;++n)if(u=t[n],u===e||u!==u&&e!==e)return n;return-1}e.__esModule=!0;var o=Object.prototype.toString,r="undefined"!=typeof Buffer?function(t){return Buffer.isBuffer(t)}:function(){return!1},u="function"==typeof Object.keys?function(t){return Object.keys(t)}:function(t){var e=typeof t;if(null===t||"function"!==e&&"object"!==e)throw new TypeError("obj must be an Object");var n=[],o=void 0;for(o in t)Object.prototype.hasOwnProperty.call(t,o)&&n.push(o);return n},i="function"==typeof Symbol?function(t){return Object.getOwnPropertySymbols(t)}:function(){return[]};e.getKeys=u,e.getSymbols=i,e.indexOf=n,e.isBuffer=r},function(t,e,n){"use strict";function o(t,e){var n=u(t);return null!==n?n:r(t,e)}function r(t,e){if("function"!=typeof e)throw new TypeError("customizer is must be a Function");if("function"==typeof t){var n=String(t);return/^\s*function\s*\S*\([^\)]*\)\s*{\s*\[native code\]\s*}/.test(n)?t:new Function("return "+String(n))()}var o=c.call(t);if("[object Array]"===o)return[];if("[object Object]"===o&&t.constructor===Object)return{};if("[object Date]"===o)return new Date(t.getTime());if("[object RegExp]"===o){var r=String(t),u=r.lastIndexOf("/");return new RegExp(r.slice(1,u),r.slice(u+1))}if((0,i.isBuffer)(t)){var f=new Buffer(t.length);return t.copy(f),f}var l=e(t);return void 0!==l?l:null}function u(t){var e=typeof t;return null!==t&&"object"!==e&&"function"!==e?t:null}e.__esModule=!0,e.copyValue=e.copyCollection=e.copy=void 0;var i=n(1),c=Object.prototype.toString;e.copy=o,e.copyCollection=r,e.copyValue=u},function(t,e,n){"use strict";function o(t){}function r(t){var e=arguments.length<=1||void 0===arguments[1]?o:arguments[1];if(null===t)return null;var n=(0,i.copyValue)(t);if(null!==n)return n;var r=(0,i.copyCollection)(t,e),c=null!==r?r:t,f=[t],l=[c];return u(t,e,c,f,l)}function u(t,e,n,o,r){if(null===t)return null;var f=(0,i.copyValue)(t);if(null!==f)return f;var l=(0,c.getKeys)(t).concat((0,c.getSymbols)(t)),p=void 0,s=void 0,a=void 0,y=void 0,d=void 0,v=void 0,b=void 0,j=void 0;for(p=0,s=l.length;s>p;++p)a=l[p],y=t[a],d=(0,c.indexOf)(o,y),v=void 0,b=void 0,j=void 0,-1===d?(v=(0,i.copy)(y,e),b=null!==v?v:y,null!==y&&/^(?:function|object)$/.test(typeof y)&&(o.push(y),r.push(b))):j=r[d],n[a]=j||u(y,e,b,o,r);return n}e.__esModule=!0;var i=n(2),c=n(1);e["default"]=r,t.exports=e["default"]}])});</script><script type="module">
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { Base } from '@polymer/polymer/polymer-legacy.js';
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js';
import { Polymer as Polymer$0 } from '@polymer/polymer/lib/legacy/polymer-fn.js';
/* jshint -W100 */
(function(document) {
'use strict';
var html = document.querySelector('html');
if (window.ShadowDOMPolyfill) {
// Fix #38. Add reflectToAttribute effect on html.lang property
// for supplementing Shadow DOM MutationObserver polyfill
Object.defineProperty(html, 'lang', {
get: function () {
return this.getAttribute('lang');
},
set: function (value) {
this.setAttribute('lang', value);
}
});
}
// Safari 7 predefines non-configurable standard properties
// Note: They become configurable with ShadowDOMPolyfill, which wraps them.
var isStandardPropertyConfigurable = (function () {
var langPropertyDescriptor = Object.getOwnPropertyDescriptor(document.createElement('span'), 'lang');
return !langPropertyDescriptor || langPropertyDescriptor.configurable;
})();
// Polymer 1.4.0 on Safari 7 inserts extra unexpected whitepace node at the beginning of template
var extraWhiteSpaceNode = !isStandardPropertyConfigurable;
// app global bundle storage
var bundles = { '': {} }; // with an empty default bundle
// app global default language
var defaultLang = html.hasAttribute('lang') ? html.getAttribute('lang') : '';
// shared fetching instances for bundles
var bundleFetchingInstances = {};
// path for start URL
var startUrl = (function () {
var path = window.location.pathname;
if (document.querySelector('meta[name=app-root]') &&
document.querySelector('meta[name=app-root]').getAttribute('content')) {
// <meta name="app-root" content="/"> to customize application root
path = document.querySelector('meta[name=app-root]').getAttribute('content');
}
else if (document.querySelector('link[rel=manifest]') &&
document.querySelector('link[rel=manifest]').getAttribute('href') &&
document.querySelector('link[rel=manifest]').getAttribute('href').match(/^\//)) {
// assume manifest is located at the application root folder
path = document.querySelector('link[rel=manifest]').getAttribute('href');
}
return path.replace(/\/[^\/]*$/,'/');
})();
// path for locales from <html locales-path="locales">
var localesPath = html.hasAttribute('locales-path') ?
html.getAttribute('locales-path') : 'locales';
var attributesRepository = document.createElement('i18n-attr-repo');
// set up userPreference
var userPreference = document.querySelector('i18n-preference');
if (!userPreference) {
userPreference = document.createElement('i18n-preference');
// append to body
document.querySelector('body').appendChild(userPreference);
}
// debug log when <html debug> attribute exists
var debuglog = html.hasAttribute('debug') ?
function (arg) {
console.log(arg);
} :
function () {};
window.BehaviorsStore = window.BehaviorsStore || {};
/**
* Apply `BehaviorsStore.I18nControllerBehavior` to manipulate internal variables for I18N
*
* Note: This behavior is not for normal custom elements to apply I18N. UI is not expected.
*/
BehaviorsStore.I18nControllerBehavior = {
properties: {
/**
* Flag for detection of `I18nControllerBehavior`
*
* `true` if I18nControllerBehavior is applied
*
* Note: Module-specific JSON resources are NOT fetched for `I18nControllerBehavior`
*/
isI18nController: {
type: Boolean,
value: true,
readOnly: true
},
/**
* HTML element object for the current document
*/
html: {
type: Object,
value: html
},
/**
* Master bundles object for storing all the localized and default resources
*/
masterBundles: {
type: Object,
value: bundles
},
/**
* Default lang for the document, i.e., the initial value of `<html lang>` attribute
*/
defaultLang: {
type: String,
value: defaultLang,
readOnly: true
},
/**
* List of elements which are fetching bundles
*/
bundleFetchingInstances: {
type: Object,
value: bundleFetchingInstances
},
/**
* Root URL path of the application ends with '/' to fetch bundles
*/
startUrl: {
type: String,
value: startUrl,
readOnly: true
},
/**
* Path for locales
*
* Default value is `'locales'`
*/
localesPath: {
type: String,
value: localesPath,
readOnly: true
},
/**
* <i18n-attr-repo> element to store attributes repository
*/
attributesRepository: {
type: Object,
value: attributesRepository,
readOnly: true
},
/**
* <i18n-preference> element
*/
userPreference: {
type: Object,
value: userPreference,
readOnly: true
}
}
};
/**
* Apply `BehaviorsStore.I18nBehavior` to implement localizable elements.
*
* <dom-module id="custom-element">
* <template>
* <span>Hard-coded UI texts are automatically made localizable</span>
* </template>
* <script>
* Polymer({
* is: 'custom-element',
* behaviors: [
* BehaviorsStore.I18nBehavior // Add this behavior
* ]
* });
* </script>
* </dom-module>
*
* `I18nBehavior` automatically extracts UI texts from `template` and
* binds them to localizable variables in `this.text` object.
*
* According to the `lang` attribute value, `this.text`, and thus the bound UI texts,
* dynamically mutates by loading localized values from a JSON file in the `locales` directory.
* By default, `lang` attribute values of all the localizable elements with `I18nBehavior` are
* automatically updated according to `<html lang>` attribute value.
*
* The UI text externalization can be processed at build time as well by `gulp-*` task
* so that `I18nBehavior` can immediately recognize the extracted texts in JSON and
* skip run-time externalization.
*
* Run-time externalization is suitable for development and debugging
* since the code changes are immediately reflected at reloading without build-time preprocesses.
* In contrast, build-time externalization is suitable for production builds
* since it eliminates run-time externalization overheads.
*
* ### Steps to localize a custom element
*
* 1. [JavaScript] Add `BehaviorsStore.I18nBehavior` to `behaviors`
* 1. [gulp] Add `gulp-*` filter for `custom-element.html` and generate `custom-element.json`
* 1. [locales] Put `custom-element.lang.json` in `locales` directory
* 1. [translation] Translate `locales/custom-element.lang.json`
*
* - - -
*
* ### Directory structure of bundle files
*
* Normal bundles (`/element-root/locales/element-name.*.json`) for elements
* are stored under their root directories.
*
* Shared bundles (`/locales/bundle.*.json`) are generated at build time
* by merging all the targeted bundles of the localizable elements.
*
* Once the shared bundles are loaded, there should be no need to search for
* normal bundles per element unless the element is intentionally excluded
* from the shared bundles.
*
* ```
* /bundle.json
* /locales/bundle.ja.json
* /bundle.fr.json
* /bundle.zh-Hans.json
*
* /elements/my-list/my-list.json
* /locales/my-list.ja.json
* /my-list.zh-Hans.json
*
* /google-chart-demo/google-chart-demo.json
* /locales/google-chart-demo.ja.json
* /google-chart-demo.fr.json
* ```
*
* - - -
*
* ### Localizable `<template is="i18n-dom-bind" id="app">` element
*
* `<template is="i18n-dom-bind">` template element extends
* `<template is="dom-bind">` template element with all the capabilities of
* `I18nBehavior`.
*
* The `id` attribute value is used for naming bundle files instead of the element name.
*
* The bundle files are stored at the locales directory under the application root.
*
* ```
* /app.json
* /locales/app.ja.json
* /app.fr.json
* /app.zh-Hans.json
* ```
*
* - - -
*
* ### TODOs
*
* - Support user locale preference per user
*
* @polymerBehavior BehaviorsStore.I18nBehavior
* @group I18nBehavior
* @hero hero.svg
* @demo demo/index.html
*/
BehaviorsStore.I18nBehavior = {
/**
* Fired when the text message bundle object (`this.text`) is updated after `this.lang` is changed.
*
* @event lang-updated
*/
/**
* Fired when a shared bundle is fetched.
*
* @event bundle-fetched
*/
properties: {
/**
* The locale of the element.
* The default value is copied from `<html lang>` attribute of the current page.
* If `<html lang>` is not specified, `''` is set to use the template default language.
*
* The value is synchronized with `<html lang>` attribute of the current page by default.
*
* ### Note:
* - The value may not reflect the current UI locale until the localized texts are loaded.
*/
lang: {
type: String,
value: defaultLang,
reflectToAttribute: true,
observer: '_langChanged'
},
/**
* Text message bundle object for the current locale.
* The object is shared among all the instances of the same element.
* The value is updated when `lang-updated` event is fired.
*/
text: {
type: Object,
computed: '_getBundle(lang)'
},
/**
* Data model bundle object for the current locale.
* The data are bound to localizable attribute values in the element template.
* The object is cloned from `this.text.model` per instance.
* The value is NOT automatically updated in sync with `this.text`.
*
* How to manually update the model object when `lang-updated` event is fired:
* ```
* this.model = deepcopy(this.text.model);
* ```
*/
model: {
type: Object,
notify: true
},
/**
* The locale of the hard-coded texts in the element's template.
* The read-only value can be specified by the `lang` attribute of the element's `template`.
* The default value is 'en' if not specified in the `template` element.
*
* ```
* <dom-module id="custom-element">
* <template lang="en">
* <span>Hard-coded text in English</span>
* </template>
* <dom-module>
* ```
*/
templateDefaultLang: {
type: String,
value: 'en'
},
/**
* The effective locale of the element.
* The value is updated when the localized texts are loaded and `lang-updated` event is fired.
*/
effectiveLang: {
type: String
},
/**
* Boolean flag to synchronize with the value of `<html lang>` attribute.
*/
observeHtmlLang: {
type: Boolean,
value: true,
observer: '_observeHtmlLangChanged'
}
},
listeners: {
'lang-updated': '_updateEffectiveLang'
},
/*
bundles =
{
"": {},
"en": {
"my-list": {
"p_2": "You now have:",
"model": {
"list": {
"items": [
"item 1", "item 2"
]
}
}
},
"google-chart-demo": {
"simple-chart-desc": [
"template {1} string", "param 1"
]
"model": {
"simple-chart": {
"options": { "title": "Simple Chart" },
"rows": []
}
}
}
},
"ja": {
"my-list": {},
"google-chart-demo": {}
}
}
bundles[lang]
/bundle.json - fallback
/locales/bundle.en.json
/bundle.ja.json
/bundle.fr.json
/bundle.zh-Hans.json
bundles[lang][is]
/elements/my-list/my-list.json - fallback
/locales/my-list.en.json
/my-list.ja.json
/my-list.zh-Hans.json
/google-chart-demo/google-chart-demo.json - fallback
/locales/google-chart-demo.en.json
/google-chart-demo.ja.json
/google-chart-demo.zh-Hans.json
app/elements/my-list/my-list.json
/locales/my-list.fr.json
/my-list.ja.json
/my-list.zh-Hans.json
dist/elements/my-list/my-list.json
/locales/my-list.fr.json
/my-list.ja.json
/my-list.zh-Hans.json
*/
/**
* The backend logic for `this.text` object.
*
* @param {string} lang Locale for the text message bundle.
* @return {Object} Text message bundle for the locale.
*/
_getBundle: function (lang) {
//console.log('_getBundle called for ' + this.is + ' with lang = ' + lang);
var resolved;
var id = this.is === 'i18n-dom-bind' ? this.id : this.is;
if (lang && lang.length > 0) {
var fallbackLanguageList = this._enumerateFallbackLanguages(lang);
var tryLang;
while ((tryLang = fallbackLanguageList.shift())) {
if (!bundles[tryLang]) {
// set up an empty bundle for the language if missing
bundles[tryLang] = {};
}
if (bundles[tryLang][id]) {
// bundle found
resolved = bundles[tryLang][id];
break;
}
}
}
else {
// lang is not specified
lang = '';
resolved = bundles[lang][id];
}
// Fallback priorities: last > app default > element default > fallback > {}
// TODO: need more research on fallback priorities
if (!resolved) {
if (bundles[this._fetchStatus.lastLang] && bundles[this._fetchStatus.lastLang][id]) {
// old bundle for now (no changes should be shown)
resolved = bundles[this._fetchStatus.lastLang][id];
}
else if (defaultLang && defaultLang.length > 0 &&
bundles[defaultLang] && bundles[defaultLang][id]) {
// app default language for now
resolved = bundles[defaultLang][id];
}
else if (this.templateDefaultLang && this.templateDefaultLang.length > 0 &&
bundles[this.templateDefaultLang] && bundles[this.templateDefaultLang][id]) {
// element default language for now
resolved = bundles[this.templateDefaultLang][id];
}
/* no more fallback should happen */
/* istanbul ignore else */
else if (bundles[''][id]) {
// fallback language for now (this should be the same as element default)
resolved = bundles[''][id];
}
else {
// give up providing a bundle (this should not happen)
resolved = {};
}
}
return resolved;
},
/**
* 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.
*/
_enumerateFallbackLanguages: function (lang) {
var result = [];
var parts;
var match;
var isExtLangCode = 0;
var extLangCode;
var isScriptCode = 0;
var scriptCode;
var isCountryCode = 0;
var countryCode;
var n;
if (!lang || lang.length === 0) {
result.push('');
}
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
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;
},
/**
* Get the next fallback locale for the target locale.
*
* Subset implementation of BCP47 (https://tools.ietf.org/html/bcp47).
*
* ### Examples:
*
*| Target Locale | Next Fallback |
*|:--------------|:--------------|
*| ru | null |
*| en-GB | en |
*| fr-CA | fr |
*| zh-Hans-CN | zh-Hans |
*
* @param {string} lang Target locale.
* @return {string} Next fallback locale. `null` if there are no fallback languages.
*/
/*
_getNextFallbackLanguage: function (lang) {
var fallbackLanguageList = this._enumerateFallbackLanguages(lang);
fallbackLanguageList.shift();
var nextFallbackLanguage = fallbackLanguageList.shift();
return nextFallbackLanguage ? nextFallbackLanguage : null;
},
*/
/**
* MutationObserver callback of `lang` attribute for Safari 7
*
* @param {Array} mutations Array of MutationRecord (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
*/
_handleLangAttributeChange: function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'attributes':
if (mutation.attributeName === 'lang') {
//console.log('_handleLangAttributeChange lang = ' + this.lang + ' oldValue = ' + mutation.oldValue +
// ' typeof oldValue = ' + typeof mutation.oldValue);
if (!(typeof mutation.oldValue === 'object' && !mutation.oldValue) &&
mutation.oldValue !== this.lang) {
if (this._lang !== mutation.oldValue) {
//console.log('assigning this._lang = ' + mutation.oldValue + ' from old value');
this._lang = mutation.oldValue;
}
//console.log('assigning this._lang = ' + this.lang);
this._lang = this.lang;
}
}
break;
default:
/* istanbul ignore next: mutation.type is always attributes */
break;
}
}, this);
},
/**
* Observer of `this.lang` changes.
*
* Update `this.text` object if the text message bundle of the new `lang` is locally available.
*
* Trigger fetching of the text message bundle of the new `lang` if the bundle is not locally available.
*
* @param {string} lang New value of `lang`.
* @param {string} oldLang Old value of `lang`.
*/
_langChanged: function (lang, oldLang) {
//console.log(this.id + ':_langChanged lang = ' + lang + ' oldLang = ' + oldLang);
var id = (this.is || this.getAttribute('is')) === 'i18n-dom-bind' ? this.id : this.is;
lang = lang || ''; // undefined and null are treated as default ''
oldLang = oldLang || '';
if (lang !== oldLang &&
bundles[oldLang] && bundles[oldLang][id]) {
this._fetchStatus.lastLang = oldLang;
}
if (bundles[lang] && bundles[lang][id]) {
// bundle available for the new language
if (lang !== this._fetchStatus.ajaxLang) {
// reset error status
this._fetchStatus.error = null;
}
this.notifyPath('text', this._getBundle(this.lang));
this.fire('lang-updated', {
lang: this.lang,
oldLang: oldLang,
lastLang: this._fetchStatus.lastLang
});
}
else {
// fetch the missing bundle
this._fetchLanguage(lang);
}
},
/**
* Called on `lang-updated` events and update `this.effectiveLang` with the value of `this.lang`.
*/
_updateEffectiveLang: function (event) {
if (dom(event).rootTarget === this) {
//console.log('_updateEffectiveLang: lang = ' + this.lang);
this.effectiveLang = this.lang;
}
},
/**
* Trigger fetching of the appropriate text message bundle of the target locale.
*
* ### Two Layers of Fallbacks:
*
* 1. Missing bundles fall back to those of their fallback locales.
* 1. Missing texts in the non-default bundles fall back to those in the default bundle.
*
* ### Fallback Examples:
*
*| Locale | Bundle Status |
*|:------------|:---------------------------------|
*| fr-CA | existent with sparse texts |
*| fr | existent with full texts |
*| ja | existent with some missing texts |
*| zh-Hans-CN | missing |
*| zh-Hans | existent with some missing texts |
*| zh | missing |
*| en | existent with full texts |
*| ''(default) | existent with full texts |
*
*| Target | Fallback bundle | Resolved locale |
*|:------------|:----------------------|:----------------|
*| en | en | en |
*| ja | ja + ''(default) | ja |
*| fr-CA | fr-CA + fr | fr-CA |
*| zh-Hans-CN | zh-Hans + ''(default) | zh-Hans |
*
* @param {string} lang Target locale.
*/
_fetchLanguage: function (lang) {
if (this._fetchStatus) {
this._fetchStatus.fallbackLanguageList = this._enumerateFallbackLanguages(lang);
this._fetchStatus.fallbackLanguageList.push('');
this._fetchStatus.targetLang = this._fetchStatus.fallbackLanguageList.shift();
this._fetchBundle(this._fetchStatus.targetLang);
}
},
/**
* Fetch the text message bundle of the target locale
* cooperatively with other instances.
*
* @param {string} lang Target locale.
*/
_fetchBundle: function (lang) {
//console.log('_fetchBundle lang = ' + lang);
if (!lang || lang.length === 0) {
// handle empty cases
if (defaultLang && defaultLang.length > 0) {
lang = defaultLang; // app default language
}
else if (this.templateDefaultLang && this.templateDefaultLang.length > 0) {
lang = this.templateDefaultLang; // element default language
}
else {
lang = ''; // fallback default language
}
}
// set up an empty bundle if inexistent
bundles[lang] = bundles[lang] || {};
var id = this.is === 'i18n-dom-bind' ? this.id : this.is;
if (bundles[lang][id]) {
// bundle is available; no need to fetch
if (this._fetchStatus.targetLang === lang) {
// reset error status
this._fetchStatus.error = null;
if (this.lang === lang) {
this.notifyPath('text', this._getBundle(this.lang));
this.fire('lang-updated', {
lang: this.lang,
lastLang: this._fetchStatus.lastLang
});
}
else {
this.lang = lang; // trigger lang-updated event
}
}
else {
var nextFallbackLanguage = this._fetchStatus.fallbackLanguageList.shift();
// bundle is available; no need to fetch
this._fetchStatus.fetchingInstance = null;
if (nextFallbackLanguage) {
this._fetchBundle(nextFallbackLanguage);
}
else {
this._constructBundle(this._fetchStatus.targetLang);
// reset error status
this._fetchStatus.error = null;
if (this.lang === this._fetchStatus.targetLang) {
this.notifyPath('text', this._getBundle(this.lang));
this.fire('lang-updated', {
lang: this.lang,
lastLang: this._fetchStatus.lastLang
});
}
else {
this.lang = this._fetchStatus.targetLang; // trigger lang-updated event
}
}
}
}
else if (this._fetchStatus.fetchingInstance) {
if (this._fetchStatus.fetchingInstance !== this) {
// fetching in progress by another instance
// TODO: redundant addEventListener multiple times
this._forwardLangEventBindThis = this._forwardLangEventBindThis ||
this._forwardLangEvent.bind(this);
this._fetchStatus.fetchingInstance
.addEventListener('lang-updated', this._forwardLangEventBindThis);
}
}
else if (bundleFetchingInstances[lang]) {
// fetching bundle.lang.json in progress by an instance of another element
this._fetchStatus.fetchingInstance = this;
this._fetchStatus.ajaxLang = lang;
this._handleBundleFetchedBindThis = this._handleBundleFetchedBindThis ||
this._handleBundleFetched.bind(this);
bundleFetchingInstances[lang]
.addEventListener('bundle-fetched', this._handleBundleFetchedBindThis);
//console.log(this.is + ' addEventListener bundle-fetched');
}
else {
// proceed to fetch
this._fetchStatus.fetchingInstance = this;
if (!this._fetchStatus.ajax) {
// set up ajax client
this._fetchStatus.ajax = Base.create('iron-ajax');
this._fetchStatus.ajax.handleAs = 'json';
this._fetchStatus._handleResponseBindFetchingInstance = this._handleResponse.bind(this);
this._fetchStatus._handleErrorBindFetchingInstance = this._handleError.bind(this);
this._fetchStatus.ajax.addEventListener('response', this._fetchStatus._handleResponseBindFetchingInstance);
this._fetchStatus.ajax.addEventListener('error', this._fetchStatus._handleErrorBindFetchingInstance);
}
else {
if (this._fetchStatus._handleResponseBindFetchingInstance) {
this._fetchStatus.ajax.removeEventListener('response', this._fetchStatus._handleResponseBindFetchingInstance);
}
if (this._fetchStatus._handleErrorBindFetchingInstance) {
this._fetchStatus.ajax.removeEventListener('error', this._fetchStatus._handleErrorBindFetchingInstance);
}
this._fetchStatus._handleResponseBindFetchingInstance = this._handleResponse.bind(this);
this._fetchStatus._handleErrorBindFetchingInstance = this._handleError.bind(this);
this._fetchStatus.ajax.addEventListener('response', this._fetchStatus._handleResponseBindFetchingInstance);
this._fetchStatus.ajax.addEventListener('error', this._fetchStatus._handleErrorBindFetchingInstance);
}
// TODO: app global bundles have to be handled
var url;
var skipFetching = false;
if (lang === '') {
url = this.resolveUrl(id + '.json');
}
else {
if (bundles[lang] && bundles[lang].bundle) {
// missing in the bundle
url = this.resolveUrl(localesPath + '/' + id + '.' + lang + '.json');
skipFetching = !!this.isI18nController;
}
else {
// fetch the bundle
bundleFetchingInstances[lang] = this;
url = this.resolveUrl(startUrl + localesPath + '/bundle.' + lang + '.json');
}
}
this._fetchStatus.ajax.url = url;
this._fetchStatus.ajaxLang = lang;
try {
this._fetchStatus.error = null;
if (skipFetching) {
this._handleError({ detail: { error: 'skip fetching for I18nController' }});
}
else {
this._fetchStatus.ajax.generateRequest();
}
}
catch (e) {
// TODO: extract error message from the exception e
this._handleError({ detail: { error: 'ajax request failed: ' + e }});
}
}
},
/**
* Handle Ajax success response for a bundle.
*
* @param {Object} event `iron-ajax` success event.
*/
_handleResponse: function (event) {
//console.log('_handleResponse ajaxLang = ' + this._fetchStatus.ajaxLang);
if (this._fetchStatus.ajax.url.indexOf('/' + localesPath + '/bundle.') >= 0) {
bundles[this._fetchStatus.ajaxLang] = bundles[this._fetchStatus.ajaxLang] || {};
this._deepMap(bundles[this._fetchStatus.ajaxLang],
event.detail.response,
function (text) { return text; });
bundles[this._fetchStatus.ajaxLang].bundle = true;
bundleFetchingInstances[this._fetchStatus.ajaxLang] = null;
//console.log('bundle-fetched ' + this.is + ' ' + this._fetchStatus.ajaxLang);
this.fire('bundle-fetched', { success: true, lang: this._fetchStatus.ajaxLang });
var id = this.is === 'i18n-dom-bind' ? this.id : this.is;
if (bundles[this._fetchStatus.ajaxLang][id]) {
this._fetchStatus.lastResponse = bundles[this._fetchStatus.ajaxLang][id];
}
else {
// bundle does not contain text for this.is
this._fetchStatus.fetchingInstance = null;
this._fetchBundle(this._fetchStatus.ajaxLang);
return;
}
}
else {
this._fetchStatus.lastResponse = event.detail.response;
}
if (this._fetchStatus.lastResponse) {
var nextFallbackLanguage = this._fetchStatus.fallbackLanguageList.shift();
// store the raw response
this._fetchStatus.rawResponses[this._fetchStatus.ajaxLang] =
this._fetchStatus.lastResponse;
this._fetchStatus.fetchingInstance = null;
if (nextFallbackLanguage) {
this._fetchBundle(nextFallbackLanguage);
}
else {
this._fetchBundle('');
}
}
else {
event.detail.error = 'empty response for ' + this._fetchStatus.ajax.url;
this._handleError(event);
}
},
/**
* Handle Ajax error response for a bundle.
*
* @param {Object} event `iron-ajax` error event.
*/
_handleError: function (event) {
var nextFallbackLanguage;
this._fetchStatus.fetchingInstance = null;
if (this._fetchStatus.ajax.url.indexOf('/' + localesPath + '/bundle.') >= 0) {
bundles[this._fetchStatus.ajaxLang] = bundles[this._fetchStatus.ajaxLang] || {};
bundles[this._fetchStatus.ajaxLang].bundle = true;
bundleFetchingInstances[this._fetchStatus.ajaxLang] = null;
// falls back to its element-specific bundle
this._fetchBundle(this._fetchStatus.ajaxLang);
//console.log('bundle-fetched ' + this.is + ' ' + this._fetchStatus.ajaxLang);
this.fire('bundle-fetched', { success: false, lang: this._fetchStatus.ajaxLang });
return;
}
nextFallbackLanguage = this._fetchStatus.fallbackLanguageList.shift();
if (this._fetchStatus.ajaxLang === this._fetchStatus.targetLang) {
if (nextFallbackLanguage) {
//console.log(this.is + ': ' + this._fetchStatus.ajaxLang +
// ' falls back to ' + nextFallbackLanguage);
this._fetchStatus.targetLang = nextFallbackLanguage;
this._fetchBundle(nextFallbackLanguage);
}
else {
this._fetchStatus.error = event.detail.error;
//console.log(this._fetchStatus.error);
// falls back to default
this.lang = '';
}
}
else {
// fetching dependent fallback languages
if (nextFallbackLanguage) {
//console.log(this.is + ': ' + this._fetchStatus.ajaxLang +
// ' is missing and skipped');
//console.log(this.is + ': step to the next dependent fallback ' +
// nextFallbackLanguage);
this._fetchBundle(nextFallbackLanguage);
}
else {
this._fetchBundle('');
}
}
},
/**
* Forward `lang-updated` event to other instances of the same element.
*
* @param {Object} event `lang-updated` event object.
*/
_forwardLangEvent: function (event) {
//console.log('_forwardLangEvent ' + this.is + ' ' + event.detail.lang);
event.target.removeEventListener(event.type, this._forwardLangEventBindThis);
if (this.lang === event.detail.lang) {
this.notifyPath('text', this._getBundle(this.lang));
this.fire(event.type, event.detail);
}
else {
this.lang = event.detail.lang;
this.notifyPath('text', this._getBundle(this.lang));
}
},
/**
* Handle `bundle-fetched` event.
*
* @param {Object} event `bundle-fetched` event object.
*/
_handleBundleFetched: function (event) {
var detail = event.detail;
//console.log('_handleBundleFetched ' + this.is + ' ' + detail.lang);
event.target.removeEventListener(event.type, this._handleBundleFetchedBindThis);
if (this._fetchStatus.ajaxLang === detail.lang) {
this._fetchStatus.fetchingInstance = null;
this._fetchBundle(this._fetchStatus.ajaxLang);
}
},
/**
* Handle changes of `observeHtmlLang` property.
*
* @param {Boolean} value Value of `observeHtmlLang`
*/
_observeHtmlLangChanged: function (value) {
if (value) {
this._htmlLangObserver = this._htmlLangObserver ||
new MutationObserver(this._handleHtmlLangChange.bind(this));
this._htmlLangObserver.observe(html, { attributes: true });
}
else {
if (this._htmlLangObserver) {
this._htmlLangObserver.disconnect();
}
}
},
/**
* MutationObserver callback of `<html lang>` attribute.
*
* @param {Array} mutations Array of MutationRecord (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
*/
_handleHtmlLangChange: function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'attributes':
if (mutation.attributeName === 'lang') {
this.lang = html.lang;
}
break;
default:
break;
}
}, this);
},
/**
* Construct the text message bundle of the target locale with fallback of missing texts.
*
* @param {strings} lang Target locale.
*/
_constructBundle: function (lang) {
var fallbackLanguageList = this._enumerateFallbackLanguages(lang);
var bundle = {};
var raw;
var baseLang;
var id = this.is === 'i18n-dom-bind' ? this.id : this.is;
var i;
fallbackLanguageList.push('');
for (i = 0; i < fallbackLanguageList.length; i++) {
if (bundles[fallbackLanguageList[i]] &&
bundles[fallbackLanguageList[i]][id]) {
break;
}
}
fallbackLanguageList.splice(i + 1, fallbackLanguageList.length);
while ((baseLang = fallbackLanguageList.pop()) !== undefined) {
if (bundles[baseLang][id]) {
bundle = deepcopy(bundles[baseLang][id]);
}
else {
raw = this._fetchStatus.rawResponses[baseLang];
if (raw) {
this._deepMap(bundle, raw, function (text) { return text; });
}
}
}
// store the constructed bundle
if (!bundles[lang]) {
bundles[lang] = {};
}
bundles[lang][id] = bundle;
},
/**
* Construct a pseudo-bundle for the target locale. (Not used for now)
*
* @param {string} lang Target locale.
*/
/*
_constructPseudoBundle: function (lang) {
var bundle = {};
var id = this.is === 'i18n-dom-bind' ? this.id : this.is;
this._deepMap(bundle, bundles[''][id], function (value) {
return typeof value === 'string' ? lang + ' ' + value : value;
});
bundles[lang] = bundles[lang] || {};
bundles[lang][id] = bundle;
return bundle;
},
*/
/**
* Recursively map the source object onto the target object with the specified map function.
*
* The method is used to merge a bundle into its fallback bundle.
*
* @param {Object} target Target object.
* @param {Object} source Source object.
* @param {Function} map Mapping function.
*/
_deepMap: function (target, source, map) {
var value;
for (var prop in source) {
value = source[prop];
switch (typeof value) {
case 'string':
case 'number':
case 'boolean':
if (typeof target === 'object') {
target[prop] = map(value, prop);
}
break;
case 'object':
if (typeof target === 'object') {
if (Array.isArray(value)) {
// TODO: cannot handle deep objects properly
target[prop] = target[prop] || [];
this._deepMap(target[prop], value, map);
}
else {
target[prop] = target[prop] || {};
this._deepMap(target[prop], value, map);
}
}
break;
default:
if (typeof target === 'object') {
target[prop] = value;
}
break;
}
}
},
/**
* Construct the default bundle from the element's template.
*
* Extract the default bundle from the template if it is embedded as JSON at build time.
*
* ### Hard-coded UI text example:
* ```
* <dom-module id="custom-element">
* <template>
* <span id="label">UI Text Label:</span>
* <input id="input-el"
* value="{{keyword}}"
* placeholder="Keyword">
* </template>
* </dom-module>
* ```
*
* ### Constructed default bundle for the above example:
* ```
* {
* "model" : {
* "input-el": {
* "placeholder": "Keyword"
* }
* },
* "label": "UI Text Label:"
* }
* ```
*
* ### Processed template with bound annotations for the above example:
* ```
* <dom-module id="custom-element">
* <template localizable-text="embedded">
* <span id="label">{{text.label}}</span>
* <input id="input-el"
* value="{{keyword}}"
* placeholder="{{model.input-el.placeholder}}">
* </template>
* </dom-module>
* ```
*
* ### Embedded JSON bundle format for the above example:
* ```
* <dom-module id="custom-element">
* <template localizable-text="embedded">
* <span id="label">{{text.label}}</span>
* <input id="input-el"
* value="{{keyword}}"
* placeholder="{{model.input-el.placeholder}}">
* <template id="localizable-text">
* <json-data>{
* "model" : {
* "input-el": {
* "placeholder": "Keyword"
* }
* },
* "label": "UI Text Label:"
* }</json-data>
* </template>
* </template>
* </dom-module>
* ```
*/
_constructDefaultBundle: function () {
var template;
var id = this.is;
if (this.is === 'i18n-dom-bind') {
template = this;
id = this.id;
/* istanbul ignore if */
if (template.content.childNodes.length === 0) {
// Find the real template in Internet Explorer 11 when i18n-dom-bind is concealed in a parent template
// This does not happen on Polymer 1.3.1 or later. So ignore this 'if' statement in code coverage.
template = Array.prototype.map.call(document.querySelectorAll('template'), function (parentTemplate) {
return parentTemplate.content.querySelector('template#' + id + '[is="i18n-dom-bind"]');
}).reduce(function (prev, current) {
return prev || current;
});
// Patch this.content with the real one
if (template) {
this.content = template.content;
}
}
}
else {
template = DomModule.import(id, 'template');
}
if (template) {
this.templateDefaultLang = template.hasAttribute('lang') ? template.lang : 'en';
}
else {
this.templateDefaultLang = 'en';
}
var bundle = { model: {} };
var path = [];
var templateDefaultLang = this.templateDefaultLang;
var localizableText, jsonData;
if (template) {
// register localizable attributes of the element itself
attributesRepository.registerLocalizableAttributes(id, template);
if (template.getAttribute('localizable-text') === 'embedded') {
// pick up embedded JSON from the template
localizableText = template.content.querySelector('#localizable-text');
if (localizableText) {
jsonData = localizableText.content.querySelector('json-data');
if (jsonData) {
bundle = JSON.parse(jsonData.textContent);
}
else {
console.error('<json-data> not found in <template id=\"localizable-text\">');
}
}
else {
console.error('<template id=\"localizable-text\"> not found');
}
}
else {
if (extraWhiteSpaceNode) {
template.setAttribute('strip-whitespace', '');
}
// traverse template to generate bundle
this._traverseTemplateTree(template.content, path, bundle, 0);
}
}
bundles[''][id] = bundle;
bundles[templateDefaultLang] = bundles[templateDefaultLang] || {};
bundles[templateDefaultLang][id] = bundle;
//console.log('text = ');
//console.log(JSON.stringify(bundle, null, 2));
return true;
},
/**
* Traverse localizable attributes of the target element node and
* add them to the target bundle under the `model` object.
*
* The `<i18n-attr-repo>` object is used
* to judge if the target attributes are localizable.
*
* @param {Object} node Target element node.
* @param {string} path Path to the target node.
* @param {Object} bundle Default bundle.
*/
_traverseAttributes: function (node, path, bundle) {
var name = node.nodeName.toLowerCase();
var id = node.getAttribute ?
(node.getAttribute('text-id') ||
node.getAttribute('id')) : null;
var text;
var messageId;
var attrId;
var isLocalizable;
var dummy;
// pick up element attributes
Array.prototype.forEach.call(node.attributes, function (attribute) {
text = attribute.value;
switch (attribute.name) {
case 'id':
case 'text-id':
case 'is':
case 'lang':
case 'class':
// verification required before removing these attributes
case 'href':
case 'src':
case 'style':
case 'url':
case 'selected':
break;
default:
if (!(isLocalizable = attributesRepository.isLocalizableAttribute(node, attribute.name))) {
break;
}
if (text.length === 0) {
// skip empty value attribute
}
else if (text.match(/^{{[^{}]*}}$/) || text.match(/^\[\[[^\[\]]*\]\]$/)) {
// skip annotation attribute
}
else if (text.replace(/\n/g, ' ').match(/^{.*}|\[.*\]$/g) &&
!text.match(/^{{[^{}]*}}|\[\[[^\[\]]*\]\]/) &&
!text.match(/{{[^{}]*}}|\[\[[^\[\]]*\]\]$/)) {
// generate message id
messageId = this._generateMessageId(path, id);
try {
//console.log(messageId + ' parsing attribute ' + attribute.name + ' = ' + text);
var value = JSON.parse(text.replace(/\n/g, ' '));
//console.log('parsed JSON object = ');
//console.log(value);
switch (typeof value) {
case 'string':
case 'number':
case 'object':
// put into model
attrId = ['model', messageId, attribute.name].join('.');
debuglog(attrId + ' = ' + text);
this._setBundleValue(bundle, attrId, value);
attribute.value = '{{' + attrId + '}}';
break;
default: // skip other types
break;
}
}
catch (e) {
// invalid JSON
console.warn(e, 'Invalid JSON at <' + name + ' ' + attribute.name + '> with value = ' + text);
}
}
else if (text.match(/{{[^{}]{1,}}}|\[\[[^\[\]]{1,}\]\]/)) {
// compound binding attribute
// Parameterized:
// e.g., attr="Compound binding attribute has [[bound.value]] {{parameters}} in the value string"
// replaced as "{{i18nFormat(attrId.0,bound.value,parameters)}}"
// extracted as [ "Compound binding attribute has {1} {2} in the value string", "[[bound.value]]", "{{parameters}}" ]
// Concatenated: (Parameters with functions cannot be reordered in translation)
// e.g., attr2="Compound binding attribute has [[f1(bound.value)]] {{f2(parameters)}} in the value string"
// replaced as "{{attrId.0}}[[f1(bound.value)]]{{attrId.2}}{{f2(parameters)}}{{attrId.4}}"
// extracted as [ "Compound binding attribute has ", "[[f1(bound.value)]]", " ", "{{f2(parameters)}}", " in the value string" ]
var parsed = text.match(/([^{}\[\]]{1,})|({{[^{}]{1,}}})|(\[\[[^\[\]]{1,}\]\])/g);
var parameterized;
var processed;
var n;
messageId = this._generateMessageId(path, id);
attrId = ['model', messageId, attribute.name.replace(/\$$/, '')].join('.');
if (text.match(/\)}}|\)\]\]/)) { // check for function parameter
// Concatenate
debuglog(attrId + ' = ' + JSON.stringify(parsed));
this._setBundleValue(bundle, attrId, parsed);
processed = '';
for (n = 0; n < parsed.length; n++) {
if (parsed[n].match(/^{{[^{}]{1,}}}|\[\[[^\[\]]{1,}\]\]$/)) {
processed += parsed[n];
}
else {
processed += '{{' + attrId + '.' + n + '}}';
}
}
if (isLocalizable === '$' && !attribute.name.match(/\$$/)) {
dummy = document.createElement('span');
dummy.innerHTML = '<span ' + attribute.name + '$="' + processed + '"></span>';
node.setAttributeNode(dummy.childNodes[0].attributes[0].cloneNode());
}
else {
attribute.value = processed;
}
}
else {
// Parameterize
parameterized = [ '' ];
while (parsed.length) {
if (parsed[0].match(/^{{[^{}]{1,}}}|\[\[[^\[\]]{1,}\]\]$/)) {
parameterized.push(parsed[0]);
parameterized[0] += '{' + (parameterized.length - 1) + '}';
}
else {
parameterized[0] += parsed[0];
}
parsed.shift();
}
debuglog(attrId + ' = ' + JSON.stringify(parameterized));
this._setBundleValue(bundle, attrId, parameterized);
processed = '{{i18nFormat(' + attrId + '.0';
for (n = 1; n < parameterized.length; n++) {
processed += ',' + parameterized[n].replace(/^[{\[][{\[](.*)[}\]][}\]]$/, '$1');
}
processed += ')}}';
if (isLocalizable === '$' && !attribute.name.match(/\$$/)) {
dummy = document.createElement('span');
dummy.innerHTML = '<span ' + attribute.name + '$="' + processed + '"></span>';
node.setAttributeNode(dummy.childNodes[0].attributes[0].cloneNode());
}
else {
attribute.value = processed;
}
}
}
else {
// string attribute
messageId = this._generateMessageId(path, id);
attrId = ['model', messageId, attribute.name].join('.');
debuglog(attrId + ' = ' + text);
this._setBundleValue(bundle, attrId, text);
if (isLocalizable === '$' && !attribute.name.match(/\$$/)) {
dummy = document.createElement('span');
dummy.innerHTML = '<span ' + attribute.name + '$=' + '"{{' + attrId + '}}"' + '></span>';
node.setAttributeNode(dummy.childNodes[0].attributes[0].cloneNode());
}
else {
attribute.value = '{{' + attrId + '}}';
}
}
break;
}
}, this);
},
/**
* Recursively traverse text contents of the target element node
* and add them to the target bundle object.
*
* Traversed text contents are replaced with annotations
* for the corresponding text in the bundle.
*
* - - -
*
* There are some special treatments in the following cases.
*
* ### Sentence with parameterized child parameter-like elements:
*
* As the order of the parameters can change in different languages,
* `<i18n-format>` element is used to make the sentence localizable.
*
* ### Before processing
*
* ```
* <p id="p"><code>i18n-format</code> is
* used for
* <a href="https://www.google.com">parameterized</a>
* sentences.</p>
* ```
*
* ### After processing
*
* ```
* <p id="p">
* <i18n-format lang="{{effectiveLang}}">
* <span>{{text.p.0}}</span>
* <code>{{text.p.1}}</code>
* <a href="https://www.google.com">{{text.p.2}}</a>
* </i18n-format>
* </p>
* ```
*
* ### Constructed bundle data: Texts are stored in an Array of strings.
*
* ```
* {
* "p" : [
* "{1} is\n used for\n {2}\n sentences.",
* "i18n-format",
* "parameterized"
* ]
* }
* ```
*
* - - -
*
* ### `<i18n-format>` element with compound templates:
*
* Texts with compound templates for `<i18n-format>` element are
* processed as below.
*
* `lang="{{effectiveLang}}"` attribute is added to `<i18n-format>` node
* as well as `<i18n-number>` node.
*
* ### Before processing
*
* ```
* <i18n-format id="sentence">
* <json-data>{
* "0": "You ({3}) gave no gifts.",
* "1": {
* "male": "You ({3}) gave him ({4}) {5}.",
* "female": "You ({3}) gave her ({4}) {5}.",
* "other": "You ({3}) gave them ({4}) {5}."
* },
* "one": {
* "male":
* "You ({3}) gave him ({4}) and one other {5}.",
* "female":
* "You ({3}) gave her ({4}) and one other {5}.",
* "other":
* "You ({3}) gave them ({4}) and one other {5}."
* },
* "other":
* "You ({3}) gave them ({4}) and {1} others gifts."
* }</json-data>
* <i18n-number
* offset="1"
* >{{recipients.length}}</i18n-number>
* <span>{{recipients.0.gender}}</span>
* <span>{{sender.name}}</span>
* <span>{{recipients.0.name}}</span>
* <span>a gift</span>
* </i18n-format>
* ```
*
* ### After processing
*
* ```
* <i18n-format id="sentence"
* lang="{{effectiveLang}}">
* <json-data>{{serialize(text.sentence.0)}}</json-data>
* <i18n-number
* offset="1"
* lang="{{effectiveLang}}"
* >{{recipients.length}}</i18n-number>
* <span>{{recipients.0.gender}}</span>
* <span>{{sender.name}}</span>
* <span>{{recipients.0.name}}</span>
* <span>{{text.sentence.5}}</span>
* </i18n-format>
* ```
*
* ### Constructed bundle data:
*
* ```
* {
* "sentence" : [
* {
* "0": "You ({3}) gave no gifts.",
* "1": {
* "male": "You ({3}) gave him ({4}) {5}.",
* "female": "You ({3}) gave her ({4}) {5}.",
* "other": "You ({3}) gave them ({4}) {5}."
* },
* "one": {
* "male":
* "You ({3}) gave him ({4}) and one other {5}.",
* "female":
* "You ({3}) gave her ({4}) and one other {5}.",
* "other":
* "You ({3}) gave them ({4}) and one other {5}."
* },
* "other":
* "You ({3}) gave them ({4}) and {1} others gifts."
* },
* "{{recipients.length - 1}}",
* "{{recipients.0.gender}}",
* "{{sender.name}}",
* "{{recipients.0.name}}",
* "a gift"
* ]
* }
* ```
*
* @param {Object} node Target element node.
* @param {string} path Path to the target node.
* @param {Object} bundle Default bundle.
* @param {Number} index Index in the siblings of the target node excluding whitespace nodes.
*/
_traverseTemplateTree: function (node, path, bundle, index) {
var i;
var whiteSpaceElements = 0;
var isWhiteSpace = false;
var isCompoundAnnotatedNode = false;
var text;
var span;
var name = node.nodeName.toLowerCase();
var id = node.getAttribute ?
(node.getAttribute('text-id') ||
node.getAttribute('id')) : null;
var messageId;
var n;
var templateText;
var templateTextParams;
path.push(id ? '#' + id : name + (index > 0 ? '_' + index : ''));
//console.log(path.join(':'));
switch (node.nodeType) {
case node.ELEMENT_NODE:
switch (name) {
case 'style':
case 'script':
case 'meta':
// skip
break;
case 'i18n-format':
// pick up element attributes
this._traverseAttributes(node, path, bundle);
// generate message id
messageId = this._generateMessageId(path, id);
if (!node.hasAttribute('lang')) {
node.setAttribute('lang', '{{effectiveLang}}');
}
text = Array.prototype.filter.call(node.childNodes, function (child) {
return child.nodeType === child.ELEMENT_NODE;
}).map(function (param, n) {
var value = param.textContent;
var parsedValue = value.match(/^({{)(.*)(}})$/) ||
value.match(/^(\[\[)(.*)(\]\])$/);
if (n === 0) {
// template element
if (param.tagName.toLowerCase() === 'json-data') {
if (parsedValue) {
var parsedValue2 = value.match(/^({{)(serialize\(.*\))(}})$/) ||
value.match(/^(\[\[)(serialize\(.*\))(\]\])$/);
if (!parsedValue2) {
// convert to {{serialize(id)}}
parsedValue.shift();
parsedValue.splice(1, 0, 'serialize(');
parsedValue.splice(3, 0, ')');
param.textContent = parsedValue.join('');
}
}
else {
value = JSON.parse(value);
param.textContent = '{{serialize(text.' + messageId + '.' + n + ')}}';
}
}
else {
if (!parsedValue) {
param.textContent = '{{text.' + messageId + '.' + n + '}}';
}
}
}
else {
// param element
// TODO: handle localization of param nodes and attributes
if (!param.hasAttribute('param')) {
param.setAttribute('param', n);
}
if (param.tagName.toLowerCase() === 'i18n-number') {
if (!param.hasAttribute('lang')) {
param.setAttribute('lang', '{{effectiveLang}}');
}
var offset = param.getAttribute('offset');
if (offset) {
offset = ' - ' + offset;
}
else {
offset = '';
}
if (parsedValue) {
// convert to {{path - offset}}
parsedValue.shift();
parsedValue.splice(2, 0, offset);
value = parsedValue.join('');
}
else {
param.textContent = '{{text.' + messageId + '.' + n + '}}';
}
}
else {
if (!parsedValue) {
param.textContent = '{{text.' + messageId + '.' + n + '}}';
}
}
}
return value;
}, this);
debuglog(messageId + ' = ' + text);
this._setBundleValue(bundle, messageId, text);
break;
case 'template':
// traverse into its content
//console.log(path.join(':') + ':' + node.content.nodeName + ':' + 0);
if (extraWhiteSpaceNode) {
//if (node.hasAttribute('is') && node.getAttribute('is').match(/^(i18n-)?dom-/)) {
node.setAttribute('strip-whitespace', '');
//}
}
this._traverseTemplateTree(node.content, path, bundle, 0);
break;
default:
// element node
if (name === 'i18n-number' ||
name === 'i18n-datetime') {
if (!node.hasAttribute('lang')) {
node.setAttribute('lang', '{{effectiveLang}}');
}
}
// pick up element attributes
this._traverseAttributes(node, path, bundle);
// check annonated node
isCompoundAnnotatedNode = false;
if (node.childElementCount === 0) {
if (node.textContent) {
isCompoundAnnotatedNode = this._isCompoundAnnotatedText(node.textContent);
}
}
if (node.childElementCount === 0 && !isCompoundAnnotatedNode) {
if (node.textContent) { // use textContent for Firefox compatibility
text = node.textContent;
if (text.length === 0 || text.match(/^\s*$/g)) {
// skip empty or whitespace node
}
else if (text.trim().match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/)) {
// skip annotation node
// TODO: compound bindings support
}
else {
// a text message found
// generate message id
messageId = this._generateMessageId(path, id);
// store the text message
text = text.replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' ');
if (name === 'json-data') {
this._setBundleValue(bundle, messageId, JSON.parse(text));
}
else {
this._setBundleValue(bundle, messageId, text);
}
// replace textContent with annotation
node.textContent = '{{text.' + messageId + '}}';
if (!id) {
//node.id = messageId;
//console.warn('add missing node id as ' + messageId + ' for ' + text);
}
debuglog(messageId + ' = ' + text);
}
}
else {
// skip
}
}
else {
// has children or compound annotation
// check if i18n-format is applicable
var childStatus = Array.prototype.map.call(
node.childNodes, function (child) {
var result;
if (child.nodeType === child.ELEMENT_NODE &&
child.tagName === 'TEMPLATE') {
var templateNonCommentChildNodes =
Array.prototype.filter.call(child.content.childNodes, function (templateChild) {
switch (templateChild.nodeType) {
case templateChild.COMMENT_NODE:
return false;
case templateChild.TEXT_NODE:
return !templateChild.textContent.match(/^\s*$/g);
default:
case templateChild.ELEMENT_NODE:
return true;
}
});
var firstChild = templateNonCommentChildNodes.shift();
// Examples:
// hasText: <template>text</template>
// hasCompoundAnnotatedText: <template>{{item.name}} text</template>
// hasTextChild: <template><b>text</b></template> or <template><br></template>
// hasCompoundAnnotatedChildNode: <template><b>{{item.name}} text</b></template>
// hasGrandChildren: <template><span><b>text</b></span></template> or
// <template><b>A</b><i>B</i></template> or
// hasCompoundAnnotatedText
result = {
hasText: templateNonCommentChildNodes.length === 0 &&
firstChild &&
firstChild.nodeType === firstChild.TEXT_NODE &&
firstChild.textContent.length > 0 &&
!firstChild.textContent.match(/^\s*$/g),
hasCompoundAnnotatedText: firstChild &&
firstChild.nodeType === firstChild.TEXT_NODE &&
this._isCompoundAnnotatedText(firstChild.textContent),
hasTextChild: templateNonCommentChildNodes.length === 0 &&
firstChild &&
firstChild.nodeType === child.ELEMENT_NODE &&
firstChild.childElementCount === 0, // including <br>
hasCompoundAnnotatedChildNode: firstChild &&
firstChild.nodeType === firstChild.ELEMENT_NODE &&
firstChild.childElementCount === 0 &&
this._isCompoundAnnotatedText(firstChild.textContent),
hasGrandChildren: templateNonCommentChildNodes.length > 0 ||
(firstChild &&
firstChild.nodeType === firstChild.ELEMENT_NODE &&
Array.prototype.map.call(
firstChild.childNodes,
function (grandChild) {
return grandChild.nodeType !== grandChild.TEXT_NODE;
}
).reduce(function (prev, current) {
return prev || current;
}, false)) ||
(firstChild &&
firstChild.nodeType === firstChild.TEXT_NODE &&
this._isCompoundAnnotatedText(firstChild.textContent))
};
}
else {
result = {
hasText: child.nodeType === child.TEXT_NODE &&
child.textContent.length > 0 &&
!child.textContent.match(/^\s*$/g),
hasCompoundAnnotatedText: child.nodeType === child.TEXT_NODE &&
this._isCompoundAnnotatedText(child.textContent),
hasTextChild: child.nodeType === child.ELEMENT_NODE &&
child.childElementCount === 0, // including <br>
hasCompoundAnnotatedChildNode: child.nodeType === child.ELEMENT_NODE &&
child.childElementCount === 0 &&
this._isCompoundAnnotatedText(child.textContent),
hasGrandChildren: child.nodeType === child.ELEMENT_NODE &&
Array.prototype.map.call(
child.childNodes,
function (grandChild) {
return grandChild.nodeType !== grandChild.TEXT_NODE;
}
).reduce(function (prev, current) {
return prev || current;
}, false)
};
}
return result;
}.bind(this)).reduce(function (prev, current) {
return {
hasText: prev.hasText || current.hasText,
hasCompoundAnnotatedText: prev.hasCompoundAnnotatedText || current.hasCompoundAnnotatedText,
hasTextChild: prev.hasTextChild || current.hasTextChild,
hasCompoundAnnotatedChildNode: prev.hasCompoundAnnotatedChildNode || current.hasCompoundAnnotatedChildNode,
hasGrandChildren: prev.hasGrandChildren || current.hasGrandChildren
};
}, {
hasText: false,
hasCompoundAnnotatedText: false,
hasTextChild: false,
hasCompoundAnnotatedChildNode: false,
hasGrandChildren: false
});
if ((childStatus.hasText || node.hasAttribute('text-id')) &&
(childStatus.hasTextChild || childStatus.hasCompoundAnnotatedText) &&
!childStatus.hasGrandChildren &&
!childStatus.hasCompoundAnnotatedChildNode) {
// apply i18n-format
/*
<i18n-format>
<span>{{text.simpleChartDesc.0}}</span>
<code param="1">{{text.simpleChartDesc.1}}</code>
<a param="2" href="link">{{text.simpleChartDesc.2}}</a>
<a param="3" href="link2">{{text.simpleChartDesc.3}}</a>
</i18n-format>
*/
n = 0;
messageId = this._generateMessageId(path, id);
templateTextParams = Array.prototype.map.call(
node.childNodes, function (child) {
var firstChild;
if (child.nodeType === child.TEXT_NODE &&
this._hasAnnotatedText(child.textContent)) {
return this._compoundAnnotationToSpan(child)
.map(function (_child) {
return {
node: _child,
templateNode: null,
type: _child.nodeType,
text: _child.nodeType === _child.TEXT_NODE ?
_child.textContent : null,
childTextNode: _child.nodeType === _child.ELEMENT_NODE &&
_child.childNodes.length > 0
};
});
}
else if (child.nodeType === child.ELEMENT_NODE &&
child.tagName === 'TEMPLATE') {
firstChild =
Array.prototype.filter.call(child.content.childNodes, function (templateChild) {
switch (templateChild.nodeType) {
case templateChild.COMMENT_NODE:
return false;
case templateChild.TEXT_NODE:
return !templateChild.textContent.match(/^\s*$/g);
default:
case templateChild.ELEMENT_NODE:
return true;
}
}).shift();
if (!firstChild) {
firstChild =
Array.prototype.filter.call(child.content.childNodes, function (templateChild) {
switch (templateChild.nodeType) {
case templateChild.COMMENT_NODE:
return false;
default:
return true;
}
}).shift();
}
if (firstChild) {
return [{
node: firstChild,
templateNode: child,
type: firstChild.nodeType,
text: null,
childTextNode: true
}];
}
else {
return [];
}
}
else {
return [{
node: child,
templateNode: null,
type: child.nodeType,
text: child.nodeType === child.TEXT_NODE ?
child.textContent : null,
childTextNode: child.nodeType === child.ELEMENT_NODE &&
child.childNodes.length > 0
}];
}
}.bind(this)).reduce(function (prev, currentList) {
var current;
var textContent;
for (var i = 0; i < currentList.length; i++) {
current = currentList[i];
if (current.text) {
prev.text[0] += current.text;
}
if (current.type === current.node.ELEMENT_NODE) {
n++;
prev.text[0] += '{' + n + '}';
path.push(n);
this._traverseAttributes(current.node, path, bundle);
path.pop();
if (current.childTextNode) {
textContent = current.node.textContent;
if (textContent.length === 0) {
// tag without textContent
prev.text.push('<' + current.node.nodeName.toLowerCase() + '>');
current.node.textContent = '';
}
else if (textContent.match(/^\s*$/g)) {
// tag with whitespace textContent
prev.text.push('<' + current.node.nodeName.toLowerCase() + '>');
current.node.textContent = ' ';
}
else if (textContent.match(/^[\s]*({{.*}}|\[\[.*\]\])[\s]*$/)) {
// tag with annotation
prev.text.push(textContent);
// textContent is untouched
}
else {
prev.text.push(current.node.textContent.replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' '));
current.node.textContent = '{{text.' + messageId + '.' + n + '}}';
}
}
else {
prev.text.push('<' + current.node.nodeName.toLowerCase() + '>');
}
current.node.setAttribute('param', n.toString());
prev.params.push(current.templateNode || current.node);
}
else if (current.type === current.node.TEXT_NODE &&
current.childTextNode) {
// in template node
n++;
prev.text[0] += '{' + n + '}';
textContent = current.node.textContent;
if (textContent.length === 0) {
// template without textContent
prev.text.push('<template>');
current.node.textContent = '';
}
else if (textContent.match(/^\s*$/g)) {
// template with whitespace textContent
prev.text.push('<template>');
current.node.textContent = ' ';
}
else if (textContent.match(/^[\s]*({{.*}}|\[\[.*\]\])[\s]*$/)) {
// tag with annotation
prev.text.push(textContent);
// textContent is untouched
}
else {
prev.text.push(textContent.replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' '));
current.node.textContent = '{{text.' + messageId + '.' + n + '}}';
}
span = document.createElement('span');
span.setAttribute('param', n.toString());
current.templateNode.content.removeChild(current.node);
span.appendChild(current.node);
current.templateNode.content.appendChild(span);
prev.params.push(current.templateNode);
}
}
return prev;
}.bind(this), { text: [ '' ], params: [ '{{text.' + messageId + '.0}}' ] });
templateText = document.createElement('i18n-format');
templateText.setAttribute('lang', '{{effectiveLang}}');
span = document.createElement('span');
// span.innerText does not set an effective value in Firefox
span.textContent = templateTextParams.params.shift();
templateText.appendChild(span);
Array.prototype.forEach.call(templateTextParams.params,
function (param) {
templateText.appendChild(param);
}
);
// store the text message
templateTextParams.text[0] = templateTextParams.text[0].replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' ');
this._setBundleValue(bundle, messageId, templateTextParams.text);
// insert i18n-format
node.innerHTML = '';
dom(node).appendChild(templateText);
if (!id) {
//node.id = messageId;
//console.warn('add missing node id as ' + messageId + ' for ' + templateTextParams.text[0]);
}
debuglog(messageId + ' = ' + templateTextParams.text);
}
else {
// traverse childNodes
for (i = 0; i < node.childNodes.length; i++) {
//console.log(path.join(':') + ':' + node.childNodes[i].nodeName + ':' + (i - whiteSpaceElements) + ' i = ' + i + ' whiteSpaceElements = ' + whiteSpaceElements);
if (this._traverseTemplateTree(node.childNodes[i], path, bundle, i - whiteSpaceElements)) {
whiteSpaceElements++;
}
}
}
}
break;
}
break;
case node.TEXT_NODE:
// text node
text = node.textContent;
if (text.length === 0 || text.match(/^\s*$/g)) {
// skip empty or whitespace node
isWhiteSpace = true;
}
else if (text.trim().match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/)) {
// skip annotation node
}
else {
var parent = node.parentNode;
if (this._isCompoundAnnotatedText(text)) {
// apply i18n-format
n = 0;
messageId = this._generateMessageId(path, id);
templateTextParams = Array.prototype.map.call(
[ node ], function (child) {
return this._compoundAnnotationToSpan(child)
.map(function (_child) {
return {
node: _child,
type: _child.nodeType,
text: _child.nodeType === _child.TEXT_NODE ?
_child.textContent : null,
childTextNode: _child.nodeType === _child.ELEMENT_NODE &&
_child.childNodes.length > 0
};
});
}.bind(this)).reduce(function (prev, currentList) {
var current;
for (var i = 0; i < currentList.length; i++) {
current = currentList[i];
if (current.text) {
prev.text[0] += current.text;
}
if (current.type === current.node.ELEMENT_NODE) {
n++;
prev.text[0] += '{' + n + '}';
path.push(n);
this._traverseAttributes(current.node, path, bundle);
path.pop();
/* current.childTextNode is always true since current.node is <span>{{annotation}}</span> */
prev.text.push(current.node.textContent);
current.node.setAttribute('param', n.toString());
prev.params.push(current.node);
}
}
return prev;
}.bind(this), { text: [ '' ], params: [ '{{text.' + messageId + '.0}}' ] });
templateText = document.createElement('i18n-format');
templateText.setAttribute('lang', '{{effectiveLang}}');
span = document.createElement('span');
// span.innerText does not set an effective value in Firefox
span.textContent = templateTextParams.params.shift();
templateText.appendChild(span);
Array.prototype.forEach.call(templateTextParams.params,
function (param) {
templateText.appendChild(param);
}
);
// store the text message
templateTextParams.text[0] = templateTextParams.text[0].replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' ');
this._setBundleValue(bundle, messageId, templateTextParams.text);
// insert i18n-format
dom(parent).insertBefore(templateText, node);
dom(parent).removeChild(node);
debuglog(messageId + ' = ' + templateTextParams.text);
}
else {
// generate message id
messageId = this._generateMessageId(path, id);
// store the text message
text = text.replace(/^[\s]*[\s]/, ' ').replace(/[\s][\s]*$/, ' ');
this._setBundleValue(bundle, messageId, text);
// replace textContent with annotation
node.textContent = '{{text.' + messageId + '}}';
if (!id) {
//span.id = messageId;
//console.warn('add missing span with id as ' + messageId + ' for ' + text);
}
debuglog(messageId + ' = ' + text);
}
}
break;
case node.DOCUMENT_NODE:
case node.DOCUMENT_FRAGMENT_NODE:
// traverse childNodes
for (i = 0; i < node.childNodes.length; i++) {
//console.log(path.join(':') + ':' + node.childNodes[i].nodeName + ':' + (i - whiteSpaceElements) + ' i = ' + i + ' whiteSpaceElements = ' + whiteSpaceElements);
if (this._traverseTemplateTree(node.childNodes[i], path, bundle, i - whiteSpaceElements)) {
whiteSpaceElements++;
}
}
break;
default:
isWhiteSpace = true;
// comment node, etc.
break;
}
path.pop();
return isWhiteSpace;
},
/**
* Check if the text has compound annotation
*
* @param {string} text target text to check compound annotation
* @return {Boolean} true if the text contains compound annotation
*/
_isCompoundAnnotatedText: function (text) {
return !text.trim().match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/) &&
!!text.match(/({{[^{}]*}}|\[\[[^\[\]]*\]\])/);
},
/**
* Check if the text has annotation
*
* @param {string} text target text to check annotation
* @return {Boolean} true if the text contains annotation
*/
_hasAnnotatedText: function (text) {
return !!text.match(/({{[^{}]*}}|\[\[[^\[\]]*\]\])/);
},
/**
* Convert compound annotations to span elements
*
* @param {Text} node target text node to convert compound annotations
* @return {Object[]} Array of Text or span elements
*/
_compoundAnnotationToSpan: function (node) {
var result;
/* istanbul ignore else: node is prechecked to contain annotation(s) */
if (node.textContent.match(/({{[^{}]*}}|\[\[[^\[\]]*\]\])/)) {
result = node.textContent
.match(/({{[^{}]*}}|\[\[[^\[\]]*\]\]|[^{}\[\]]{1,}|[{}\[\]]{1,})/g)
.reduce(function (prev, current) {
if (current.match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/)) {
prev.push(current);
prev.push('');
}
else {
if (prev.length === 0) {
prev.push(current);
}
else {
prev[prev.length - 1] += current;
}
}
return prev;
}.bind(this), [])
.map(function (item) {
var childNode;
if (item.match(/^({{[^{}]*}}|\[\[[^\[\]]*\]\])$/)) {
childNode = document.createElement('span');
childNode.textContent = item;
}
else if (item) {
childNode = document.createTextNode(item);
}
else {
childNode = null;
}
return childNode;
});
if (result.length > 0) {
if (!result[result.length - 1]) {
result.pop(); // pop null node for ''
}
}
}
else {
// no compound annotation
result = [ node ];
}
return result;
},
/**
* Add the value to the target default bundle with the specified message Id
*
* @param {Object} bundle Default bundle.
* @param {string} messageId ID string of the value.
* @param {Object} value Value of the text message. Normally a string.
*/
_setBundleValue: function (bundle, messageId, value) {
var messageIdPath = messageId.split('.');
bundle.model = bundle.model || {};
if (messageIdPath.length === 1) {
bundle[messageId] = value;
}
else {
var cursor = bundle;
for (var i = 0; i < messageIdPath.length; i++) {
if (i < messageIdPath.length - 1) {
cursor[messageIdPath[i]] = cursor[messageIdPath[i]] || {};
cursor = cursor[messageIdPath[i]];
}
else {
cursor[messageIdPath[i]] = value;
}
}
}
},
/**
* Generate a message ID from the specified path and id.
*
* ### TODO:
*
* - Shorten or optimize ids
*
* @param {Array} path List of ascestor elements of the current node in traversal.
* @param {id} id Value of `id` or `text-id` attribute of the current node.
*/
_generateMessageId: function (path, id) {
var messageId;
if (!id || id.length === 0) {
for (var i = 1; i < path.length; i++) {
if (path[i][0] === '#') {
if (path[i] !== '#document-fragment') {
if (messageId && path[i].substr(0, 5) === '#text') {
messageId += ':' + path[i].substr(1);
}
else {
messageId = path[i].substr(1);
}
}
}
else {
if (messageId) {
messageId += ':' + path[i];
}
else {
messageId = path[i];
}
}
}
}
else {
messageId = id;
}
return messageId;
},
/**
* Merge `this.defaultText` into the target default bundle.
*
* ### TODO:
*
* - Need more research on the effective usage of this feature.
*
* @param {Object} bundle Default bundle.
*/
/*
_mergeDefaultText: function (bundle) {
if (this.defaultText) {
this._deepMap(bundle, this.defaultText, function (text) { return text; });
}
},
*/
/**
* Return the first non-null argument.
*
* Utility method for use in annotations.
*
* ### Example Usage:
* ```
* <input is="iron-input" class="flex"
* type="search" id="query" bind-value="{{query}}"
* autocomplete="off"
* placeholder="{{or(placeholder,text.search)}}">
* ```
*
* @param {*} arguments List of arguments.
*/
or: function () {
var result = arguments[0];
var i = 1;
while (!result && i < arguments.length) {
result = arguments[i++];
}
return result;
},
/**
* Translate a string by a message table.
*
* Utility method for use in annotations.
*
* ### Example Usage:
* ```
* <span>{{tr(status,text.statusMsgs)}}</span>
* <span>{{tr(errorId,text)}}</span>
* <template>
* <json-data text-id="statusMsgs">{
* "signed-in": "Authenticated",
* "signed-out": "Not Authenticated",
* "error": "Error in Authentication",
* "default": "Unknown Status in Authentication"
* }</json-data>
* <span text-id="http-404">File Not Found</span>
* <span text-id="http-301">Moved Permanently</span>
* </template>
* ```
*
* Note: The second `table` parameter should always be specified in order
* to trigger automatic updates on `this.text` mutations, i.e., updates of `this.effectiveLang`.
*
* @param {string} key Key of the message.
* @param {Object} table The message table object or this.text itself if omitted
* @return {string} Translated string, `table.default` if `table[key]` is undefined, or key string if table.default is undefined.
*/
tr: function (key, table) {
if (table) {
if (typeof table === 'object') {
if (typeof table[key] !== 'undefined') {
return table[key];
}
else if (typeof table['default'] !== 'undefined') {
return table['default'];
}
else {
return key;
}
}
else {
return key;
}
}
else {
return (typeof this.text === 'object') &&
(typeof key !== 'undefined') &&
(typeof this.text[key] !== 'undefined') ? this.text[key] : key;
}
},
/**
* Format a parameterized string.
*
* Utility method for use in annotations.
*
* ### Example Usage:
* ```
* <span attr="{{i18nFormat(text.param.0,text.textparam1,text.textparam2)}}"></span>
* <template>
* <json-data text-id="param">[
* "String with {1} and {2} are formetted",
* "[[text.textparam1]]",
* "[[text.textparam2]]"
* ]</json-data>
* <span text-id="textparam1">Parameter 1</span>
* <span text-id="textparam2">Parameter 2</span>
* </template>
* ```
*
* Note: Compound bindings in attributes are automatically converted to {{i18nFormat()}} in preprocessing.
*
* @param {*} arguments List of arguments.
* @return {string} Formatted string
*/
i18nFormat: function () {
if (arguments.length > 0) {
var formatted = arguments[0];
for (var n = 1; n < arguments.length; n++) {
formatted = formatted.replace('{' + n + '}', arguments[n]);
}
}
return formatted;
},
// Lifecycle callbacks
/**
* Lifecycle callback before registration of the custom element.
*
* The default bundle is constructed via traversal of the element's template at this timing per registration.
*
* ### Notes:
*
* - For `i18n-dom-bind` elements, bundle construction is put off until `ready` lifecycle callback.
* - As called twice per custom element registration, the method skips bundle construction at the second call.
*/
beforeRegister: function () {
if (this.is !== 'i18n-dom-bind') {
if (!this._templateLocalizable) {
this._templateLocalizable = this._constructDefaultBundle();
}
}
},
/**
* Lifecycle callback at registration of the custom element.
*
* this._fetchStatus is initialized per registration.
*/
registered: function () {
if (this.is !== 'i18n-dom-bind') {
this._fetchStatus = deepcopy({ // per custom element
fetchingInstance: null,
ajax: null,
ajaxLang: null,
lastLang: null,
fallbackLanguageList: null,
targetLang: null,
lastResponse: {},
rawResponses: {}
});
}
},
/**
* Lifecycle callback on instance creation
*/
created: function () {
// Fix #34. [Polymer 1.4.0] _propertyEffects have to be maintained per instance
if (this.is === 'i18n-dom-bind') {
this._propertyEffects = deepcopy(this._propertyEffects);
}
if (!isStandardPropertyConfigurable) {
// Fix #36. Emulate lang's observer since Safari 7 predefines non-configurable lang property
this.observer = new MutationObserver(this._handleLangAttributeChange.bind(this));
this.observer.observe(this, {
attributes: true,
attributeFilter: [ 'lang' ],
attributeOldValue: true
});
}
},
/**
* Lifecycle callback when the template children are ready.
*/
ready: function () {
if (this.is === 'i18n-dom-bind') {
if (!this._templateLocalizable) {
this._templateLocalizable = this._constructDefaultBundle();
}
if (!this._fetchStatus) {
this._fetchStatus = deepcopy({ // per instance
fetchingInstance: null,
ajax: null,
ajaxLang: null,
lastLang: null,
fallbackLanguageList: null,
targetLang: null,
lastResponse: {},
rawResponses: {}
});
}
this._onDomChangeBindThis = this._onDomChange.bind(this);
this.addEventListener('dom-change', this._onDomChangeBindThis);
// Fix #34. [Polymer 1.4.0] Supply an empty object if this.__data__ is undefined
this.__data__ = this.__data__ || Object.create(null);
}
else {
if (!isStandardPropertyConfigurable) {
// Fix #36. Patch missing properties except for lang
for (var p in this._propertyEffects) {
if (this._propertyEffects[p] &&
!Object.getOwnPropertyDescriptor(this, p)) {
//console.log('ready: creating accessors for ' + p);
Polymer.Bind._createAccessors(this, p, this._propertyEffects[p]);
}
}
}
this._langChanged(this.getAttribute('lang'), undefined);
// model per instance
this.model = deepcopy(this.text.model);
}
},
/**
* attached lifecycle callback.
*/
attached: function () {
if (this.is === 'i18n-dom-bind') {
if (this._properties) {
// Fix #35. [IE10] Restore properties for use in rendering
this.properties = this._properties;
delete this._properties;
}
}
if (this.observeHtmlLang) {
this.lang = html.lang;
// TODO: this call is redundant
this._observeHtmlLangChanged(true);
}
},
/**
* Handle `dom-change` event for `i18n-dom-bind`
*/
_onDomChange: function () {
// Fix #16: [IE11][Polymer 1.3.0] On IE11, i18n-dom-bind does not work with Polymer 1.3.0
// Patch the broken lang property accessors manually if it is missing
// Fix #34: [IE11][Polymer 1.4.0] Create missing property accessors including lang
for (var p in this._propertyEffects) {
if (this._propertyEffects[p] &&
!Object.getOwnPropertyDescriptor(this, p)) {
Polymer.Bind._createAccessors(this, p, this._propertyEffects[p]);
}
}
this.removeEventListener('dom-change', this._onDomChangeBindThis);
if (this.text && this.text.model) {
this.model = deepcopy(this.text.model);
}
// Fix #17: [Polymer 1.3.0] observeHtmlLang is undefined in i18n-dom-bind
// Explicitly initialize observeHtmlLang if the value is undefined.
if (typeof this.observeHtmlLang === 'undefined' &&
!this.hasAttribute('observe-html-lang')) {
this.observeHtmlLang = true;
}
if (this.observeHtmlLang) {
this.lang = html.lang;
this._observeHtmlLangChanged(true);
}
},
/**
* detached lifecycle callback
*/
detached: function () {
if (this.observeHtmlLang) {
this._observeHtmlLangChanged(false);
}
}
};
// Fix #36. Rename lang property as _lang to avoid conflict with the predefined lang property
if (!isStandardPropertyConfigurable) {
var _properties = Object.create(null);
for (var p in BehaviorsStore.I18nBehavior.properties) {
if (p === 'lang') {
_properties._lang = BehaviorsStore.I18nBehavior.properties.lang;
}
else {
_properties[p] = BehaviorsStore.I18nBehavior.properties[p];
}
}
BehaviorsStore.I18nBehavior.properties = _properties;
BehaviorsStore.I18nBehavior.properties._lang.reflectToAttribute = false;
BehaviorsStore.I18nBehavior.properties.text.computed = '_getBundle(_lang)';
BehaviorsStore.I18nBehavior._updateEffectiveLang = function () {
//console.log('lang-updated: _updateEffectiveLang: assigning effectiveLang = ' + this._lang);
this.effectiveLang = this._lang;
};
BehaviorsStore.I18nBehavior.hostAttributes = {
'lang': defaultLang
};
}
/**
* `<template is="i18n-dom-bind">` element extends `dom-bind` template element with `I18nBehavior`
*
* @group I18nBehavior
* @element i18n-dom-bind
*/
var i18nBehaviorDomBind = {};
Base.extend(i18nBehaviorDomBind, BehaviorsStore.I18nBehavior);
var i18nDomBind = {};
var domBind = document.createElement('template', 'dom-bind');
var domBindProto = Object.getPrototypeOf(domBind);
if (typeof domBindProto.render !== 'function') {
domBindProto = domBind.__proto__; // fallback for IE10
}
Base.extend(i18nDomBind, domBindProto);
i18nDomBind.is = 'i18n-dom-bind';
if (!navigator.language && navigator.browserLanguage) { // Detect IE10
// Fix #35. [IE10] Hide properties until attached phase in IE10
// to avoid exceptions in overriding unconfigurable properties in Object.defineProperty
i18nBehaviorDomBind._properties = i18nBehaviorDomBind.properties;
i18nBehaviorDomBind.properties = Object.create(null);
}
/* As of Polymer 1.3.1, dom-bind does not have predefined behaviors */
/* istanbul ignore if */
if (i18nDomBind.behaviors) {
i18nDomBind.behaviors.push(i18nBehaviorDomBind);
}
else {
i18nDomBind.behaviors = [ i18nBehaviorDomBind ];
}
var _Polymer = Polymer$0;
_Polymer(i18nDomBind);
})(document);
</script>
<dom-module id="preference-element" assetpath="preference/">
<template localizable-text="embedded">
<span id="oldLang"></span>
<template id="localizable-text">
<json-data>
{
"meta": {},
"model": {}
}
</json-data>
</template>
</template>
<script type="module">
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
Polymer({
is: 'preference-element',
behaviors: [
BehaviorsStore.I18nBehavior
],
listeners: {
'lang-updated': '_langUpdated'
},
_langUpdated: function (e) {
if (dom(e).rootTarget === this) {
console.log(e.detail);
console.log('navigator.language = ' + navigator.language);
if (e.detail.lastLang === 'en') {
this.$.oldLang.lang = e.detail.oldLang;
this.fire('local-dom-ready');
}
}
}
});
</script>
</dom-module>
</div>
<h2 id="test-name"></h2>
<test-fixture class="test-container" id="preference-element-fixture">
<template>
<preference-element></preference-element>
</template>
</test-fixture>
<i18n-preference persist=""></i18n-preference>
<script>
suite('I18nBehavior with ' +
(window.location.href.indexOf('?dom=Shadow') >= 0 ? 'Shadow DOM' : 'Shady DOM'),
function () {
var lang0 = '';
var lang1 = 'en';
var lang2 = 'fr';
var lang3 = 'ja';
var lang4 = 'fr-CA';
var lang5 = 'zh-Hans-CN';
var lang6 = 'ru';
var lang7 = 'zh-yue-Hans-CN';
var lang8 = 'zh-CN';
var lang9 = 'zh-TW';
var lang10 = 'zh-Hans-CN-x-Linux';
var navigatorLanguage = navigator.language || navigator.browserLanguage;
var isNavigatorLanguageEn = navigatorLanguage.match(/^en/);
var suites = [
s('preference', null, {
fixture: 'preference-element-fixture',
fixtureModel: undefined,
assign: undefined,
lang: isNavigatorLanguageEn ? lang1 : lang0,
effectiveLang: isNavigatorLanguageEn ? lang1 : lang0,
templateDefaultLang: lang1,
observeHtmlLang: true,
event: 'local-dom-ready',
text: { model: {} },
model: {},
localDOM: [
{ select: 'span#oldLang', 'lang.raw': navigatorLanguage }
],
lightDOM: undefined
})
];
suitesRunner(suites);
});
</script>
</body></html>