1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * NOTE: The use of this file is deprecated. Use i18n_template2.js instead.
7 *
8 * @fileoverview This is a simple template engine inspired by JsTemplates
9 * optimized for i18n.
10 *
11 * It currently supports two handlers:
12 *
13 *   * i18n-content which sets the textContent of the element
14 *
15 *     <span i18n-content="myContent"></span>
16 *     i18nTemplate.process(element, {'myContent': 'Content'});
17 *
18 *   * i18n-values is a list of attribute-value or property-value pairs.
19 *     Properties are prefixed with a '.' and can contain nested properties.
20 *
21 *     <span i18n-values="title:myTitle;.style.fontSize:fontSize"></span>
22 *     i18nTemplate.process(element, {
23 *       'myTitle': 'Title',
24 *       'fontSize': '13px'
25 *     });
26 */
27
28/**
29 * @typedef {function(!Element, string, Object)}
30 * TODO(dbeam): move inside (function() {...})() after
31 * https://github.com/google/closure-compiler/issues/544 is fixed.
32 */
33var Handler;
34
35var i18nTemplate = (function() {
36  /**
37   * This provides the handlers for the templating engine. The key is used as
38   * the attribute name and the value is the function that gets called for every
39   * single node that has this attribute.
40   * @type {Object.<Handler>}
41   */
42  var handlers = {
43    /**
44     * This handler sets the textContent of the element.
45     */
46    'i18n-content': function(element, attributeValue, obj) {
47      element.textContent = obj[attributeValue];
48    },
49
50    /**
51     * This handler adds options to a select element.
52     */
53    'i18n-options': function(element, attributeValue, obj) {
54      var options = obj[attributeValue];
55      options.forEach(function(values) {
56        var option = typeof values == 'string' ? new Option(values) :
57            new Option(values[1], values[0]);
58        element.appendChild(option);
59      });
60    },
61
62    /**
63     * This is used to set HTML attributes and DOM properties,. The syntax is:
64     *   attributename:key;
65     *   .domProperty:key;
66     *   .nested.dom.property:key
67     */
68    'i18n-values': function(element, attributeValue, obj) {
69      var parts = attributeValue.replace(/\s/g, '').split(/;/);
70      for (var j = 0; j < parts.length; j++) {
71        var a = parts[j].match(/^([^:]+):(.+)$/);
72        if (a) {
73          var propName = a[1];
74          var propExpr = a[2];
75
76          // Ignore missing properties
77          if (propExpr in obj) {
78            var value = obj[propExpr];
79            if (propName.charAt(0) == '.') {
80              var path = propName.slice(1).split('.');
81              var object = element;
82              while (object && path.length > 1) {
83                object = object[path.shift()];
84              }
85              if (object) {
86                object[path] = value;
87                // In case we set innerHTML (ignoring others) we need to
88                // recursively check the content
89                if (path == 'innerHTML')
90                  process(element, obj);
91              }
92            } else {
93              element.setAttribute(propName, value);
94            }
95          } else {
96            console.warn('i18n-values: Missing value for "' + propExpr + '"');
97          }
98        }
99      }
100    }
101  };
102
103  var attributeNames = [];
104  for (var key in handlers) {
105    attributeNames.push(key);
106  }
107  var selector = '[' + attributeNames.join('],[') + ']';
108
109  /**
110   * Processes a DOM tree with the {@code obj} map.
111   * @param {Node} node A node to process.
112   * @param {Object} obj Values to process |node| with.
113   */
114  function process(node, obj) {
115    var elements = node.querySelectorAll(selector);
116    for (var element, i = 0; element = elements[i]; i++) {
117      for (var j = 0; j < attributeNames.length; j++) {
118        var name = attributeNames[j];
119        var att = element.getAttribute(name);
120        if (att != null)
121          handlers[name](element, att, obj);
122      }
123    }
124  }
125
126  return {
127    process: process
128  };
129})();
130