| // 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.a11y.aria'); |
| goog.require('goog.asserts'); |
| goog.require('goog.dom.NodeType'); |
| goog.require('goog.dom.classlist'); |
| goog.require('goog.style'); |
| goog.require('goog.ui.PaletteRenderer'); |
| goog.require('goog.ui.emoji.Emoji'); |
| |
| |
| |
| /** |
| * 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); |
| goog.asserts.assert(inner); |
| // The first case is a palette item with a CSS class representing the sprite, |
| // and an animated emoji. |
| var classes = goog.dom.classlist.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.a11y.aria.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; |
| }; |