/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* The SlideOverlay layout allows content to be placed in an always visible container where some additional overlaid
* content can be animated to slide in over the top of it. An example might be where you select an item in the main
* content and you want a configuration overlay to appear.
*
* When defining the widget model to be processed simply set an attribute of "align" to "overlay" for it to be placed
* in the overlay container and everything else will be placed in the main (or underlay) container.
*
* @module alfresco/layout/SlideOverlay
* @extends external:dijit/_WidgetBase
* @mixes external:dojo/_TemplatedMixin
* @mixes module:alfresco/core/Core
* @mixes module:alfresco/core/CoreWidgetProcessing
* @author Dave Draper
*/
define(["dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!./templates/SlideOverlay.html",
"alfresco/core/Core",
"alfresco/core/CoreWidgetProcessing",
"alfresco/core/ResizeMixin",
"dojo/_base/lang",
"dojo/_base/array",
"dojo/on",
"dojo/dom-geometry",
"dojo/dom-class",
"dojo/dom-style",
"dojo/fx",
"dojo/_base/fx"],
function(declare, _WidgetBase, _TemplatedMixin, template, AlfCore, CoreWidgetProcessing, ResizeMixin,
lang, array, on, domGeom, domClass, domStyle, coreFx, baseFx) {
return declare([_WidgetBase, _TemplatedMixin, AlfCore, CoreWidgetProcessing, ResizeMixin], {
/**
* An array of the CSS files to use with this widget.
*
* @instance
* @type {object[]}
* @default [{cssFile:"./css/SlideOverlay.css"}]
*/
cssRequirements: [{cssFile:"./css/SlideOverlay.css"}],
/**
* The HTML template to use for the widget.
* @instance
* @type {string}
*/
templateString: template,
/**
* This should be configured to be an array of Strings where each string represents a topic that
* when published on will trigger the overlay to be displayed.
*
* that
* @instance
* @type {string[]}
* @default
*/
showTopics: null,
/**
* This should be configured to be an array of Strings where each string represents a topic that
* when published on will trigger the overlay to be hidden.
*
* @instance
* @type {string[]}
* @default
*/
hideTopics: null,
/**
* This should be configured to be an array of Strings where each string represents a custom event (e.g.
* one that is triggered by calling the .emit() function) that will trigger the overlay to be displayed.
*
* that
* @instance
* @type {string[]}
* @default
*/
showEvents: null,
/**
* This should be configured to be an array of Strings where each string represents a custom event (e.g.
* one that is triggered by calling the .emit() function) that will trigger the overlay to be hidden.
*
* @instance
* @type {string[]}
* @default
*/
hideEvents: null,
/**
* This should be configured to be an array of Strings where each string represents a topic that
* when published on will trigger the overall height to be updated.
*
* that
* @instance
* @type {string[]}
* @default
*/
adjustHeightTopics: null,
/**
* This should be configured to be an array of Strings where each string represents a custom event (e.g.
* one that is triggered by calling the .emit() function) that will trigger the overall height to be updated.
*
* that
* @instance
* @type {string[]}
* @default
*/
adjustHeightEvents: null,
/**
* Sets up the subscriptions and event handlers to showing and hiding the overlay and then processes all
* the configured widets to place them into the correct DOM element (i.e the underlay or the overlay).
*
* @instance
*/
postCreate: function alfresco_layout_SlideOverlay__postCreate() {
// Set up all the subscription and event handlers...
array.forEach(this.showTopics, function(topic) {
this.alfSubscribe(topic, lang.hitch(this, "showOverlay"));
}, this);
array.forEach(this.hideTopics, function(topic) {
this.alfSubscribe(topic, lang.hitch(this, "hideOverlay"));
}, this);
array.forEach(this.showEvents, function(eventName) {
on(this.domNode, eventName, lang.hitch(this, "showOverlay"));
}, this);
array.forEach(this.hideEvents, function(eventName) {
on(this.domNode, eventName, lang.hitch(this, "hideOverlay"));
}, this);
array.forEach(this.adjustHeightTopics, function(topic) {
this.alfSubscribe(topic, lang.hitch(this, "adjustHeight"));
}, this);
array.forEach(this.adjustHeightEvents, function(eventName) {
on(this.domNode, eventName, lang.hitch(this, "adjustHeight"));
}, this);
// Process the widgets..
if (this.widgets)
{
// Iterate over all the widgets in the configuration object and add them...
this.processWidgets(this.widgets);
}
// A MutationObserver allows us to capture events that occur as the DOM model is updated.
// Unfortunately it is not supported in all browsers, but for those that do it is possible
// to update the height of the widget much more accurately...
if (typeof MutationObserver === "function")
{
var observer = new MutationObserver(lang.hitch(this, "adjustHeight")),
config = { attributes: true, childList: true, characterData: true, subtree: true };
observer.observe(this.overlayNode, config);
observer.observe(this.underlayNode, config);
}
},
/**
* @instance
* @param {Element} rootNode
* @param {object} widgetConfig
* @param {number} index
*/
processWidget: function alfresco_layout_SlideOverlay__processWidget(rootNode, widgetConfig, /*jshint unused:false*/ index) {
if (this.filterWidget(widgetConfig))
{
var domNode = null;
if (widgetConfig.align === "overlay")
{
domNode = this.createWidgetDomNode(widgetConfig, this.overlayNode, widgetConfig.className);
}
else
{
domNode = this.createWidgetDomNode(widgetConfig, this.underlayNode, widgetConfig.className);
}
this.createWidget(widgetConfig, domNode, this._registerProcessedWidget, this);
}
},
/**
* Used to indicate whether or not the overlay is currently hidden.
*
* @instance
* @type {boolean}
* @default
*/
overlayHidden: true,
/**
* This displays the overlay by sliding it in over the main node. By default this will slide
* to the middle of the main DOM node.
*
* @instance
*/
showOverlay: function alfresco_layout_SlideOverlay__showOverlay() {
domClass.remove(this.overlayNode, "hide");
this.overlayHidden = false;
window.setTimeout(lang.hitch(this, function() {
this.alfPublishResizeEvent(this.overlayNode);
}), 100);
},
/**
* Adjusts the height of the overall DOM node (through animation) to be as high as is required. This
* will either be the height of the overlay or the height of the underlay depending upon which is greater.
*
* @instance
*/
adjustHeight: function alfresco_layout_SlideOverlay__adjustHeight() {
// TODO:
// 1) Does it make sense to set inherit as the dom node height when the overlay is not displayed (this allows the dom to be updated)
// 2) How to adjust height of the overlay as it changes
// Get the current computed heights of both the overlay and underlay...
var overlayMarginBox = domGeom.getMarginBox(this.overlayNode),
underlayMarginBox = domGeom.getMarginBox(this.underlayNode);
// Pick the tallest and set it on the DOM node...
var newHeight = (overlayMarginBox.h > underlayMarginBox.h) ? overlayMarginBox.h : underlayMarginBox.h;
baseFx.animateProperty({
node: this.domNode,
properties: {
height: newHeight
}
}).play();
},
/**
* Hides the overlay.
*
* @instance
*/
hideOverlay: function alfresco_layout_SlideOverlay__hideOverlay() {
domClass.add(this.overlayNode, "hide");
this.overlayHidden = true;
}
});
});