<!DOCTYPE html>
<html>
<!--
Copyright The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<title>goog.ui.Container</title>
<script src="../base.js"></script>
<script>
goog.require('goog.array');
goog.require('goog.debug.DivConsole');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.log');
goog.require('goog.object');
goog.require('goog.style');
goog.require('goog.ui.Container');
goog.require('goog.ui.ContainerScroller');
goog.require('goog.ui.Control');
goog.require('goog.ui.CustomButton');
goog.require('goog.ui.Menu');
goog.require('goog.ui.MenuButton');
goog.require('goog.ui.Option');
goog.require('goog.ui.Select');
goog.require('goog.ui.Separator');
goog.require('goog.ui.ToggleButton');
goog.require('goog.dom.TagName');
</script>
<link rel="stylesheet" href="css/demo.css">
<link rel="stylesheet" href="../css/button.css">
<link rel="stylesheet" href="../css/menubutton.css">
<style>
/* Demo styles for goog.ui.Control. */
.goog-control {
position: relative;
margin: 2px;
border: 2px solid #036;
padding: 2px;
font: normal 9pt "Trebuchet MS", Tahoma, Arial, sans-serif;
color: #036;
background-color:#69c;
cursor: pointer;
outline: none !important;
}
.goog-control-disabled {
border-color: #888;
color: #888;
background-color: #ccc;
}
.goog-control-hover {
border-color: #369;
color: #369;
background-color: #9cf;
}
.goog-control-active,
.goog-control-selected,
.goog-control-checked {
border-color: #9cf;
color: #9cf;
background-color: #369;
}
.goog-control-focused {
border-color: orange;
}
/* Demo styles for goog.ui.Container */
.goog-container {
position: relative;
margin: 0;
border: 0;
padding: 0;
background-color: #eee;
outline: none !important;
zoom: 1; /* The container element must have layout on IE. */
}
.goog-container-vertical {
width: 25ex;
border: 1px solid #888;
}
.goog-container-horizontal {
border-bottom: 1px solid #d5d5d5;
background: #fafafa url(../images/toolbar-bg.png) repeat-x bottom left;
}
/* Additional demo styles. */
.goog-month .goog-menu-button-caption {
width: 18ex;
}
.goog-year .goog-menu-button-caption {
width: 6ex;
}
.goog-edit-font .goog-menu-button-caption {
width: 15ex;
}
.goog-edit-font-size .goog-menu-button-caption {
width: 5ex;
}
.goog-edit-bold {
width: 14px;
background: url(../images/toolbar_icons.gif) no-repeat -1px;
}
.goog-edit-italic {
width: 14px;
background: url(../images/toolbar_icons.gif) no-repeat -17px;
}
.goog-edit-underline {
width: 14px;
background: url(../images/toolbar_icons.gif) no-repeat -33px;
}
#tb4_highlight_links span {
border: 1px solid #888;
cursor: pointer;
padding: 2px 4px;
}
</style>
</head>
<body>
<h2>goog.ui.Container</h2>
<p><b>goog.ui.Container</b> is a base class for menus and toolbars.</p>
<fieldset>
<legend>These containers were created programmatically:</legend>
<table border="0" cellpadding="8" cellspacing="0" width="100%">
<tbody>
<tr valign="top">
<td width="50%" id="vc">
Vertical container example:
</td>
<td width="50%" id="hc">
Horizontal container example:
</td>
</tr>
<tr valign="top">
<td>
<label>
Show vertical container:
<input type="checkbox" id="show_vc" checked>
</label>
<label>
Enable vertical container:
<input type="checkbox" id="enable_vc" checked>
</label>
<br>
<label>
Show Porthos:
<input type="checkbox" id="show_porthos" checked>
</label>
<label>
Enable Porthos:
<input type="checkbox" id="enable_porthos">
</label>
<br>
<label>
Enable transition events:
<input type="checkbox" id="enable_vc_events" checked>
</label>
</td>
<td>
<label>
Show horizontal container:
<input type="checkbox" id="show_hc" checked>
</label>
<label>
Enable horizontal container:
<input type="checkbox" id="enable_hc" checked>
</label>
<br>
<label>
Show Doc:
<input type="checkbox" id="show_doc" checked>
</label>
<label>
Enable Doc:
<input type="checkbox" id="enable_doc">
</label>
<br>
<label>
Enable transition events:
<input type="checkbox" id="enable_hc_events" checked>
</label>
</td>
</tr>
</tbody>
</table>
<span class="hint">Try enabling and disabling containers with & without
state transition events, and compare performance!</span>
</fieldset>
<br>
<br>
<fieldset>
<legend>Non-focusable container with focusable controls:</legend>
In this case, the container itself isn't focusable, but each control is:<br>
<div id="nfc"></div>
</fieldset>
<br>
<br>
<fieldset>
<legend>Another horizontal container:</legend>
<label>
This is starting to look useful... Enable toolbar:
<input type="checkbox" id="enable_tb" checked>
</label>
<div id="tb"></div>
</fieldset>
<br>
<br>
<fieldset>
<legend>A decorated container:</legend>
<label>
It's much easier to decorate than to create programmatically...
Enable decorated toolbar:
<input type="checkbox" id="enable_tb2">
</label>
<div id="tb2" class="goog-container-horizontal goog-container-disabled">
<div id="month" class="goog-month goog-select">
Select month
<div class="goog-menu">
<div class="goog-option">January</div>
<div class="goog-option">February</div>
<div class="goog-option">March</div>
<div class="goog-option">April</div>
<div class="goog-option">May</div>
<div class="goog-option">June</div>
<div class="goog-option">July</div>
<div class="goog-option">August</div>
<div class="goog-option">September</div>
<div class="goog-option">October</div>
<div class="goog-option">November</div>
<div class="goog-option">December</div>
</div>
</div>
<div id="year" class="goog-year goog-select">
Year
<div class="goog-menu">
<div class="goog-option">2001</div>
<div class="goog-option">2002</div>
<div class="goog-option">2003</div>
<div class="goog-option">2004</div>
<div class="goog-option">2005</div>
<div class="goog-option">2006</div>
<div class="goog-option">2007</div>
<div class="goog-option">2008</div>
<div class="goog-option">2009</div>
<div class="goog-option">2010</div>
</div>
</div>
<div id="foo" class="goog-toggle-button">
Toggle Button
</div>
<div id="bar" class="goog-toggle-button">
<div><b><i>Fancy</i></b> Toggle Button</div>
</div>
<div id="fee" class="goog-toggle-button">
Another Button
</div>
</div>
</fieldset>
<br>
<br>
<fieldset>
<legend>The same container, right-to-left:</legend>
<label>
Show right-to-left toolbar:
<input type="checkbox" id="show_tb3" checked>
</label>
<label>
Enable right-to-left toolbar:
<input type="checkbox" id="enable_tb3">
</label>
<div id="tb3" class="goog-container-horizontal goog-container-disabled"
dir="rtl">
<div class="goog-month goog-select">
Select month
<div class="goog-menu" dir="rtl">
<div class="goog-option">January</div>
<div class="goog-option">February</div>
<div class="goog-option">March</div>
<div class="goog-option">April</div>
<div class="goog-option">May</div>
<div class="goog-option">June</div>
<div class="goog-option">July</div>
<div class="goog-option">August</div>
<div class="goog-option">September</div>
<div class="goog-option">October</div>
<div class="goog-option">November</div>
<div class="goog-option">December</div>
</div>
</div>
<div class="goog-year goog-select" dir="rtl">
Year
<div class="goog-menu">
<div class="goog-option">2001</div>
<div class="goog-option">2002</div>
<div class="goog-option">2003</div>
<div class="goog-option">2004</div>
<div class="goog-option">2005</div>
<div class="goog-option">2006</div>
<div class="goog-option">2007</div>
<div class="goog-option">2008</div>
<div class="goog-option">2009</div>
<div class="goog-option">2010</div>
</div>
</div>
<div class="goog-toggle-button">
Toggle Button
</div>
<div class="goog-toggle-button">
<div><b><i>Fancy</i></b> Toggle Button</div>
</div>
<div class="goog-toggle-button">
Another Button
</div>
</div>
</fieldset>
<br>
<br>
<fieldset>
<legend>A scrolling container:</legend>
<label>
This container scrolls so that the highlighted item is visible.
Here's a mix of block items and inline block items, which both work.
</label>
<p>
Put focus in the text box and use the arrow keys:
<input id="tb4_key_target">
</p>
<p>
Or quick jump to item:
<span id="tb4_highlight_links">
<span>0</span> <span>1</span> <span>2</span> <span>3</span>
<span>4</span> <span>5</span> <span>6</span> <span>7</span>
<span>8</span> <span>9</span> <span>10</span> <span>11</span>
<span>12</span> <span>13</span> <span>14</span> <span>15</span>
</span>
</p>
<div id="tb4" class="goog-container-vertical"
style="height: 100px; overflow-y: scroll">
<div class="goog-month goog-menuitem">menuitem 0</div>
<div class="goog-month goog-menuitem">menuitem 1</div>
<div class="goog-month goog-menuitem">menuitem 2</div>
<div class="goog-month goog-menuitem">menuitem 3</div>
<div class="goog-month goog-toggle-button">tog 4</div>
<div class="goog-month goog-toggle-button">tog 5</div>
<div class="goog-month goog-toggle-button">tog 6</div>
<div class="goog-month goog-toggle-button">toggley 7</div>
<div class="goog-month goog-toggle-button">toggley 8</div>
<div class="goog-month goog-toggle-button">toggley 9</div>
<div class="goog-month goog-toggle-button">toggley 10</div>
<div class="goog-month goog-toggle-button">toggley 11</div>
<div class="goog-month goog-toggle-button">toggley 12</div>
<div class="goog-month goog-toggle-button">toggley 13</div>
<div class="goog-month goog-menuitem">menuitem 14</div>
<div class="goog-month goog-menuitem">menuitem 15</div>
</div>
</fieldset>
<br>
<br>
<!-- Event log. -->
<fieldset class="goog-debug-panel">
<legend>Event Log</legend>
<div id="log"></div>
</fieldset>
<div id="perf"></div>
<script>
var timer = goog.now();
// Set up a logger.
goog.log.setLevel(goog.log.getRootLogger(), goog.log.Level.ALL);
var logger = goog.log.getLogger('demo');
var logconsole = new goog.debug.DivConsole(goog.dom.getElement('log'));
logconsole.setCapturing(true);
var EVENTS = goog.object.getValues(goog.ui.Component.EventType);
goog.log.fine(logger, 'Listening for: ' + EVENTS.join(', ') + '.');
function logEvent(e) {
var source =
typeof e.target.getCaption == 'function' && e.target.getCaption() ||
e.target.getId();
goog.log.info(logger, '"' + source + '" dispatched: ' + e.type);
}
// Programmatically create a vertical container.
var vc = new goog.ui.Container();
vc.setId('Vertical Container');
goog.array.forEach(
['Athos', 'Porthos', 'Aramis', 'd\'Artagnan'],
function(item) {
var c = new goog.ui.Control(item);
c.setId(item);
// For demo purposes, have controls dispatch transition events.
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
vc.addChild(c, true);
});
vc.addChildAt(new goog.ui.Separator(), 3, true);
vc.getChild('Porthos').setEnabled(false);
vc.render(goog.dom.getElement('vc'));
goog.events.listen(vc, EVENTS, logEvent);
// Hook up checkboxes.
goog.events.listen(goog.dom.getElement('show_vc'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
vc.setVisible(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Showed' : 'Hid') +
' vertical container in ' + (goog.now() - t) + 'ms');
});
goog.events.listen(goog.dom.getElement('enable_vc'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
vc.setEnabled(e.target.checked);
// If the container as a whole is disabled, you can't enable/disable
// child controls.
goog.dom.getElement('enable_porthos').disabled = !vc.isEnabled();
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' vertical container in ' + (goog.now() - t) + 'ms');
});
goog.events.listen(goog.dom.getElement('show_porthos'),
goog.events.EventType.CLICK,
function(e) {
vc.getChild('Porthos').setVisible(e.target.checked);
});
goog.events.listen(goog.dom.getElement('enable_porthos'),
goog.events.EventType.CLICK,
function(e) {
vc.getChild('Porthos').setEnabled(e.target.checked);
});
goog.events.listen(goog.dom.getElement('enable_vc_events'),
goog.events.EventType.CLICK,
function(e) {
vc.forEachChild(function(c) {
if (e.target.checked) {
// Enable all transition events.
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
} else {
// Disable all transition events (except for HOVER, which is used
// by containers internally).
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, false);
c.setDispatchTransitionEvents(goog.ui.Component.State.HOVER,
true);
}
});
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' state transition events for this container\'s children');
});
// Programmatically create a horizontal container.
var hc = new goog.ui.Container(goog.ui.Container.Orientation.HORIZONTAL);
hc.setId('Horizontal Container');
// Pre-render the container, just to do something different.
hc.render(goog.dom.getElement('hc'));
goog.array.forEach(
['Happy', 'Sleepy', 'Doc', 'Bashful', 'Sneezy', 'Grumpy', 'Dopey'],
function(item) {
var c = new goog.ui.Control(item);
c.addClassName('goog-inline-block');
c.setId(item);
// For demo purposes, have controls dispatch transition events.
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
hc.addChild(c, true);
});
hc.getChild('Doc').setEnabled(false);
goog.events.listen(hc, EVENTS, logEvent);
// Hook up checkboxes.
goog.events.listen(goog.dom.getElement('show_hc'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
hc.setVisible(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Showed' : 'Hid') +
' horizontal container in ' + (goog.now() - t) + 'ms');
});
goog.events.listen(goog.dom.getElement('enable_hc'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
hc.setEnabled(e.target.checked);
// If the container as a whole is disabled, you can't enable/disable
// child controls.
goog.dom.getElement('enable_doc').disabled = !hc.isEnabled();
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' horizontal container in ' + (goog.now() - t) + 'ms');
});
goog.events.listen(goog.dom.getElement('show_doc'),
goog.events.EventType.CLICK,
function(e) {
hc.getChild('Doc').setVisible(e.target.checked);
});
goog.events.listen(goog.dom.getElement('enable_doc'),
goog.events.EventType.CLICK,
function(e) {
hc.getChild('Doc').setEnabled(e.target.checked);
});
goog.events.listen(goog.dom.getElement('enable_hc_events'),
goog.events.EventType.CLICK,
function(e) {
hc.forEachChild(function(c) {
if (e.target.checked) {
// Enable all transition events.
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
} else {
// Disable all transition events (except for HOVER, which is used
// by containers internally).
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, false);
c.setDispatchTransitionEvents(goog.ui.Component.State.HOVER,
true);
}
});
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' state transition events for this container\'s children');
});
// Programmatically create a non-focusable container.
var nfc = new goog.ui.Container(goog.ui.Container.Orientation.HORIZONTAL);
nfc.setId('NonFocusableContainer');
nfc.setFocusable(false);
goog.array.forEach(['Vicky', 'Cristina', 'Barcelona'], function(item) {
var c = new goog.ui.Control(item);
c.setId(item);
c.addClassName('goog-inline-block');
// For demo purposes, have controls dispatch transition events.
c.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
nfc.addChild(c, /* opt_render */ true);
// Since the container itself is non-focusable, we need to make each
// child individually focusable; this has to happen *after* addChild().
// See e.g. bug http://b/1359754.
c.setSupportedState(goog.ui.Component.State.FOCUSED, true);
});
nfc.render(goog.dom.getElement('nfc'));
goog.events.listen(nfc, EVENTS, logEvent);
// Programmatically create a toolbar.
var tb = new goog.ui.Container(goog.ui.Container.Orientation.HORIZONTAL);
tb.setId('Toolbar');
// Programmatically create & add toolbar items.
var fontMenu = new goog.ui.Select('Select font');
fontMenu.setId('Font Menu');
fontMenu.setTooltip('Font');
fontMenu.addItem(new goog.ui.Option('Arial', 'Arial, sans-serif'));
fontMenu.addItem(new goog.ui.Option('Courier', 'Courier, monospace'));
fontMenu.addItem(new goog.ui.Option('Times', 'Times, serif'));
fontMenu.addClassName('goog-edit-font');
tb.addChild(fontMenu, true);
var sizeMenu = new goog.ui.Select(null);
sizeMenu.setId('Font Size Menu');
sizeMenu.setTooltip('Font Size');
sizeMenu.addItem(new goog.ui.Option('8pt'));
sizeMenu.addItem(new goog.ui.Option('10pt'));
sizeMenu.addItem(new goog.ui.Option('12pt'));
sizeMenu.addItem(new goog.ui.Option('16pt'));
sizeMenu.setSelectedIndex(1);
sizeMenu.addClassName('goog-edit-font-size');
tb.addChild(sizeMenu, true);
var boldButton = new goog.ui.ToggleButton(goog.dom.createDom(goog.dom.TagName.DIV,
'goog-edit-bold', '\u00A0'));
boldButton.setId('Bold Button');
boldButton.setTooltip('Bold');
tb.addChild(boldButton, true);
var italicButton = new goog.ui.ToggleButton(goog.dom.createDom(goog.dom.TagName.DIV,
'goog-edit-italic', '\u00A0'));
italicButton.setId('Italic Button');
italicButton.setTooltip('Italic');
tb.addChild(italicButton, true);
var underlineButton = new goog.ui.ToggleButton(goog.dom.createDom(goog.dom.TagName.DIV,
'goog-edit-underline', '\u00A0'));
underlineButton.setId('Underline Button');
underlineButton.setTooltip('Underline');
tb.addChild(underlineButton, true);
tb.render(goog.dom.getElement('tb'));
goog.events.listen(tb, EVENTS, logEvent);
// Hook up checkbox.
goog.events.listen(goog.dom.getElement('enable_tb'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
tb.setEnabled(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' toolbar in ' + (goog.now() - t) + 'ms');
});
var tb2 = new goog.ui.Container();
tb2.decorate(goog.dom.getElement('tb2'));
goog.events.listen(tb2, EVENTS, logEvent);
// Hook up checkbox.
goog.events.listen(goog.dom.getElement('enable_tb2'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
tb2.setEnabled(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' toolbar in ' + (goog.now() - t) + 'ms');
});
// BiDi container example:
var tb3 = new goog.ui.Container();
tb3.decorate(goog.dom.getElement('tb3'));
goog.events.listen(tb3, EVENTS, logEvent);
// Hook up checkboxes.
goog.events.listen(goog.dom.getElement('enable_tb3'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
tb3.setEnabled(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Enabled' : 'Disabled') +
' toolbar in ' + (goog.now() - t) + 'ms');
});
goog.events.listen(goog.dom.getElement('show_tb3'),
goog.events.EventType.CLICK,
function(e) {
var t = goog.now();
tb3.setVisible(e.target.checked);
goog.log.info(logger, (e.target.checked ? 'Showed' : 'Hid') +
' content element in ' + (goog.now() - t) + 'ms');
});
// Scrolling container.
var tb4 = new goog.ui.Container();
tb4.decorate(goog.dom.getElement('tb4'));
tb4.setKeyEventTarget(goog.dom.getElement('tb4_key_target'));
tb4.setFocusable(true);
new goog.ui.ContainerScroller(tb4);
goog.events.listen(goog.dom.getElement('tb4_highlight_links'),
goog.events.EventType.CLICK,
function(event) {
var index = parseInt(event.target.innerHTML, 10);
if (!isNaN(index)) {
tb4.getChildAt(index).setHighlighted(true);
}
});
goog.dom.setTextContent(goog.dom.getElement('perf'),
(goog.now() - timer) + 'ms');
</script>
</body>
</html>