[Mobile] Merge

Merged with master and resolved conflicts.
This commit is contained in:
Shivam Dave
2015-08-25 12:36:50 -07:00
294 changed files with 11631 additions and 9569 deletions

View File

@ -42,6 +42,7 @@ define(
* * `ungrouped`: All actions which did not have a defined
* group.
*
* @memberof platform/commonUI/general
* @constructor
*/
function ActionGroupController($scope) {
@ -102,4 +103,4 @@ define(
return ActionGroupController;
}
);
);

View File

@ -29,6 +29,7 @@ define(
/**
* Controller for the bottombar template. Exposes
* available indicators (of extension category "indicators")
* @memberof platform/commonUI/general
* @constructor
*/
function BottomBarController(indicators) {
@ -42,20 +43,19 @@ define(
};
}
indicators = indicators.map(present);
return {
/**
* Get all indicators to display.
* @returns {Indicator[]} all indicators
* to display in the bottom bar.
*/
getIndicators: function () {
return indicators;
}
};
this.indicators = indicators.map(present);
}
/**
* Get all indicators to display.
* @returns {Indicator[]} all indicators
* to display in the bottom bar.
* @memberof platform/commonUI/general.BottomBarController#
*/
BottomBarController.prototype.getIndicators = function () {
return this.indicators;
};
return BottomBarController;
}
);
);

View File

@ -31,71 +31,69 @@ define(
* menus) where clicking elsewhere in the document while the toggle
* is in an active state is intended to dismiss the toggle.
*
* @memberof platform/commonUI/general
* @constructor
* @param $scope the scope in which this controller is active
* @param $document the document element, injected by Angular
*/
function ClickAwayController($scope, $document) {
var state = false,
clickaway;
var self = this;
// Track state, but also attach and detach a listener for
// mouseup events on the document.
function deactivate() {
state = false;
$document.off("mouseup", clickaway);
}
function activate() {
state = true;
$document.on("mouseup", clickaway);
}
function changeState() {
if (state) {
deactivate();
} else {
activate();
}
}
this.state = false;
this.$scope = $scope;
this.$document = $document;
// Callback used by the document listener. Deactivates;
// note also $scope.$apply is invoked to indicate that
// the state of this controller has changed.
clickaway = function () {
deactivate();
this.clickaway = function () {
self.deactivate();
$scope.$apply();
return false;
};
return {
/**
* Get the current state of the toggle.
* @return {boolean} true if active
*/
isActive: function () {
return state;
},
/**
* Set a new state for the toggle.
* @return {boolean} true to activate
*/
setState: function (newState) {
if (state !== newState) {
changeState();
}
},
/**
* Toggle the current state; activate if it is inactive,
* deactivate if it is active.
*/
toggle: function () {
changeState();
}
};
}
// Track state, but also attach and detach a listener for
// mouseup events on the document.
ClickAwayController.prototype.deactivate = function () {
this.state = false;
this.$document.off("mouseup", this.clickaway);
};
ClickAwayController.prototype.activate = function () {
this.state = true;
this.$document.on("mouseup", this.clickaway);
};
/**
* Get the current state of the toggle.
* @return {boolean} true if active
*/
ClickAwayController.prototype.isActive =function () {
return this.state;
};
/**
* Set a new state for the toggle.
* @return {boolean} true to activate
*/
ClickAwayController.prototype.setState = function (newState) {
if (this.state !== newState) {
this.toggle();
}
};
/**
* Toggle the current state; activate if it is inactive,
* deactivate if it is active.
*/
ClickAwayController.prototype.toggle = function () {
if (this.state) {
this.deactivate();
} else {
this.activate();
}
};
return ClickAwayController;
}
);
);

View File

@ -33,6 +33,7 @@ define(
* Controller for the context menu. Maintains an up-to-date
* list of applicable actions (those from category "contextual")
*
* @memberof platform/commonUI/general
* @constructor
*/
function ContextMenuController($scope) {
@ -49,4 +50,4 @@ define(
return ContextMenuController;
}
);
);

View File

@ -54,6 +54,7 @@ define(
* parameter it received.) Getter-setter functions are never the
* target of a scope assignment and so avoid this problem.
*
* @memberof platform/commonUI/general
* @constructor
* @param {Scope} $scope the controller's scope
*/
@ -87,4 +88,4 @@ define(
return GetterSetterController;
}
);
);

View File

