| Index: client/view/SliderMenu.dart
|
| ===================================================================
|
| --- client/view/SliderMenu.dart (revision 4144)
|
| +++ client/view/SliderMenu.dart (working copy)
|
| @@ -1,176 +0,0 @@
|
| -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -typedef void SelectHandler(String menuText);
|
| -
|
| -/**
|
| - * This implements a horizontal menu bar with a sliding triangle arrow
|
| - * that points at the currently selected item.
|
| - */
|
| -class SliderMenu extends View {
|
| - static final int TRIANGLE_WIDTH = 24;
|
| -
|
| - // currently selected menu item
|
| - Element selectedItem;
|
| -
|
| - // This holds the element where a touchstart occured. (This is set
|
| - // in touchstart, and cleared in touchend.) If this is null, then a
|
| - // touch operation is not in progress.
|
| - // TODO(mattsh) - move this to a touch mixin
|
| - Element touchItem;
|
| -
|
| - /**
|
| - * Callback function that we call when the user chooses something from
|
| - * the menu. This is passed the menu item text.
|
| - */
|
| - SelectHandler onSelect;
|
| -
|
| - List<String> _menuItems;
|
| -
|
| - SliderMenu(this._menuItems, this.onSelect) : super() {}
|
| -
|
| - Element render() {
|
| - // Create a div for each menu item.
|
| - final items = new StringBuffer();
|
| - for (final item in _menuItems) {
|
| - items.add('<div class="sm-item">$item</div>');
|
| - }
|
| -
|
| - // Create a root node to hold this view.
|
| - return new Element.html('''
|
| - <div class="sm-root">
|
| - <div class="sm-item-box">
|
| - <div class="sm-item-filler"></div>
|
| - $items
|
| - <div class="sm-item-filler"></div>
|
| - </div>
|
| - <div class="sm-slider-box">
|
| - <div class="sm-triangle"></div>
|
| - </div>
|
| - </div>
|
| - ''');
|
| - }
|
| -
|
| - void enterDocument() {
|
| - // select the first item
|
| - // todo(jacobr): too much actual work is performed in enterDocument.
|
| - // Ideally, enterDocument should do nothing more than redecorate a view
|
| - // and perhaps calculating the correct child sizes for edge cases that
|
| - // cannot be handled by the browser layout engine.
|
| - selectItem(node.query('.sm-item'), false);
|
| -
|
| - // TODO(mattsh), abstract this somehow into a touch click mixin
|
| - if (Device.supportsTouch) {
|
| - node.on.touchStart.add((event) {
|
| - touchItem = itemOfTouchEvent(event);
|
| - if (touchItem != null) {
|
| - selectItemText(touchItem);
|
| - }
|
| - event.preventDefault();
|
| - });
|
| - node.on.touchEnd.add((event) {
|
| - if (touchItem != null) {
|
| - if (itemOfTouchEvent(event) == touchItem) {
|
| - selectItem(touchItem, true);
|
| - } else {
|
| - // the Touch target is somewhere other where than the touchstart
|
| - // occured, so revert the selected menu text back to where it was
|
| - // before the touchstart,
|
| - selectItemText(selectedItem);
|
| - }
|
| - // touch operation has ended
|
| - touchItem = null;
|
| - }
|
| - event.preventDefault();
|
| - });
|
| - } else {
|
| - node.on.click.add((event) => selectItem(event.target, true));
|
| - }
|
| -
|
| - window.on.resize.add((Event event) => updateIndicator(false));
|
| - }
|
| -
|
| - /**
|
| - * Walks the parent chain of the first Touch target to find the first ancestor
|
| - * that has sm-item class.
|
| - */
|
| - Element itemOfTouchEvent(event) {
|
| - Node node = event.changedTouches[0].target;
|
| - return itemOfNode(node);
|
| - }
|
| -
|
| - Element itemOfNode(Node node) {
|
| - // TODO(jmesserly): workaround for bug 5399957, document.parent == document
|
| - while (node != null && node != document) {
|
| - if (node is Element) {
|
| - Element element = node;
|
| - if (element.classes.contains('sm-item')) {
|
| - return element;
|
| - }
|
| - }
|
| - node = node.parent;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - void selectItemText(Element item) {
|
| - // unselect all menu items
|
| - for (final sliderItem in node.queryAll('.sm-item')) {
|
| - sliderItem.classes.remove('sel');
|
| - }
|
| -
|
| - // select the item the user clicked on
|
| - item.classes.add('sel');
|
| - }
|
| -
|
| - void selectItem(Element item, bool animate) {
|
| - if (!item.classes.contains('sm-item')) {
|
| - return;
|
| - }
|
| -
|
| - selectedItem = item;
|
| - selectItemText(item);
|
| - updateIndicator(animate);
|
| - onSelect(item.text);
|
| - }
|
| -
|
| - void selectNext(bool animate) {
|
| - final result = node.query('.sm-item.sel').nextElementSibling;
|
| - if (result != null) {
|
| - selectItem(result, animate);
|
| - }
|
| - }
|
| -
|
| - void selectPrevious(bool animate) {
|
| - final result = node.query('.sm-item.sel').previousElementSibling;
|
| - if (result != null) {
|
| - selectItem(result, animate);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * animate - if true, then animate the movement of the triangle slider
|
| - */
|
| - void updateIndicator(bool animate) {
|
| - if (selectedItem != null) {
|
| - // calculate where we want to put the triangle
|
| - selectedItem.rect.then((ElementRect rect) {
|
| - num x = rect.offset.left +
|
| - rect.offset.width / 2 - TRIANGLE_WIDTH / 2;
|
| - _moveIndicator(x, animate);
|
| - });
|
| - } else {
|
| - _moveIndicator(0, animate);
|
| - }
|
| - }
|
| -
|
| - void _moveIndicator(num x, bool animate) {
|
| - // find the slider filler (the div element to the left of the
|
| - // triangle) set its width the push the triangle to where we want it.
|
| - String duration = animate ? '.3s' : '0s';
|
| - final triangle = node.query('.sm-triangle');
|
| - triangle.style.transitionDuration = duration;
|
| - FxUtil.setWebkitTransform(triangle, x, 0);
|
| - }
|
| -}
|
|
|