devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
712 lines (620 loc) • 24.4 kB
JavaScript
var $ = require("../../core/renderer"),
iconUtils = require("../../core/utils/icon"),
hasWindow = require("../../core/utils/window").hasWindow(),
isDefined = require("../../core/utils/type").isDefined,
extend = require("../../core/utils/extend").extend,
inArray = require("../../core/utils/array").inArray,
iteratorUtils = require("../../core/utils/iterator"),
messageLocalization = require("../../localization/message"),
registerComponent = require("../../core/component_registrator"),
pivotGridUtils = require("./ui.pivot_grid.utils"),
TreeView = require("../tree_view"),
ContextMenu = require("../context_menu"),
BaseFieldChooser = require("./ui.pivot_grid.field_chooser_base"),
inArray = inArray,
each = iteratorUtils.each,
DIV = "<div>";
require("./data_source");
var FIELDCHOOSER_CLASS = "dx-pivotgridfieldchooser",
FIELDCHOOSER_CONTAINER_CLASS = "dx-pivotgridfieldchooser-container",
FIELDS_CONTAINER_CLASS = "dx-pivotgrid-fields-container",
AREA_DRAG_CLASS = "dx-pivotgrid-drag-action";
function getDimensionFields(item, fields) {
var result = [];
if (item.items) {
for (var i = 0; i < item.items.length; i++) {
result.push.apply(result, getDimensionFields(item.items[i], fields));
}
} else {
if (isDefined(item.index)) {
result.push(fields[item.index]);
}
}
return result;
}
function getFirstItem(item, condition) {
if (item.items) {
for (var i = 0; i < item.items.length; i++) {
var childrenItem = getFirstItem(item.items[i], condition);
if (childrenItem) {
return childrenItem;
}
}
}
if (condition(item)) {
return item;
}
}
var compareOrder = [function (a, b) {
var aValue = -!!a.isMeasure,
bValue = +!!b.isMeasure;
return aValue + bValue;
}, function (a, b) {
var aValue = -!!(a.items && a.items.length),
bValue = +!!(b.items && b.items.length);
return aValue + bValue;
}, function (a, b) {
var aValue = +!!(a.field && a.field.levels && a.field.levels.length),
bValue = -!!(b.field && b.field.levels && b.field.levels.length);
return aValue + bValue;
}, pivotGridUtils.getCompareFunction(function (item) {
return item.text;
})];
function compareItems(a, b) {
var result = 0,
i = 0;
while (!result && compareOrder[i]) {
result = compareOrder[i++](a, b);
}
return result;
}
function getScrollable(container) {
return container.find(".dx-scrollable").dxScrollable("instance");
}
var FieldChooser = BaseFieldChooser.inherit({
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
/**
* @name dxPivotGridFieldChooserOptions.height
* @publicName height
* @type number|string|function
* @default 400
* @type_function_return number|string
*/
height: 400,
/**
* @name dxPivotGridFieldChooserOptions.layout
* @publicName layout
* @type Enums.PivotGridFieldChooserLayout
* @default 0
*/
layout: 0,
/**
* @name dxPivotGridFieldChooserOptions.dataSource
* @publicName dataSource
* @type PivotGridDataSource
* @default null
* @ref
*/
dataSource: null,
/**
* @name dxPivotGridFieldChooserOptions.onContextMenuPreparing
* @publicName onContextMenuPreparing
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 items:Array<Object>
* @type_function_param1_field5 area:string
* @type_function_param1_field6 field:PivotGridDataSourceOptions.fields
* @type_function_param1_field7 jQueryEvent:jQuery.Event:deprecated(event)
* @type_function_param1_field8 event:event
* @extends Action
* @action
*/
onContextMenuPreparing: null,
/**
* @name dxPivotGridFieldChooserOptions.allowSearch
* @publicName allowSearch
* @type boolean
* @default false
*/
allowSearch: false,
/**
* @name dxPivotGridFieldChooserOptions.texts
* @publicName texts
* @type object
*/
texts: {
/**
* @name dxPivotGridFieldChooserOptions.texts.columnFields
* @publicName columnFields
* @type string
* @default 'Column Fields'
*/
columnFields: messageLocalization.format("dxPivotGrid-columnFields"),
/**
* @name dxPivotGridFieldChooserOptions.texts.rowFields
* @publicName rowFields
* @type string
* @default 'Row Fields'
*/
rowFields: messageLocalization.format("dxPivotGrid-rowFields"),
/**
* @name dxPivotGridFieldChooserOptions.texts.dataFields
* @publicName dataFields
* @type string
* @default 'Data Fields'
*/
dataFields: messageLocalization.format("dxPivotGrid-dataFields"),
/**
* @name dxPivotGridFieldChooserOptions.texts.filterFields
* @publicName filterFields
* @type string
* @default 'Filter Fields'
*/
filterFields: messageLocalization.format("dxPivotGrid-filterFields"),
/**
* @name dxPivotGridFieldChooserOptions.texts.allFields
* @publicName allFields
* @type string
* @default 'All Fields'
*/
allFields: messageLocalization.format("dxPivotGrid-allFields")
}
/**
* @name dxPivotGridFieldChooserOptions.applyChangesMode
* @publicName applyChangesMode
* @type Enums.ApplyChangesMode
* @default "instantly"
*/
/**
* @name dxPivotGridFieldChooserOptions.state
* @publicName state
* @type object
* @default null
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter
* @publicName headerFilter
* @type object
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.width
* @publicName width
* @type number
* @default 252
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.height
* @publicName height
* @type number
* @default 325
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.allowSearch
* @publicName allowSearch
* @type boolean
* @default undefined
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.texts
* @publicName texts
* @type object
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.texts.emptyValue
* @publicName emptyValue
* @type string
* @default "(Blanks)"
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.texts.ok
* @publicName ok
* @type string
* @default "Ok"
*/
/**
* @name dxPivotGridFieldChooserOptions.headerFilter.texts.cancel
* @publicName cancel
* @type string
* @default "Cancel"
*/
});
},
_refreshDataSource: function _refreshDataSource() {
var that = this;
that._expandedPaths = [];
that._changedHandler = that._changedHandler || function () {
each(that._dataChangedHandlers, function (_, func) {
func();
});
that._fireContentReadyAction();
that._skipStateChange = true;
that.option("state", that._dataSource.state());
that._skipStateChange = false;
};
if (that._dataSource) {
that._dataSource.off("changed", that._changedHandler);
that._dataSource = undefined;
}
that.callBase();
that._dataSource && that._dataSource.on("changed", that._changedHandler);
},
_init: function _init() {
this.callBase();
this._refreshDataSource();
this._dataChangedHandlers = [];
this._initActions();
},
_initActions: function _initActions() {
this._actions = {
onContextMenuPreparing: this._createActionByOption("onContextMenuPreparing")
};
},
_trigger: function _trigger(eventName, eventArg) {
this._actions[eventName](eventArg);
},
_setOptionsByReference: function _setOptionsByReference() {
this.callBase();
extend(this._optionsByReference, {
dataSource: true
});
},
_optionChanged: function _optionChanged(args) {
var that = this;
switch (args.name) {
case "dataSource":
that._refreshDataSource();
that._invalidate();
break;
case "layout":
case "texts":
case "allowSearch":
that._invalidate();
break;
case "onContextMenuPreparing":
that._actions[args.name] = that._createActionByOption(args.name);
break;
default:
that.callBase(args);
}
},
_clean: function _clean(skipStateSetting) {
!skipStateSetting && this._dataSource && this.option("state", this._dataSource.state());
this.$element().children("." + FIELDCHOOSER_CONTAINER_CLASS).remove();
},
_initMarkup: function _initMarkup() {
var that = this,
$element = this.$element(),
$container = $(DIV).addClass(FIELDCHOOSER_CONTAINER_CLASS).appendTo($element),
layout = that.option("layout"),
$col1,
$col2;
that.callBase();
$element.addClass(FIELDCHOOSER_CLASS).addClass(FIELDS_CONTAINER_CLASS);
that._dataChangedHandlers = [];
if (layout === 0) {
$col1 = $(DIV).addClass("dx-col").appendTo($container);
$col2 = $(DIV).addClass("dx-col").appendTo($container);
that._renderArea($col1, "all");
that._renderArea($col1, "filter");
that._renderArea($col2, "row");
that._renderArea($col2, "column");
that._renderArea($col2, "data");
} else if (layout === 1) {
$col1 = $(DIV).addClass("dx-col").appendTo($container);
$col2 = $(DIV).addClass("dx-col").appendTo($container);
that._renderArea($col1, "all");
that._renderArea($col2, "filter");
that._renderArea($col2, "row");
that._renderArea($col2, "column");
that._renderArea($col2, "data");
} else {
$container.addClass("dx-layout-2");
this._renderArea($container, "all");
var $layout2Container = $(DIV).addClass("dx-fields-container").appendTo($container);
$col1 = $(DIV).addClass("dx-col").appendTo($layout2Container);
$col2 = $(DIV).addClass("dx-col").appendTo($layout2Container);
that._renderArea($col1, "filter");
that._renderArea($col1, "row");
that._renderArea($col2, "column");
that._renderArea($col2, "data");
}
},
_renderContentImpl: function _renderContentImpl() {
this.callBase();
this.renderSortable();
this._renderContextMenu();
this.updateDimensions();
},
_fireContentReadyAction: function _fireContentReadyAction() {
if (!this._dataSource || !this._dataSource.isLoading()) {
this.callBase();
}
},
_getContextMenuArgs: function _getContextMenuArgs(dxEvent) {
var targetFieldElement = $(dxEvent.target).closest(".dx-area-field"),
targetGroupElement = $(dxEvent.target).closest(".dx-area-fields"),
field,
area;
if (targetFieldElement.length) {
field = targetFieldElement.data("field");
}
if (targetGroupElement.length) {
area = targetGroupElement.attr("group");
}
return {
event: dxEvent,
field: field,
area: area,
items: []
};
},
_renderContextMenu: function _renderContextMenu() {
var that = this,
$container = that.$element();
if (that._contextMenu) {
that._contextMenu.$element().remove();
}
that._contextMenu = that._createComponent($(DIV).appendTo($container), ContextMenu, {
onPositioning: function onPositioning(actionArgs) {
var event = actionArgs.event,
args;
if (!event) {
return;
}
args = that._getContextMenuArgs(event);
that._trigger("onContextMenuPreparing", args);
if (args.items && args.items.length) {
actionArgs.component.option("items", args.items);
} else {
actionArgs.cancel = true;
}
},
target: $container,
onItemClick: function onItemClick(params) {
params.itemData.onItemClick && params.itemData.onItemClick(params);
},
cssClass: "dx-pivotgridfieldchooser-context-menu"
});
},
_createTreeItems: function _createTreeItems(fields, groupFieldNames, path) {
var that = this,
isMeasure,
resultItems = [],
groupedItems = [],
groupFieldName = groupFieldNames[0],
fieldsByGroup = {};
if (!groupFieldName) {
each(fields, function (index, field) {
var icon;
if (field.isMeasure === true) {
icon = "measure";
}
if (field.isMeasure === false) {
icon = field.groupName ? "hierarchy" : "dimension";
}
resultItems.push({
index: field.index,
field: field,
key: field.dataField,
selected: isDefined(field.area),
text: field.caption || field.dataField,
icon: icon,
isMeasure: field.isMeasure,
isDefault: field.isDefault
});
});
} else {
each(fields, function (index, field) {
var groupName = field[groupFieldName] || "";
fieldsByGroup[groupName] = fieldsByGroup[groupName] || [];
fieldsByGroup[groupName].push(field);
if (isMeasure === undefined) {
isMeasure = true;
}
isMeasure = isMeasure && field.isMeasure === true;
});
each(fieldsByGroup, function (groupName, fields) {
var currentPath = path ? path + '.' + groupName : groupName;
var items = that._createTreeItems(fields, groupFieldNames.slice(1), currentPath);
if (groupName) {
groupedItems.push({
key: groupName,
text: groupName,
path: currentPath,
isMeasure: items.isMeasure,
expanded: inArray(currentPath, that._expandedPaths) >= 0,
items: items
});
} else {
resultItems = items;
}
});
resultItems = groupedItems.concat(resultItems);
resultItems.isMeasure = isMeasure;
}
return resultItems;
},
_createFieldsDataSource: function _createFieldsDataSource(dataSource) {
var fields = dataSource && dataSource.fields() || [],
treeItems;
fields = iteratorUtils.map(fields, function (field) {
return field.visible === false || isDefined(field.groupIndex) ? null : field;
});
treeItems = this._createTreeItems(fields, ["dimension", "displayFolder"]);
pivotGridUtils.foreachDataLevel(treeItems, function (items) {
items.sort(compareItems);
}, 0, "items");
return treeItems;
},
_renderFieldsTreeView: function _renderFieldsTreeView(container) {
var that = this,
dataSource = that._dataSource,
treeView = that._createComponent(container, TreeView, {
dataSource: that._createFieldsDataSource(dataSource),
showCheckBoxesMode: 'normal',
searchEnabled: that.option("allowSearch"),
itemTemplate: function itemTemplate(itemData, itemIndex, itemElement) {
if (itemData.icon) {
iconUtils.getImageContainer(itemData.icon).appendTo(itemElement);
}
$('<span>').toggleClass("dx-area-field", !itemData.items).data("field", itemData.field).text(itemData.text).appendTo(itemElement);
},
onItemCollapsed: function onItemCollapsed(e) {
var index = inArray(e.itemData.path, that._expandedPaths);
if (index >= 0) {
that._expandedPaths.splice(index, 1);
}
},
onItemExpanded: function onItemExpanded(e) {
var index = inArray(e.itemData.path, that._expandedPaths);
if (index < 0) {
that._expandedPaths.push(e.itemData.path);
}
},
onItemSelectionChanged: function onItemSelectionChanged(e) {
var data = e.itemData,
field,
fields,
needSelectDefaultItem = true,
area;
if (data.items) {
if (data.selected) {
treeView.unselectItem(data);
return;
}
fields = getDimensionFields(data, dataSource.fields());
for (var i = 0; i < fields.length; i++) {
if (fields[i].area) {
needSelectDefaultItem = false;
break;
}
}
if (needSelectDefaultItem) {
var item = getFirstItem(data, function (item) {
return item.isDefault;
}) || getFirstItem(data, function (item) {
return isDefined(item.index);
});
item && treeView.selectItem(item);
return;
}
} else {
field = dataSource.fields()[data.index];
if (data.selected) {
area = field.isMeasure ? "data" : "column";
}
if (field) {
fields = [field];
}
}
that._applyChanges(fields, {
area: area,
areaIndex: undefined
});
}
}),
dataChanged = function dataChanged() {
var scrollable = getScrollable(container),
scrollTop = scrollable ? scrollable.scrollTop() : 0;
treeView.option({ dataSource: that._createFieldsDataSource(dataSource) });
scrollable = getScrollable(container);
if (scrollable) {
scrollable.scrollTo({ y: scrollTop });
scrollable.update();
}
};
that._dataChangedHandlers.push(dataChanged);
},
_renderAreaFields: function _renderAreaFields($container, area) {
var that = this,
dataSource = that._dataSource,
fields = dataSource ? extend(true, [], dataSource.getAreaFields(area, true)) : [];
$container.empty();
each(fields, function (_, field) {
if (field.visible !== false) {
that.renderField(field, true).appendTo($container);
}
});
},
_renderArea: function _renderArea(container, area) {
var that = this,
$areaContainer = $(DIV).addClass("dx-area").appendTo(container),
$fieldsHeaderContainer = $(DIV).addClass("dx-area-fields-header").appendTo($areaContainer),
caption = that.option("texts." + area + "Fields"),
$fieldsContainer,
$fieldsContent,
render;
$("<span>").addClass("dx-area-icon").addClass("dx-area-icon-" + area).appendTo($fieldsHeaderContainer);
$("<span>").html(" ").appendTo($fieldsHeaderContainer);
$("<span>").addClass("dx-area-caption").text(caption).appendTo($fieldsHeaderContainer);
$fieldsContainer = $(DIV).addClass("dx-area-fields").addClass(AREA_DRAG_CLASS).appendTo($areaContainer);
if (area !== "all") {
$fieldsContainer.attr("group", area).attr("allow-scrolling", true);
$fieldsContent = $(DIV).addClass("dx-area-field-container").appendTo($fieldsContainer);
render = function render() {
that._renderAreaFields($fieldsContent, area);
};
that._dataChangedHandlers.push(render);
render();
$fieldsContainer.dxScrollable();
} else {
$areaContainer.addClass("dx-all-fields");
$fieldsContainer.addClass("dx-treeview-border-visible");
that._renderFieldsTreeView($fieldsContainer);
}
},
_getSortableOptions: function _getSortableOptions() {
// TODO
return {};
},
_adjustSortableOnChangedArgs: function _adjustSortableOnChangedArgs() {},
resetTreeView: function resetTreeView() {
var treeView = this.$element().find(".dx-treeview").dxTreeView("instance");
if (treeView) {
treeView.option("searchValue", "");
treeView.collapseAll();
}
},
/**
* @name dxPivotGridFieldChooserMethods.applyChanges
* @publicName applyChanges()
*/
applyChanges: function applyChanges() {
var state = this.option("state");
if (isDefined(state)) {
this._dataSource.state(state);
}
},
/**
* @name dxPivotGridFieldChooserMethods.cancelChanges
* @publicName cancelChanges()
*/
cancelChanges: function cancelChanges() {
this.option("state", this._dataSource.state());
},
/**
* @name dxPivotGridFieldChooserMethods.getDataSource
* @publicName getDataSource()
* @return PivotGridDataSource
*/
getDataSource: function getDataSource() {
return this._dataSource;
},
/**
* @name dxPivotGridFieldChooserMethods.updateDimensions
* @publicName updateDimensions()
*/
updateDimensions: function updateDimensions() {
var $scrollableElements = this.$element().find(".dx-area .dx-scrollable");
$scrollableElements.dxScrollable("update");
},
_visibilityChanged: function _visibilityChanged(visible) {
if (visible && hasWindow) {
this.updateDimensions();
}
}
});
registerComponent("dxPivotGridFieldChooser", FieldChooser);
module.exports = FieldChooser;
;