nbot

A clone of the eBot by @deStrO fully based on node.js with build in Web Page - WIP
git clone git://archive.git.mtrnord.blog/MTRNord/nbot.git
Log | Files | Refs | README | LICENSE

api-list.js (6770B)


      1 YUI.add('api-list', function (Y) {
      2 
      3 var Lang   = Y.Lang,
      4     YArray = Y.Array,
      5 
      6     APIList = Y.namespace('APIList'),
      7 
      8     classesNode    = Y.one('#api-classes'),
      9     elementsNode   = Y.one('#api-elements'),
     10     inputNode      = Y.one('#api-filter'),
     11     modulesNode    = Y.one('#api-modules'),
     12     tabviewNode    = Y.one('#api-tabview'),
     13 
     14     tabs = APIList.tabs = {},
     15 
     16     filter = APIList.filter = new Y.APIFilter({
     17         inputNode : inputNode,
     18         maxResults: 1000,
     19 
     20         on: {
     21             results: onFilterResults
     22         }
     23     }),
     24 
     25     search = APIList.search = new Y.APISearch({
     26         inputNode : inputNode,
     27         maxResults: 100,
     28 
     29         on: {
     30             clear  : onSearchClear,
     31             results: onSearchResults
     32         }
     33     }),
     34 
     35     tabview = APIList.tabview = new Y.TabView({
     36         srcNode  : tabviewNode,
     37         panelNode: '#api-tabview-panel',
     38         render   : true,
     39 
     40         on: {
     41             selectionChange: onTabSelectionChange
     42         }
     43     }),
     44 
     45     focusManager = APIList.focusManager = tabviewNode.plug(Y.Plugin.NodeFocusManager, {
     46         circular   : true,
     47         descendants: '#api-filter, .yui3-tab-panel-selected .api-list-item a, .yui3-tab-panel-selected .result a',
     48         keys       : {next: 'down:40', previous: 'down:38'}
     49     }).focusManager,
     50 
     51     LIST_ITEM_TEMPLATE =
     52         '<li class="api-list-item {typeSingular}">' +
     53             '<a href="{rootPath}{typePlural}/{name}.html">{displayName}</a>' +
     54         '</li>';
     55 
     56 // -- Init ---------------------------------------------------------------------
     57 
     58 // Duckpunch FocusManager's key event handling to prevent it from handling key
     59 // events when a modifier is pressed.
     60 Y.before(function (e, activeDescendant) {
     61     if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
     62         return new Y.Do.Prevent();
     63     }
     64 }, focusManager, '_focusPrevious', focusManager);
     65 
     66 Y.before(function (e, activeDescendant) {
     67     if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
     68         return new Y.Do.Prevent();
     69     }
     70 }, focusManager, '_focusNext', focusManager);
     71 
     72 // Create a mapping of tabs in the tabview so we can refer to them easily later.
     73 tabview.each(function (tab, index) {
     74     var name = tab.get('label').toLowerCase();
     75 
     76     tabs[name] = {
     77         index: index,
     78         name : name,
     79         tab  : tab
     80     };
     81 });
     82 
     83 // Switch tabs on Ctrl/Cmd-Left/Right arrows.
     84 tabviewNode.on('key', onTabSwitchKey, 'down:37,39');
     85 
     86 // Focus the filter input when the `/` key is pressed.
     87 Y.one(Y.config.doc).on('key', onSearchKey, 'down:83');
     88 
     89 // Keep the Focus Manager up to date.
     90 inputNode.on('focus', function () {
     91     focusManager.set('activeDescendant', inputNode);
     92 });
     93 
     94 // Update all tabview links to resolved URLs.
     95 tabview.get('panelNode').all('a').each(function (link) {
     96     link.setAttribute('href', link.get('href'));
     97 });
     98 
     99 // -- Private Functions --------------------------------------------------------
    100 function getFilterResultNode() {
    101     var queryType = filter.get('queryType');
    102     return queryType === 'classes' ? classesNode
    103             : queryType === 'elements' ? elementsNode : modulesNode;
    104 }
    105 
    106 // -- Event Handlers -----------------------------------------------------------
    107 function onFilterResults(e) {
    108     var frag         = Y.one(Y.config.doc.createDocumentFragment()),
    109         resultNode   = getFilterResultNode(),
    110         typePlural   = filter.get('queryType'),
    111         typeSingular = typePlural === 'classes' ? 'class' : typePlural === 'elements' ? 'element' : 'module';
    112 
    113     if (e.results.length) {
    114         YArray.each(e.results, function (result) {
    115             frag.append(Lang.sub(LIST_ITEM_TEMPLATE, {
    116                 rootPath    : APIList.rootPath,
    117                 displayName : filter.getDisplayName(result.highlighted),
    118                 name        : result.text,
    119                 typePlural  : typePlural,
    120                 typeSingular: typeSingular
    121             }));
    122         });
    123     } else {
    124         frag.append(
    125             '<li class="message">' +
    126                 'No ' + typePlural + ' found.' +
    127             '</li>'
    128         );
    129     }
    130 
    131     resultNode.empty(true);
    132     resultNode.append(frag);
    133 
    134     focusManager.refresh();
    135 }
    136 
    137 function onSearchClear(e) {
    138 
    139     focusManager.refresh();
    140 }
    141 
    142 function onSearchKey(e) {
    143     var target = e.target;
    144 
    145     if (target.test('input,select,textarea')
    146             || target.get('isContentEditable')) {
    147         return;
    148     }
    149 
    150     e.preventDefault();
    151 
    152     inputNode.focus();
    153     focusManager.refresh();
    154 }
    155 
    156 function onSearchResults(e) {
    157     var frag = Y.one(Y.config.doc.createDocumentFragment());
    158 
    159     if (e.results.length) {
    160         YArray.each(e.results, function (result) {
    161             frag.append(result.display);
    162         });
    163     } else {
    164         frag.append(
    165             '<li class="message">' +
    166                 'No results found. Maybe you\'ll have better luck with a ' +
    167                 'different query?' +
    168             '</li>'
    169         );
    170     }
    171 
    172 
    173     focusManager.refresh();
    174 }
    175 
    176 function onTabSelectionChange(e) {
    177     var tab  = e.newVal,
    178         name = tab.get('label').toLowerCase();
    179 
    180     tabs.selected = {
    181         index: tab.get('index'),
    182         name : name,
    183         tab  : tab
    184     };
    185 
    186     switch (name) {
    187     case 'elements':// fallthru
    188     case 'classes': // fallthru
    189     case 'modules':
    190         filter.setAttrs({
    191             minQueryLength: 0,
    192             queryType     : name
    193         });
    194 
    195         search.set('minQueryLength', -1);
    196 
    197         // Only send a request if this isn't the initially-selected tab.
    198         if (e.prevVal) {
    199             filter.sendRequest(filter.get('value'));
    200         }
    201         break;
    202 
    203     case 'everything':
    204         filter.set('minQueryLength', -1);
    205         search.set('minQueryLength', 1);
    206 
    207         if (search.get('value')) {
    208             search.sendRequest(search.get('value'));
    209         } else {
    210             inputNode.focus();
    211         }
    212         break;
    213 
    214     default:
    215         // WTF? We shouldn't be here!
    216         filter.set('minQueryLength', -1);
    217         search.set('minQueryLength', -1);
    218     }
    219 
    220     if (focusManager) {
    221         setTimeout(function () {
    222             focusManager.refresh();
    223         }, 1);
    224     }
    225 }
    226 
    227 function onTabSwitchKey(e) {
    228     var currentTabIndex = tabs.selected.index;
    229 
    230     if (!(e.ctrlKey || e.metaKey)) {
    231         return;
    232     }
    233 
    234     e.preventDefault();
    235 
    236     switch (e.keyCode) {
    237     case 37: // left arrow
    238         if (currentTabIndex > 0) {
    239             tabview.selectChild(currentTabIndex - 1);
    240             inputNode.focus();
    241         }
    242         break;
    243 
    244     case 39: // right arrow
    245         if (currentTabIndex < (Y.Object.size(tabs) - 2)) {
    246             tabview.selectChild(currentTabIndex + 1);
    247             inputNode.focus();
    248         }
    249         break;
    250     }
    251 }
    252 
    253 }, '3.4.0', {requires: [
    254     'api-filter', 'api-search', 'event-key', 'node-focusmanager', 'tabview'
    255 ]});