| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/base/task.html"> |
| <link rel="import" href="/core/filter.html"> |
| <link rel="import" href="/core/selection.html"> |
| |
| <script> |
| 'use strict'; |
| |
| /** |
| * @fileoverview FindController. |
| */ |
| tv.exportTo('tv.c', function() { |
| var Task = tv.b.Task; |
| |
| function FindController(selectionController) { |
| this.selectionController_ = selectionController; |
| this.filterText_ = ''; |
| this.filterHits_ = new tv.c.Selection(); |
| this.filterHitsDirty_ = true; |
| this.currentHitIndex_ = -1; |
| }; |
| |
| FindController.prototype = { |
| __proto__: Object.prototype, |
| |
| get model() { |
| return this.selectionController_.model; |
| }, |
| |
| get selectionController() { |
| return this.selectionController_; |
| }, |
| |
| get filterText() { |
| return this.filterText_; |
| }, |
| |
| set filterText(f) { |
| if (f == this.filterText_) |
| return; |
| this.filterText_ = f; |
| this.filterHitsDirty_ = true; |
| }, |
| |
| getFilterPromise_: function(filterText) { |
| if (!this.selectionController_) |
| return; |
| var promise = Promise.resolve(); |
| |
| |
| var sc = this.selectionController_; |
| |
| var filter = new tv.c.TitleOrCategoryFilter(filterText); |
| var filterHits = new tv.c.Selection(); |
| var filterTask = sc.addAllEventsMatchingFilterToSelectionAsTask( |
| filter, filterHits); |
| promise = Task.RunWhenIdle(filterTask); |
| promise.then(function() { |
| this.filterHitsDirty_ = false; |
| this.filterHits_ = filterHits; |
| sc.findTextChangedTo(filterHits); |
| }.bind(this)); |
| return promise; |
| }, |
| |
| clearFindSelections_: function() { |
| this.selectionController_.findTextCleared(); |
| }, |
| |
| /** |
| * Updates the filter hits based on the current filtering settings. Returns |
| * a promise which resolves when |filterHits| has been refreshed. |
| */ |
| updateFilterHits: function() { |
| var promise = Promise.resolve(); |
| |
| if (!this.filterHitsDirty_) |
| return promise; |
| |
| this.filterHits_ = new tv.c.Selection(); |
| this.currentHitIndex_ = -1; |
| |
| // Try constructing a UIState from the filterText. |
| // UIState.fromUserFriendlyString will throw an error only if the string |
| // is syntactically correct to a UI state string but with invalid values. |
| // It will return undefined if there is no syntactic match. |
| var stateFromString; |
| try { |
| stateFromString = this.selectionController_.uiStateFromString( |
| this.filterText); |
| } catch (e) { |
| var overlay = new tv.b.ui.Overlay(); |
| overlay.textContent = e.message; |
| overlay.title = 'UI State Navigation Error'; |
| overlay.visible = true; |
| return promise; |
| } |
| |
| if (stateFromString !== undefined) { |
| this.selectionController_.navToPosition(stateFromString, true); |
| } else { |
| // filterText is not a navString here -- proceed with find and filter. |
| if (this.filterText.length === 0) |
| this.clearFindSelections_(); |
| else |
| promise = this.getFilterPromise_(this.filterText); |
| } |
| return promise; |
| }, |
| |
| /** |
| * Returns the most recent filter hits as a tv.c.Selection. Call |
| * |updateFilterHits| to ensure this is up to date after the filter |
| * settings have been changed. |
| */ |
| get filterHits() { |
| return this.filterHits_; |
| }, |
| |
| get currentHitIndex() { |
| return this.currentHitIndex_; |
| }, |
| |
| find_: function(dir) { |
| var firstHit = this.currentHitIndex_ === -1; |
| if (firstHit && dir < 0) |
| this.currentHitIndex_ = 0; |
| |
| var N = this.filterHits.length; |
| this.currentHitIndex_ = (this.currentHitIndex_ + dir + N) % N; |
| |
| if (!this.selectionController_) |
| return; |
| |
| this.selectionController_.findFocusChangedTo( |
| this.filterHits.subSelection(this.currentHitIndex_, 1)); |
| }, |
| |
| findNext: function() { |
| this.find_(1); |
| }, |
| |
| findPrevious: function() { |
| this.find_(-1); |
| }, |
| |
| reset: function() { |
| this.filterText_ = ''; |
| this.filterHitsDirty_ = true; |
| } |
| }; |
| |
| return { |
| FindController: FindController |
| }; |
| }); |
| </script> |