2013-02-11 5 views
0

Хотя я пытался выяснить, как аккуратно отображать очень длинные навигационные ссылки, я наткнулся на этот плагин jQuery IOS Drill Down Menu (исходная статья: jQuery Wiki Menu). Я попытался реализовать его как виджет в свое решение, но я думаю, что проблемы лежат в некоторых из его устаревших методов, таких как .left и .right.jQuery UI ipod Drill Down Menu

В настоящее время я использую jquery 1.9.0 и jQuery UI 1.10.0.

Я не очень разбираюсь в написании виджетов/обновлении их, поэтому любая помощь с этим будет очень признательна, поскольку она кажется действительно полезным виджетами для отображения сложных меню.

CSS Snipet:

.ios-style, .ios-style ul, .ios-style ol { background: #fff; height: 200px; padding: 2px; width: 260px; } 
    .ios-style { overflow-x: hidden; overflow-y: auto; } 
    .ios-style::-webkit-scrollbar { width: 5px; height: 5px; } 
    .ios-style::-webkit-scrollbar-thumb { background: rgba(128, 128, 128, 0.6); border-radius: 4px; } 
    .ios-style ul, .ios-style ol { overflow-y: visible; border: none; } 
    .ios-style.ui-menu-icons .ui-menu-item a { position: inherit; } 
    .ios-style .ui-menu-item a { cursor: pointer; outline: none; } 

JQuery виджет Код:

<script type="text/javascript"> 
    $.widget("ui.iosMenu", { 
     options: { 
      backText:  'Back', 
      slideDuration: 400, 
      slideEasing: 'linear' 
     }, 

     _insertBackButtons: function() { 
      this.element.find('li ul, li ol').prepend(
       $('<li>' + 
        ' <span class="ui-icon ui-icon-carat-1-w"></span>' + 
        ' <a href="#menu-back" class="ios-menu-back-link">' + 
           this.options.backText + 
        ' </a>' + 
        '</li>' 
      )); 
      return this; 
     }, 

     _create: function(options) { 
      var iosMenu = this; 

      iosMenu 
       ._insertBackButtons() 
       .element 
        .addClass('ios-style') 
        .menu({ 
         // When a submenu shows up, place it just to the right 
         // of the current menu. Later, we'll slide it into view. 
         position: { 
          my: 'left top', 
          at: 'right top', 
          of: iosMenu.element 
         } 
        }); 

      var menu = iosMenu.element.data('menu'); 

      // Override menu#select to account for nesting and back buttons: 
      menu.select = function(event) { 
       if (menu.active && menu.active.find('> .ios-menu-back-link').length) { 
        // if you selected "back", go back: 
        menu.focus(event, menu.active); 
        if (menu.left(event)) { 
         event.stopImmediatePropagation(); 
        } 
        event.preventDefault(); 
       } else if (menu.active && menu.active.find('> ul').length) { 
        // if you selected something with children, show the children: 
        menu.focus(event, menu.active); 
        if (menu.right(event)) { 
         event.stopImmediatePropagation(); 
        } 
        event.preventDefault(); 
       } else { 
        menu._trigger('select', event, { item: menu.active }); 
       } 
      }; 

      // Override menu#left to enable sliding behavior: 
      menu.left = function(event) { 
       var newItem = this.active && this.active.parents('li:not(.ui-menubar-item) ').first(), 
         self  = this, 
         parent; 
       if (newItem && newItem.length) { 
        newItem.find('> a').addClass('ui-state-focus').removeClass('ui-state-active'); 
        parent = this.active.parent(); 
        parent 
         .attr('aria-hidden', 'true') 
         .attr('aria-expanded', 'false') 
         .animate({ 
          left: self.element.css('width') 
         }, iosMenu.options.slideDuration, iosMenu.options.slideEasing, function() { 
          parent.hide(); 
          self.focus(event, newItem); 
         }) 
        return true; 
       } else if (event && event.which === $.ui.keyCode.ESCAPE) { 
        // #left gets called both for left-arrow and escape. If it's the 
        // latter and we're at the top, fire a "close" event: 
        self._trigger('close', event); 
       } 
      }; 

      // Override menu#_open to enable sliding behavior: 
      var menuOpenWithoutSliding = menu._open; 
      menu._open = function (submenu) { 
       menuOpenWithoutSliding.call(this, submenu); 
       submenu.animate({ 
        left: 0 
       }, iosMenu.options.slideDuration, iosMenu.options.slideEasing); 
      }; 

      // Override menu#_startOpening so that hovering doesn't 
      // initiate the sliding: 
      menu._startOpening = function() { 
       clearTimeout(this.timer); 
      } 
     }, 

     destroy: function() { 
      var menu = this.element && this.element.data('menu'); 
      menu && menu.destroy(); 
     } 
    }); 

    $(function() { 
     var list = $('#breakfast-menu'); 
     var firstLI = list.find('li').first(); 
     list 
      .iosMenu() 
      .focus() 
      .menu('focus', {}, firstLI) 
      .bind('menuselect', function(event, ui) { 
       $('#log').append('<li>' + $(ui.item).text() + '</li>'); 
      }); 
    }); 
</script> 

Ошибка

var menu = iosMenu.element.data('menu'); 

кидает «людей u 'неопределенная ошибка в firebug.

ответ

1

Я не использую эти другие изменения. Я хотел использовать CDN-версию jQuery UI, поэтому я не общался с ними. Вот моя совместимая версия.

$.widget("ui.iosMenu", { 
    options: { 
     backText:  'Back', 
     slideDuration: 200, 
     slideEasing: 'linear' 
    }, 

    _insertBackButtons: function() { 
     this.element.find('li ul, li ol').prepend(
      $('<li class="ui-menu-item ios-menu-back-link" role="presentation">' + 
       ' <a href="#menu-back" class="ui-corner-role" tabindex="-1" role="menuitem" aria-haspopup="true" >' + 
       ' <span class="ui-menu-icon ui-icon ui-icon-carat-1-w"></span>' + 
          this.options.backText + 
       ' </a>' + 
       '</li>' 
     )); 
     return this; 
    }, 

    _create: function(options) { 
     var iosMenu = this; 

     iosMenu 
      ._insertBackButtons() 
      .element 
       .addClass('ios-style') 
       .menu({ 
        // When a submenu shows up, place it just to the right 
        // of the current menu. Later, we'll slide it into view. 
        position: { 
         my: 'left top', 
         at: 'right top', 
         of: iosMenu.element 
        } 
       }); 

     var menu = iosMenu.element.data('uiMenu'); 

     // Override menu#select to account for nesting and back buttons: 
     menu.select = function(event) { 
      //menu.active = menu.active || $(event.target).closest(".ui-menu-item"); //new random line 
      if (menu.active && menu.active.find('a').attr("href") == "#menu-back") { 
       // if you selected "back", go back: 
       menu.focus(event, menu.active); 
       menu.collapse(event); 
       /* 
       if (menu.collapse(event)) { 
        event.stopImmediatePropagation(); 
       } 
       event.preventDefault();*/ 
      } else if (menu.active && menu.active.find('> ul').length) { 
       // if you selected something with children, show the children: 
       menu.focus(event, menu.active); 
       menu.expand(event); 
       /* 
       if (menu.expand(event)) { 
        event.stopImmediatePropagation(); 
       } 
       event.preventDefault();*/ 
      } else { 
       menu._trigger('select', event, { item: menu.active }); 
      } 
     }; 
     /* 
     // Override menu#expand to add return true: 
     menu.expand = function(event) { 
      var newItem = this.active && 
       this.active 
        .children(".ui-menu ") 
        .children(".ui-menu-item") 
        .first(); 

      if (newItem && newItem.length) { 
       this._open(newItem.parent()); 

       // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 
       this._delay(function() { 
        this.focus(event, newItem); 
       }); 
       return true; 
      } 
     };*/ 

     // Override menu#collapse to enable sliding behavior: 
     menu.collapse = function(event) { 
      var newItem = this.active && this.active.parents('li:not(.ui-menubar-item) ').first(), 
        self  = this, 
        parent; 
      if (newItem && newItem.length) { 
       newItem.find('> a').addClass('ui-state-focus').removeClass('ui-state-active'); 
       parent = this.active.parent(); 
       parent 
        .attr('aria-hidden', 'true') 
        .attr('aria-expanded', 'false') 
        .animate({ 
         left: self.element.css('width') 
        }, iosMenu.options.slideDuration, iosMenu.options.slideEasing, function() { 
         parent.hide(); 
         self.focus(event, newItem); 
        }) 
       //return true; 
      } else if (event && event.which === $.ui.keyCode.ESCAPE) { 
       // #left gets called both for left-arrow and escape. If it's the 
       // latter and we're at the top, fire a "close" event: 
       self._trigger('close', event); 
      } 
     }; 




     // Override menu#_open to enable sliding behavior: 
     var menuOpenWithoutSliding = menu._open; 
     menu._open = function (submenu) { 
      menuOpenWithoutSliding.call(this, submenu); 

      submenu.animate({ 
       left: 0, 
       height: menu.element[0].clientHeight - 4 , 
       width: menu.element[0].clientWidth 
      }, iosMenu.options.slideDuration, iosMenu.options.slideEasing); 
     }; 

     // Override menu#_startOpening so that hovering doesn't 
     // initiate the sliding: 
     menu._startOpening = function(submenu) { 
      clearTimeout(this.timer); 
      // Don't open if already open fixes a Firefox bug that caused a .5 pixel 
      // shift in the submenu position when mousing over the carat icon 
      if (submenu.attr("aria-hidden") !== "true") { 
       return; 
      } 
     } 
    }, 

    destroy: function() { 
     var menu = this.element && this.element.data('uiMenu'); 
     menu && menu.destroy(); 
    } 
}); 
+0

Это очень хорошо, работает совершенно гладко. Только несколько графических проблем, которые могут быть браузером, но +1 :). – Tay

