MODx.SearchBar = function(config) { config = config || {}; Ext.applyIf(config, { renderTo: 'modx-manager-search' ,listClass: 'modx-manager-search-results' ,emptyText: _('search') ,id: 'modx-uberbar' ,maxHeight: this.getViewPortSize() ,typeAhead: true // ,listAlign: [ 'tl-bl?', [0, 0] ] // this is default ,listAlign: [ 'tl-bl?', [-12, 0] ] // account for padding + border width of container (added by Ext JS) ,triggerConfig: { tag: 'button' ,type: "submit" ,"aria-label": "Go" ,cls: 'x-form-trigger icon icon-large icon-search' } ,defaultAutoCreate: { tag: "input" ,type: "text" ,size: "24" ,autocomplete: "off" ,"aria-label" : _('search') } ,minChars: 1 ,displayField: 'name' ,valueField: '_action' ,width: 259 ,maxWidth: 437 // Increase to animate + grow when focused ,itemSelector: '.x-combo-list-item' ,tpl: new Ext.XTemplate( '', // Section wrapper '
', // Display header only once '', '', '

{label:htmlEncode}

', '
', // Real result, make it use the default styles for a combobox dropdown with x-combo-list-item '

{name:htmlEncode} – {description:htmlEncode}

', '
', '
' ,{ /** * Get the appropriate CSS class based on the result type * * @param {Array} values * @returns {string} */ getClass: function(values) { if (values.icon) { return values.icon; } if (values.class) { switch (values.class) { case 'modDocument': return 'file'; case 'modSymLink': return 'files-o'; case 'modWebLink': return 'link'; case 'modStaticResource': return 'file-text-o'; default: break; } } switch (values.type) { case 'resources': return 'file'; case 'chunks': return 'th-large'; case 'templates': return 'columns'; case 'snippets': return 'code'; case 'tvs': return 'list-alt'; case 'plugins': return 'cogs'; case 'users': return 'user'; case 'actions': return 'mail-forward'; } } /** * Get the result type lexicon * * @param {Array} values * * @returns {String} */ ,getLabel: function(values) { if (values.label) { return values.label; } return _('search_resulttype_' + values.type); } } ) ,store: new Ext.data.JsonStore({ url: MODx.config.connector_url ,baseParams: { action: 'search/search' } ,root: 'results' ,totalProperty: 'total' ,fields: ['name', '_action', 'description', 'type', 'icon', 'label', 'class'] ,listeners: { beforeload: function(store, options) { if (options.params._action) { // Prevent weird query on first combo box blur return false; } } } }) ,listeners: { beforequery: { fn: function() { this.tpl.type = null; } } ,focus: this.focusBar ,blur: this.blurBar ,scope: this } }); MODx.SearchBar.superclass.constructor.call(this, config); this.setKeyMap(); }; Ext.extend(MODx.SearchBar, Ext.form.ComboBox, { // Initialize the keyboard shortcuts to focus the bar (ctrl + alt + /) and hide it (esc) setKeyMap: function() { // This keymap is conflicting with typing certain characters, see #11974 /*new Ext.KeyMap(document, { key: [191, 0] ,ctrl: true ,alt: true ,handler: function() { this.hideBar(); this.toggle(); } ,scope: this ,stopEvent: true });*/ // Escape to hide SearchBar new Ext.KeyMap(document, { key: 27 ,handler: function() { this.hideBar(); } ,scope: this ,stopEvent: false }); } /** * Override to support opening results in new window/tab */ ,initList : function() { if(!this.list){ var cls = 'x-combo-list', listParent = Ext.getDom(this.getListParent() || Ext.getBody()); this.list = new Ext.Layer({ parentEl: listParent, shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false, zindex: this.getZIndex(listParent) }); var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth); this.list.setSize(lw, 0); this.list.swallowEvent('mousewheel'); this.assetHeight = 0; if(this.syncFont !== false){ this.list.setStyle('font-size', this.el.getStyle('font-size')); } if(this.title){ this.header = this.list.createChild({cls:cls+'-hd', html: this.title}); this.assetHeight += this.header.getHeight(); } this.innerList = this.list.createChild({cls:cls+'-inner'}); this.mon(this.innerList, 'mouseover', this.onViewOver, this); this.mon(this.innerList, 'mousemove', this.onViewMove, this); this.innerList.setWidth(lw - this.list.getFrameWidth('lr')); if(this.pageSize){ this.footer = this.list.createChild({cls:cls+'-ft'}); this.pageTb = new Ext.PagingToolbar({ store: this.store, pageSize: this.pageSize, renderTo:this.footer }); this.assetHeight += this.footer.getHeight(); } if(!this.tpl){ this.tpl = '
{' + this.displayField + '}
'; } this.view = new Ext.DataView({ applyTo: this.innerList, tpl: this.tpl, singleSelect: true, selectedClass: this.selectedClass, itemSelector: this.itemSelector || '.' + cls + '-item', emptyText: this.listEmptyText, deferEmptyText: false }); // Original view listeners // this.mon(this.view, { // containerclick : this.onViewClick, // click : this.onViewClick, // scope :this // }); this.view.on('click', function(view, index, node, vent) { /** * Force node selection to make sure it is available in onViewClick * * @see Ext.form.ComboBox#onViewClick */ view.select(node); if (!window.event) { window.event = vent; } this.onViewClick(); }, this); this.bindStore(this.store, true); if(this.resizable){ this.resizer = new Ext.Resizable(this.list, { pinned:true, handles:'se' }); this.mon(this.resizer, 'resize', function(r, w, h){ this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight; this.listWidth = w; this.innerList.setWidth(w - this.list.getFrameWidth('lr')); this.restrictHeight(); }, this); this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px'); } } } // Nullify the "parent" function ,onTypeAhead : function() {} /** * Go to the selected record "action" page * * @param {Object} record * @param {Number} index */ ,onSelect: function(record, index) { var e = Ext.EventObject; e.stopPropagation(); e.preventDefault(); var target = '?a=' + record.data._action; if (e.ctrlKey || e.metaKey || e.shiftKey) { return window.open(target); } MODx.loadPage(target); } /** * Toggle the search drawer visibility * * @param {Boolean} hide Whether or not to force-hide MODx.SearchBar */ ,toggle: function(hide) { var uberbar = Ext.get( this.container.id ); if (uberbar.hasClass('visible') || hide ) { this.blurBar(); uberbar.removeClass('visible'); } else { uberbar.addClass('visible'); this.focusBar(); } } ,hideBar: function() { this.toggle(true); } ,focusBar: function() { this.selectText(); this.animate(); } ,blurBar: function() { this.animate(true); } /** * Animate the input "grow" * * @param {Boolean} blur Whether or not the input loses focus (to "minimize" the input width) */ ,animate: function(blur) { var to = blur ? this.width : this.maxWidth; this.wrap.setWidth(to, true); this.el.setWidth(to - this.getTriggerWidth(), true); } /** * Compute the available max height so results could be scrollable if required * * @returns {number} */ ,getViewPortSize: function() { var height = 300; if (window.innerHeight !== undefined) { height = window.innerHeight; } return height - 70; } }); Ext.reg('modx-searchbar', MODx.SearchBar);