3.0 source code
This commit is contained in:
846
OfficeWeb/vendor/touch/src/dataview/NestedList.js
vendored
Normal file
846
OfficeWeb/vendor/touch/src/dataview/NestedList.js
vendored
Normal file
@@ -0,0 +1,846 @@
|
||||
/**
|
||||
* NestedList provides a miller column interface to navigate between nested sets
|
||||
* and provide a clean interface with limited screen real-estate.
|
||||
*
|
||||
* @example miniphone preview
|
||||
* var data = {
|
||||
* text: 'Groceries',
|
||||
* items: [{
|
||||
* text: 'Drinks',
|
||||
* items: [{
|
||||
* text: 'Water',
|
||||
* items: [{
|
||||
* text: 'Sparkling',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Still',
|
||||
* leaf: true
|
||||
* }]
|
||||
* }, {
|
||||
* text: 'Coffee',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Espresso',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Redbull',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Coke',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Diet Coke',
|
||||
* leaf: true
|
||||
* }]
|
||||
* }, {
|
||||
* text: 'Fruit',
|
||||
* items: [{
|
||||
* text: 'Bananas',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Lemon',
|
||||
* leaf: true
|
||||
* }]
|
||||
* }, {
|
||||
* text: 'Snacks',
|
||||
* items: [{
|
||||
* text: 'Nuts',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Pretzels',
|
||||
* leaf: true
|
||||
* }, {
|
||||
* text: 'Wasabi Peas',
|
||||
* leaf: true
|
||||
* }]
|
||||
* }]
|
||||
* };
|
||||
*
|
||||
* Ext.define('ListItem', {
|
||||
* extend: 'Ext.data.Model',
|
||||
* config: {
|
||||
* fields: [{
|
||||
* name: 'text',
|
||||
* type: 'string'
|
||||
* }]
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* var store = Ext.create('Ext.data.TreeStore', {
|
||||
* model: 'ListItem',
|
||||
* defaultRootProperty: 'items',
|
||||
* root: data
|
||||
* });
|
||||
*
|
||||
* var nestedList = Ext.create('Ext.NestedList', {
|
||||
* fullscreen: true,
|
||||
* title: 'Groceries',
|
||||
* displayField: 'text',
|
||||
* store: store
|
||||
* });
|
||||
*
|
||||
* @aside guide nested_list
|
||||
* @aside example nested-list
|
||||
* @aside example navigation-view
|
||||
*/
|
||||
Ext.define('Ext.dataview.NestedList', {
|
||||
alternateClassName: 'Ext.NestedList',
|
||||
extend: 'Ext.Container',
|
||||
xtype: 'nestedlist',
|
||||
requires: [
|
||||
'Ext.List',
|
||||
'Ext.TitleBar',
|
||||
'Ext.Button',
|
||||
'Ext.XTemplate',
|
||||
'Ext.data.StoreManager',
|
||||
'Ext.data.NodeStore',
|
||||
'Ext.data.TreeStore'
|
||||
],
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg
|
||||
* @inheritdoc
|
||||
*/
|
||||
cls: Ext.baseCSSPrefix + 'nested-list',
|
||||
|
||||
/**
|
||||
* @cfg {String/Object/Boolean} cardSwitchAnimation
|
||||
* Animation to be used during transitions of cards.
|
||||
* @removed 2.0.0 please use {@link Ext.layout.Card#animation}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} backText
|
||||
* The label to display for the back button.
|
||||
* @accessor
|
||||
*/
|
||||
backText: 'Back',
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} useTitleAsBackText
|
||||
* `true` to use title as a label for back button.
|
||||
* @accessor
|
||||
*/
|
||||
useTitleAsBackText: true,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} updateTitleText
|
||||
* Update the title with the currently selected category.
|
||||
* @accessor
|
||||
*/
|
||||
updateTitleText: true,
|
||||
|
||||
/**
|
||||
* @cfg {String} displayField
|
||||
* Display field to use when setting item text and title.
|
||||
* This configuration is ignored when overriding {@link #getItemTextTpl} or
|
||||
* {@link #getTitleTextTpl} for the item text or title.
|
||||
* @accessor
|
||||
*/
|
||||
displayField: 'text',
|
||||
|
||||
/**
|
||||
* @cfg {String} loadingText
|
||||
* Loading text to display when a subtree is loading.
|
||||
* @accessor
|
||||
*/
|
||||
loadingText: 'Loading...',
|
||||
|
||||
/**
|
||||
* @cfg {String} emptyText
|
||||
* Empty text to display when a subtree is empty.
|
||||
* @accessor
|
||||
*/
|
||||
emptyText: 'No items available.',
|
||||
|
||||
/**
|
||||
* @cfg {Boolean/Function} onItemDisclosure
|
||||
* Maps to the {@link Ext.List#onItemDisclosure} configuration for individual lists.
|
||||
* @accessor
|
||||
*/
|
||||
onItemDisclosure: false,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} allowDeselect
|
||||
* Set to `true` to allow the user to deselect leaf items via interaction.
|
||||
* @accessor
|
||||
*/
|
||||
allowDeselect: false,
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Please set the {@link #toolbar} configuration to `false` instead
|
||||
* @cfg {Boolean} useToolbar `true` to show the header toolbar.
|
||||
* @accessor
|
||||
*/
|
||||
useToolbar: null,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.Toolbar/Object/Boolean} toolbar
|
||||
* The configuration to be used for the toolbar displayed in this nested list.
|
||||
* @accessor
|
||||
*/
|
||||
toolbar: {
|
||||
docked: 'top',
|
||||
xtype: 'titlebar',
|
||||
ui: 'light',
|
||||
inline: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {String} title The title of the toolbar
|
||||
* @accessor
|
||||
*/
|
||||
title: '',
|
||||
|
||||
/**
|
||||
* @cfg {String} layout
|
||||
* @hide
|
||||
* @accessor
|
||||
*/
|
||||
layout: {
|
||||
type: 'card',
|
||||
animation: {
|
||||
type: 'slide',
|
||||
duration: 250,
|
||||
direction: 'left'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {Ext.data.TreeStore/String} store The tree store to be used for this nested list.
|
||||
*/
|
||||
store: null,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.Container} detailContainer The container of the `detailCard`.
|
||||
* @accessor
|
||||
*/
|
||||
detailContainer: undefined,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.Component} detailCard to provide a final card for leaf nodes.
|
||||
* @accessor
|
||||
*/
|
||||
detailCard: null,
|
||||
|
||||
/**
|
||||
* @cfg {Object} backButton The configuration for the back button used in the nested list.
|
||||
*/
|
||||
backButton: {
|
||||
ui: 'back',
|
||||
hidden: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {Object} listConfig An optional config object which is merged with the default
|
||||
* configuration used to create each nested list.
|
||||
*/
|
||||
listConfig: null,
|
||||
|
||||
// @private
|
||||
lastNode: null,
|
||||
|
||||
// @private
|
||||
lastActiveList: null
|
||||
},
|
||||
|
||||
/**
|
||||
* @event itemtap
|
||||
* Fires when a node is tapped on.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.dataview.List} list The Ext.dataview.List that is currently active.
|
||||
* @param {Number} index The index of the item tapped.
|
||||
* @param {Ext.dom.Element} target The element tapped.
|
||||
* @param {Ext.data.Record} record The record tapped.
|
||||
* @param {Ext.event.Event} e The event object.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event itemdoubletap
|
||||
* Fires when a node is double tapped on.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.dataview.List} list The Ext.dataview.List that is currently active.
|
||||
* @param {Number} index The index of the item that was tapped.
|
||||
* @param {Ext.dom.Element} target The element tapped.
|
||||
* @param {Ext.data.Record} record The record tapped.
|
||||
* @param {Ext.event.Event} e The event object.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event containertap
|
||||
* Fires when a tap occurs and it is not on a template node.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.dataview.List} list The Ext.dataview.List that is currently active.
|
||||
* @param {Ext.event.Event} e The raw event object.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event selectionchange
|
||||
* Fires when the selected nodes change.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.dataview.List} list The Ext.dataview.List that is currently active.
|
||||
* @param {Array} selections Array of the selected nodes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event beforeselectionchange
|
||||
* Fires before a selection is made.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.dataview.List} list The Ext.dataview.List that is currently active.
|
||||
* @param {HTMLElement} node The node to be selected.
|
||||
* @param {Array} selections Array of currently selected nodes.
|
||||
* @deprecated 2.0.0 Please listen to the {@link #selectionchange} event with an order of `before` instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event listchange
|
||||
* Fires when the user taps a list item.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Object} listitem The new active list.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event leafitemtap
|
||||
* Fires when the user taps a leaf list item.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.List} list The subList the item is on.
|
||||
* @param {Number} index The index of the item tapped.
|
||||
* @param {Ext.dom.Element} target The element tapped.
|
||||
* @param {Ext.data.Record} record The record tapped.
|
||||
* @param {Ext.event.Event} e The event.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event back
|
||||
* @preventable doBack
|
||||
* Fires when the user taps Back.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {HTMLElement} node The node to be selected.
|
||||
* @param {Ext.dataview.List} lastActiveList The Ext.dataview.List that was last active.
|
||||
* @param {Boolean} detailCardActive Flag set if the detail card is currently active.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event beforeload
|
||||
* Fires before a request is made for a new data object.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.data.Store} store The store instance.
|
||||
* @param {Ext.data.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to
|
||||
* load the Store.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event load
|
||||
* Fires whenever records have been loaded into the store.
|
||||
* @param {Ext.dataview.NestedList} this
|
||||
* @param {Ext.data.Store} store The store instance.
|
||||
* @param {Ext.util.Grouper[]} records An array of records.
|
||||
* @param {Boolean} successful `true` if the operation was successful.
|
||||
* @param {Ext.data.Operation} operation The associated operation.
|
||||
*/
|
||||
constructor: function (config) {
|
||||
if (Ext.isObject(config)) {
|
||||
if (config.getTitleTextTpl) {
|
||||
this.getTitleTextTpl = config.getTitleTextTpl;
|
||||
}
|
||||
if (config.getItemTextTpl) {
|
||||
this.getItemTextTpl = config.getItemTextTpl;
|
||||
}
|
||||
}
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
onItemInteraction: function () {
|
||||
if (this.isGoingTo) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
applyDetailContainer: function (config) {
|
||||
if (!config) {
|
||||
config = this;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
|
||||
updateDetailContainer: function (newContainer, oldContainer) {
|
||||
if (newContainer) {
|
||||
newContainer.onBefore('activeitemchange', 'onBeforeDetailContainerChange', this);
|
||||
newContainer.onAfter('activeitemchange', 'onDetailContainerChange', this);
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeDetailContainerChange: function () {
|
||||
this.isGoingTo = true;
|
||||
},
|
||||
|
||||
onDetailContainerChange: function () {
|
||||
this.isGoingTo = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when an list item has been tapped.
|
||||
* @param {Ext.List} list The subList the item is on.
|
||||
* @param {Number} index The id of the item tapped.
|
||||
* @param {Ext.Element} target The list item tapped.
|
||||
* @param {Ext.data.Record} record The record which as tapped.
|
||||
* @param {Ext.event.Event} e The event.
|
||||
*/
|
||||
onItemTap: function (list, index, target, record, e) {
|
||||
var me = this,
|
||||
store = list.getStore(),
|
||||
node = store.getAt(index);
|
||||
|
||||
me.fireEvent('itemtap', this, list, index, target, record, e);
|
||||
if (node.isLeaf()) {
|
||||
me.fireEvent('leafitemtap', this, list, index, target, record, e);
|
||||
me.goToLeaf(node);
|
||||
}
|
||||
else {
|
||||
this.goToNode(node);
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeSelect: function () {
|
||||
this.fireEvent.apply(this, [].concat('beforeselect', this, Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
onContainerTap: function () {
|
||||
this.fireEvent.apply(this, [].concat('containertap', this, Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
onSelectionChange: function () {
|
||||
this.fireEvent.apply(this, [].concat('selectionchange', this, Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
onItemDoubleTap: function () {
|
||||
this.fireEvent.apply(this, [].concat('itemdoubletap', this, Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
onStoreBeforeLoad: function () {
|
||||
var loadingText = this.getLoadingText(),
|
||||
scrollable = this.getScrollable();
|
||||
|
||||
if (loadingText) {
|
||||
this.setMasked({
|
||||
xtype: 'loadmask',
|
||||
message: loadingText
|
||||
});
|
||||
|
||||
//disable scrolling while it is masked
|
||||
if (scrollable) {
|
||||
scrollable.getScroller().setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
this.fireEvent.apply(this, [].concat('beforeload', this, Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
onStoreLoad: function (store, records, successful, operation) {
|
||||
this.setMasked(false);
|
||||
this.fireEvent.apply(this, [].concat('load', this, Array.prototype.slice.call(arguments)));
|
||||
|
||||
if (store.indexOf(this.getLastNode()) === -1) {
|
||||
this.goToNode(store.getRoot());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the backButton has been tapped.
|
||||
*/
|
||||
onBackTap: function () {
|
||||
var me = this,
|
||||
node = me.getLastNode(),
|
||||
detailCard = me.getDetailCard(),
|
||||
detailCardActive = detailCard && me.getActiveItem() == detailCard,
|
||||
lastActiveList = me.getLastActiveList();
|
||||
|
||||
this.fireAction('back', [this, node, lastActiveList, detailCardActive], 'doBack');
|
||||
},
|
||||
|
||||
doBack: function (me, node, lastActiveList, detailCardActive) {
|
||||
var layout = me.getLayout(),
|
||||
animation = (layout) ? layout.getAnimation() : null;
|
||||
|
||||
if (detailCardActive && lastActiveList) {
|
||||
if (animation) {
|
||||
animation.setReverse(true);
|
||||
}
|
||||
me.setActiveItem(lastActiveList);
|
||||
me.setLastNode(node.parentNode);
|
||||
me.syncToolbar();
|
||||
}
|
||||
else {
|
||||
this.goToNode(node.parentNode);
|
||||
}
|
||||
},
|
||||
|
||||
updateData: function (data) {
|
||||
if (!this.getStore()) {
|
||||
this.setStore(new Ext.data.TreeStore({
|
||||
root: data
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
applyStore: function (store) {
|
||||
if (store) {
|
||||
if (Ext.isString(store)) {
|
||||
// store id
|
||||
store = Ext.data.StoreManager.get(store);
|
||||
} else {
|
||||
// store instance or store config
|
||||
if (!(store instanceof Ext.data.TreeStore)) {
|
||||
store = Ext.factory(store, Ext.data.TreeStore, null);
|
||||
}
|
||||
}
|
||||
|
||||
// <debug>
|
||||
if (!store) {
|
||||
Ext.Logger.warn("The specified Store cannot be found", this);
|
||||
}
|
||||
//</debug>
|
||||
}
|
||||
|
||||
return store;
|
||||
},
|
||||
|
||||
storeListeners: {
|
||||
rootchange: 'onStoreRootChange',
|
||||
load: 'onStoreLoad',
|
||||
beforeload: 'onStoreBeforeLoad'
|
||||
},
|
||||
|
||||
updateStore: function (newStore, oldStore) {
|
||||
var me = this,
|
||||
listeners = this.storeListeners;
|
||||
|
||||
listeners.scope = me;
|
||||
|
||||
if (oldStore && Ext.isObject(oldStore) && oldStore.isStore) {
|
||||
if (oldStore.autoDestroy) {
|
||||
oldStore.destroy();
|
||||
}
|
||||
oldStore.un(listeners);
|
||||
}
|
||||
|
||||
if (newStore) {
|
||||
me.goToNode(newStore.getRoot());
|
||||
newStore.on(listeners);
|
||||
}
|
||||
},
|
||||
|
||||
onStoreRootChange: function (store, node) {
|
||||
this.goToNode(node);
|
||||
},
|
||||
|
||||
applyBackButton: function (config) {
|
||||
return Ext.factory(config, Ext.Button, this.getBackButton());
|
||||
},
|
||||
|
||||
applyDetailCard: function (config, oldDetailCard) {
|
||||
if (config === null) {
|
||||
return Ext.factory(config, Ext.Component, oldDetailCard);
|
||||
} else {
|
||||
return Ext.factory(config, Ext.Component);
|
||||
}
|
||||
},
|
||||
|
||||
updateBackButton: function (newButton, oldButton) {
|
||||
if (newButton) {
|
||||
var me = this;
|
||||
newButton.on('tap', me.onBackTap, me);
|
||||
newButton.setText(me.getBackText());
|
||||
me.getToolbar().insert(0, newButton);
|
||||
}
|
||||
else if (oldButton) {
|
||||
oldButton.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
applyToolbar: function (config) {
|
||||
return Ext.factory(config, Ext.TitleBar, this.getToolbar());
|
||||
},
|
||||
|
||||
updateToolbar: function (newToolbar, oldToolbar) {
|
||||
var me = this;
|
||||
if (newToolbar) {
|
||||
newToolbar.setTitle(me.getTitle());
|
||||
if (!newToolbar.getParent()) {
|
||||
me.add(newToolbar);
|
||||
}
|
||||
}
|
||||
else if (oldToolbar) {
|
||||
oldToolbar.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
updateUseToolbar: function (newUseToolbar, oldUseToolbar) {
|
||||
if (!newUseToolbar) {
|
||||
this.setToolbar(false);
|
||||
}
|
||||
},
|
||||
|
||||
updateTitle: function (newTitle) {
|
||||
var me = this,
|
||||
toolbar = me.getToolbar();
|
||||
if (toolbar) {
|
||||
if (me.getUpdateTitleText()) {
|
||||
toolbar.setTitle(newTitle);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Override this method to provide custom template rendering of individual
|
||||
* nodes. The template will receive all data within the Record and will also
|
||||
* receive whether or not it is a leaf node.
|
||||
* @param {Ext.data.Record} node
|
||||
* @return {String}
|
||||
*/
|
||||
getItemTextTpl: function (node) {
|
||||
return '{' + this.getDisplayField() + '}';
|
||||
},
|
||||
|
||||
/**
|
||||
* Override this method to provide custom template rendering of titles/back
|
||||
* buttons when {@link #useTitleAsBackText} is enabled.
|
||||
* @param {Ext.data.Record} node
|
||||
* @return {String}
|
||||
*/
|
||||
getTitleTextTpl: function (node) {
|
||||
return '{' + this.getDisplayField() + '}';
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
renderTitleText: function (node, forBackButton) {
|
||||
if (!node.titleTpl) {
|
||||
node.titleTpl = Ext.create('Ext.XTemplate', this.getTitleTextTpl(node));
|
||||
}
|
||||
|
||||
if (node.isRoot()) {
|
||||
var initialTitle = this.getInitialConfig('title');
|
||||
return (forBackButton && initialTitle === '') ? this.getInitialConfig('backText') : initialTitle;
|
||||
}
|
||||
|
||||
return node.titleTpl.applyTemplate(node.data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method to handle going to a specific node within this nested list. Node must be part of the
|
||||
* internal {@link #store}.
|
||||
* @param {Ext.data.NodeInterface} node The specified node to navigate to.
|
||||
*/
|
||||
goToNode: function (node) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
var me = this,
|
||||
activeItem = me.getActiveItem(),
|
||||
detailCard = me.getDetailCard(),
|
||||
detailCardActive = detailCard && me.getActiveItem() == detailCard,
|
||||
reverse = me.goToNodeReverseAnimation(node),
|
||||
firstList = me.firstList,
|
||||
secondList = me.secondList,
|
||||
layout = me.getLayout(),
|
||||
animation = (layout) ? layout.getAnimation() : null,
|
||||
list;
|
||||
|
||||
//if the node is a leaf, throw an error
|
||||
if (node.isLeaf()) {
|
||||
throw new Error('goToNode: passed a node which is a leaf.');
|
||||
}
|
||||
|
||||
//if we are currently at the passed node, do nothing.
|
||||
if (node == me.getLastNode() && !detailCardActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (detailCardActive) {
|
||||
if (animation) {
|
||||
animation.setReverse(true);
|
||||
}
|
||||
list = me.getLastActiveList();
|
||||
list.getStore().setNode(node);
|
||||
node.expand();
|
||||
me.setActiveItem(list);
|
||||
}
|
||||
else {
|
||||
if (firstList && secondList) {
|
||||
//firstList and secondList have both been created
|
||||
activeItem = me.getActiveItem();
|
||||
|
||||
me.setLastActiveList(activeItem);
|
||||
list = (activeItem == firstList) ? secondList : firstList;
|
||||
list.getStore().setNode(node);
|
||||
node.expand();
|
||||
|
||||
if (animation) {
|
||||
animation.setReverse(reverse);
|
||||
}
|
||||
me.setActiveItem(list);
|
||||
list.deselectAll();
|
||||
}
|
||||
else if (firstList) {
|
||||
//only firstList has been created
|
||||
me.setLastActiveList(me.getActiveItem());
|
||||
me.setActiveItem(me.getList(node));
|
||||
me.secondList = me.getActiveItem();
|
||||
}
|
||||
else {
|
||||
//no lists have been created
|
||||
me.setActiveItem(me.getList(node));
|
||||
me.firstList = me.getActiveItem();
|
||||
}
|
||||
}
|
||||
|
||||
me.fireEvent('listchange', this, me.getActiveItem());
|
||||
|
||||
me.setLastNode(node);
|
||||
|
||||
me.syncToolbar();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The leaf you want to navigate to. You should pass a node instance.
|
||||
* @param {Ext.data.NodeInterface} node The specified node to navigate to.
|
||||
*/
|
||||
goToLeaf: function (node) {
|
||||
if (!node.isLeaf()) {
|
||||
throw new Error('goToLeaf: passed a node which is not a leaf.');
|
||||
}
|
||||
|
||||
var me = this,
|
||||
card = me.getDetailCard(node),
|
||||
container = me.getDetailContainer(),
|
||||
sharedContainer = container == this,
|
||||
layout = me.getLayout(),
|
||||
animation = (layout) ? layout.getAnimation() : false;
|
||||
|
||||
if (card) {
|
||||
if (container.getItems().indexOf(card) === -1) {
|
||||
container.add(card);
|
||||
}
|
||||
if (sharedContainer) {
|
||||
if (me.getActiveItem() instanceof Ext.dataview.List) {
|
||||
me.setLastActiveList(me.getActiveItem());
|
||||
}
|
||||
me.setLastNode(node);
|
||||
}
|
||||
if (animation) {
|
||||
animation.setReverse(false);
|
||||
}
|
||||
container.setActiveItem(card);
|
||||
me.syncToolbar();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Method which updates the {@link #backButton} and {@link #toolbar} with the latest information from
|
||||
* the current node.
|
||||
*/
|
||||
syncToolbar: function (forceDetail) {
|
||||
var me = this,
|
||||
detailCard = me.getDetailCard(),
|
||||
node = me.getLastNode(),
|
||||
detailActive = forceDetail || (detailCard && (me.getActiveItem() == detailCard)),
|
||||
parentNode = (detailActive) ? node : node.parentNode,
|
||||
backButton = me.getBackButton();
|
||||
|
||||
//show/hide the backButton, and update the backButton text, if one exists
|
||||
if (backButton) {
|
||||
backButton[parentNode ? 'show' : 'hide']();
|
||||
if (parentNode && me.getUseTitleAsBackText()) {
|
||||
backButton.setText(me.renderTitleText(node.parentNode, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (node) {
|
||||
me.setTitle(me.renderTitleText(node));
|
||||
}
|
||||
},
|
||||
|
||||
updateBackText: function (newText) {
|
||||
this.getBackButton().setText(newText);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns `true` if the passed node should have a reverse animation from the previous current node.
|
||||
* @param {Ext.data.NodeInterface} node
|
||||
*/
|
||||
goToNodeReverseAnimation: function (node) {
|
||||
var me = this,
|
||||
lastNode = me.getLastNode();
|
||||
if (!lastNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (!lastNode.contains(node) && lastNode.isAncestor(node)) ? true : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns the list config for a specified node.
|
||||
* @param {HTMLElement} node The node for the list config.
|
||||
*/
|
||||
getList: function (node) {
|
||||
var me = this,
|
||||
nodeStore = Ext.create('Ext.data.NodeStore', {
|
||||
recursive: false,
|
||||
node: node,
|
||||
rootVisible: false,
|
||||
model: me.getStore().getModel()
|
||||
});
|
||||
|
||||
node.expand();
|
||||
|
||||
return Ext.Object.merge({
|
||||
xtype: 'list',
|
||||
pressedDelay: 250,
|
||||
autoDestroy: true,
|
||||
store: nodeStore,
|
||||
onItemDisclosure: me.getOnItemDisclosure(),
|
||||
allowDeselect: me.getAllowDeselect(),
|
||||
variableHeights: false,
|
||||
listeners: [
|
||||
{ event: 'itemdoubletap', fn: 'onItemDoubleTap', scope: me },
|
||||
{ event: 'itemtap', fn: 'onItemInteraction', scope: me, order: 'before'},
|
||||
{ event: 'itemtouchstart', fn: 'onItemInteraction', scope: me, order: 'before'},
|
||||
{ event: 'itemtap', fn: 'onItemTap', scope: me },
|
||||
{ event: 'beforeselectionchange', fn: 'onBeforeSelect', scope: me },
|
||||
{ event: 'containertap', fn: 'onContainerTap', scope: me },
|
||||
{ event: 'selectionchange', fn: 'onSelectionChange', order: 'before', scope: me }
|
||||
],
|
||||
itemTpl: '<span<tpl if="leaf == true"> class="x-list-item-leaf"</tpl>>' + me.getItemTextTpl(node) + '</span>'
|
||||
}, this.getListConfig());
|
||||
}
|
||||
|
||||
}, function () {
|
||||
//<deprecated product=touch since=2.0>
|
||||
|
||||
/**
|
||||
* @member Ext.dataview.NestedList
|
||||
* @method getSubList
|
||||
* Returns the subList for a specified node.
|
||||
* @removed 2.0.0
|
||||
*/
|
||||
Ext.deprecateMethod(this, 'getSubList', null, "Ext.dataview.NestedList.getSubList() has been removed");
|
||||
|
||||
/**
|
||||
* @member Ext.dataview.NestedList
|
||||
* @cfg {Number} clearSelectionDelay
|
||||
* Number of milliseconds to show the highlight when going back in a list.
|
||||
* @removed 2.0.0
|
||||
*/
|
||||
Ext.deprecateProperty(this, 'clearSelectionDelay', null, "Ext.dataview.NestedList.clearSelectionDelay has been removed");
|
||||
//</deprecated>
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user