+0

Только проблема, которую я вижу, - это небольшое удаление из меню внизу справа (предположим, что это место, где расположено полоса прокрутки). – Tay

+0

В качестве быстрого исправления я прокомментировал (ширина: menu.element [0] .clientWidth), и пусть ширина определяется родительским div. Кажется, сделать трюк и еще раз спасибо. Может быть, идея отправить это в jquery, поскольку это довольно удобное меню. – Tay

1

Похоже на ту же ошибку. Взял меня некоторое время, чтобы найти виновного, но здесь идет:

jquery.ui.menu.js

добавил

this.mouseHandled = false; 

для collapseAll и расширения ФУНКЦИИ размытости функции (within _create) заменены версия от 1.9.0

jquery.ui.widget.js

добавлен

$.data(element, this.widgetName, this); 

к _createWidget функции

JQuery-ui.iosmenu.js

добавленного

menu.active = menu.active || $(event.target).closest(".ui-menu-item"); 

к menu.selec т

Надеюсь, что это поможет

0

Если вам нужно использовать этот код в одном приложении страницы и должны избегать использования «HREF =» меню-назад»использовать отн =„“атрибут вместо

$.widget("ui.iosMenu", { 
    options: { 
     backText:  'Back', 
     slideDuration: 200, 
     slideEasing: 'linear' 
    }, 

    _insertBackButtons: function() { 
     this.element.find('li ul, li ol').prepend(
     $('<li class="ui-menu-item ios-menu-back-link" role="presentation">' + 
       ' <a rel="#menu-back" class="ui-corner-role" tabindex="-1" role="menuitem" aria-haspopup="true" >' + 
       ' <span class="ui-menu-icon ui-icon ui-icon-carat-1-w"></span>' + 
          this.options.backText + 
       ' </a>' + 
       '</li>' 
     )); 
     return this; 
    }, 

    _create: function(options) { 
     var iosMenu = this; 

     iosMenu 
      ._insertBackButtons() 
      .element 
       .addClass('ios-style') 
       .menu({ 
        // When a submenu shows up, place it just to the right 
        // of the current menu. Later, we'll slide it into view. 
        position: { 
         my: 'left top', 
         at: 'right top', 
         of: iosMenu.element 
        } 
       }); 

     var menu = iosMenu.element.data('uiMenu'); 

     // Override menu#select to account for nesting and back buttons: 
     menu.select = function(event) { 

      if (menu.active && menu.active.find('a').attr("rel") == "#menu-back") { 
       // if you selected "back", go back: 
       menu.focus(event, menu.active); 
       menu.collapse(event); 

      } else if (menu.active && menu.active.find('> ul').length) { 
       // if you selected something with children, show the children: 
       menu.focus(event, menu.active); 
       menu.expand(event); 

      } else { 
       menu._trigger('select', event, { item: menu.active }); 
      } 
     }; 


     // Override menu#collapse to enable sliding behavior: 
     menu.collapse = function(event) { 
      var newItem = this.active && this.active.parents('li:not(.ui-menubar-item) ').first(), 
        self  = this, 
        parent; 
      if (newItem && newItem.length) { 
       newItem.find('> a').addClass('ui-state-focus').removeClass('ui-state-active'); 
       parent = this.active.parent(); 
       parent 
        .attr('aria-hidden', 'true') 
        .attr('aria-expanded', 'false') 
        .animate({ 
         left: self.element.css('width') 
        }, iosMenu.options.slideDuration, iosMenu.options.slideEasing, function() { 
         parent.hide(); 
         self.focus(event, newItem); 
        }) 
       //return true; 
      } else if (event && event.which === $.ui.keyCode.ESCAPE) { 

       self._trigger('close', event); 
      } 
     }; 

     // Override menu#_open to enable sliding behavior: 
     var menuOpenWithoutSliding = menu._open; 
     menu._open = function (submenu) { 
      menuOpenWithoutSliding.call(this, submenu); 

      submenu.animate({ 
       left: 0, 
       height: menu.element[0].clientHeight - 4 , 
       width: menu.element[0].clientWidth 
      }, iosMenu.options.slideDuration, iosMenu.options.slideEasing); 
     }; 

     // Override menu#_startOpening so that hovering doesn't 
     // initiate the sliding: 
     menu._startOpening = function(submenu) { 
      clearTimeout(this.timer); 
      // Don't open if already open fixes a Firefox bug that caused a .5 pixel 
      // shift in the submenu position when mousing over the carat icon 
      if (submenu.attr("aria-hidden") !== "true") { 
       return; 
      } 
     } 
    }, 

    destroy: function() { 
     var menu = this.element && this.element.data('uiMenu'); 
     menu && menu.destroy(); 
    } 
}); 

UPDATE.: Поддержка jQuery 2.1.0, я должен был изменить эту строку ...

var menu = iosMenu.element.data('uiMenu'); 

в этом

var menu = iosMenu.element.data('ui-menu'); 

Я также погрузили Jquery-Migrate-1.2.1.min.js только в случае, если кто-либо другой аналогичный вопрос.