1 /* 2 * Copyright © 2009 Apple Inc. All rights reserved. 3 */ 4 5 TKPositioningController.inherits = TKController; 6 TKPositioningController.synthetizes = ['positioningViewData']; 7 8 function TKPositioningController (data) { 9 this.previousButton = null; 10 this.nextButton = null; 11 this.movesWithElementHighlight = true; 12 // set up the positioning view 13 this.positioningView = new TKPositioningView(); 14 this.positioningView.delegate = this; 15 this.positioningView.ready = false; 16 // set up default pointers for arrows 17 this._previousButton = null; 18 this._nextButton = null; 19 // 20 this.callSuper(data); 21 }; 22 23 TKPositioningController.prototype.processView = function () { 24 this.callSuper(); 25 // wire up actions if we have a previous and next button wired 26 if (this.previousButton !== null) { 27 this._previousButton = this.view.querySelector(this.previousButton); 28 if (this._previousButton !== null) { 29 this._previousButton.addEventListener('click', this, false); 30 this.addNavigableElement(this._previousButton); 31 } 32 } 33 if (this.nextButton !== null) { 34 this._nextButton = this.view.querySelector(this.nextButton); 35 if (this._nextButton !== null) { 36 this._nextButton.addEventListener('click', this, false); 37 this.addNavigableElement(this._nextButton); 38 } 39 } 40 // ensure our first page gets told about its being highlighted 41 this.syncPageButtons(); 42 // highlight the first page in case we have no explicit highlighted element 43 if (this.highlightedElement === null && this.positioningView.ready && this.movesWithElementHighlight) { 44 this.highlightedElement = this.positioningView._elements[this.positioningView.activeElementIndex]; 45 } 46 }; 47 48 TKPositioningController.prototype.setPositioningViewData = function (data) { 49 // set up the data source if we have .elements on the data object 50 if (!TKUtils.objectIsUndefined(data.elements)) { 51 this.positioningView.dataSource = new TKPositioningViewDataSourceHelper(data.elements); 52 // FIXME: huh? 53 //delete data.element; 54 } 55 // copy properties 56 TKUtils.copyPropertiesFromSourceToTarget(data, this.positioningView); 57 // init our view 58 this.positioningView.init(); 59 this.syncPageButtons(); 60 // 61 if (this.movesWithElementHighlight) { 62 for (var i = 0; i < this.positioningView._elements.length; i++) { 63 var element = this.positioningView._elements[i]; 64 element.addEventListener('focus', this, false); 65 this.addNavigableElement(element); 66 } 67 } 68 // 69 this.positioningView.ready = true; 70 // add the currently focused element to the list of keyboard elements and highlight it 71 // if we're not directly a child of the navigation controller 72 if (this.viewWasProcessed && this.movesWithElementHighlight && this.parentController === TKNavigationController.sharedNavigation) { 73 TKSpatialNavigationManager.sharedManager.highlightElement(this.positioningView._elements[this.positioningView.activeElementIndex]); 74 } 75 // 76 this._view.appendChild(this.positioningView.element); 77 }; 78 79 TKPositioningController.prototype.syncPageButtons = function () { 80 if (this._previousButton !== null) { 81 this._previousButton[(this.positioningView.activeElementIndex <= 0 ? 'add' : 'remove') + 'ClassName']('inactive'); 82 } 83 if (this._nextButton !== null) { 84 this._nextButton[(this.positioningView.activeElementIndex >= this.positioningView.numberOfElements - 1 ? 'add' : 'remove') + 'ClassName']('inactive'); 85 } 86 }; 87 88 89 /* ==================== Event Handling ==================== */ 90 91 TKPositioningController.prototype.elementWasActivated = function (element) { 92 // see if we hit one of the previous / next buttons 93 if (event.currentTarget === this._previousButton) { 94 this.positioningView.activeElementIndex--; 95 TKSpatialNavigationManager.soundToPlay = (this.positioningView.activeElementIndex > 0) ? SOUND_MOVED : SOUND_LIMIT; 96 } 97 else if (event.currentTarget === this._nextButton) { 98 this.positioningView.activeElementIndex++; 99 TKSpatialNavigationManager.soundToPlay = (this.positioningView.activeElementIndex < this.positioningView.numberOfElements - 1) ? SOUND_MOVED : SOUND_LIMIT; 100 } 101 // focused element in the positioning view 102 else if (element.hasClassName(TKPositioningViewCSSFocusedClass)) { 103 // we only need to trigger selection on activation when running on Apple TV 104 if (IS_APPLE_TV) { 105 this.elementWasSelected(this.positioningView.activeElementIndex); 106 } 107 } 108 else { 109 this.callSuper(element); 110 } 111 }; 112 113 TKPositioningController.prototype.handleEvent = function (event) { 114 this.callSuper(event); 115 // 116 if (event.currentTarget._positioningViewIndex !== undefined) { 117 if (event.type == 'highlight') { 118 this.positioningView.activeElementIndex = event.currentTarget._positioningViewIndex; 119 } 120 } 121 }; 122 123 /* ==================== TKPositioningView Protocol ==================== */ 124 125 TKPositioningController.prototype.positioningViewDidFocusElementAtIndex = function (view, index) { 126 // update the states of previous and next buttons 127 this.syncPageButtons(); 128 }; 129 130 TKPositioningController.prototype.positioningViewDidBlurElementAtIndex = function (view, index) {}; 131 132 TKPositioningController.prototype.positioningViewDidSelectActiveElement = function (view, index) { 133 this.elementWasSelected(index); 134 }; 135 136 // placeholders to be over-riden by instance 137 TKPositioningController.prototype.elementWasSelected = function (index) {}; 138 139 TKClass(TKPositioningController); 140