1 Ext.BLANK_IMAGE_URL = 'resources/s.gif';
5 ApiPanel = function() {
6 ApiPanel.superclass.constructor.call(this, {
22 loader: new Ext.tree.TreeLoader({
23 preloadChildren: true,
26 root: new Ext.tree.AsyncTreeNode({
30 children:[Docs.classData]
35 //new Ext.tree.TreeSorter(this, {folderSort:true,leafAttr:'isClass'});
37 this.getSelectionModel().on('beforeselect', function(sm, node){
42 Ext.extend(ApiPanel, Ext.tree.TreePanel, {
43 initComponent: function(){
47 new Ext.form.TextField({
49 emptyText:'Find a Class',
50 enableKeyEvents: true,
53 this.filter = new Ext.tree.TreeFilter(this, {
67 iconCls: 'icon-expand-all',
68 tooltip: 'Expand All',
69 handler: function(){ this.root.expand(true); },
72 iconCls: 'icon-collapse-all',
73 tooltip: 'Collapse All',
74 handler: function(){ this.root.collapse(true); },
78 ApiPanel.superclass.initComponent.call(this);
80 filterTree: function(t, e){
81 var text = t.getValue();
82 Ext.each(this.hiddenPkgs, function(n){
91 var re = new RegExp('^' + Ext.escapeRe(text), 'i');
92 this.filter.filterBy(function(n){
93 return !n.attributes.isClass || re.test(n.text);
96 // hide empty packages that weren't filtered
98 this.root.cascade(function(n){
99 if(!n.attributes.isClass && n.ui.ctNode.offsetHeight < 3){
101 this.hiddenPkgs.push(n);
105 selectClass : function(cls){
107 var parts = cls.split('.');
108 var last = parts.length-1;
111 for(var i = 0; i < last; i++){ // things get nasty - static classes can have .
113 var fc = p.charAt(0);
114 var staticCls = fc.toUpperCase() == fc;
115 if(p == 'Ext' || !staticCls){
117 res[i] = 'pkg-'+pkg.join('.');
125 this.selectPath('/root/apidocs/'+res.join('/'));
131 DocPanel = Ext.extend(Ext.Panel, {
135 initComponent : function(){
136 var ps = this.cclass.split('.');
137 this.title = ps[ps.length-1];
140 text: 'Config Options',
141 handler: this.scrollToMember.createDelegate(this, ['configs']),
142 iconCls: 'icon-config'
145 handler: this.scrollToMember.createDelegate(this, ['props']),
149 handler: this.scrollToMember.createDelegate(this, ['methods']),
150 iconCls: 'icon-method'
153 handler: this.scrollToMember.createDelegate(this, ['events']),
154 iconCls: 'icon-event'
157 handler: this.directLink,
161 tooltip:'Hide Inherited Members',
162 iconCls: 'icon-hide-inherited',
165 toggleHandler : function(b, pressed){
166 this.body[pressed ? 'addClass' : 'removeClass']('hide-inherited');
169 tooltip:'Expand All Members',
170 iconCls: 'icon-expand-members',
173 toggleHandler : function(b, pressed){
174 this.body[pressed ? 'addClass' : 'removeClass']('full-details');
178 DocPanel.superclass.initComponent.call(this);
181 directLink : function(){
182 var link = String.format(
183 "<a href=\"{0}\" target=\"_blank\">{0}</a>",
184 document.location.href+'?class='+this.cclass
186 Ext.Msg.alert('Direct Link to ' + this.cclass,link);
189 scrollToMember : function(member){
190 var el = Ext.fly(this.cclass + '-' + member);
192 var top = (el.getOffsetsTo(this.body)[1]) + this.body.dom.scrollTop;
193 this.body.scrollTo('top', top-25, {duration:0.75, callback: this.hlMember.createDelegate(this, [member])});
197 scrollToSection : function(id){
198 var el = Ext.getDom(id);
200 var top = (Ext.fly(el).getOffsetsTo(this.body)[1]) + this.body.dom.scrollTop;
201 this.body.scrollTo('top', top-25, {duration:0.5, callback: function(){
202 Ext.fly(el).next('h2').pause(0.2).highlight('#8DB2E3', {attr:'color'});
207 hlMember : function(member){
208 var el = Ext.fly(this.cclass + '-' + member);
210 if (tr = el.up('tr')) {
211 tr.highlight('#cadaf9');
218 MainPanel = function(){
220 this.searchStore = new Ext.data.Store({
221 proxy: new Ext.data.ScriptTagProxy({
222 url: 'http://extjs.com/playpen/api.php'
224 reader: new Ext.data.JsonReader({
227 ['cls', 'member', 'type', 'doc']
231 'beforeload' : function(){
232 this.baseParams.qt = Ext.getCmp('search-type').getValue();
237 MainPanel.superclass.constructor.call(this, {
244 plugins: new Ext.ux.TabCloseMenu(),
245 enableTabScroll: true,
251 autoLoad: {url: 'welcome.html', callback: this.initSearch, scope: this},
256 new Ext.ux.SelectBox({
257 listClass:'x-combo-list-small',
261 store: new Ext.data.SimpleStore({
264 data : ['Starts with', 'Ends with', 'Any match']
268 new Ext.app.SearchField({
270 store: this.searchStore,
278 Ext.extend(MainPanel, Ext.TabPanel, {
280 initEvents : function(){
281 MainPanel.superclass.initEvents.call(this);
282 this.body.on('click', this.onClick, this);
285 onClick: function(e, target){
286 if(target = e.getTarget('a:not(.exi)', 3)){
287 var cls = Ext.fly(target).getAttributeNS('ext', 'cls');
290 var member = Ext.fly(target).getAttributeNS('ext', 'member');
291 this.loadClass(target.href, cls, member);
292 }else if(target.className == 'inner-link'){
293 this.getActiveTab().scrollToSection(target.href.split('#')[1]);
295 window.open(target.href);
297 }else if(target = e.getTarget('.micon', 2)){
299 var tr = Ext.fly(target.parentNode);
300 if(tr.hasClass('expandable')){
301 tr.toggleClass('expanded');
306 loadClass : function(href, cls, member){
307 var id = 'docs-' + cls;
308 var tab = this.getComponent(id);
310 this.setActiveTab(tab);
312 tab.scrollToMember(member);
315 var autoLoad = {url: href};
317 autoLoad.callback = function(){
318 Ext.getCmp(id).scrollToMember(member);
321 var p = this.add(new DocPanel({
325 iconCls: Docs.icons[cls]
327 this.setActiveTab(p);
331 initSearch : function(){
332 // Custom rendering Template for the View
333 var resultTpl = new Ext.XTemplate(
335 '<div class="search-item">',
336 '<a class="member" ext:cls="{cls}" ext:member="{member}" href="output/{cls}.html">',
337 '<img src="resources/images/default/s.gif" class="item-icon icon-{type}"/>{member}',
339 '<a class="cls" ext:cls="{cls}" href="output/{cls}.html">{cls}</a>',
344 var p = new Ext.DataView({
347 loadingText:'Searching...',
348 store: this.searchStore,
349 itemSelector: 'div.search-item',
350 emptyText: '<h3>Use the search field above to search the Ext API for classes, properties, config options, methods and events.</h3>'
354 doSearch : function(e){
356 if(!e.isSpecialKey()){
357 var text = e.target.value;
359 this.searchStore.baseParams.q = '';
360 this.searchStore.removeAll();
362 this.searchStore.baseParams.q = text;
363 this.searchStore.reload();
371 * Makes a ComboBox more closely mimic an HTML SELECT. Supports clicking and dragging
372 * through the list, with item selection occurring when the mouse button is released.
373 * When used will automatically set {@link #editable} to false and call {@link Ext.Element#unselectable}
374 * on inner elements. Re-enabling editable after calling this will NOT work.
376 * @author Corey Gilmore
377 * http://extjs.com/forum/showthread.php?t=6392
379 * @history 2007-07-08 jvs
380 * Slight mods for Ext 2.0
382 Ext.ux.SelectBox = function(config){
383 this.searchResetDelay = 1000;
384 config = config || {};
385 config = Ext.apply(config || {}, {
387 forceSelection: true,
389 lastSearchTerm: false,
390 triggerAction: 'all',
394 Ext.ux.SelectBox.superclass.constructor.apply(this, arguments);
396 this.lastSelectedIndex = this.selectedIndex || 0;
399 Ext.extend(Ext.ux.SelectBox, Ext.form.ComboBox, {
401 initEvents : function(){
402 Ext.ux.SelectBox.superclass.initEvents.apply(this, arguments);
403 // you need to use keypress to capture upper/lower case and shift+key, but it doesn't work in IE
404 this.el.on('keydown', this.keySearch, this, true);
405 this.cshTask = new Ext.util.DelayedTask(this.clearSearchHistory, this);
408 keySearch : function(e, target, options) {
409 var raw = e.getKey();
410 var key = String.fromCharCode(raw);
413 if( !this.store.getCount() ) {
418 case Ext.EventObject.HOME:
423 case Ext.EventObject.END:
428 case Ext.EventObject.PAGEDOWN:
429 this.selectNextPage();
433 case Ext.EventObject.PAGEUP:
434 this.selectPrevPage();
439 // skip special keys other than the shift key
440 if( (e.hasModifier() && !e.shiftKey) || e.isNavKeyPress() || e.isSpecialKey() ) {
443 if( this.lastSearchTerm == key ) {
444 startIndex = this.lastSelectedIndex;
446 this.search(this.displayField, key, startIndex);
447 this.cshTask.delay(this.searchResetDelay);
450 onRender : function(ct, position) {
451 this.store.on('load', this.calcRowsPerPage, this);
452 Ext.ux.SelectBox.superclass.onRender.apply(this, arguments);
453 if( this.mode == 'local' ) {
454 this.calcRowsPerPage();
458 onSelect : function(record, index, skipCollapse){
459 if(this.fireEvent('beforeselect', this, record, index) !== false){
460 this.setValue(record.data[this.valueField || this.displayField]);
461 if( !skipCollapse ) {
464 this.lastSelectedIndex = index + 1;
465 this.fireEvent('select', this, record, index);
469 render : function(ct) {
470 Ext.ux.SelectBox.superclass.render.apply(this, arguments);
472 this.el.swallowEvent('mousedown', true);
474 this.el.unselectable();
475 this.innerList.unselectable();
476 this.trigger.unselectable();
477 this.innerList.on('mouseup', function(e, target, options) {
478 if( target.id && target.id == this.innerList.id ) {
484 this.innerList.on('mouseover', function(e, target, options) {
485 if( target.id && target.id == this.innerList.id ) {
488 this.lastSelectedIndex = this.view.getSelectedIndexes()[0] + 1;
489 this.cshTask.delay(this.searchResetDelay);
492 this.trigger.un('click', this.onTriggerClick, this);
493 this.trigger.on('mousedown', function(e, target, options) {
495 this.onTriggerClick();
498 this.on('collapse', function(e, target, options) {
499 Ext.getDoc().un('mouseup', this.collapseIf, this);
502 this.on('expand', function(e, target, options) {
503 Ext.getDoc().on('mouseup', this.collapseIf, this);
507 clearSearchHistory : function() {
508 this.lastSelectedIndex = 0;
509 this.lastSearchTerm = false;
512 selectFirst : function() {
513 this.focusAndSelect(this.store.data.first());
516 selectLast : function() {
517 this.focusAndSelect(this.store.data.last());
520 selectPrevPage : function() {
521 if( !this.rowHeight ) {
524 var index = Math.max(this.selectedIndex-this.rowsPerPage, 0);
525 this.focusAndSelect(this.store.getAt(index));
528 selectNextPage : function() {
529 if( !this.rowHeight ) {
532 var index = Math.min(this.selectedIndex+this.rowsPerPage, this.store.getCount() - 1);
533 this.focusAndSelect(this.store.getAt(index));
536 search : function(field, value, startIndex) {
537 field = field || this.displayField;
538 this.lastSearchTerm = value;
539 var index = this.store.find.apply(this.store, arguments);
541 this.focusAndSelect(index);
545 focusAndSelect : function(record) {
546 var index = typeof record === 'number' ? record : this.store.indexOf(record);
547 this.select(index, this.isExpanded());
548 this.onSelect(this.store.getAt(record), index, this.isExpanded());
551 calcRowsPerPage : function() {
552 if( this.store.getCount() ) {
553 this.rowHeight = Ext.fly(this.view.getNode(0)).getHeight();
554 this.rowsPerPage = this.maxHeight / this.rowHeight;
556 this.rowHeight = false;
562 Ext.onReady(function(){
564 Ext.QuickTips.init();
566 var api = new ApiPanel();
567 var mainPanel = new MainPanel();
569 api.on('click', function(node, e){
572 mainPanel.loadClass(node.attributes.href, node.id);
576 mainPanel.on('tabchange', function(tp, tab){
577 api.selectClass(tab.cclass);
580 var viewport = new Ext.Viewport({
593 api.expandPath('/root/apidocs');
596 var page = window.location.href.split('?')[1];
598 var ps = Ext.urlDecode(page);
599 var cls = ps['class'];
600 mainPanel.loadClass('output/' + cls + '.html', cls, ps.member);
605 setTimeout(function(){
606 Ext.get('loading').remove();
607 Ext.get('loading-mask').fadeOut({remove:true});
613 Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
614 initComponent : function(){
615 if(!this.store.baseParams){
616 this.store.baseParams = {};
618 Ext.app.SearchField.superclass.initComponent.call(this);
619 this.on('specialkey', function(f, e){
620 if(e.getKey() == e.ENTER){
621 this.onTrigger2Click();
626 validationEvent:false,
627 validateOnBlur:false,
628 trigger1Class:'x-form-clear-trigger',
629 trigger2Class:'x-form-search-trigger',
635 onTrigger1Click : function(){
637 this.store.baseParams[this.paramName] = '';
638 this.store.removeAll();
639 this.el.dom.value = '';
640 this.triggers[0].hide();
641 this.hasSearch = false;
646 onTrigger2Click : function(){
647 var v = this.getRawValue();
649 this.onTrigger1Click();
653 Ext.Msg.alert('Invalid Search', 'You must enter a minimum of 2 characters to search the API');
656 this.store.baseParams[this.paramName] = v;
658 this.store.reload({params:o});
659 this.hasSearch = true;
660 this.triggers[0].show();
667 Ext.Ajax.on('requestcomplete', function(ajax, xhr, o){
668 if(typeof urchinTracker == 'function' && o && o.url){
669 urchinTracker(o.url);