Ext.ns('Zarafa.common.searchfield.ui');
/**
* @class Zarafa.common.searchfield.ui.SearchFolderCombo
* @extends Ext.form.ComboBox
* @xtype zarafa.searchfoldercombo
*
* This class can be used to construct a search folder combo box which
* manly contains 'All folders', 'Current folder', 'Imported folder' and 'Other..' options.
* which represent IPM_SUBTREE, currently selected folder in hierarchy, folder which imported
* in search folder combo box using {@link Zarafa.advancesearch.dialogs.SelectFolderContentPanel SelectFolderContentPanel}
* respectively. while 'Other...' option used to open the {@link Zarafa.advancesearch.dialogs.SelectFolderContentPanel SelectFolderContentPanel}
*/
Zarafa.common.searchfield.ui.SearchFolderCombo = Ext.extend(Ext.form.ComboBox, {
/**
* The {@link Zarafa.core.ContextModel} which is obtained from the {@link #context}.
* @property
* @type Zarafa.core.ContextModel
*/
model : undefined,
/**
* @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to <tt>70</tt>, will
* be ignored if <tt>{@link #listWidth}</tt> has a higher value)
*/
minListWidth : 150,
/**
* @cfg {Number} ellipsisStringStartLength maximum length of text allowed before truncations,
* truncation will be replaced with ellipsis ('...').
*/
ellipsisStringStartLength : 15,
/**
* @constructor
* @param {Object} config Configuration object
*/
constructor : function(config)
{
this.model = config.model;
var defaultStore = container.getHierarchyStore().getDefaultStore();
var index = 0;
var subtreeEntryid = '';
var folderName = '';
var folderEntryid = '';
// We have to add this check due to some js unit test. Test are
// related to when default store/folder not found while loading webapp.
if (defaultStore) {
subtreeEntryid = defaultStore.getSubtreeFolder().get('entryid');
var defaultFolder = this.model.getDefaultFolder();
if (defaultFolder) {
folderName = defaultFolder.getDisplayName();
folderEntryid = defaultFolder.get('entryid');
if (defaultFolder.getDefaultFolderKey() !== 'inbox' || defaultFolder.getMAPIStore().isSharedStore()) {
index = 1;
}
}
}
if (!this.tpl) {
var tplString =
'<tpl for=".">' +
'<tpl if="Ext.isEmpty(values.flag)">' +
'<div class="k-search-combobox-menu-sep-parent">'+
'<span class="x-menu-sep k-search-combobox-menu-sep"></span>' +
'</div>'+
'</tpl>' +
'<div class="x-combo-list-item" ext:qtip="{[this.getQtip(values)]}" ext:qwidth="100%">' +
'<tpl if="this.isOtherStoreFolder(values.value)">' +
'<span>{name:htmlEncodeElide(' + this.ellipsisStringStartLength + ', 0, true)}</span>' +
'<span class="k-search-node-owner">' +
' - {this.ownerName:htmlEncodeElide(' + this.ellipsisStringStartLength + ', 0, true)}' +
'</span>' +
'</tpl>' +
'<tpl if="!this.isOtherStoreFolder(values.value)">' +
'<span>{name:htmlEncodeElide(' + this.ellipsisStringStartLength + ', 0, true)}</span>' +
'</tpl>' +
'</div>' +
'</tpl>';
this.tpl = new Ext.XTemplate(tplString, {
ownerName: '',
compiled: true,
ellipsisStringLength: this.ellipsisStringStartLength,
isOtherStoreFolder: function (entryid) {
var hierarchyStore = container.getHierarchyStore();
var folder = hierarchyStore.getFolder(entryid);
if (folder) {
var store = hierarchyStore.getById(folder.get('store_entryid'));
if (store.isSharedStore()) {
this.ownerName = store.get('mailbox_owner_name');
return true;
}
}
return false;
},
getQtip: function (values) {
var folderNameQtip, ownerNameQtip;
if (values.name.length > this.ellipsisStringLength) {
folderNameQtip = values.name;
}
if (this.isOtherStoreFolder(values.value)) {
if (this.ownerName.length > this.ellipsisStringLength) {
ownerNameQtip = this.ownerName;
}
}
if (folderNameQtip || ownerNameQtip) {
if (folderNameQtip && ownerNameQtip) {
return folderNameQtip + " - " + ownerNameQtip;
} else {
return folderNameQtip ? folderNameQtip : ownerNameQtip;
}
} else {
return '';
}
}
});
}
var searchFolderStore = new Ext.data.JsonStore({
idIndex: 0,
idProperty: 'value',
fields: ['name', 'value', 'flag', 'include_subfolder'],
data : [{
'name' : _('All folders'),
'value' : subtreeEntryid,
'include_subfolder' : true,
'flag' : Zarafa.advancesearch.data.SearchComboBoxFieldsFlags.ALL_FOLDERS
},{
'name' : Ext.util.Format.htmlEncode(folderName),
'value' : folderEntryid,
'include_subfolder' : false,
'flag' : Zarafa.advancesearch.data.SearchComboBoxFieldsFlags.CURRENT_SELECTED_FOLDER
},{
'name' : _('Other...'),
'value' : 'other'
}],
autoDestroy: true
});
Ext.apply(config, {
xtype : 'zarafa.searchfoldercombo',
mode: 'local',
ref : 'searchFolderCombo',
valueField: 'value',
displayField: 'name',
store: searchFolderStore,
triggerAction: 'all',
value: searchFolderStore.getAt(index).get('value'),
editable: false,
width: 100,
listWidth : 150,
listeners : {
expand : this.onExpandComboBox,
scope : this
}
});
Zarafa.common.searchfield.ui.SearchFolderCombo.superclass.constructor.call(this, config);
},
/**
* initialize events for the grid panel
* @private
*/
initEvents : function()
{
Zarafa.common.searchfield.ui.SearchFolderCombo.superclass.initEvents.apply(this, arguments);
this.on('beforeselect', this.onBeforeSelectSearchFolder, this);
this.on('select', this.onSelectSearchFolder, this);
this.mon(this.model, 'folderchange', this.onFolderChange, this);
this.mon(this.model, 'activate', this.onActiveFolder, this);
this.mon(container, 'aftercontextswitch', this.onAfterContextSwitch, this);
},
/**
* Event handler triggered before selection performs in search folder combo
* Will open {@link Zarafa.advancesearch.dialogs.SelectFolderContentPanel SelectFolderContentPanel}, if
* "Other.." option was selected.
*
* @param {Zarafa.common.searchfield.ui.SearchFolderCombo} combo The combo which fired the event.
* @param {Ext.data.Record} record The data record returned from the underlying store
* @param {number} index The index of the selected item in the dropdown list
* @return {boolean} true if selected record is not 'Other...' else false.
*/
onBeforeSelectSearchFolder : function (combo, record, index)
{
if(record.get('value') === 'other') {
combo.collapse();
Zarafa.advancesearch.Actions.openSelectSearchFolderDialog({
searchFolderCombo : combo,
model : this.model
});
return false;
} else if (!container.getHierarchyStore().getFolder(combo.getValue())) {
// Check if current selected folder is available in hierarchy tree,
// If not then remove that folder from search combo box.
var folderRecord = this.findRecord('value', combo.getValue());
this.getStore().remove(folderRecord);
}
return true;
},
/**
* Event handler triggered when {@link Zarafa.calendar.ui.CalendarMultiView CalendarMultiView}
* was activated and user select the calendar by using clicking on tab of calender.
* it was used to set the selected calender folder as current folder in search folder combo box.
*
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder which will be current folder in search folder combo box.
*/
onActiveFolder : function(folder)
{
this.setFolder(folder, true);
},
/**
* Event handler which is triggered when the folder is changed.
*
* @param {Zarafa.core.ContextModel} model The model which fired the event.
* @param {Zarafa.hierarchy.data.MAPIFolderRecord[]} folders selected folders as an array of
* {@link Zarafa.hierarchy.data.MAPIFolderRecord MAPIFolder} objects.
* @private
*/
onFolderChange: function (model, folders)
{
var folder = model.getDefaultFolder();
this.setFolder(folder, true);
},
/**
* Event handler triggers when context was switch successfully.
*
* @param {Object} folders contains folder details
* @param {Context} oldContext previously selected context
* @param {Context} context selected context
*/
onAfterContextSwitch : function (folders, oldContext, context)
{
var folder = context.getModel().getDefaultFolder();
this.setFolder(folder, false);
},
/**
* Function is used to set the folder in {@link Zarafa.common.searchfield.ui.SearchFolderCombo SearchFolderCombo}
* according to folder type.
*
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder folder that should be shown by the selected context.
* @param {Boolean} changeCurrentFolder true to change the current folder in search folder combo box.
*/
setFolder : function(folder, changeCurrentFolder)
{
// Don't update search folder combo box which belongs to search panel toolbar or we
// not found folder.
if (this.findParentByType("zarafa.searchpaneltoolbar") || !Ext.isDefined(folder)) {
return;
} else if (Ext.isArray(folder)) {
folder = folder[0];
}
var store = this.getStore();
if (changeCurrentFolder) {
this.doChangeCurrentFolder(store, folder);
}
// Check if closed or deleted folder is available in hierarchy tree,
// If yes then remove that folder from search combo box.
this.getStore().each(function (record) {
var value = record.get('value');
if (value !== 'other' && !container.getHierarchyStore().getFolder(value)) {
this.getStore().remove(record);
return false;
}
}, this);
// Select 'All folders' if select folder is 'Inbox' folder of own store.
if (folder.getDefaultFolderKey() === 'inbox' && !folder.getMAPIStore().isSharedStore()) {
var allFolderRecord = store.getAt(store.find('flag', Zarafa.advancesearch.data.SearchComboBoxFieldsFlags.ALL_FOLDERS));
this.setValue(allFolderRecord.get('value'));
} else {
this.setValue(folder.get('entryid'));
}
},
/**
* Function is used to change the current folder with selected folder from hierarchy
* in search folder combo.
*
* @param {Ext.data.JsonStore} store of search folder combo box.
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder folder that should be shown by the selected context.
*/
doChangeCurrentFolder : function(store, folder)
{
var currentFolder = store.getAt(store.find('flag', Zarafa.advancesearch.data.SearchComboBoxFieldsFlags.CURRENT_SELECTED_FOLDER));
currentFolder.beginEdit();
currentFolder.set("name", folder.getDisplayName());
currentFolder.set("value", folder.get('entryid'));
currentFolder.set("include_subfolder", false);
currentFolder.id = folder.get('entryid');
currentFolder.endEdit();
currentFolder.commit();
},
/**
* Helper function which is use to resize the search combobox list according to the widest list item content
* @private
*/
onExpandComboBox: function ()
{
var store = this.store;
var listWidth = 0;
var textMetrics = Ext.util.TextMetrics.createInstance(this.view.el);
// Get the width of the maximum text in list.
store.each(function (record) {
// Get the folder name and append the ellipsis if require
var name = Ext.util.Format.htmlEncodeElide(record.get('name'), this.ellipsisStringStartLength, 0, true);
var hierarchyStore = container.getHierarchyStore();
var folder = hierarchyStore.getFolder(record.get('value'));
if (folder) {
var store = hierarchyStore.getById(folder.get('store_entryid'));
// In case of shared folder, post-fix the owning store name.
if (store.isSharedStore()) {
name += " - " + Ext.util.Format.htmlEncodeElide(store.get('mailbox_owner_name'), this.ellipsisStringStartLength, 0, true);
}
}
var curWidth = textMetrics.getWidth(name);
if (curWidth > listWidth) {
listWidth = curWidth;
}
}, this);
if (listWidth > 0) {
// Set maximum width in between minimum list width and text width,
// Where as text width also have actual list width with padding.
listWidth = Math.max(this.minListWidth, listWidth + 25);
this.list.setWidth(listWidth);
this.innerList.setWidth(listWidth - this.list.getFrameWidth('lr'));
}
},
/**
* Event handler triggered when a search combo list item is selected.
* It will fire click event of search button to automatically triggers a search
* when user selects a different folder from the search-tab drop-down.
*
*/
onSelectSearchFolder: function ()
{
var searchTextField = this.searchFieldContainer.searchTextField;
if (searchTextField.searchPanelRendered) {
searchTextField.onTriggerClick();
}
}
});
Ext.reg('zarafa.searchfoldercombo', Zarafa.common.searchfield.ui.SearchFolderCombo);