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); |
- } |
-} |