123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- // 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 Generic factory functions for creating the building blocks for
- * an editor toolbar.
- *
- * @author attila@google.com (Attila Bodis)
- */
- goog.provide('goog.ui.editor.ToolbarFactory');
- goog.require('goog.array');
- goog.require('goog.dom');
- goog.require('goog.dom.TagName');
- goog.require('goog.string');
- goog.require('goog.string.Unicode');
- goog.require('goog.style');
- goog.require('goog.ui.Component');
- goog.require('goog.ui.Container');
- goog.require('goog.ui.Option');
- goog.require('goog.ui.Toolbar');
- goog.require('goog.ui.ToolbarButton');
- goog.require('goog.ui.ToolbarColorMenuButton');
- goog.require('goog.ui.ToolbarMenuButton');
- goog.require('goog.ui.ToolbarRenderer');
- goog.require('goog.ui.ToolbarSelect');
- goog.require('goog.userAgent');
- /**
- * Takes a font spec (e.g. "Arial, Helvetica, sans-serif") and returns the
- * primary font name, normalized to lowercase (e.g. "arial").
- * @param {string} fontSpec Font specification.
- * @return {string} The primary font name, in lowercase.
- */
- goog.ui.editor.ToolbarFactory.getPrimaryFont = function(fontSpec) {
- var i = fontSpec.indexOf(',');
- var fontName = (i != -1 ? fontSpec.substring(0, i) : fontSpec).toLowerCase();
- // Strip leading/trailing quotes from the font name (bug 1050118).
- return goog.string.stripQuotes(fontName, '"\'');
- };
- /**
- * Bulk-adds fonts to the given font menu button. The argument must be an
- * array of font descriptor objects, each of which must have the following
- * attributes:
- * <ul>
- * <li>{@code caption} - Caption to show in the font menu (e.g. 'Tahoma')
- * <li>{@code value} - Value for the corresponding 'font-family' CSS style
- * (e.g. 'Tahoma, Arial, sans-serif')
- * </ul>
- * @param {!goog.ui.Select} button Font menu button.
- * @param {!Array<{caption: string, value: string}>} fonts Array of
- * font descriptors.
- */
- goog.ui.editor.ToolbarFactory.addFonts = function(button, fonts) {
- goog.array.forEach(fonts, function(font) {
- goog.ui.editor.ToolbarFactory.addFont(button, font.caption, font.value);
- });
- };
- /**
- * Adds a menu item to the given font menu button. The first font listed in
- * the {@code value} argument is considered the font ID, so adding two items
- * whose CSS style starts with the same font may lead to unpredictable results.
- * @param {!goog.ui.Select} button Font menu button.
- * @param {string} caption Caption to show for the font menu.
- * @param {string} value Value for the corresponding 'font-family' CSS style.
- */
- goog.ui.editor.ToolbarFactory.addFont = function(button, caption, value) {
- // The font ID is the first font listed in the CSS style, normalized to
- // lowercase.
- var id = goog.ui.editor.ToolbarFactory.getPrimaryFont(value);
- // Construct the option, and add it to the button.
- var option = new goog.ui.Option(caption, value, button.getDomHelper());
- option.setId(id);
- button.addItem(option);
- // Captions are shown in their own font.
- option.getContentElement().style.fontFamily = value;
- };
- /**
- * Bulk-adds font sizes to the given font size menu button. The argument must
- * be an array of font size descriptor objects, each of which must have the
- * following attributes:
- * <ul>
- * <li>{@code caption} - Caption to show in the font size menu (e.g. 'Huge')
- * <li>{@code value} - Value for the corresponding HTML font size (e.g. 6)
- * </ul>
- * @param {!goog.ui.Select} button Font size menu button.
- * @param {!Array<{caption: string, value:number}>} sizes Array of font
- * size descriptors.
- */
- goog.ui.editor.ToolbarFactory.addFontSizes = function(button, sizes) {
- goog.array.forEach(sizes, function(size) {
- goog.ui.editor.ToolbarFactory.addFontSize(button, size.caption, size.value);
- });
- };
- /**
- * Adds a menu item to the given font size menu button. The {@code value}
- * argument must be a legacy HTML font size in the 0-7 range.
- * @param {!goog.ui.Select} button Font size menu button.
- * @param {string} caption Caption to show in the font size menu.
- * @param {number} value Value for the corresponding HTML font size.
- */
- goog.ui.editor.ToolbarFactory.addFontSize = function(button, caption, value) {
- // Construct the option, and add it to the button.
- var option = new goog.ui.Option(caption, value, button.getDomHelper());
- button.addItem(option);
- // Adjust the font size of the menu item and the height of the checkbox
- // element after they've been rendered by addItem(). Captions are shown in
- // the corresponding font size, and lining up the checkbox is tricky.
- var content = option.getContentElement();
- content.style.fontSize =
- goog.ui.editor.ToolbarFactory.getPxFromLegacySize(value) + 'px';
- content.firstChild.style.height = '1.1em';
- };
- /**
- * Converts a legacy font size specification into an equivalent pixel size.
- * For example, {@code <font size="6">} is {@code font-size: 32px;}, etc.
- * @param {number} fontSize Legacy font size spec in the 0-7 range.
- * @return {number} Equivalent pixel size.
- */
- goog.ui.editor.ToolbarFactory.getPxFromLegacySize = function(fontSize) {
- return goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_[fontSize] || 10;
- };
- /**
- * Converts a pixel font size specification into an equivalent legacy size.
- * For example, {@code font-size: 32px;} is {@code <font size="6">}, etc.
- * If the given pixel size doesn't exactly match one of the legacy sizes, -1 is
- * returned.
- * @param {number} px Pixel font size.
- * @return {number} Equivalent legacy size spec in the 0-7 range, or -1 if none
- * exists.
- */
- goog.ui.editor.ToolbarFactory.getLegacySizeFromPx = function(px) {
- // Use lastIndexOf to get the largest legacy size matching the pixel size
- // (most notably returning 1 instead of 0 for 10px).
- return goog.array.lastIndexOf(
- goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_, px);
- };
- /**
- * Map of legacy font sizes (0-7) to equivalent pixel sizes.
- * @type {!Array<number>}
- * @private
- */
- goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_ =
- [10, 10, 13, 16, 18, 24, 32, 48];
- /**
- * Bulk-adds format options to the given "Format block" menu button. The
- * argument must be an array of format option descriptor objects, each of
- * which must have the following attributes:
- * <ul>
- * <li>{@code caption} - Caption to show in the menu (e.g. 'Minor heading')
- * <li>{@code command} - Corresponding {@link goog.dom.TagName} (e.g.
- * 'H4')
- * </ul>
- * @param {!goog.ui.Select} button "Format block" menu button.
- * @param {!Array<{caption: string, command: !goog.dom.TagName}>} formats Array
- * of format option descriptors.
- */
- goog.ui.editor.ToolbarFactory.addFormatOptions = function(button, formats) {
- goog.array.forEach(formats, function(format) {
- goog.ui.editor.ToolbarFactory.addFormatOption(
- button, format.caption, format.command);
- });
- };
- /**
- * Adds a menu item to the given "Format block" menu button.
- * @param {!goog.ui.Select} button "Format block" menu button.
- * @param {string} caption Caption to show in the menu.
- * @param {!goog.dom.TagName} tag Corresponding block format tag.
- */
- goog.ui.editor.ToolbarFactory.addFormatOption = function(button, caption, tag) {
- // Construct the option, and add it to the button.
- // TODO(attila): Create boring but functional menu item for now...
- var buttonDom = button.getDomHelper();
- var option = new goog.ui.Option(
- buttonDom.createDom(goog.dom.TagName.DIV, null, caption), tag, buttonDom);
- option.setId(String(tag));
- button.addItem(option);
- };
- /**
- * Creates a {@link goog.ui.Toolbar} containing the specified set of
- * toolbar buttons, and renders it into the given parent element. Each
- * item in the {@code items} array must a {@link goog.ui.Control}.
- * @param {!Array<goog.ui.Control>} items Toolbar items; each must
- * be a {@link goog.ui.Control}.
- * @param {!Element} elem Toolbar parent element.
- * @param {boolean=} opt_isRightToLeft Whether the editor chrome is
- * right-to-left; defaults to the directionality of the toolbar parent
- * element.
- * @return {!goog.ui.Toolbar} Editor toolbar, rendered into the given parent
- * element.
- */
- goog.ui.editor.ToolbarFactory.makeToolbar = function(
- items, elem, opt_isRightToLeft) {
- var domHelper = goog.dom.getDomHelper(elem);
- // Create an empty horizontal toolbar using the default renderer.
- var toolbar = new goog.ui.Toolbar(
- goog.ui.ToolbarRenderer.getInstance(),
- goog.ui.Container.Orientation.HORIZONTAL, domHelper);
- // Optimization: Explicitly test for the directionality of the parent
- // element here, so we can set it for both the toolbar and its children,
- // saving a lot of expensive calls to goog.style.isRightToLeft() during
- // rendering.
- var isRightToLeft = opt_isRightToLeft || goog.style.isRightToLeft(elem);
- toolbar.setRightToLeft(isRightToLeft);
- // Optimization: Set the toolbar to non-focusable before it is rendered,
- // to avoid creating unnecessary keyboard event handler objects.
- toolbar.setFocusable(false);
- for (var i = 0, button; button = items[i]; i++) {
- // Optimization: Set the button to non-focusable before it is rendered,
- // to avoid creating unnecessary keyboard event handler objects. Also set
- // the directionality of the button explicitly, to avoid expensive calls
- // to goog.style.isRightToLeft() during rendering.
- button.setSupportedState(goog.ui.Component.State.FOCUSED, false);
- button.setRightToLeft(isRightToLeft);
- toolbar.addChild(button, true);
- }
- toolbar.render(elem);
- return toolbar;
- };
- /**
- * Creates a toolbar button with the given ID, tooltip, and caption. Applies
- * any custom CSS class names to the button's caption element.
- * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
- * built-in buttons, anything else for custom buttons.
- * @param {string} tooltip Tooltip to be shown on hover.
- * @param {goog.ui.ControlContent} caption Button caption.
- * @param {string=} opt_classNames CSS class name(s) to apply to the caption
- * element.
- * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
- * {@link goog.ui.ToolbarButtonRenderer} if unspecified.
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!goog.ui.Button} A toolbar button.
- */
- goog.ui.editor.ToolbarFactory.makeButton = function(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper) {
- var button = new goog.ui.ToolbarButton(
- goog.ui.editor.ToolbarFactory.createContent_(
- caption, opt_classNames, opt_domHelper),
- opt_renderer, opt_domHelper);
- button.setId(id);
- button.setTooltip(tooltip);
- return button;
- };
- /**
- * Creates a toggle button with the given ID, tooltip, and caption. Applies
- * any custom CSS class names to the button's caption element. The button
- * returned has checkbox-like toggle semantics.
- * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
- * built-in buttons, anything else for custom buttons.
- * @param {string} tooltip Tooltip to be shown on hover.
- * @param {goog.ui.ControlContent} caption Button caption.
- * @param {string=} opt_classNames CSS class name(s) to apply to the caption
- * element.
- * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
- * {@link goog.ui.ToolbarButtonRenderer} if unspecified.
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!goog.ui.Button} A toggle button.
- */
- goog.ui.editor.ToolbarFactory.makeToggleButton = function(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper) {
- var button = goog.ui.editor.ToolbarFactory.makeButton(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper);
- button.setSupportedState(goog.ui.Component.State.CHECKED, true);
- return button;
- };
- /**
- * Creates a menu button with the given ID, tooltip, and caption. Applies
- * any custom CSS class names to the button's caption element. The button
- * returned doesn't have an actual menu attached; use {@link
- * goog.ui.MenuButton#setMenu} to attach a {@link goog.ui.Menu} to the
- * button.
- * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
- * built-in buttons, anything else for custom buttons.
- * @param {string} tooltip Tooltip to be shown on hover.
- * @param {goog.ui.ControlContent} caption Button caption.
- * @param {string=} opt_classNames CSS class name(s) to apply to the caption
- * element.
- * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
- * {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!goog.ui.MenuButton} A menu button.
- */
- goog.ui.editor.ToolbarFactory.makeMenuButton = function(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper) {
- var button = new goog.ui.ToolbarMenuButton(
- goog.ui.editor.ToolbarFactory.createContent_(
- caption, opt_classNames, opt_domHelper),
- null, opt_renderer, opt_domHelper);
- button.setId(id);
- button.setTooltip(tooltip);
- return button;
- };
- /**
- * Creates a select button with the given ID, tooltip, and caption. Applies
- * any custom CSS class names to the button's root element. The button
- * returned doesn't have an actual menu attached; use {@link
- * goog.ui.Select#setMenu} to attach a {@link goog.ui.Menu} containing
- * {@link goog.ui.Option}s to the select button.
- * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
- * built-in buttons, anything else for custom buttons.
- * @param {string} tooltip Tooltip to be shown on hover.
- * @param {goog.ui.ControlContent} caption Button caption; used as the
- * default caption when nothing is selected.
- * @param {string=} opt_classNames CSS class name(s) to apply to the button's
- * root element.
- * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer;
- * defaults to {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!goog.ui.Select} A select button.
- */
- goog.ui.editor.ToolbarFactory.makeSelectButton = function(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper) {
- var button =
- new goog.ui.ToolbarSelect(null, null, opt_renderer, opt_domHelper);
- if (opt_classNames) {
- // Unlike the other button types, for goog.ui.Select buttons we apply the
- // extra class names to the root element, because for select buttons the
- // caption isn't stable (as it changes each time the selection changes).
- goog.array.forEach(
- opt_classNames.split(/\s+/), button.addClassName, button);
- }
- button.addClassName(goog.getCssName('goog-toolbar-select'));
- button.setDefaultCaption(caption);
- button.setId(id);
- button.setTooltip(tooltip);
- return button;
- };
- /**
- * Creates a color menu button with the given ID, tooltip, and caption.
- * Applies any custom CSS class names to the button's caption element. The
- * button is created with a default color menu containing standard color
- * palettes.
- * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
- * built-in toolbar buttons, but can be anything else for custom buttons.
- * @param {string} tooltip Tooltip to be shown on hover.
- * @param {goog.ui.ControlContent} caption Button caption.
- * @param {string=} opt_classNames CSS class name(s) to apply to the caption
- * element.
- * @param {goog.ui.ColorMenuButtonRenderer=} opt_renderer Button renderer;
- * defaults to {@link goog.ui.ToolbarColorMenuButtonRenderer}
- * if unspecified.
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!goog.ui.ColorMenuButton} A color menu button.
- */
- goog.ui.editor.ToolbarFactory.makeColorMenuButton = function(
- id, tooltip, caption, opt_classNames, opt_renderer, opt_domHelper) {
- var button = new goog.ui.ToolbarColorMenuButton(
- goog.ui.editor.ToolbarFactory.createContent_(
- caption, opt_classNames, opt_domHelper),
- null, opt_renderer, opt_domHelper);
- button.setId(id);
- button.setTooltip(tooltip);
- return button;
- };
- /**
- * Creates a new DIV that wraps a button caption, optionally applying CSS
- * class names to it. Used as a helper function in button factory methods.
- * @param {goog.ui.ControlContent} caption Button caption.
- * @param {string=} opt_classNames CSS class name(s) to apply to the DIV that
- * wraps the caption (if any).
- * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
- * creation; defaults to the current document if unspecified.
- * @return {!Element} DIV that wraps the caption.
- * @private
- */
- goog.ui.editor.ToolbarFactory.createContent_ = function(
- caption, opt_classNames, opt_domHelper) {
- // FF2 doesn't like empty DIVs, especially when rendered right-to-left.
- if ((!caption || caption == '') && goog.userAgent.GECKO &&
- !goog.userAgent.isVersionOrHigher('1.9a')) {
- caption = goog.string.Unicode.NBSP;
- }
- return (opt_domHelper || goog.dom.getDomHelper())
- .createDom(goog.dom.TagName.DIV, opt_classNames, caption);
- };
|