[Common UI] Generalize click-away behavior

Add a general-purpose controller for UI elements which
have 'click-away' behavior; that is, they should be
deactivated on document clicks.

This generalizes existing behavior added for the Create
menu, such that it may be used on other, similar menus
and UI elements.

Part of ongoing transition of common user interface
components, WTD-574.
This commit is contained in:
Victor Woeltjen 2014-11-24 07:12:45 -08:00
parent 42de4b8b13
commit 3a5a015097
3 changed files with 88 additions and 3 deletions

View File

@ -1,8 +1,8 @@
<div class="menu-element wrapper" ng-controller="CreateButtonController">
<div class="btn btn-menu create-btn major" ng-click="toggle()">
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
<div class="btn btn-menu create-btn major" ng-click="createController.toggle()">
<span class='ui-symbol major' href=''>+</span> Create<!--span class='ui-symbol invoke-menu'>v</span-->
</div>
<div class="menu dropdown super-menu" ng-show="createState.visible">
<div class="menu dropdown super-menu" ng-show="createController.isActive()">
<mct-representation mct-object="domainObject" key="'create-menu'">
</mct-representation>
</div>

View File

@ -36,6 +36,11 @@
"key": "ContextMenuController",
"implementation": "ContextMenuController.js",
"depends": [ "$scope" ]
},
{
"key": "ClickAwayController",
"implementation": "ClickAwayController.js",
"depends": [ "$scope", "$document" ]
}
],
"directives": [

View File

@ -0,0 +1,80 @@
/*global define,Promise*/
define(
[],
function () {
"use strict";
/**
* A ClickAwayController is used to toggle things (such as context
* menus) where clicking elsewhere in the document while the toggle
* is in an active state is intended to dismiss the toggle.
*
* @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;
// 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();
}
}
// 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();
$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();
}
};
}
return ClickAwayController;
}
);