Merge pull request #17861 from totten/master-dao-event
[civicrm-core.git] / js / crm.menubar.js
index 9fa49f63d69a5fc0d23f4bdf21f3c9ea74eec42f..d28f0983498f6a908f41c5b3839575871977f3ba 100644 (file)
@@ -8,6 +8,7 @@
     data: null,
     settings: {collapsibleBehavior: 'accordion'},
     position: 'over-cms-menu',
+    toggleButton: true,
     attachTo: (CRM.menubar && CRM.menubar.position === 'above-crm-container') ? '#crm-container' : 'body',
     initialize: function() {
       var cache = CRM.cache.get('menubar');
             })
             .on('show.smapi', function(e, menu) {
               // Focus menu when opened with an accesskey
-              $(menu).siblings('a[accesskey]').focus();
+              if ($(menu).parent().data('name') === 'Home') {
+                $('#crm-menubar-drilldown').focus();
+              } else {
+                $(menu).siblings('a[accesskey]').focus();
+              }
             })
             .smartmenus(CRM.menubar.settings);
           initialized = true;
           CRM.menubar.initializeResponsive();
           CRM.menubar.initializeSearch();
+          CRM.menubar.initializeDrill();
         });
       }
     },
     getItem: function(itemName) {
       return traverse(CRM.menubar.data.menu, itemName, 'get');
     },
+    findItems: function(searchTerm) {
+      return findRecursive(CRM.menubar.data.menu, searchTerm.toLowerCase().replace(/ /g, ''));
+    },
     addItems: function(position, targetName, items) {
       var list, container, $ul;
       if (position === 'before' || position === 'after') {
       }
     },
     initializePosition: function() {
-      if (CRM.menubar.position === 'over-cms-menu' || CRM.menubar.position === 'below-cms-menu') {
+      if (CRM.menubar.toggleButton && (CRM.menubar.position === 'over-cms-menu' || CRM.menubar.position === 'below-cms-menu')) {
         $('#civicrm-menu')
           .on('click', 'a[href="#toggle-position"]', function(e) {
             e.preventDefault();
             CRM.menubar.togglePosition();
           })
-          .append('<li id="crm-menubar-toggle-position"><a href="#toggle-position" title="' + ts('Adjust menu position') + '"><i class="crm-i fa-arrow-up"></i></a>');
+          .append('<li id="crm-menubar-toggle-position"><a href="#toggle-position" title="' + ts('Adjust menu position') + '"><i class="crm-i fa-arrow-up" aria-hidden="true"></i></a>');
         CRM.menubar.position = CRM.cache.get('menubarPosition', CRM.menubar.position);
       }
       $('body').addClass('crm-menubar-visible crm-menubar-' + CRM.menubar.position);
     },
+    removeToggleButton: function() {
+      $('#crm-menubar-toggle-position').remove();
+      CRM.menubar.toggleButton = false;
+      if (CRM.menubar.position === 'below-cms-menu') {
+        CRM.menubar.togglePosition();
+      }
+    },
     initializeResponsive: function() {
       var $mainMenuState = $('#crm-menubar-state');
       // hide mobile menu beforeunload
         var $selection = $('.crm-quickSearchField input:checked'),
           label = $selection.parent().text(),
           value = $selection.val();
-        // These fields are not supported by advanced search
-        if (!value || value === 'first_name' || value === 'last_name') {
-          value = 'sort_name';
-        }
         $('#crm-qsearch-input').attr({name: value, placeholder: '\uf002 ' + label});
       }
       $('.crm-quickSearchField').click(function() {
         return !$('ul.crm-quickSearch-results').is(':visible:not(.ui-state-disabled)');
       });
     },
+    initializeDrill: function() {
+      $('#civicrm-menu').on('keyup', '#crm-menubar-drilldown', function() {
+        var term = $(this).val(),
+          results = term ? CRM.menubar.findItems(term).slice(0, 20) : [];
+        $(this).parent().next('ul').html(getTpl('branch')({items: results, branchTpl: getTpl('branch'), drillTpl: _.noop}));
+        $('#civicrm-menu').smartmenus('refresh').smartmenus('itemActivate', $(this).closest('a'));
+      });
+    },
     treeTpl:
       '<nav id="civicrm-menu-nav">' +
         '<input id="crm-menubar-state" type="checkbox" />' +
           '<% }) %>' +
         '</ul>' +
       '</li>',
+    drillTpl:
+      '<li class="crm-menu-border-bottom" data-name="MenubarDrillDown">' +
+        '<a href="#"><input type="text" id="crm-menubar-drilldown" placeholder="' + _.escape(ts('Find menu item...')) + '"></a>' +
+        '<ul></ul>' +
+      '</li>',
     branchTpl:
       '<% _.forEach(items, function(item) { %>' +
         '<li <%= attr("li", item) %>>' +
             '<% } %>' +
           '</a>' +
           '<% if (item.child) { %>' +
-            '<ul><%= branchTpl({items: item.child, branchTpl: branchTpl}) %></ul>' +
+            '<ul>' +
+              '<% if (item.name === "Home") { %><%= drillTpl() %><% } %>' +
+              '<%= branchTpl({items: item.child, branchTpl: branchTpl}) %>' +
+            '</ul>' +
           '<% } %>' +
         '</li>' +
       '<% }) %>'
   function getTpl(name) {
     if (!templates) {
       templates = {
-        branch: _.template(CRM.menubar.branchTpl, {imports: {_: _, attr: attr}}),
+        drill: _.template(CRM.menubar.drillTpl, {}),
         search: _.template(CRM.menubar.searchTpl, {imports: {_: _, ts: ts, CRM: CRM}})
       };
+      templates.branch = _.template(CRM.menubar.branchTpl, {imports: {_: _, attr: attr, drillTpl: templates.drill}});
       templates.tree = _.template(CRM.menubar.treeTpl, {imports: {branchTpl: templates.branch, searchTpl: templates.search, ts: ts}});
     }
     return templates[name];
     return found;
   }
 
+  function findRecursive(collection, searchTerm) {
+    var items = _.filter(collection, function(item) {
+      return item.label && _.includes(item.label.toLowerCase().replace(/ /g, ''), searchTerm);
+    });
+    _.each(collection, function(item) {
+      if (_.isPlainObject(item) && item.child) {
+        var childMatches = findRecursive(item.child, searchTerm);
+        if (childMatches.length) {
+          Array.prototype.push.apply(items, childMatches);
+        }
+      }
+    });
+    return items;
+  }
+
   function attr(el, item) {
     var ret = [], attr = _.cloneDeep(item.attr || {}), a = ['rel', 'accesskey', 'target'];
     if (el === 'a') {