@ -30,6 +30,7 @@ define(
/**
* Controller for the domain object selector control.
* @memberof platform/commonUI/general
* @constructor
* @param {ObjectService} objectService service from which to
* read domain objects
@ -38,28 +39,17 @@ define(
function SelectorController(objectService, $scope) {
var treeModel = {},
listModel = {},
selectedObjects = [],
rootObject,
previousSelected;
previousSelected,
self = this;
// For watch; look at the user's selection in the tree
function getTreeSelection() {
return treeModel.selectedObject;
}
// Get the value of the field being edited
function getField() {
return $scope.ngModel[$scope.field] || [];
}
// Get the value of the field being edited
function setField(value) {
$scope.ngModel[$scope.field] = value;
}
// Store root object for subsequent exposure to template
function storeRoot(objects) {
rootObject = objects[ROOT_ID];
self.rootObject = objects[ROOT_ID];
}
// Check that a selection is of the valid type
@ -82,7 +72,8 @@ define(
function updateSelectedObjects(objects) {
// Look up from the
function getObject(id) { return objects[id]; }
selectedObjects = ids.filter(getObject).map(getObject);
self.selectedObjects =
ids.filter(getObject).map(getObject);
}
// Look up objects by id, then populate right-hand list
@ -93,64 +84,85 @@ define(
$scope.$watch(getTreeSelection, validateTreeSelection);
// Make sure right-hand list matches underlying model
$scope.$watchCollection(getField, updateList);
$scope.$watchCollection(function () {
return self.getField();
}, updateList);
// Look up root object, then store it
objectService.getObjects([ROOT_ID]).then(storeRoot);
return {
/**
* Get the root object to show in the left-hand tree.
* @returns {DomainObject} the root object
*/
root: function () {
return rootObject;
},
/**
* Add a domain object to the list of selected objects.
* @param {DomainObject} the domain object to select
*/
select: function (domainObject) {
var id = domainObject && domainObject.getId(),
list = getField() || [];
// Only select if we have a valid id,
// and it isn't already selected
if (id && list.indexOf(id) === -1) {
setField(list.concat([id]));
}
},
/**
* Remove a domain object from the list of selected objects.
* @param {DomainObject} the domain object to select
*/
deselect: function (domainObject) {
var id = domainObject && domainObject.getId(),
list = getField() || [];
// Only change if this was a valid id,
// for an object which was already selected
if (id && list.indexOf(id) !== -1) {
// Filter it out of the current field
setField(list.filter(function (otherId) {
return otherId !== id;
}));
// Clear the current list selection
delete listModel.selectedObject;
}
},
/**
* Get the currently-selected domain objects.
* @returns {DomainObject[]} the current selection
*/
selected: function () {
return selectedObjects;
},
// Expose tree/list model for use in template directly
treeModel: treeModel,
listModel: listModel
};
this.$scope = $scope;
this.selectedObjects = [];
// Expose tree/list model for use in template directly
this.treeModel = treeModel;
this.listModel = listModel;
}
// Set the value of the field being edited
SelectorController.prototype.setField = function (value) {
this.$scope.ngModel[this.$scope.field] = value;
};
// Get the value of the field being edited
SelectorController.prototype.getField = function () {
return this.$scope.ngModel[this.$scope.field] || [];
};
/**
* Get the root object to show in the left-hand tree.
* @returns {DomainObject} the root object
*/
SelectorController.prototype.root = function () {
return this.rootObject;
};
/**
* Add a domain object to the list of selected objects.
* @param {DomainObject} the domain object to select
*/
SelectorController.prototype.select = function (domainObject) {
var id = domainObject && domainObject.getId(),
list = this.getField() || [];
// Only select if we have a valid id,
// and it isn't already selected
if (id && list.indexOf(id) === -1) {
this.setField(list.concat([id]));
}
};
/**
* Remove a domain object from the list of selected objects.
* @param {DomainObject} the domain object to select
*/
SelectorController.prototype.deselect = function (domainObject) {
var id = domainObject && domainObject.getId(),
list = this.getField() || [];
// Only change if this was a valid id,
// for an object which was already selected
if (id && list.indexOf(id) !== -1) {
// Filter it out of the current field
this.setField(list.filter(function (otherId) {
return otherId !== id;
}));
// Clear the current list selection
delete this.listModel.selectedObject;
}
};
/**
* Get the currently-selected domain objects.
* @returns {DomainObject[]} the current selection
*/
SelectorController.prototype.selected = function () {
return this.selectedObjects;
};
return SelectorController;
}
);
);

View File

