3 * Copyright(c) 2006-2009 Ext JS, LLC
5 * http://www.extjs.com/license
7 Ext.BLANK_IMAGE_URL = 'resources/s.gif';
11 ApiPanel = function() {
12 ApiPanel.superclass.constructor.call(this, {
28 loader: new Ext.tree.TreeLoader({
29 preloadChildren: true,
32 root: new Ext.tree.AsyncTreeNode({
36 children:[Docs.classData]
41 //new Ext.tree.TreeSorter(this, {folderSort:true,leafAttr:'isClass'});
43 this.getSelectionModel().on('beforeselect', function(sm, node){
48 Ext.extend(ApiPanel, Ext.tree.TreePanel, {
49 selectClass : function(cls){
51 var parts = cls.split('.');
52 var last = parts.length-1;
55 for(var i = 0; i < last; i++){ // things get nasty - static classes can have .
58 var staticCls = fc.toUpperCase() == fc;
59 if(p == 'Ext' || !staticCls){
61 res[i] = 'pkg-'+pkg.join('.');
69 this.selectPath('/root/apidocs/'+res.join('/'));
75 DocPanel = Ext.extend(Ext.Panel, {
79 initComponent : function(){
80 var ps = this.cclass.split('.');
81 this.title = ps[ps.length-1];
83 DocPanel.superclass.initComponent.call(this);
86 scrollToMember : function(member){
87 var el = Ext.fly(this.cclass + '-' + member);
89 var top = (el.getOffsetsTo(this.body)[1]) + this.body.dom.scrollTop;
90 this.body.scrollTo('top', top-25, {duration:.75, callback: this.hlMember.createDelegate(this, [member])});
94 scrollToSection : function(id){
95 var el = Ext.getDom(id);
97 var top = (Ext.fly(el).getOffsetsTo(this.body)[1]) + this.body.dom.scrollTop;
98 this.body.scrollTo('top', top-25, {duration:.5, callback: function(){
99 Ext.fly(el).next('h2').pause(.2).highlight('#8DB2E3', {attr:'color'});
104 hlMember : function(member){
105 var el = Ext.fly(this.cclass + '-' + member);
107 el.up('tr').highlight('#cadaf9');
113 MainPanel = function(){
115 this.searchStore = new Ext.data.Store({
116 proxy: new Ext.data.ScriptTagProxy({
117 url: 'http://extjs.com/playpen/api.php'
119 reader: new Ext.data.JsonReader({
122 ['cls', 'member', 'type', 'doc']
126 'beforeload' : function(){
127 this.baseParams.qt = Ext.getCmp('search-type').getValue();
132 MainPanel.superclass.constructor.call(this, {
139 plugins: new Ext.ux.TabCloseMenu(),
140 enableTabScroll: true,
146 autoLoad: {url: 'welcome.html', callback: this.initSearch, scope: this},
151 new Ext.ux.SelectBox({
152 listClass:'x-combo-list-small',
156 store: new Ext.data.SimpleStore({
159 data : ['Starts with', 'Ends with', 'Any match']
163 new Ext.app.SearchField({
165 store: this.searchStore,
173 Ext.extend(MainPanel, Ext.TabPanel, {
175 initEvents : function(){
176 MainPanel.superclass.initEvents.call(this);
177 this.body.on('click', this.onClick, this);
180 onClick: function(e, target){
181 if(target = e.getTarget('a:not(.exi)', 3)){
182 var cls = Ext.fly(target).getAttributeNS('ext', 'cls');
185 var member = Ext.fly(target).getAttributeNS('ext', 'member');
186 this.loadClass(target.href, cls, member);
187 }else if(target.className == 'inner-link'){
188 this.getActiveTab().scrollToSection(target.href.split('#')[1]);
190 window.open(target.href);
192 }else if(target = e.getTarget('.micon', 2)){
194 var tr = Ext.fly(target.parentNode);
195 if(tr.hasClass('expandable')){
196 tr.toggleClass('expanded');
201 loadClass : function(href, cls, member){
202 var id = 'docs-' + cls;
203 var tab = this.getComponent(id);
205 this.setActiveTab(tab);
207 tab.scrollToMember(member);
210 var autoLoad = {url: href};
212 autoLoad.callback = function(){
213 Ext.getCmp(id).scrollToMember(member);
216 var p = this.add(new DocPanel({
220 iconCls: Docs.icons[cls]
222 this.setActiveTab(p);
226 initSearch : function(){
227 // Custom rendering Template for the View
228 var resultTpl = new Ext.XTemplate(
230 '<div class="search-item">',
231 '<a class="member" ext:cls="{cls}" ext:member="{member}" href="output/{cls}.html">',
232 '<img src="resources/images/default/s.gif" class="item-icon icon-{type}"/>{member}',
234 '<a class="cls" ext:cls="{cls}" href="output/{cls}.html">{cls}</a>',
239 var p = new Ext.DataView({
242 loadingText:'Searching...',
243 store: this.searchStore,
244 itemSelector: 'div.search-item',
245 emptyText: '<h3>Use the search field above to search the Ext API for classes, properties, config options, methods and events.</h3>'
249 doSearch : function(e){
251 if(!e.isSpecialKey()){
252 var text = e.target.value;
254 this.searchStore.baseParams.q = '';
255 this.searchStore.removeAll();
257 this.searchStore.baseParams.q = text;
258 this.searchStore.reload();
265 Ext.onReady(function(){
267 Ext.QuickTips.init();
269 var api = new ApiPanel();
270 var mainPanel = new MainPanel();
272 api.on('click', function(node, e){
275 mainPanel.loadClass(node.attributes.href, node.id);
279 mainPanel.on('tabchange', function(tp, tab){
280 api.selectClass(tab.cclass);
283 var hd = new Ext.Panel({
298 new Ext.form.TextField({
300 emptyText:'Find a Class',
303 f.el.on('keydown', filterTree, f, {buffer: 350});
308 iconCls: 'icon-expand-all',
309 tooltip: 'Expand All',
310 handler: function(){ api.root.expand(true); }
312 iconCls: 'icon-collapse-all',
313 tooltip: 'Collapse All',
314 handler: function(){ api.root.collapse(true); }
316 tooltip:'Hide Inherited Members',
317 iconCls: 'icon-hide-inherited',
319 toggleHandler : function(b, pressed){
320 mainPanel[pressed ? 'addClass' : 'removeClass']('hide-inherited');
323 tooltip:'Expand All Members',
324 iconCls: 'icon-expand-members',
326 toggleHandler : function(b, pressed){
327 mainPanel[pressed ? 'addClass' : 'removeClass']('full-details');
333 var viewport = new Ext.Viewport({
335 items:[ hd, api, mainPanel ]
338 api.expandPath('/root/apidocs');
341 var page = window.location.href.split('?')[1];
343 var ps = Ext.urlDecode(page);
344 var cls = ps['class'];
345 mainPanel.loadClass('output/' + cls + '.html', cls, ps.member);
350 setTimeout(function(){
351 Ext.get('loading').remove();
352 Ext.get('loading-mask').fadeOut({remove:true});
355 var filter = new Ext.tree.TreeFilter(api, {
360 function filterTree(e){
361 var text = e.target.value;
362 Ext.each(hiddenPkgs, function(n){
371 var re = new RegExp('^' + Ext.escapeRe(text), 'i');
372 filter.filterBy(function(n){
373 return !n.attributes.isClass || re.test(n.text);
376 // hide empty packages that weren't filtered
378 api.root.cascade(function(n){
379 if(!n.attributes.isClass && n.ui.ctNode.offsetHeight < 3){
389 Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
390 initComponent : function(){
391 if(!this.store.baseParams){
392 this.store.baseParams = {};
394 Ext.app.SearchField.superclass.initComponent.call(this);
395 this.on('specialkey', function(f, e){
396 if(e.getKey() == e.ENTER){
397 this.onTrigger2Click();
402 validationEvent:false,
403 validateOnBlur:false,
404 trigger1Class:'x-form-clear-trigger',
405 trigger2Class:'x-form-search-trigger',
411 onTrigger1Click : function(){
413 this.store.baseParams[this.paramName] = '';
414 this.store.removeAll();
415 this.el.dom.value = '';
416 this.triggers[0].hide();
417 this.hasSearch = false;
422 onTrigger2Click : function(){
423 var v = this.getRawValue();
425 this.onTrigger1Click();
429 Ext.Msg.alert('Invalid Search', 'You must enter a minimum of 2 characters to search the API');
432 this.store.baseParams[this.paramName] = v;
434 this.store.reload({params:o});
435 this.hasSearch = true;
436 this.triggers[0].show();
443 * Makes a ComboBox more closely mimic an HTML SELECT. Supports clicking and dragging
444 * through the list, with item selection occurring when the mouse button is released.
445 * When used will automatically set {@link #editable} to false and call {@link Ext.Element#unselectable}
446 * on inner elements. Re-enabling editable after calling this will NOT work.
448 * @author Corey Gilmore
449 * http://extjs.com/forum/showthread.php?t=6392
451 * @history 2007-07-08 jvs
452 * Slight mods for Ext 2.0
454 Ext.ux.SelectBox = function(config){
455 this.searchResetDelay = 1000;
456 config = config || {};
457 config = Ext.apply(config || {}, {
459 forceSelection: true,
461 lastSearchTerm: false,
462 triggerAction: 'all',
466 Ext.ux.SelectBox.superclass.constructor.apply(this, arguments);
468 this.lastSelectedIndex = this.selectedIndex || 0;
471 Ext.extend(Ext.ux.SelectBox, Ext.form.ComboBox, {
473 initEvents : function(){
474 Ext.ux.SelectBox.superclass.initEvents.apply(this, arguments);
475 // you need to use keypress to capture upper/lower case and shift+key, but it doesn't work in IE
476 this.el.on('keydown', this.keySearch, this, true);
477 this.cshTask = new Ext.util.DelayedTask(this.clearSearchHistory, this);
480 keySearch : function(e, target, options) {
481 var raw = e.getKey();
482 var key = String.fromCharCode(raw);
485 if( !this.store.getCount() ) {
490 case Ext.EventObject.HOME:
495 case Ext.EventObject.END:
500 case Ext.EventObject.PAGEDOWN:
501 this.selectNextPage();
505 case Ext.EventObject.PAGEUP:
506 this.selectPrevPage();
511 // skip special keys other than the shift key
512 if( (e.hasModifier() && !e.shiftKey) || e.isNavKeyPress() || e.isSpecialKey() ) {
515 if( this.lastSearchTerm == key ) {
516 startIndex = this.lastSelectedIndex;
518 this.search(this.displayField, key, startIndex);
519 this.cshTask.delay(this.searchResetDelay);
522 onRender : function(ct, position) {
523 this.store.on('load', this.calcRowsPerPage, this);
524 Ext.ux.SelectBox.superclass.onRender.apply(this, arguments);
525 if( this.mode == 'local' ) {
526 this.calcRowsPerPage();
530 onSelect : function(record, index, skipCollapse){
531 if(this.fireEvent('beforeselect', this, record, index) !== false){
532 this.setValue(record.data[this.valueField || this.displayField]);
533 if( !skipCollapse ) {
536 this.lastSelectedIndex = index + 1;
537 this.fireEvent('select', this, record, index);
541 render : function(ct) {
542 Ext.ux.SelectBox.superclass.render.apply(this, arguments);
544 this.el.swallowEvent('mousedown', true);
546 this.el.unselectable();
547 this.innerList.unselectable();
548 this.trigger.unselectable();
549 this.innerList.on('mouseup', function(e, target, options) {
550 if( target.id && target.id == this.innerList.id ) {
556 this.innerList.on('mouseover', function(e, target, options) {
557 if( target.id && target.id == this.innerList.id ) {
560 this.lastSelectedIndex = this.view.getSelectedIndexes()[0] + 1;
561 this.cshTask.delay(this.searchResetDelay);
564 this.trigger.un('click', this.onTriggerClick, this);
565 this.trigger.on('mousedown', function(e, target, options) {
567 this.onTriggerClick();
570 this.on('collapse', function(e, target, options) {
571 Ext.getDoc().un('mouseup', this.collapseIf, this);
574 this.on('expand', function(e, target, options) {
575 Ext.getDoc().on('mouseup', this.collapseIf, this);
579 clearSearchHistory : function() {
580 this.lastSelectedIndex = 0;
581 this.lastSearchTerm = false;
584 selectFirst : function() {
585 this.focusAndSelect(this.store.data.first());
588 selectLast : function() {
589 this.focusAndSelect(this.store.data.last());
592 selectPrevPage : function() {
593 if( !this.rowHeight ) {
596 var index = Math.max(this.selectedIndex-this.rowsPerPage, 0);
597 this.focusAndSelect(this.store.getAt(index));
600 selectNextPage : function() {
601 if( !this.rowHeight ) {
604 var index = Math.min(this.selectedIndex+this.rowsPerPage, this.store.getCount() - 1);
605 this.focusAndSelect(this.store.getAt(index));
608 search : function(field, value, startIndex) {
609 field = field || this.displayField;
610 this.lastSearchTerm = value;
611 var index = this.store.find.apply(this.store, arguments);
613 this.focusAndSelect(index);
617 focusAndSelect : function(record) {
618 var index = typeof record === 'number' ? record : this.store.indexOf(record);
619 this.select(index, this.isExpanded());
620 this.onSelect(this.store.getAt(record), index, this.isExpanded());
623 calcRowsPerPage : function() {
624 if( this.store.getCount() ) {
625 this.rowHeight = Ext.fly(this.view.getNode(0)).getHeight();
626 this.rowsPerPage = this.maxHeight / this.rowHeight;
628 this.rowHeight = false;
634 Ext.Ajax.on('requestcomplete', function(ajax, xhr, o){
635 if(typeof urchinTracker == 'function' && o && o.url){
636 urchinTracker(o.url);