[Common UI] Reorganize general UI bundle

Reorganize sources for bundle platform/commonUI/general;
number of classes here has grown as a consequence of
additions for WTD-614 and so an additional layer of
organization is helpful.

Conflicts:
	platform/commonUI/general/bundle.json
	platform/commonUI/general/src/directives/MCTResize.js
This commit is contained in:
Victor Woeltjen
2014-12-30 13:34:24 -08:00
parent 8dfee64dc8
commit 112622ab9f
12 changed files with 97 additions and 10 deletions

View File

@ -0,0 +1,78 @@
/*global define,Promise*/
/**
* Module defining MCTContainer. Created by vwoeltje on 11/17/14.
*/
define(
[],
function () {
"use strict";
/**
* The mct-container is similar to the mct-include directive
* insofar as it allows templates to be referenced by
* symbolic keys instead of by URL. Unlike mct-include, it
* supports transclusion.
*
* Unlike mct-include, mct-container accepts a key as a
* plain string attribute, instead of as an Angular
* expression.
*
* @constructor
*/
function MCTContainer(containers) {
var containerMap = {};
// Initialize container map from extensions
containers.forEach(function (container) {
var key = container.key;
containerMap[key] = Object.create(container);
containerMap[key].templateUrl = [
container.bundle.path,
container.bundle.resources,
container.templateUrl
].join("/");
});
return {
// Allow only at the element level
restrict: 'E',
// Support transclusion
transclude: true,
// Create a new (non-isolate) scope
scope: true,
// Populate initial scope based on attributes requested
// by the container definition
link: function (scope, element, attrs) {
var key = attrs.key,
container = containerMap[key],
alias = "container",
copiedAttributes = {};
if (container) {
alias = container.alias || alias;
(container.attributes || []).forEach(function (attr) {
copiedAttributes[attr] = attrs[attr];
});
}
scope[alias] = copiedAttributes;
},
// Get the template URL for this container, based
// on its attributes.
templateUrl: function (element, attrs) {
var key = attrs.key;
return containerMap[key].templateUrl;
}
};
}
return MCTContainer;
}
);

View File

@ -0,0 +1,130 @@
/*global define*/
define(
[],
function () {
"use strict";
/**
* The mct-drag directive allows drag functionality
* (in the mousedown-mousemove-mouseup sense, as opposed to
* the drag-and-drop sense) to be attached to specific
* elements. This takes the form of three attributes:
*
* * `mct-drag`: An Angular expression to evaluate during
* drag movement.
* * `mct-drag-down`: An Angular expression to evaluate
* when the drag begins.
* * `mct-drag-up`: An Angular expression to evaluate when
* dragging ends.
*
* In each case, a variable `delta` will be provided to the
* expression; this is a two-element array or the horizontal
* and vertical pixel offset of the current mouse position
* relative to the mouse position where dragging began.
*
* @constructor
*
*/
function MCTDrag($document) {
// Link; install event handlers.
function link(scope, element, attrs) {
// Keep a reference to the body, to attach/detach
// mouse event handlers; mousedown and mouseup cannot
// only be attached to the element being linked, as the
// mouse may leave this element during the drag.
var body = $document.find('body'),
initialPosition,
delta;
// Utility function to cause evaluation of mctDrag,
// mctDragUp, etc
function fireListener(name) {
// Evaluate the expression, with current delta
scope.$eval(attrs[name], { delta: delta });
// Trigger prompt digestion
scope.$apply();
}
// Update positions (both actual and relative)
// based on a new mouse event object.
function updatePosition(event) {
// Get the current position, as an array
var currentPosition = [ event.pageX, event.pageY ];
// Track the initial position, if one hasn't been observed
initialPosition = initialPosition || currentPosition;
// Compute relative position
delta = currentPosition.map(function (v, i) {
return v - initialPosition[i];
});
}
// Called during a drag, on mousemove
function continueDrag(event) {
updatePosition(event);
fireListener("mctDrag");
// Don't show selection highlights, etc
event.preventDefault();
return false;
}
// Called only when the drag ends (on mouseup)
function endDrag(event) {
// Detach event handlers
body.off("mouseup", endDrag);
body.off("mousemove", continueDrag);
// Also call continueDrag, to fire mctDrag
// and do its usual position update
continueDrag(event);
fireListener("mctDragUp");
// Clear out start-of-drag position
initialPosition = undefined;
// Don't show selection highlights, etc
event.preventDefault();
return false;
}
// Called on mousedown on the element
function startDrag(event) {
// Listen for mouse events at the body level,
// since the mouse may leave the element during
// the drag.
body.on("mouseup", endDrag);
body.on("mousemove", continueDrag);
// Set an initial position
updatePosition(event);
// Fire listeners, including mctDrag
fireListener("mctDragDown");
fireListener("mctDrag");
// Don't show selection highlights, etc
event.preventDefault();
return false;
}
// Listen for mousedown on the element
element.on("mousedown", startDrag);
}
return {
// mct-drag only makes sense as an attribute
restrict: "A",
// Link function, to install event handlers
link: link
};
}
return MCTDrag;
}
);

View File

@ -0,0 +1,82 @@
/*global define*/
define(
[],
function () {
"use strict";
// Default resize interval
var DEFAULT_INTERVAL = 100;
/**
* The mct-resize directive allows the size of a displayed
* HTML element to be tracked. This is done by polling,
* since the DOM API does not currently provide suitable
* events to watch this reliably.
*
* Attributes related to this directive are interpreted as
* follows:
*
* * `mct-resize`: An Angular expression to evaluate when
* the size changes; the variable `bounds` will be provided
* with two fields, `width` and `height`, both in pixels.
* * `mct-resize-interval`: Optional; the interval, in milliseconds,
* at which to watch for updates. In some cases checking for
* resize can carry a cost (it forces recalculation of
* positions within the document) so it may be preferable to watch
* infrequently. If omitted, a default of 100ms will be used.
* This is an Angular expression, and it will be re-evaluated after
* each interval.
*
* @constructor
*
*/
function MCTResize($timeout) {
// Link; start listening for changes to an element's size
function link(scope, element, attrs) {
var lastBounds;
// Determine how long to wait before the next update
function currentInterval() {
return attrs.mctResizeInterval ?
scope.$eval(attrs.mctResizeInterval) :
DEFAULT_INTERVAL;
}
// Evaluate mct-resize with the current bounds
function fireEval(bounds) {
// Only update when bounds actually change
if (!lastBounds ||
lastBounds.width !== bounds.width ||
lastBounds.height !== bounds.height) {
scope.$eval(attrs.mctResize, { bounds: bounds });
lastBounds = bounds;
}
}
// Callback to fire after each timeout;
// update bounds and schedule another timeout
function onInterval() {
fireEval({
width: element[0].offsetWidth,
height: element[0].offsetHeight
});
$timeout(onInterval, currentInterval());
}
// Handle the initial callback
onInterval();
}
return {
// mct-resize only makes sense as an attribute
restrict: "A",
// Link function, to begin watching for changes
link: link
};
}
return MCTResize;
}
);