@ -32,59 +32,58 @@ define(
/**
* Controller for the splitter in Browse mode. Current implementation
* uses many hard-coded constants; this could be generalized.
* @memberof platform/commonUI/general
* @constructor
*/
function SplitPaneController() {
var current = 200,
start = 200,
assigned = false;
return {
/**
* Get the current position of the splitter, in pixels
* from the left edge.
* @returns {number} position of the splitter, in pixels
*/
state: function (defaultState) {
// Set the state to the desired default, if we don't have a
// "real" current state yet.
if (arguments.length > 0 && !assigned) {
current = defaultState;
assigned = true;
}
return current;
},
/**
* Begin moving the splitter; this will note the splitter's
* current position, which is necessary for correct
* interpretation of deltas provided by mct-drag.
*/
startMove: function () {
start = current;
},
/**
* Move the splitter a number of pixels to the right
* (negative numbers move the splitter to the left.)
* This movement is relative to the position of the
* splitter when startMove was last invoked.
* @param {number} delta number of pixels to move
*/
move: function (delta, minimum, maximum) {
// Ensure defaults for minimum/maximum
maximum = isNaN(maximum) ? DEFAULT_MAXIMUM : maximum;
minimum = isNaN(minimum) ? DEFAULT_MINIMUM : minimum;
// Update current splitter state
current = Math.min(
maximum,
Math.max(minimum, start + delta)
);
//console.log(current + "; minimum: " + minimum + "; max: " + maximum);
}
};
this.current = 200;
this.start = 200;
this.assigned = false;
}
/**
* Get the current position of the splitter, in pixels
* from the left edge.
* @returns {number} position of the splitter, in pixels
*/
SplitPaneController.prototype.state = function (defaultState) {
// Set the state to the desired default, if we don't have a
// "real" current state yet.
if (arguments.length > 0 && !this.assigned) {
this.current = defaultState;
this.assigned = true;
}
return this.current;
};
/**
* Begin moving the splitter; this will note the splitter's
* current position, which is necessary for correct
* interpretation of deltas provided by mct-drag.
*/
SplitPaneController.prototype.startMove = function () {
this.start = this.current;
};
/**
* Move the splitter a number of pixels to the right
* (negative numbers move the splitter to the left.)
* This movement is relative to the position of the
* splitter when startMove was last invoked.
* @param {number} delta number of pixels to move
*/
SplitPaneController.prototype.move = function (delta, minimum, maximum) {
// Ensure defaults for minimum/maximum
maximum = isNaN(maximum) ? DEFAULT_MAXIMUM : maximum;
minimum = isNaN(minimum) ? DEFAULT_MINIMUM : minimum;
// Update current splitter state
this.current = Math.min(
maximum,
Math.max(minimum, this.start + delta)
);
};
return SplitPaneController;
}
);
);

View File

@ -30,37 +30,37 @@ define(
* A ToggleController is used to activate/deactivate things.
* A common usage is for "twistie"
*
* @memberof platform/commonUI/general
* @constructor
*/
function ToggleController() {
var state = false;
return {
/**
* Get the current state of the toggle.
* @return {boolean} true if active
*/
isActive: function () {
return state;
},
/**
* Set a new state for the toggle.
* @return {boolean} true to activate
*/
setState: function (newState) {
state = newState;
},
/**
* Toggle the current state; activate if it is inactive,
* deactivate if it is active.
*/
toggle: function () {
state = !state;
}
};
this.state = false;
}
/**
* Get the current state of the toggle.
* @return {boolean} true if active
*/
ToggleController.prototype.isActive = function () {
return this.state;
};
/**
* Set a new state for the toggle.
* @return {boolean} true to activate
*/
ToggleController.prototype.setState = function (newState) {
this.state = newState;
};
/**
* Toggle the current state; activate if it is inactive,
* deactivate if it is active.
*/
ToggleController.prototype.toggle = function () {
this.state = !this.state;
};
return ToggleController;
}
);
);

View File

