123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /**
- * @class Ext.ux.TreePicker
- * @extends Ext.form.field.Picker
- *
- * A Picker field that contains a tree panel on its popup, enabling selection of tree nodes.
- */
- Ext.define('Ext.ux.TreePicker', {
- extend: 'Ext.form.field.Picker',
- xtype: 'treepicker',
- triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
- config: {
- /**
- * @cfg {Ext.data.TreeStore} store
- * A tree store that the tree picker will be bound to
- */
- store: null,
- /**
- * @cfg {String} displayField
- * The field inside the model that will be used as the node's text.
- * Defaults to the default value of {@link Ext.tree.Panel}'s `displayField` configuration.
- */
- displayField: null,
- /**
- * @cfg {Array} columns
- * An optional array of columns for multi-column trees
- */
- columns: null,
- /**
- * @cfg {Boolean} selectOnTab
- * Whether the Tab key should select the currently highlighted item. Defaults to `true`.
- */
- selectOnTab: true,
- /**
- * @cfg {Number} maxPickerHeight
- * The maximum height of the tree dropdown. Defaults to 300.
- */
- maxPickerHeight: 300,
- /**
- * @cfg {Number} minPickerHeight
- * The minimum height of the tree dropdown. Defaults to 100.
- */
- minPickerHeight: 100
- },
-
- editable: false,
- initComponent: function() {
- var me = this;
- me.callParent(arguments);
- this.addEvents(
- /**
- * @event select
- * Fires when a tree node is selected
- * @param {Ext.ux.TreePicker} picker This tree picker
- * @param {Ext.data.Model} record The selected record
- */
- 'select'
- );
- me.store.on('load', me.onLoad, me);
- },
- /**
- * Creates and returns the tree panel to be used as this field's picker.
- * @private
- */
- createPicker: function() {
- var me = this,
- picker = Ext.create('Ext.tree.Panel', {
- store: me.store,
- floating: true,
- hidden: true,
- displayField: me.displayField,
- columns: me.columns,
- maxHeight: me.maxTreeHeight,
- shadow: false,
- manageHeight: false,
- listeners: {
- itemclick: Ext.bind(me.onItemClick, me)
- },
- viewConfig: {
- listeners: {
- render: function(view) {
- view.getEl().on('keypress', me.onPickerKeypress, me);
- }
- }
- }
- }),
- view = picker.getView();
- view.on('render', me.setPickerViewStyles, me);
- if (Ext.isIE9 && Ext.isStrict) {
- // In IE9 strict mode, the tree view grows by the height of the horizontal scroll bar when the items are highlighted or unhighlighted.
- // Also when items are collapsed or expanded the height of the view is off. Forcing a repaint fixes the problem.
- view.on('highlightitem', me.repaintPickerView, me);
- view.on('unhighlightitem', me.repaintPickerView, me);
- view.on('afteritemexpand', me.repaintPickerView, me);
- view.on('afteritemcollapse', me.repaintPickerView, me);
- }
- return picker;
- },
- /**
- * Sets min/max height styles on the tree picker's view element after it is rendered.
- * @param {Ext.tree.View} view
- * @private
- */
- setPickerViewStyles: function(view) {
- view.getEl().setStyle({
- 'min-height': this.minPickerHeight + 'px',
- 'max-height': this.maxPickerHeight + 'px'
- });
- },
- /**
- * repaints the tree view
- */
- repaintPickerView: function() {
- var style = this.picker.getView().getEl().dom.style;
- // can't use Element.repaint because it contains a setTimeout, which results in a flicker effect
- style.display = style.display;
- },
- /**
- * Aligns the picker to the input element
- * @private
- */
- alignPicker: function() {
- var me = this,
- picker;
- if (me.isExpanded) {
- picker = me.getPicker();
- if (me.matchFieldWidth) {
- // Auto the height (it will be constrained by max height)
- picker.setWidth(me.bodyEl.getWidth());
- }
- if (picker.isFloating()) {
- me.doAlign();
- }
- }
- },
- /**
- * Handles a click even on a tree node
- * @private
- * @param {Ext.tree.View} view
- * @param {Ext.data.Model} record
- * @param {HTMLElement} node
- * @param {Number} rowIndex
- * @param {Ext.EventObject} e
- */
- onItemClick: function(view, record, node, rowIndex, e) {
- this.selectItem(record);
- },
- /**
- * Handles a keypress event on the picker element
- * @private
- * @param {Ext.EventObject} e
- * @param {HTMLElement} el
- */
- onPickerKeypress: function(e, el) {
- var key = e.getKey();
- if(key === e.ENTER || (key === e.TAB && this.selectOnTab)) {
- this.selectItem(this.picker.getSelectionModel().getSelection()[0]);
- }
- },
- /**
- * Changes the selection to a given record and closes the picker
- * @private
- * @param {Ext.data.Model} record
- */
- selectItem: function(record) {
- var me = this;
- me.setValue(record.get('id'));
- me.picker.hide();
- me.inputEl.focus();
- me.fireEvent('select', me, record)
- },
- /**
- * Runs when the picker is expanded. Selects the appropriate tree node based on the value of the input element,
- * and focuses the picker so that keyboard navigation will work.
- * @private
- */
- onExpand: function() {
- var me = this,
- picker = me.picker,
- store = picker.store,
- value = me.value;
- if(value) {
- picker.selectPath(store.getNodeById(value).getPath());
- } else {
- picker.getSelectionModel().select(store.getRootNode());
- }
- Ext.defer(function() {
- picker.getView().focus();
- }, 1);
- },
- /**
- * Sets the specified value into the field
- * @param {Mixed} value
- * @return {Ext.ux.TreePicker} this
- */
- setValue: function(value) {
- var me = this,
- record;
- me.value = value;
- if (me.store.loading) {
- // Called while the Store is loading. Ensure it is processed by the onLoad method.
- return me;
- }
-
- // try to find a record in the store that matches the value
- record = value ? me.store.getNodeById(value) : me.store.getRootNode();
- // set the raw value to the record's display field if a record was found
- me.setRawValue(record ? record.get(this.displayField) : '');
- return me;
- },
- /**
- * Returns the current data value of the field (the idProperty of the record)
- * @return {Number}
- */
- getValue: function() {
- return this.value;
- },
- /**
- * Handles the store's load event.
- * @private
- */
- onLoad: function() {
- var value = this.value;
- if (value) {
- this.setValue(value);
- }
- }
- });
|