/*
* Copyright 2017 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tree for displaying a hierarchy of simple contents
* @private
*/
Ext.define('Ametys.plugins.cms.content.tree.HierarchicalReferenceTablesTree', {
extend: 'Ext.tree.Panel',
/**
* @cfg {Object} rootCfg The configuration of the root node
*/
/**
* @cfg {String} [referenceTableId] The content type of the leaves of this tree. Not mandatory, can be set later with {@link #setReferenceTableId} method.
*/
/**
* @cfg {Boolean} checkMode To select contents with checkboxes. Defaults to 'false'.
*/
checkMode : false,
/**
* @property {Boolean} true if this tool supports candidates.
*/
allowCandidates: false,
/**
* @cfg {String/String[]} [values] If {@link #cfg-checkMode}=true, the list of contents to initially check
*/
values: [],
/**
* @private
* @property {String[]} _valuesToBeChecked The values to be checked
*/
/**
* @private
* @property {String} _referenceTableId The simple content type the tree is displaying
*/
/**
* @cfg {Boolean} [allowToggleAutoposting=false] Set to `true` to allow autoposting during search.
*/
/**
* @cfg {Boolean} [activeAutoposting=false] Set to `true` to allow autoposting during search.
*/
/**
* @property {Boolean} [_activeAutoposting=false] See {@link #cfg-activeAutoposting}
* @private
*/
_activeAutoposting: false,
/**
* @property {Boolean} [_activeSelectAllChildren=false] Enabled if {@link #_activeAutoposting} is true.
* @private
*/
_activeSelectAllChildren: false,
/**
* @cfg {String} buttonAutopostingEnabledIconCls The separated CSS classes to apply to button for autoposting enabled
*/
buttonAutopostingEnabledIconCls: 'ametysicon-text decorator-ametysicon-check34 referencetable-autoposting referencetable-autoposting-enabled',
/**
* @cfg {String} buttonAutopostingDisabledIconCls The separated CSS classes to apply to button for autoposting disabled
*/
buttonAutopostingDisabledIconCls: 'ametysicon-text decorator-ametysicon-delete30 referencetable-autoposting referencetable-autoposting-disabled',
/**
* @cfg {Boolean} [checkSelection=false] Set to true to disable selection if node is not 'selectable'
*/
checkSelection: false,
statics: {
/**
* The default filter.
*/
DEFAULT_FILTER: function(node)
{
return node ? true : false;
}
},
initComponent: function ()
{
this.on('checkchange', this._onCheckChange, this);
this.on('beforeselect', this._onBeforeSelect, this);
this.callParent();
},
constructor: function(config)
{
this.contenttypesIds = config.rootCfg.contenttypesIds;
Ext.apply(this, {
store: this._getStoreCfg(config.rootCfg || {}, config.checkSelection)
});
// Docked items
var dockedItems = [];
dockedItems.push(this._getTopToolbarCfg(config));
dockedItems.push(this._getNoResultPanelCfg());
config.dockedItems = dockedItems;
this._counter = {};
this._filterConfig = config.filter || Ametys.plugins.cms.content.tree.HierarchicalReferenceTablesTree.DEFAULT_FILTER;
this._filterValue = null;
this._referenceTableId = config.referenceTableId;
this.values = [];
var values = config.values ? Ext.Array.from(config.values) : [];
this.callParent(arguments);
this.on('itemmouseenter', this._createQtip, this);
if (this.checkMode)
{
this.store.on('load', this._updateCheckboxes, this);
}
},
/**
* Sets the id of reference table of the leaves of this tree
* @param {String} referenceTableId The content type of the leaves of this tree
*/
setReferenceTableId: function(referenceTableId)
{
this._referenceTableId = referenceTableId;
},
/**
* Initialize the tree
* @param {String} cTypeId The id of content type to initialize the tree's root node
* @param {Boolean} [allowCandidates] Set to true to allow candidates
*/
initializeTree: function(cTypeId, allowCandidates)
{
var cType = Ametys.cms.content.ContentTypeDAO.getContentType(cTypeId);
// Set the root node
this.setRootNode({
title: cType.getLabel(),
text: cType.getLabel(),
contenttypesIds: [cType.getId()],
contentId: 'root',
id: 'root',
allowDrag : false,
allowDrop : true,
iconGlyph: cType.getIconGlyph(),
iconDecorator: cType.getIconDecorator(),
iconSmall: cType.getIconSmall(),
iconMedium: cType.getIconMedium(),
iconLarge: cType.getIconLarge()
});
this.allowCandidates = allowCandidates || false;
// Initialize no filter result action
this.down("button[itemId='no-result']").handler = this.allowCandidates ? this._createCandidateFromFilter : this._clearSearchFilter;
var noResultText = "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH}}";
noResultText += this.allowCandidates ? "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH_CREATE_CANDIDATE_ACTION}}" : "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH_ACTION}}";
this.down("button[itemId='no-result']").setText(noResultText);
// Load the tree
var node = this.getRootNode();
this.getStore().load({
node: node,
callback: function () {
this.expandNode (node, false);
},
scope: this
});
},
/**
* @protected
* Gets the configuration of the store
* @param {Object} rootCfg The configuration of the root node
* @param {Boolean} checkSelection True to check if selection is authorized
* @return {Object} The config of the store
*/
_getStoreCfg: function(rootCfg, checkSelection)
{
return {
model: 'Ametys.plugins.cms.content.tree.HierarchicalReferenceTablesTree.HierarchicalReferenceTablesTreeEntry',
autoLoad: false,
proxy: {
type: 'ametys',
plugin: 'cms',
url: 'hierarchical-reference-tables/tree.json',
reader: {
type: 'json',
rootProperty: 'children'
},
extraParams: {
checkSelection: checkSelection === true
}
},
root: Ext.apply(rootCfg, {
id: 'root',
contentId: 'root',
name: 'root'
}),
rootCandidate: {
id: 'rootCandidate',
contentId: 'rootCandidate',
name: 'rootCandidate',
cls: 'root-candidate'
},
folderSort: true,
sorters: [{
property: 'type',
direction: 'ASC'
},
{
property: 'text',
direction: 'ASC'
}],
listeners: {
'beforeload': {fn: this._onBeforeLoad, scope: this},
'load': {fn: this._onLoad, scope: this, single: true}
}
};
},
/**
* @protected
* @param {Object} config The configuration passed to the constructor
* Retrieves the top toolbar config object.
*/
_getTopToolbarCfg: function(config)
{
var items = [{
// Filter input
xtype: 'textfield',
cls: 'ametys',
flex: 1,
maxWidth: 300,
itemId: 'search-filter-input',
emptyText: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER}}",
enableKeyEvents: true,
minLength: 3,
minLengthText: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_INVALID}}",
msgTarget: 'qtip',
listeners: {change: Ext.Function.createBuffered(this._searchFilter, 500, this)},
style: {
marginRight: '0px'
}
},
{
// Clear filter
tooltip: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_TREE_CLEAR_FILTER}}",
handler: Ext.bind (this._clearSearchFilter, this),
iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
cls: 'a-btn-light'
},
{
xtype: 'tbspacer',
flex: 0.0001
},
{
// Collapse all
tooltip: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_COLLAPSE_ALL}}",
handler: Ext.bind (this.collapseAll, this, [function(){this.expandNode(this.getRootNode())}], false),
iconCls: 'a-btn-glyph ametysicon-minus-sign4 size-16',
cls: 'a-btn-light'
},
{
// Refresh node
tooltip: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_REFRESH_PAGE}}",
handler: Ext.bind (this.refreshNode, this, [], false),
iconCls: 'a-btn-glyph ametysicon-arrow123 size-16',
cls: 'a-btn-light'
}
];
var allowToggleAutoposting = config.allowToggleAutoposting === true || config.allowToggleAutoposting == 'true';
if (allowToggleAutoposting)
{
this._activeAutoposting = config.activeAutoposting === true || config.activeAutoposting == 'true';
// Button to activate / deactivate autoposting
items.push(Ext.create('Ext.button.Button', {
itemId: 'toggle-autoposting',
text: '',
iconCls: this._activeAutoposting ? this.buttonAutopostingEnabledIconCls : this.buttonAutopostingDisabledIconCls,
tooltip: this._activeAutoposting ? "{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_ENABLED}}" : "{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_DISABLED}}",
enableToggle: true,
pressed: this._activeAutoposting,
toggleHandler: function (btn, state) {
this._activeAutoposting = state;
if (this._activeAutoposting)
{
btn.setIconCls(this.buttonAutopostingEnabledIconCls);
btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_ENABLED}}")
}
else
{
btn.setIconCls(this.buttonAutopostingDisabledIconCls);
btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_DISABLED}}");
}
if (this.checkMode)
{
var childrenBtn = this.down("button[itemId='select-children']");
childrenBtn.setDisabled(this._activeAutoposting);
if (this._activeAutoposting)
{
childrenBtn.toggle(false);
}
}
},
scope: this
}));
if (config.checkMode)
{
this._activeSelectAllChildren = false;
// Button to automatically select children in the tree
items.push({
iconCls: 'a-btn-glyph ametysicon-blank32 size-16',
itemId: 'select-children',
tooltip: "{{i18n WIDGET_REFERENCE_TABLE_SELECT_ALL_CHILDREN_INACTIVE}}",
pressed: false,
disabled: this._activeAutoposting,
enableToggle: true,
toggleHandler: function (btn, state) {
this._activeSelectAllChildren = state;
if (this._activeSelectAllChildren)
{
btn.setIconCls('a-btn-glyph ametysicon-check51 size-16');
btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_SELECT_ALL_CHILDREN_ACTIVE}}");
}
else
{
btn.setIconCls('a-btn-glyph ametysicon-blank32 size-16');
btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_SELECT_ALL_CHILDREN_INACTIVE}}");
}
},
scope: this
});
}
}
return {
dock: 'top',
xtype: 'toolbar',
itemId: 'top-toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
defaultType: 'button',
items: items
};
},
/**
* @protected
* Retrieves the 'no result' panel config
*/
_getNoResultPanelCfg: function()
{
var text = "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH}}";
text += "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH_ACTION}}"
return {
dock: 'top',
xtype: 'button',
hidden: true,
itemId: 'no-result',
ui: 'tool-hintmessage',
text: text,
scope: this,
handler: this._clearSearchFilter
};
},
/**
* This listener is called on 'change' event on filter input field.
* Filters the tree by text input.
* @param {Ext.form.Field} field The field
* @private
*/
_searchFilter: function (field)
{
var value = new String(field.getValue()).trim();
this._filterField = field;
if (this._filterValue == value)
{
// Do nothing
return;
}
this._filterValue = value;
if (value.length > 2)
{
var rootNode = this.getRootNode();
this._getFilteredReferenceTable(value, rootNode);
}
else
{
this._hideNoResultPanel();
this.clearFilter();
}
},
/**
* Clear all filters
*/
clearFilter: function()
{
this.getStore().clearFilter();
},
/**
* Filters by a function. The specified function will be called for each Record in this Store.
* If the function returns true the Record is included, otherwise it is filtered out.
* @param {Function} filterFn A function to be called.
*/
filterBy: function (filterFn)
{
this.clearFilter();
this.getStore().filterBy(filterFn);
},
/**
* Hide the panel showing there is no result.
* @private
*/
_hideNoResultPanel: function ()
{
this.down("button[itemId='no-result']").setVisible(false);
},
/**
* Show the panel showing there is no result.
* @private
*/
_showNoResultPanel: function ()
{
this.down("button[itemId='no-result']").setVisible(true);
},
/**
* Get the reference tables the name matches the given value
* @param {String} value The value to match
* @param {Ext.data.Model} rootNode The root node
* @param {Ext.data.Model} node The initial node to search from. Can be null. If null start from root node.
* @param {Function} [callback] The function called on server response. Transmited to #_filterTermsCb.
* @private
*/
_getFilteredReferenceTable: function (value, rootNode, node, callback)
{
node = node || rootNode;
if (node.childNodes.length == 0)
{
// There is no reference table yet, do not filter
return;
}
var leafContentType = this.contenttypesIds ? this.contenttypesIds[0]: rootNode.get("contenttypesIds")[0];
var nodeId = node.get('contentId');
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.content.referencetable.HierarchicalReferenceTablesHelper",
methodName: 'filterReferenceTablesByRegExp',
parameters: [value, nodeId, leafContentType],
errorMessage: "{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_SEARCH_ERROR}}",
callback: {
handler: this._filterTermsCb,
scope: this,
arguments: {
node: node,
callback: callback
}
},
cancelCode: this.self.getName() + '$' + this.getId()
});
},
/**
* @private
* Callback function after searching reference tables
* @param {Object} result The result object
* @param {Object[]} args The callback arguments
*/
_filterTermsCb: function(result, args)
{
var hasResult = false;
var node = args.node || this.getRootNode();
var callback = args.callback;
if (!result)
{
return;
}
if (result.length == 0)
{
this.filterBy (function () {return false});
}
else
{
hasResult = true;
this._expandAndFilter (result, this.getRootNode(), node);
}
if (!hasResult)
{
this._showNoResultPanel();
this.getSelectionModel().deselectAll();
Ext.defer (this._filterField.markInvalid, 100, this._filterField, ["{{i18n PLUGINS_CMS_REFERENCE_TABLE_TREE_FILTER_NO_MATCH}}"]);
}
else
{
this._hideNoResultPanel();
this._filterField.clearInvalid();
}
if (Ext.isFunction(callback))
{
callback();
}
},
/**
* Expand the tree to the given paths. Then filter nodes matching the given paths by calling the #_filterPaths method
* @param {Object[]} paths The paths to expand
* @param {Ext.data.Model} rootNode The concerned root node
* @param {Ext.data.Model} node The node from which apply filter
* @private
*/
_expandAndFilter: function(paths, rootNode, node)
{
node = node || rootNode;
this._counter[rootNode.getId()] = paths.length;
for (var i=0; i < paths.length; i++)
{
var path = paths[i];
var options = {
field: 'name',
separator: null,
callback: Ext.bind (this._filterPaths, this, [paths, rootNode, node], 2)
};
this.expandPath (rootNode.getPath('name') + '/' + paths[i], options);
}
},
/**
* Filter nodes by path once the last expand has been processed
* @param {Boolean} success true if the expand was successful
* @param {Ext.data.Model} lastNode the last node that was expanded
* @param {String[]} paths The path to filter by
* @param {Ext.data.Model} rootNode The concerned root node
* @param {Ext.data.Model} node The node from which apply filter
* @private
*/
_filterPaths: function (success, lastNode, paths, rootNode, node)
{
// only execute the filterBy after the last expandPath()
if (--this._counter[rootNode.getId()] == 0)
{
var filterFn = Ext.bind (this._filterByPath, this, [paths, rootNode], true);
// FIXME Ensure that expand is complete by deferring the filterBy function ...
Ext.defer(this.filterBy, 50, this, [filterFn, node]);
}
},
/**
* Returns true if the node path is a part of given paths
* @param {Ext.data.Model} node The node to test
* @param {String[]} paths The paths
* @param {Ext.data.Model} rootNode The root node to build the complete paths
* @private
*/
_filterByPath: function (node, paths, rootNode)
{
var currentPath = node.getPath('name');
for (var i=0; i < paths.length; i++)
{
var path = rootNode.getPath('name') + '/' + paths[i];
if (path.indexOf(currentPath + '/') == 0)
{
return true;
}
if (path == currentPath)
{
return this._filterConfig(node);
}
}
return false;
},
/**
* Clear the filter search
* @param {Ext.Button} btn The button
* @private
*/
_clearSearchFilter: function(btn)
{
this.clearFilter();
var filterFd = this.down("textfield[itemId='search-filter-input']");
filterFd.reset();
this._filterValue = null;
this._hideNoResultPanel();
},
/**
* Create a new candidate from filter value
* @param {Ext.Button} btn The clicked button
* @private
*/
_createCandidateFromFilter: function (btn)
{
var filterFd = this.down("textfield[itemId='search-filter-input']");
var filterValue = filterFd.getValue();
var me = this;
this._clearSearchFilter();
Ametys.plugins.cms.content.actions.CandidatesActions.open({
mode: 'new',
contentType: this._referenceTableId,
contentLanguage: Ametys.cms.language.LanguageDAO.getCurrentLanguage(),
contentTitle: filterValue,
workflowName: 'reference-table' // FIME Hard coded
});
},
/**
* @private
* Single listener invoked at first load
* Select the current values
* @param {Ext.data.TreeStore} store The tree store
* @param {Ext.data.TreeModel[]} records The records
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.Operation} operation The operation that triggered this load.
* @param {Ext.data.NodeInterface} node The loaded node
*/
_onLoad: function (store, records, successful, operation, node)
{
if (!Ext.isEmpty(this.values))
{
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.content.referencetable.HierarchicalReferenceTablesHelper",
methodName: "getPathInHierarchy",
parameters: [this.values],
callback: {
handler: this._getReferenceTablePathsCb,
scope: this
},
waitMessage: false
});
}
},
/**
* @private
* Listener invoked when loading a node
* Update the checkbox state.
* @param {Ext.data.TreeStore} store The tree store
* @param {Ext.data.TreeModel[]} records The records
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.Operation} operation The operation that triggered this load.
* @param {Ext.data.NodeInterface} node The loaded node
*/
_updateCheckboxes: function(store, records, successful, operation, node)
{
this._setCheckboxes(node);
},
/**
* Iterate through the children nodes, and call #_setCheckbox
* @param {Ext.data.Model} node The node to iterate
* @private
*/
_setCheckboxes: function(node)
{
var childNodes = node.childNodes;
for (var i=0; i < childNodes.length; i++)
{
this._setCheckbox(childNodes[i]);
this._setCheckboxes(childNodes[i]);
}
},
/**
* Put a checkbox on nodes that can be checked, with the corresponding state. Does not verify any rights.
* @param {Ext.data.Model} node The node
* @private
*/
_setCheckbox: function(node)
{
if (this.checkSelection && node.get('disabled'))
{
node.set('checked', null);
}
else if (!node.get('disabled'))
{
node.set('checked', Ext.Array.contains(this.values, node.get('contentId')));
}
},
/**
* @private
* Callback function invoked after getting path in tree of contents
* Selects or checks nodes.
* @param {Object} paths The paths for each content
*/
_getReferenceTablePathsCb: function(paths)
{
var me = this;
Ext.Object.eachValue(paths, function(path)
{
me.expandNodeByPath(path, function (sucessfull, node) {
if (sucessfull)
{
if (me.checkMode)
{
node.set('checked', true);
}
else
{
me.getSelectionModel().select(node);
}
}
});
});
},
/**
* Get the root node where all the candidates are referenced
*/
getRootCandidate: function()
{
var index = this.getStore().findExact('contentId', 'rootCandidate');
return this.getStore().getAt(index);
},
/**
* Expand the tree to the given path.
* @param {String[]} path The path to expand
* @param {Function} callback The callback function to call after expand. Can be null.
*/
expandNodeByPath: function(path, callback)
{
var rootNode = this.getRootNode();
this.expandPath (rootNode.getPath('name') + "/" + path, 'name', null, callback);
},
/**
* This function reload the given node
* @param {String} id The id of the node to reload
* @param {Function} callback The callback function to call after reload. Can be null. Has the following parameters:
* @param {Ext.data.Model} callback.node The refreshed node
*/
refreshNode: function (id, callback)
{
var node;
if (id == null)
{
var selection = this.getSelectionModel().getSelection();
node = selection.length > 0 ? selection[0] : null;
// Workaround - Refresh selection in case node is not existing anymore (deleted by another user for example).
if (node != null)
{
this.getSelectionModel().deselect(node);
this.getSelectionModel().select(node);
}
}
else
{
node = this.getStore().getNodeById(id);
}
if (node != null)
{
// Set leaf to false, to allow children to be added during the load. Leaf will be set to true again if needed after the load.
node.set('leaf', false);
this.getStore().load({
node: node,
callback: function() {
if (this._filterValue && this._filterValue.length > 2)
{
this._getFilteredReferenceTable (this._filterValue, this.getRootNode(), node, callback ? Ext.bind(callback, null, [node]) : null);
}
else
{
Ext.defer(this._expandNode, 200, this, [node, callback]);
}
},
scope: this
});
}
},
/**
* Expand the given node
* @param {String} node The node to expand.
* @param {Function} callback The callback function to call after reload. Can be null. Has the following parameters:
* @param {Ext.data.Model} callback.node The expended node
* @private
*/
_expandNode: function (node, callback)
{
if (node == null)
{
var selection = this.getSelectionModel().getSelection();
node = selection.length > 0 ? selection[0] : null;
}
if (node != null)
{
if (!node.hasChildNodes())
{
node.set('leaf', true);
}
callback = callback ? Ext.bind(callback, null, [node]) : null;
this.expandNode (node, false, callback);
}
this.expandNode (node, false, callback);
},
/**
* @private
* Listener before a request is made
* @param {Ext.data.TreeStore} store The store
* @param {Ext.data.operation.Operation} operation The Ext.data.operation.Operation object that will be passed to the Proxy to load the Store
*/
_onBeforeLoad: function(store, operation)
{
operation.setParams(Ext.apply(operation.getParams() || {}, {
leafContentType: this._referenceTableId,
contentId: operation.node.get('contentId')
}));
},
/**
* Verify if a node can be checked. If it can, his value is updated
* @param {Ext.data.Model} node The node which state was updated
* @param {Boolean} checked The new node state
* @private
*/
_onCheckChange: function(node, checked)
{
if (this.checkSelection === true && node.get('disabled'))
{
// cancel check
node.set('checked', false);
}
else if (checked === true && Ext.Array.contains(this.values, node.get('contentId')) === false)
{
this.values.push(node.get('contentId'));
if (!this._activeAutoposting && this._activeSelectAllChildren)
{
this._checkChildren(node);
}
}
else if (checked === false && Ext.Array.contains(this.values, node.get('contentId')) === true)
{
Ext.Array.remove(this.values, node.get('contentId'));
}
},
/**
* @private
* Expand and check recursively all children of the given node
* @param {Ext.data.NodeInterface} node The current node
*/
_checkChildren: function(node)
{
node.expand(false, function()
{
node.eachChild(function(childNode)
{
childNode.set('checked', true);
this.values.push(childNode.get('contentId'));
this._checkChildren(childNode);
}, this);
}, this);
},
/**
* @private
* Listener before selecting node in the tree
* @param {Ext.selection.Model} sm the selection model
* @param {Ext.data.Model} record The selected record
* @return {Boolean} return false if the selection is cancelled
*/
_onBeforeSelect: function(sm, record)
{
// Cancel selection is node is disabled
return !this.checkSelection || !record.get('disabled');
},
/**
* Destroy and create the node tooltip when the mouse enters the node
* @param {Ext.view.View} view The tree view
* @param {Ext.data.Model} node The tree node
* @param {HTMLElement} el The node's element
*/
_createQtip: function (view, node, el)
{
Ext.QuickTips.unregister(el);
var tip = this._getTooltip(node);
Ext.QuickTips.register(Ext.apply({target: el, id: el.id + '-tooltip', renderTo: Ext.getBody()}, tip));
},
/**
* Get the tooltip configuration
* @param {Ext.data.Model} node The tree node
* @returns {Object} The tooltip configuration. See Ametys.ui.fluent.Tooltip.
* @private
*/
_getTooltip: function(node)
{
return {
title: node.get('title'),
glyphIcon: node.get('iconCls'),
text: node.get('tooltip'),
imageWidth: 48,
imageHeight: 48,
inribbon: false
};
},
/**
* Return true if the autoposting button is toggled, otherwise false.
*/
isActiveAutoposting: function()
{
return this._activeAutoposting;
}
});