define(['dojo/_base/declare',
|
'dojo/_base/lang',
|
'dojo/_base/array',
|
'dojo/dom-geometry',
|
'dojo/dom-style',
|
'dojo/dom-class',
|
'dojo/dom-construct',
|
'dojo/fx',
|
'dojo/on',
|
'dojo/query',
|
'dojo/aspect',
|
'jimu/BaseWidget',
|
'jimu/PoolControllerMixin',
|
'./DockableItem',
|
'./GroupItems',
|
'./PopupMoreNodes'
|
], function(declare, lang, array, domGeometry, domStyle, domClass, domConstruct, coreFx, on,
|
query, aspect, BaseWidget, PoolControllerMixin, DockableItem, GroupItems, PopupMoreNodes){
|
/* global jimuConfig*/
|
var MIN_MARGIN = 8, ICON_SIZE = 40, ICON_IMG_SIZE = 20, BUTTON_SIZE = 60,
|
NORMAL_MODE = 1, MOBILE_MODE = 2;
|
/**
|
* @exports themes/LaunchpadTheme/widgets/AnchorBarController/Widget
|
*/
|
var clazz = declare([BaseWidget, PoolControllerMixin], {
|
baseClass: 'jimu-anchorbar-controller',
|
|
visibleIcons: 0,
|
iconList: [],
|
enableNext: false,
|
enablePrevious: false,
|
currentMode: NORMAL_MODE,
|
iconMargin: MIN_MARGIN,
|
groupList: [],
|
openedIds: [],
|
currentStyle: 'default',
|
|
postCreate: function(){
|
this.inherited(arguments);
|
|
this.iconList = [];
|
this.groupList = [];
|
this.openedIds = [];
|
this.currentStyle = this.appConfig.theme.styles[0];
|
this.allConfigs = this.getAllConfigs();
|
|
array.forEach(this.allConfigs, function(configItem, index){
|
this._createItem(configItem, index);
|
}, this);
|
},
|
|
_createItem: function(configItem, index){
|
var item, itemGroup, containerNode;
|
item = new DockableItem({
|
config: configItem,
|
backgroundIndex: index
|
});
|
item.placeAt(this.iconGroupNode);
|
this.iconList.push(item);
|
|
if(item.isGroup()){
|
//create widget group icon
|
itemGroup = new GroupItems({
|
config: configItem,
|
dockableItem: item
|
});
|
|
if(window.appInfo.isRunInMobile){
|
containerNode = jimuConfig.layoutId;
|
}else{
|
containerNode = jimuConfig.mapId;
|
}
|
itemGroup.placeAt(containerNode);
|
domStyle.set(itemGroup.domNode, 'display', 'none');
|
|
this.own(on(itemGroup, 'groupItemClicked', lang.hitch(this, function(data){
|
this._onDockableNodeClick(data.target);
|
})));
|
|
this.own(on(item, 'nodeClick', lang.hitch(this, function(data){
|
this._onGroupNodeClick(data.target, itemGroup);
|
})));
|
|
this.groupList.push(itemGroup);
|
}else{
|
this.own(on(item, 'nodeClick', lang.hitch(this, function(data){
|
this._onDockableNodeClick(data.target);
|
})));
|
}
|
|
return item;
|
},
|
|
startup: function() {
|
this.inherited(arguments);
|
this.resize();
|
|
// handle open at start widget, only one is allowed to open at start
|
array.some(this.iconList, function(iconItem, index){
|
if(iconItem.isOpenAtStart()){
|
if(!window.appInfo.isRunInMobile){
|
this._makeIconVisible(index);
|
}
|
iconItem._onNodeClick();
|
return true;
|
}
|
}, this);
|
},
|
|
destroy: function(){
|
this.inherited(arguments);
|
|
array.forEach(this.groupList, function(widgetGroup){
|
widgetGroup.destroy();
|
});
|
},
|
|
onAction: function(action, data) {
|
/*jshint unused: false*/
|
if (action === 'highLight' && data) {
|
var node = query('div[settingid="' + data.widgetId + '"]', this.domNode)[0];
|
this._highLight(node);
|
}
|
if (action === 'removeHighLight') {
|
this._removeHighLight();
|
}
|
},
|
|
onOpen: function(){
|
if(this.iconList.length === 0 && this.appConfig.mode !== 'config'){
|
this.widgetManager.closeWidget(this);
|
}
|
},
|
|
onAppConfigChanged: function(appConfig){
|
this.currentStyle = appConfig.theme.styles[0];
|
},
|
|
/**
|
* @override
|
* @param {[type]} ids [description]
|
*/
|
setOpenedIds: function(ids) {
|
var item;
|
if (ids.length === 0) {
|
return;
|
}
|
array.forEach(ids, function(id){
|
item = this._getIconItemById(id);
|
if(item !== null){
|
item._onNodeClick();
|
}
|
}, this);
|
},
|
|
getOpenedIds: function() {
|
this.inherited(arguments);
|
|
return array.filter(this.openedIds, function(item){
|
return typeof item !== 'undefined';
|
});
|
},
|
|
_highLight: function(node) {
|
if (this.hlDiv) {
|
this._removeHighLight();
|
}
|
if (!node || domStyle.get(node, 'display') === 'none') {
|
return;
|
}
|
var marginLeft = domStyle.get(node, 'margin-left');
|
var position = domGeometry.getMarginBox(node);
|
var hlStyle = {
|
position: 'absolute',
|
left: (position.l + marginLeft) + 'px',
|
top: (position.t) + 'px',
|
width: ICON_SIZE + 'px',
|
height: ICON_SIZE + 'px'
|
};
|
if(this.currentStyle !== 'style2'){
|
hlStyle['margin-top'] = (-ICON_SIZE / 2) + 'px';
|
}
|
this.hlDiv = domConstruct.create('div', {
|
"style": hlStyle,
|
"class": 'icon-highlight'
|
}, node, 'before');
|
},
|
|
_removeHighLight: function() {
|
if (this.hlDiv) {
|
domConstruct.destroy(this.hlDiv);
|
this.hlDiv = null;
|
}
|
},
|
|
clearIconGroupNode: function(){
|
while(this.iconGroupNode.firstChild) {
|
this.iconGroupNode.removeChild(this.iconGroupNode.firstChild);
|
}
|
},
|
|
resize: function(){
|
if(window.appInfo.isRunInMobile){
|
if(this.currentMode === NORMAL_MODE){
|
//mode changed
|
this.currentMode = MOBILE_MODE;
|
domClass.add(this.domNode, 'mobile');
|
this.clearIconGroupNode();
|
this.lastVisibleIcons = 0;
|
}
|
|
if(this.popupMore){
|
this.popupMore.hide();
|
}
|
|
this.switchToMobileStyle();
|
}else{
|
if(this.currentMode === MOBILE_MODE){
|
//mode changed
|
this.currentMode = NORMAL_MODE;
|
domClass.remove(this.domNode, 'mobile');
|
this.clearIconGroupNode();
|
this.lastVisibleIcons = 0;
|
|
//set width of iconGroupNode large enough to hold all the icons
|
domStyle.set(this.iconGroupNode, 'width',
|
this.allConfigs.length * 2 * ICON_SIZE + 'px');
|
|
array.forEach(this.iconList, function(iconItem){// recreate icon list once
|
iconItem.placeAt(this.iconGroupNode);
|
}, this);
|
}
|
|
this.switchToNormalStyle();
|
}
|
this._resizeOpenedPanel();
|
},
|
|
switchToMobileStyle: function(){
|
var mapBox, containerSize, iconGroupWidth;
|
|
mapBox = domGeometry.getContentBox(jimuConfig.mapId);
|
containerSize = mapBox.w;
|
|
iconGroupWidth = Math.max(containerSize, this.allConfigs.length * 2 * ICON_SIZE);
|
//set width of iconGroupNode large enough to hold all the icons
|
domStyle.set(this.iconGroupNode, 'width', iconGroupWidth + 'px');
|
|
//calculate widgets
|
this.visibleIcons = Math.floor(containerSize / (ICON_SIZE + MIN_MARGIN));
|
if(this.visibleIcons >= this.iconList.length){
|
this.visibleIcons = this.iconList.length;
|
}
|
|
if(this.visibleIcons !== this.lastVisibleIcons){
|
this.lastVisibleIcons = this.visibleIcons;
|
this.clearIconGroupNode();
|
this._reArrangeIconItems(containerSize);
|
}else{
|
this._adjustIconMargin(containerSize);
|
}
|
},
|
|
_reArrangeIconItems: function(currentWidth){
|
var showMore, normalIconNumber, moreIconItem, moreItemArray = [], args;
|
|
showMore = this.visibleIcons < this.iconList.length;
|
normalIconNumber = showMore ? (this.visibleIcons - 1) : this.visibleIcons;
|
this.iconMargin = Math.floor((currentWidth - (this.visibleIcons * ICON_SIZE)) /
|
(this.visibleIcons + 1));
|
|
array.forEach(this.iconList, function(item, index){
|
//clear styles set in PopupMoreNodes.js
|
args = {
|
display: '',
|
position: '',
|
left: '',
|
top: ''
|
};
|
//reset the size of iconItem and image
|
domStyle.set(item.iconItemNode, {
|
width: ICON_SIZE + 'px',
|
height: ICON_SIZE + 'px'
|
});
|
domStyle.set(item.imgNode, {
|
width: ICON_IMG_SIZE + 'px',
|
height: ICON_IMG_SIZE + 'px'
|
});
|
if(index < normalIconNumber){
|
if(window.isRTL){
|
args['margin-right'] = this.iconMargin + 'px';
|
}else{
|
args['margin-left'] = this.iconMargin + 'px';
|
}
|
domStyle.set(item.domNode, args);
|
item.placeAt(this.iconGroupNode);
|
}else{
|
domStyle.set(item.domNode, args);
|
moreItemArray.push(item);
|
}
|
}, this);
|
|
if(showMore){
|
moreIconItem = this._createIconItemForMore();
|
args = {};
|
if(window.isRTL){
|
args['margin-right'] = this.iconMargin + 'px';
|
}else{
|
args['margin-left'] = this.iconMargin + 'px';
|
}
|
domStyle.set(moreIconItem.domNode, args);
|
moreIconItem.placeAt(this.iconGroupNode);
|
|
this.own(on(moreIconItem, 'nodeClick', lang.hitch(this, function(data){
|
this._onShowMoreNodeClick(data.target, moreItemArray);
|
})));
|
}
|
},
|
|
_createIconItemForMore: function(){
|
var moreIconItem = new DockableItem({
|
config: {
|
id: 'show_more_widget_icons',
|
label: this.nls.more,
|
icon: this.folderUrl + 'images/more_icon.png'
|
},
|
backgroundIndex: this.visibleIcons
|
});
|
|
return moreIconItem;
|
},
|
|
_adjustIconMargin: function(currentWidth){
|
var args = {};
|
this.iconMargin = Math.floor((currentWidth - (this.visibleIcons * ICON_SIZE)) /
|
(this.visibleIcons + 1));
|
|
if(window.isRTL){
|
args['margin-right'] = this.iconMargin + 'px';
|
}else{
|
args['margin-left'] = this.iconMargin + 'px';
|
}
|
|
query('div.jimu-anchorbar-iconitem', this.iconGroupNode).forEach(function(node){
|
domStyle.set(node, args);
|
}, this);
|
},
|
|
switchToNormalStyle: function(){
|
var mapBox, widgetWidth, left, containerSize,
|
firstVisible = 0, lastVisible;
|
|
mapBox = domGeometry.getContentBox(jimuConfig.mapId);
|
widgetWidth = Math.floor(mapBox.w / 2);
|
|
if(widgetWidth > this.allConfigs.length * (ICON_SIZE + MIN_MARGIN) + BUTTON_SIZE){
|
widgetWidth = this.allConfigs.length * (ICON_SIZE + MIN_MARGIN) + BUTTON_SIZE;
|
}
|
left = Math.floor((mapBox.w - widgetWidth) / 2);
|
|
domStyle.set(this.domNode, {
|
width: widgetWidth + 'px',
|
left: left + 'px'
|
});
|
|
//calculate widgets
|
containerSize = widgetWidth - BUTTON_SIZE;
|
this.visibleIcons = Math.floor(containerSize / (ICON_SIZE + MIN_MARGIN));
|
if(this.visibleIcons > this.iconList.length){
|
this.visibleIcons = this.iconList.length;
|
}
|
|
//calculate the visible range
|
array.some(this.iconList, function(item, index){
|
if(item.visible){
|
firstVisible = index;
|
return true;
|
}
|
});
|
|
lastVisible = firstVisible + this.visibleIcons - 1;
|
if(lastVisible >= this.iconList.length){
|
lastVisible = this.iconList.length - 1;
|
firstVisible = lastVisible - this.visibleIcons + 1;
|
}
|
|
this.iconMargin = Math.floor((containerSize - (this.visibleIcons * ICON_SIZE)) /
|
(this.visibleIcons + 1));
|
|
this._adjustIconStyle(firstVisible, lastVisible);
|
},
|
|
_previous: function(){
|
var idxFirst = -1, idxLast = -1, animArray = [];
|
if(this.enablePrevious){
|
//find the first visible iconItem
|
array.some(this.iconList, function(iconItem, index){
|
if(iconItem.visible){
|
idxFirst = index - 1;//get the previous item index
|
return true;
|
}
|
}, this);
|
|
if(idxFirst >= 0){
|
idxLast = idxFirst + this.visibleIcons;
|
animArray = animArray.concat(this.iconList[idxLast].hideAnim(this.iconMargin),
|
this.iconList[idxFirst].showAnim(this.iconMargin));
|
coreFx.combine(animArray).play();
|
|
this.enableNext = true;
|
domClass.add(this.nextButton, 'enabled');
|
|
if(idxFirst === 0){
|
this.enablePrevious = false;
|
domClass.remove(this.previousButton, 'enabled');
|
}
|
}
|
}
|
},
|
|
_next: function(){
|
var idxFirst = -1, idxLast = -1, animArray = [];
|
if(this.enableNext){
|
//find the first visible iconItem
|
array.some(this.iconList, function(iconItem, index){
|
if(iconItem.visible){
|
idxFirst = index;
|
return true;
|
}
|
}, this);
|
|
if(idxFirst >= 0){
|
idxLast = idxFirst + this.visibleIcons;
|
animArray = animArray.concat(this.iconList[idxFirst].hideAnim(this.iconMargin),
|
this.iconList[idxLast].showAnim(this.iconMargin));
|
coreFx.combine(animArray).play();
|
|
this.enablePrevious = true;
|
domClass.add(this.previousButton, 'enabled');
|
|
if(idxLast === this.iconList.length - 1){
|
this.enableNext = false;
|
domClass.remove(this.nextButton, 'enabled');
|
}
|
}
|
}
|
},
|
|
_getGroupPanelPosition: function(dockableItem, widgetBox){
|
var position = {},
|
iconBox = domGeometry.position(dockableItem.iconItemNode),
|
mapBox = domGeometry.getContentBox(jimuConfig.mapId);
|
|
position.top = iconBox.y - widgetBox.h - MIN_MARGIN;
|
|
if (window.isRTL) {
|
if(iconBox.x < widgetBox.w + MIN_MARGIN){
|
position.left = MIN_MARGIN;
|
}else{
|
position.left = iconBox.x - widgetBox.w + iconBox.w;
|
}
|
} else {
|
if(iconBox.x + widgetBox.w + MIN_MARGIN > mapBox.w){
|
position.left = mapBox.w - widgetBox.w - MIN_MARGIN;
|
}else{
|
position.left = iconBox.x;
|
}
|
}
|
return position;
|
},
|
|
//off panel widget position
|
_getOffPanelPosition: function(dockableItem, widgetBox){
|
var position = {},
|
iconBox = domGeometry.position(dockableItem.iconItemNode),
|
mapBox = domGeometry.getContentBox(jimuConfig.mapId);
|
|
position.bottom = mapBox.h - (iconBox.y + MIN_MARGIN) + ICON_SIZE / 2;
|
|
if (window.isRTL) {
|
if(iconBox.x < widgetBox.w + MIN_MARGIN){
|
position.right = mapBox.w - widgetBox.w - MIN_MARGIN;
|
}else{
|
position.right = iconBox.x - widgetBox.w;
|
}
|
} else {
|
if(iconBox.x + widgetBox.w + MIN_MARGIN > mapBox.w){
|
position.left = mapBox.w - widgetBox.w - MIN_MARGIN;
|
}else{
|
position.left = iconBox.x;
|
}
|
}
|
if(dockableItem.config.position) {
|
position.relativeTo = dockableItem.config.position.relativeTo;
|
}
|
return position;
|
},
|
|
_createPopupMoreNodes: function(){
|
if(!this.popupMore){
|
this._createCoverNode();
|
|
this.popupMore = new PopupMoreNodes();
|
this.popupMore.placeAt(jimuConfig.mapId);
|
|
aspect.after(this.popupMore, 'show', lang.hitch(this, function() {
|
domStyle.set(this.moreIconPaneCoverNode, 'display', '');
|
}), true);
|
|
aspect.after(this.popupMore, 'hide', lang.hitch(this, function() {
|
domStyle.set(this.moreIconPaneCoverNode, 'display', 'none');
|
}), true);
|
}
|
},
|
|
_onShowMoreNodeClick: function(dockableItem, moreItemsArray){
|
this._createPopupMoreNodes();
|
|
if(dockableItem.isOpen){
|
this.popupMore.setForIcon(dockableItem);
|
this.popupMore.setNodes(moreItemsArray);
|
this.popupMore.show();
|
}else{
|
this.popupMore.hide();
|
}
|
},
|
|
_getIconItemById: function(id){
|
var ret = null;
|
|
array.some(this.iconList, function(item){
|
if(item.config.id === id){
|
ret = item;
|
return true;
|
}
|
});
|
|
if(ret === null){
|
array.some(this.groupList, function(groupItem){
|
return array.some(groupItem.getItemList(), function(item){
|
if(item.config.id === id){
|
ret = item;
|
return true;
|
}
|
});
|
});
|
}
|
|
return ret;
|
},
|
|
_addToOpenedIds: function(id){
|
if(this.openedIds.indexOf(id) === -1){
|
this.openedIds.push(id);
|
}
|
},
|
|
_removeFromOpenedIds: function(id){
|
var idx = this.openedIds.indexOf(id);
|
if(idx !== -1){
|
this.openedIds[idx] = undefined;
|
}
|
},
|
|
_onGroupNodeClick: function(dockableItem, groupItem){
|
var position;
|
|
if(dockableItem.isOpen){
|
position = this._getGroupPanelPosition(dockableItem, groupItem.box);
|
groupItem.setPosition(position);
|
groupItem.open();
|
this._addToOpenedIds(dockableItem.config.id);
|
}else{
|
groupItem.close();
|
this._removeFromOpenedIds(dockableItem.config.id);
|
}
|
},
|
|
_onDockableNodeClick: function(dockableItem){
|
var panelId, panelConfig;
|
if(dockableItem.config.inPanel === false){
|
if(dockableItem.isOpen){
|
this.widgetManager.loadWidget(dockableItem.config).then(
|
lang.hitch(this, function(widget) {
|
this._addToOpenedIds(dockableItem.config.id);
|
|
var position = this._getOffPanelPosition(dockableItem,
|
this.widgetManager.getWidgetMarginBox(widget));
|
position.zIndex = 100;
|
widget.setPosition(position, this.containerNode);
|
this.widgetManager.openWidget(widget);
|
|
this.own(aspect.after(widget, 'onClose', lang.hitch(this, function() {
|
dockableItem.setOpened(false);
|
this._removeFromOpenedIds(dockableItem.config.id);
|
})));
|
}));
|
}else{
|
this.widgetManager.closeWidget(dockableItem.config.id);
|
this._removeFromOpenedIds(dockableItem.config.id);
|
}
|
}else{
|
panelId = dockableItem.config.id + '_panel';
|
if(dockableItem.isOpen){
|
dockableItem.setPanelIndex(this._calPanelIndex());
|
panelConfig = dockableItem.getConfigForPanel();
|
|
this.panelManager.showPanel(panelConfig).then(lang.hitch(this, function(panel){
|
panel.setPosition(panelConfig.panel.position);
|
aspect.after(panel, 'onClose', lang.hitch(this, function(){
|
dockableItem.setOpened(false);
|
this._removeFromOpenedIds(dockableItem.config.id);
|
}));
|
}));
|
|
if(this.popupMore){
|
this.popupMore.hide();
|
}
|
this._addToOpenedIds(dockableItem.config.id);
|
}else{
|
this.panelManager.closePanel(panelId);
|
this._removeFromOpenedIds(dockableItem.config.id);
|
}
|
}
|
},
|
|
_calPanelIndex: function(){
|
var openedList = [], i, len;
|
|
//collect panel index of opened widget.
|
array.forEach(this.iconList, function(item){
|
if(!item.isGroup() && item.config.inPanel !== false && item.isOpen){
|
openedList.push(item.getPanelIndex());
|
}
|
});
|
array.forEach(this.groupList, function(groupItem){
|
array.forEach(groupItem.getItemList(), function(item){
|
if(item.config.inPanel !== false && item.isOpen){
|
openedList.push(item.getPanelIndex());
|
}
|
});
|
});
|
|
if(openedList.length === 0){
|
return 0;
|
}
|
|
//sort asc
|
openedList.sort(function(a, b){
|
return a - b;
|
});
|
|
//Find the smallest panel index that is not used.
|
if(openedList[0] > 0){
|
return 0;
|
}
|
|
for(i = 0, len = openedList.length - 1 ; i < len; i++){
|
if(openedList[i + 1] - openedList[i] > 1){
|
return openedList[i] + 1;
|
}
|
}
|
|
return openedList[len] + 1;
|
},
|
|
_createCoverNode: function() {
|
this.moreIconPaneCoverNode = domConstruct.create('div', {
|
'class': 'jimu-more-icon-cover'
|
}, jimuConfig.layoutId);
|
},
|
|
_resizeOpenedPanel: function(){
|
var panel;
|
//collect panel index of opened widget.
|
array.forEach(this.iconList, function(item){
|
if(!item.isGroup() && item.config.inPanel !== false && item.isOpen){
|
panel = this.panelManager.getPanelById(item.config.id + '_panel');
|
if(panel){
|
panel.onWindowResize();
|
}
|
}
|
}, this);
|
array.forEach(this.groupList, function(groupItem){
|
array.forEach(groupItem.getItemList(), function(item){
|
if(item.config.inPanel !== false && item.isOpen){
|
panel = this.panelManager.getPanelById(item.config.id + '_panel');
|
if(panel){
|
panel.onWindowResize();
|
}
|
}
|
}, this);
|
}, this);
|
},
|
|
/**
|
* Used by open at start widget. Make the widget icon at the center of the anchor bar.
|
* @param {number} index [description]
|
*/
|
_makeIconVisible: function(index){
|
var firstVisible, lastVisible;
|
if(this.visibleIcons === this.iconList.length){
|
return;
|
}
|
|
firstVisible = index - Math.floor(this.visibleIcons / 2);
|
firstVisible = firstVisible >= 0 ? firstVisible : 0;
|
lastVisible = firstVisible + this.visibleIcons - 1;
|
if(lastVisible >= this.iconList.length){
|
lastVisible = this.iconList.length - 1;
|
firstVisible = lastVisible - this.visibleIcons + 1;
|
}
|
|
this._adjustIconStyle(firstVisible, lastVisible);
|
},
|
|
_adjustIconStyle: function(firstVisible, lastVisible){
|
var args;
|
array.forEach(this.iconList, function(iconItem, index){
|
iconItem.visible = index >= firstVisible && index <= lastVisible;
|
args = {
|
position: '',
|
left: '',
|
top: '',
|
display: iconItem.visible ? '' : 'none'
|
};
|
if(window.isRTL){
|
args['margin-right'] = this.iconMargin + 'px';
|
}else{
|
args['margin-left'] = this.iconMargin + 'px';
|
}
|
domStyle.set(iconItem.domNode, args);
|
domStyle.set(iconItem.iconItemNode, {
|
width: ICON_SIZE + 'px',
|
height: ICON_SIZE + 'px'
|
});
|
domStyle.set(iconItem.imgNode, {
|
width: ICON_IMG_SIZE + 'px',
|
height: ICON_IMG_SIZE + 'px'
|
});
|
}, this);
|
|
if(lastVisible < this.allConfigs.length - 1){
|
domClass.add(this.nextButton, 'enabled');
|
this.enableNext = true;
|
}else{
|
domClass.remove(this.nextButton, 'enabled');
|
this.enableNext = false;
|
}
|
|
if(firstVisible > 0){
|
this.enablePrevious = true;
|
domClass.add(this.previousButton, 'enabled');
|
}else{
|
this.enablePrevious = false;
|
domClass.remove(this.previousButton, 'enabled');
|
}
|
}
|
});
|
return clazz;
|
});
|