Controller.js
Summary
No overview generated for 'Controller.js'
TKController.inherits = TKObject;
TKController.synthetizes = ['view', 'metricsView'];
const TKControllerHighlightCSSClass = 'tk-highlighted';
const TKControllerInactiveCSSClass = 'tk-inactive';
TKController.busyControllers = 0;
TKController.controllers = {};
function TKController (data) {
this.callSuper();
this._view = null;
this._metricsView = null;
this.parentController = null;
this.becomesInactiveTransition = TKViewTransitionDissolveOut;
this.becomesActiveTransition = TKViewTransitionDissolveIn;
this.explicitView = null;
this.navigatesTo = [];
this.actions = [];
this.outlets = [];
this.backButton = null;
this.highlightedElement = null;
this.viewNeverAppeared = true;
TKUtils.copyPropertiesFromSourceToTarget(data, this);
this.keyboardElements = [];
TKController.controllers[this.id] = this;
};
TKController.prototype.getView = function () {
if (this._view === null) {
this.loadView();
this.viewDidLoad();
this.processView();
}
return this._view;
};
TKController.prototype.getMetricsView = function () {
return (this._metricsView != null) ? this._metricsView : this.view;
};
TKController.prototype.setView = function (view) {
this.explicitView = view;
};
TKController.prototype.loadView = function () {
this.viewNeverAppeared = false;
var view;
if (this.explicitView !== null) {
view = this.explicitView;
this.viewNeverAppeared = !TKUtils.isNodeChildOfOtherNode(view, document);
}
else {
view = document.getElementById(this.id);
}
if (view === null) {
this.viewNeverAppeared = true;
var request = new XMLHttpRequest();
var requestFailed = false;
request.open('GET', 'views/' + this.id + ".html", false);
try {
request.send();
} catch (err) {
requestFailed = true;
}
if (!requestFailed && ((request.status <= 0 && request.responseText !== '') || request.status == 200)) {
var fragment = document.implementation.createHTMLDocument();
fragment.write(request.responseText);
view = document.importNode(fragment.getElementById(this.id), true);
}
else {
view = document.createElement('div');
view.id = this.id;
}
}
if (this.viewNeverAppeared) {
view.addEventListener('DOMNodeInsertedIntoDocument', this, false);
}
else {
this.highlightTopElement();
}
view._controller = this;
this._view = view;
};
TKController.prototype.processView = function () {
var view = this._view;
for (var i = 0; i < this.navigatesTo.length; i++) {
var item = this.navigatesTo[i];
var element = view.querySelector(item.selector);
if (element) {
element._navigationData = item;
element.addEventListener('click', this, false);
this.addKeyboardElement(element);
}
}
for (var i = 0; i < this.actions.length; i++) {
var item = this.actions[i];
var element = view.querySelector(item.selector);
if (element) {
element._actionData = item;
element.addEventListener('click', this, false);
this.addKeyboardElement(element);
}
}
for (var i = 0; i < this.outlets.length; i++) {
var item = this.outlets[i];
this[item.name] = view.querySelector(item.selector);
}
if (this.backButton !== null) {
var element = view.querySelector(this.backButton);
element._backButton = true;
element.addEventListener('click', this, false);
this.addKeyboardElement(element);
}
if (this.highlightedElement !== null) {
var element = this._view.querySelector(this.highlightedElement);
this.highlightedElement = null;
this.highlightElement(element);
}
var links = view.querySelectorAll('a');
for (var i = 0; i < links.length; i++) {
this.addKeyboardElement(links[i]);
}
};
TKController.prototype.viewDidLoad = function () {};
TKController.prototype.viewDidUnload = function () {};
TKController.prototype.isViewLoaded = function () {
return (this._view !== null);
};
TKController.prototype.viewWillAppear = function () {};
TKController.prototype.viewDidAppear = function () {};
TKController.prototype.viewWillDisappear = function () {};
TKController.prototype.viewDidDisappear = function () {};
TKController.prototype.handleEvent = function (event) {
switch (event.type) {
case 'click' :
this.elementWasActivated(event.currentTarget);
break;
case 'mouseover' :
this.elementWasHovered(event.currentTarget);
break;
case 'mouseout' :
this.elementWasUnhovered(event.currentTarget);
break;
case 'DOMNodeInsertedIntoDocument' :
this.viewWasInsertedIntoDocument(event);
break;
}
};
TKController.prototype.elementWasActivated = function (element) {
if (element._navigationData !== undefined) {
var controller = element._navigationData.controller;
if (TKUtils.objectIsString(controller)) {
controller = TKController.controllers[controller];
}
if (controller === undefined) {
console.error('TKController.elementWasActivated: trying to push an undefined controller');
return;
}
this.highlightElement(element);
TKNavigationController.sharedNavigation.pushController(controller);
}
else if (element._actionData !== undefined) {
this.highlightElement(element);
var callback = element._actionData.action;
if (TKUtils.objectIsString(callback) && TKUtils.objectHasMethod(this, callback)) {
callback = this[element._actionData.action];
}
if (TKUtils.objectIsArray(element._actionData.arguments)) {
callback.apply(this, element._actionData.arguments);
}
else {
callback.apply(this);
}
}
else if (element._backButton !== undefined) {
this.highlightElement(element);
TKNavigationController.sharedNavigation.popController();
}
else if (element.localName == 'a') {
element.dispatchEvent(TKUtils.createEvent('click', null));
}
};
TKController.prototype.elementWasHovered = function (element) {
};
TKController.prototype.elementWasUnhovered = function (element) {
};
TKController.prototype.mouseWasMoved = function () {
};
TKController.prototype.viewWasInsertedIntoDocument = function (event) {
this.viewNeverAppeared = false;
var _this = this;
setTimeout(function () {
_this.highlightTopElement();
}, 0);
};
const TKControllerKnownDirections = [KEYBOARD_UP, KEYBOARD_RIGHT, KEYBOARD_DOWN, KEYBOARD_LEFT];
TKController.prototype.handleKeydown = function (event) {
var key = event.keyCode;
if (TKController.busyControllers > 0) {
return;
}
if (key == KEYBOARD_RETURN) {
if (this.highlightedElement !== null) {
this.elementWasActivated(this.highlightedElement);
}
}
else {
if (this.keyboardElements.length == 0 || TKControllerKnownDirections.indexOf(key) == -1) {
return;
}
event.preventDefault();
if (event._resigningControllers === undefined) {
event._resigningControllers = [];
}
if (this.highlightedElement !== null && this.highlightedElement._controller !== undefined &&
event._resigningControllers.indexOf(this.highlightedElement._controller) == -1) {
this.highlightedElement._controller.handleKeydown(event);
}
else {
var index = this.nearestElementIndexInDirection(key);
if (index != -1) {
this.highlightElement(this.keyboardElements[index]);
TKFocusManager.focusElement(this.highlightedElement);
}
else {
event._resigningControllers.push(this);
if (this.parentController !== null) {
this.parentController.handleKeydown(event);
}
}
}
}
};
TKController.prototype.wantsToHandleKeyboardEvent = function (event) {
return false;
};
const TKControllerDirectionUp = KEYBOARD_UP;
const TKControllerDirectionRight = KEYBOARD_RIGHT;
const TKControllerDirectionDown = KEYBOARD_DOWN;
const TKControllerDirectionLeft = KEYBOARD_LEFT;
TKController.prototype.nearestElementIndexInDirection = function (direction) {
if (this.highlightedElement === null) {
if (direction == TKControllerDirectionUp) {
return this.bottomMostIndex();
}
else if (direction == TKControllerDirectionRight) {
return this.leftMostIndex();
}
else if (direction == TKControllerDirectionDown) {
return this.topMostIndex();
}
else if (direction == TKControllerDirectionLeft) {
return this.rightMostIndex();
}
}
var ref_position, target_position;
if (direction == TKControllerDirectionUp) {
ref_position = TKRectMiddleOfTopEdge;
target_position = TKRectMiddleOfBottomEdge;
}
else if (direction == TKControllerDirectionRight) {
ref_position = TKRectMiddleOfRightEdge;
target_position = TKRectMiddleOfLeftEdge;
}
else if (direction == TKControllerDirectionDown) {
ref_position = TKRectMiddleOfBottomEdge;
target_position = TKRectMiddleOfTopEdge;
}
else if (direction == TKControllerDirectionLeft) {
ref_position = TKRectMiddleOfLeftEdge;
target_position = TKRectMiddleOfRightEdge;
}
var index = -1;
var min_d = 10000000;
var highlight_index = this.keyboardElements.indexOf(this.highlightedElement);
var ref_metrics = this.metricsForElement(this.highlightedElement);
var ref_point = ref_metrics.pointAtPosition(ref_position);
var ref_center = ref_metrics.pointAtPosition(TKRectCenter);
for (var i = 0; i < this.keyboardElements.length; i++) {
if (!this.isElementAtIndexNavigatable(i)) {
continue;
}
var metrics = this.metricsForElement(this.keyboardElements[i]);
if ((direction == TKControllerDirectionUp && metrics.pointAtPosition(TKRectBottomLeftCorner).y > ref_center.y) ||
(direction == TKControllerDirectionRight && metrics.pointAtPosition(TKRectTopLeftCorner).x < ref_center.x) ||
(direction == TKControllerDirectionDown && metrics.pointAtPosition(TKRectTopLeftCorner).y < ref_center.y) ||
(direction == TKControllerDirectionLeft && metrics.pointAtPosition(TKRectTopRightCorner).x > ref_center.x) ||
i == highlight_index) {
continue;
}
var d = ref_point.distanceToPoint(metrics.pointAtPosition(target_position));
if (d < min_d) {
min_d = d;
index = i;
}
}
return index;
};
TKController.prototype.topMostIndex = function () {
var index = 0;
var min_y = 10000;
for (var i = 0; i < this.keyboardElements.length; i++) {
if (!this.isElementAtIndexNavigatable(i)) {
continue;
}
var y = this.metricsForElementAtIndex(i).y;
if (y < min_y) {
min_y = y;
index = i;
}
}
return index;
};
TKController.prototype.rightMostIndex = function () {
var index = 0;
var max_x = 0;
for (var i = 0; i < this.keyboardElements.length; i++) {
if (!this.isElementAtIndexNavigatable(i)) {
continue;
}
var x = this.metricsForElementAtIndex(i).pointAtPosition(TKRectTopRightCorner).x;
if (x > max_x) {
max_x = x;
index = i;
}
}
return index;
};
TKController.prototype.bottomMostIndex = function () {
var index = 0;
var max_y = 0;
for (var i = 0; i < this.keyboardElements.length; i++) {
if (!this.isElementAtIndexNavigatable(i)) {
continue;
}
var y = this.metricsForElementAtIndex(i).pointAtPosition(TKRectBottomRightCorner).y;
if (y > max_y) {
max_y = y;
index = i;
}
}
return index;
};
TKController.prototype.leftMostIndex = function () {
var index = 0;
var min_x = 10000;
for (var i = 0; i < this.keyboardElements.length; i++) {
if (!this.isElementAtIndexNavigatable(i)) {
continue;
}
var y = this.metricsForElementAtIndex(i).x;
if (y < min_x) {
min_x = y;
index = i;
}
}
return index;
};
TKController.prototype.highlightElement = function (element) {
if (!(element instanceof Element)) {
return;
}
if (this.highlightedElement !== null) {
this.highlightedElement.dispatchEvent(TKUtils.createEvent('unhighlight', element));
if (SUPPORTS_KEYBOARD_NAVIGATION) {
this.highlightedElement.removeClassName(TKControllerHighlightCSSClass);
}
}
element.dispatchEvent(TKUtils.createEvent('highlight', this.highlightedElement));
if (SUPPORTS_KEYBOARD_NAVIGATION) {
element.addClassName(TKControllerHighlightCSSClass);
}
this.highlightedElement = element;
};
TKController.prototype.addKeyboardElement = function (element) {
if (this.keyboardElements.indexOf(element) > -1) {
return;
}
element.addEventListener('highlight', this, false);
this.keyboardElements.push(element);
};
TKController.prototype.removeKeyboardElement = function (element) {
var index = this.keyboardElements.indexOf(element);
if (index < 0) {
return;
}
this.keyboardElements.splice(index, 1);
};
TKController.prototype.metricsForElement = function (element) {
var metrics_element = element;
if (element._controller !== undefined) {
metrics_element = element._controller.metricsView;
}
return metrics_element.getBounds();
};
TKController.prototype.metricsForElementAtIndex = function (index) {
return this.metricsForElement(this.keyboardElements[index]);
};
TKController.prototype.highlightTopElement = function () {
if (this.highlightedElement === null && this.keyboardElements.length > 0) {
this.highlightElement(this.keyboardElements[this.topMostIndex()]);
}
};
TKController.prototype.isElementAtIndexNavigatable = function (index) {
return !this.keyboardElements[index].hasClassName(TKControllerInactiveCSSClass);
};
TKClass(TKController);
Documentation generated by
JSDoc on Tue Sep 15 21:24:36 2009