@ -48,10 +48,12 @@ define(
* node expansion when this tree node's _subtree_ will contain
* the navigated object (recursively, this becomes an
* expand-to-show-navigated-object behavior.)
* @memberof platform/commonUI/general
* @constructor
*/
function TreeNodeController($scope, $timeout, agentService) {
var selectedObject = ($scope.ngModel || {}).selectedObject,
var self = this,
selectedObject = ($scope.ngModel || {}).selectedObject,
isSelected = false,
hasBeenExpanded = false;
@ -75,32 +77,6 @@ define(
((navPath[index] === nodePath[index]) &&
checkPath(nodePath, navPath, index + 1));
}
// Track that a node has been expanded, either by the
// user or automatically to show a selection.
function trackExpansion() {
if (!hasBeenExpanded) {
// Run on a timeout; if a lot of expansion needs to
// occur (e.g. if the selection is several nodes deep) we
// want this to be spread across multiple digest cycles.
$timeout(function () { hasBeenExpanded = true; }, 0);
}
}
// Sets the selected object in the tree, to be the
// currently represented object. If the user is on phone
// and in portrait mode, than, hide the tree menu
function setObject(ngModel, domainObject) {
ngModel.selectedObject = domainObject;
if (agentService.getOrientation() === "portrait" &&
agentService.isPhone(navigator.userAgent)) {
$scope.$emit('select-obj');
}
}
function checkMobile() {
return agentService.isMobile(navigator.userAgent);
}
// Consider the currently-navigated object and update
// parameters which support display.
@ -116,7 +92,7 @@ define(
// Deselect; we will reselect below, iff we are
// exactly at the end of the path.
isSelected = false;
self.isSelectedFlag = false;
// Expand if necessary (if the navigated object will
// be in this node's subtree)
@ -135,12 +111,12 @@ define(
// at the end of the path, highlight;
// otherwise, expand.
if (nodePath.length === navPath.length) {
isSelected = true;
self.isSelectedFlag = true;
} else { // node path is shorter: Expand!
if ($scope.toggle) {
$scope.toggle.setState(true);
}
trackExpansion();
self.trackExpansion();
}
}
@ -153,43 +129,69 @@ define(
selectedObject = object;
checkSelection();
}
this.isSelectedFlag = false;
this.hasBeenExpandedFlag = false;
this.$timeout = $timeout;
this.agentService = agentService;
this.$scope = $scope;
// Listen for changes which will effect display parameters
$scope.$watch("ngModel.selectedObject", setSelection);
$scope.$watch("domainObject", checkSelection);
return {
/**
* This method should be called when a node is expanded
* to record that this has occurred, to support one-time
* lazy loading of the node's subtree.
*/
trackExpansion: trackExpansion,
checkMobile: checkMobile,
setObject: setObject,
/**
* Check if this not has ever been expanded.
* @returns true if it has been expanded
*/
hasBeenExpanded: function () {
return hasBeenExpanded;
},
/**
* Check whether or not the domain object represented by
* this tree node should be highlighted.
* An object will be highlighted if it matches
* ngModel.selectedObject
* @returns true if this should be highlighted
*/
isSelected: function () {
return isSelected;
}
};
}
/**
* This method should be called when a node is expanded
* to record that this has occurred, to support one-time
* lazy loading of the node's subtree.
*/
TreeNodeController.prototype.trackExpansion = function () {
var self = this;
if (!self.hasBeenExpanded()) {
// Run on a timeout; if a lot of expansion needs to
// occur (e.g. if the selection is several nodes deep) we
// want this to be spread across multiple digest cycles.
self.$timeout(function () {
self.hasBeenExpandedFlag = true;
}, 0);
}
};
/**
* Check if this not has ever been expanded.
* @returns true if it has been expanded
*/
TreeNodeController.prototype.hasBeenExpanded = function () {
return this.hasBeenExpandedFlag;
};
/**
* Check whether or not the domain object represented by
* this tree node should be highlighted.
* An object will be highlighted if it matches
* ngModel.selectedObject
* @returns true if this should be highlighted
*/
TreeNodeController.prototype.isSelected = function () {
return this.isSelectedFlag;
};
// Sets the selected object in the tree, to be the
// currently represented object. If the user is on phone
// and in portrait mode, than, hide the tree menu
TreeNodeController.prototype.setObject = function (ngModel, domainObject) {
ngModel.selectedObject = domainObject;
if (this.agentService.getOrientation() === "portrait" &&
this.agentService.isPhone(navigator.userAgent)) {
this.$scope.$emit('select-obj');
}
};
TreeNodeController.prototype.checkMobile = function () {
return this.agentService.isMobile(navigator.userAgent);
};
return TreeNodeController;
}
);
);

View File

@ -32,6 +32,7 @@ define(
/**
* Controller for the view switcher; populates and maintains a list
* of applicable views for a represented domain object.
* @memberof platform/commonUI/general
* @constructor
*/
function ViewSwitcherController($scope, $timeout) {
@ -71,3 +72,4 @@ define(
return ViewSwitcherController;
}
);