aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/ui/emoji/emojipaletterenderer.js
blob: e79db27581c578ea3643880177d2971ba1547d1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Emoji Palette renderer implementation.
 *
 */

goog.provide('goog.ui.emoji.EmojiPaletteRenderer');

goog.require('goog.dom');
goog.require('goog.dom.a11y');
goog.require('goog.ui.PaletteRenderer');
goog.require('goog.ui.emoji.Emoji');
goog.require('goog.ui.emoji.SpriteInfo');



/**
 * Renders an emoji palette.
 *
 * @param {?string} defaultImgUrl Url of the img that should be used to fill up
 *     the cells in the emoji table, to prevent jittering. Will be stretched
 *     to the emoji cell size. A good image is a transparent dot.
 * @constructor
 * @extends {goog.ui.PaletteRenderer}
 */
goog.ui.emoji.EmojiPaletteRenderer = function(defaultImgUrl) {
  goog.ui.PaletteRenderer.call(this);

  this.defaultImgUrl_ = defaultImgUrl;
};
goog.inherits(goog.ui.emoji.EmojiPaletteRenderer, goog.ui.PaletteRenderer);


/**
 * Globally unique ID sequence for cells rendered by this renderer class.
 * @type {number}
 * @private
 */
goog.ui.emoji.EmojiPaletteRenderer.cellId_ = 0;


/**
 * Url of the img that should be used for cells in the emoji palette that are
 * not filled with emoji, i.e., after all the emoji have already been placed
 * on a page.
 *
 * @type {?string}
 * @private
 */
goog.ui.emoji.EmojiPaletteRenderer.prototype.defaultImgUrl_ = null;


/** @override */
goog.ui.emoji.EmojiPaletteRenderer.getCssClass = function() {
  return goog.getCssName('goog-ui-emojipalette');
};


/**
 * Creates a palette item from the given emoji data.
 *
 * @param {goog.dom.DomHelper} dom DOM helper for constructing DOM elements.
 * @param {string} id Goomoji id for the emoji.
 * @param {goog.ui.emoji.SpriteInfo} spriteInfo Spriting info for the emoji.
 * @param {string} displayUrl URL of the image served for this cell, whether
 *     an individual emoji image or a sprite.
 * @return {HTMLDivElement} The palette item for this emoji.
 */
goog.ui.emoji.EmojiPaletteRenderer.prototype.createPaletteItem =
    function(dom, id, spriteInfo, displayUrl) {
  var el;

  if (spriteInfo) {
    var cssClass = spriteInfo.getCssClass();
    if (cssClass) {
      el = dom.createDom('div', cssClass);
    } else {
      el = this.buildElementFromSpriteMetadata(dom, spriteInfo, displayUrl);
    }
  } else {
    el = dom.createDom('img', {'src': displayUrl});
  }

  var outerdiv =
      dom.createDom('div', goog.getCssName('goog-palette-cell-wrapper'), el);
  outerdiv.setAttribute(goog.ui.emoji.Emoji.ATTRIBUTE, id);
  return /** @type {HTMLDivElement} */ (outerdiv);
};


/**
 * Modifies a palette item containing an animated emoji, in response to the
 * animated emoji being successfully downloaded.
 *
 * @param {Element} item The palette item to update.
 * @param {Image} animatedImg An Image object containing the animated emoji.
 */
goog.ui.emoji.EmojiPaletteRenderer.prototype.updateAnimatedPaletteItem =
    function(item, animatedImg) {
  // An animated emoji is one that had sprite info for a static version and is
  // now being updated. See createPaletteItem for the structure of the palette
  // items we're modifying.

  var inner = (/** @type {Element} */ item.firstChild);

  // The first case is a palette item with a CSS class representing the sprite,
  // and an animated emoji.
  var classes = goog.dom.classes.get(inner);
  if (classes && classes.length == 1) {
    inner.className = '';
  }

  goog.style.setStyle(inner, {
    'width': animatedImg.width,
    'height': animatedImg.height,
    'background-image': 'url(' + animatedImg.src + ')',
    'background-position': '0 0'
  });
};


/**
 * Builds the inner contents of a palette item out of sprite metadata.
 *
 * @param {goog.dom.DomHelper} dom DOM helper for constructing DOM elements.
 * @param {goog.ui.emoji.SpriteInfo} spriteInfo The metadata to create the css
 *     for the sprite.
 * @param {string} displayUrl The URL of the image for this cell.
 * @return {HTMLDivElement} The inner element for a palette item.
 */
goog.ui.emoji.EmojiPaletteRenderer.prototype.buildElementFromSpriteMetadata =
    function(dom, spriteInfo, displayUrl) {
  var width = spriteInfo.getWidthCssValue();
  var height = spriteInfo.getHeightCssValue();
  var x = spriteInfo.getXOffsetCssValue();
  var y = spriteInfo.getYOffsetCssValue();

  var el = dom.createDom('div');
  goog.style.setStyle(el, {
    'width': width,
    'height': height,
    'background-image': 'url(' + displayUrl + ')',
    'background-repeat': 'no-repeat',
    'background-position': x + ' ' + y
  });

  return /** @type {HTMLDivElement} */ (el);
};


/** @override */
goog.ui.emoji.EmojiPaletteRenderer.prototype.createCell = function(node, dom) {
  // Create a cell with  the default img if we're out of items, in order to
  // prevent jitter in the table. If there's no default img url, just create an
  // empty div, to prevent trying to fetch a null url.
  if (!node) {
    var elem = this.defaultImgUrl_ ?
               dom.createDom('img', {'src': this.defaultImgUrl_}) :
               dom.createDom('div');
    node = dom.createDom('div', goog.getCssName('goog-palette-cell-wrapper'),
                         elem);
  }

  var cell = dom.createDom('td', {
    'class': goog.getCssName(this.getCssClass(), 'cell'),
    // Cells must have an ID, for accessibility, so we generate one here.
    'id': this.getCssClass() + '-cell-' +
        goog.ui.emoji.EmojiPaletteRenderer.cellId_++
  }, node);
  goog.dom.a11y.setRole(cell, 'gridcell');
  return cell;
};


/**
 * Returns the item corresponding to the given node, or null if the node is
 * neither a palette cell nor part of a palette item.
 * @param {goog.ui.Palette} palette Palette in which to look for the item.
 * @param {Node} node Node to look for.
 * @return {Node} The corresponding palette item (null if not found).
 * @override
 */
goog.ui.emoji.EmojiPaletteRenderer.prototype.getContainingItem =
    function(palette, node) {
  var root = palette.getElement();
  while (node && node.nodeType == goog.dom.NodeType.ELEMENT && node != root) {
    if (node.tagName == 'TD') {
      return node.firstChild;
    }
    node = node.parentNode;
  }

  return null;
};