diff --git a/tailbone/static/js/lib/jquery.ui.menubar.js b/tailbone/static/js/lib/jquery.ui.menubar.js
index 4936ed4d..41fa2a69 100644
--- a/tailbone/static/js/lib/jquery.ui.menubar.js
+++ b/tailbone/static/js/lib/jquery.ui.menubar.js
@@ -8,320 +8,320 @@
* http://docs.jquery.com/UI/Menubar
*
* Depends:
- * jquery.ui.core.js
- * jquery.ui.widget.js
- * jquery.ui.position.js
- * jquery.ui.menu.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ * jquery.ui.menu.js
*/
(function( $ ) {
-// TODO when mixing clicking menus and keyboard navigation, focus handling is broken
-// there has to be just one item that has tabindex
-$.widget( "ui.menubar", {
- version: "@VERSION",
- options: {
- autoExpand: false,
- buttons: false,
- items: "li",
- menuElement: "ul",
- menuIcon: false,
- position: {
- my: "left top",
- at: "left bottom"
- }
- },
- _create: function() {
- var that = this;
- this.menuItems = this.element.children( this.options.items );
- this.items = this.menuItems.children( "button, a" );
+ // TODO when mixing clicking menus and keyboard navigation, focus handling is broken
+ // there has to be just one item that has tabindex
+ $.widget( "ui.menubar", {
+ version: "@VERSION",
+ options: {
+ autoExpand: false,
+ buttons: false,
+ items: "li",
+ menuElement: "ul",
+ menuIcon: false,
+ position: {
+ my: "left top",
+ at: "left bottom"
+ }
+ },
+ _create: function() {
+ var that = this;
+ this.menuItems = this.element.children( this.options.items );
+ this.items = this.menuItems.children( "button, a" );
- this.menuItems
- .addClass( "ui-menubar-item" )
- .attr( "role", "presentation" );
- // let only the first item receive focus
- this.items.slice(1).attr( "tabIndex", -1 );
+ this.menuItems
+ .addClass( "ui-menubar-item" )
+ .attr( "role", "presentation" );
+ // let only the first item receive focus
+ this.items.slice(1).attr( "tabIndex", -1 );
- this.element
- .addClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
- .attr( "role", "menubar" );
- this._focusable( this.items );
- this._hoverable( this.items );
- this.items.siblings( this.options.menuElement )
- .menu({
- position: {
- within: this.options.position.within
- },
- select: function( event, ui ) {
- ui.item.parents( "ul.ui-menu:last" ).hide();
- that._close();
- // TODO what is this targetting? there's probably a better way to access it
- $(event.target).prev().focus();
- that._trigger( "select", event, ui );
- },
- menus: that.options.menuElement
- })
- .hide()
- .attr({
- "aria-hidden": "true",
- "aria-expanded": "false"
- })
- // TODO use _on
- .bind( "keydown.menubar", function( event ) {
- var menu = $( this );
- if ( menu.is( ":hidden" ) ) {
- return;
- }
- switch ( event.keyCode ) {
- case $.ui.keyCode.LEFT:
- that.previous( event );
- event.preventDefault();
- break;
- case $.ui.keyCode.RIGHT:
- that.next( event );
- event.preventDefault();
- break;
- }
- });
- this.items.each(function() {
- var input = $(this),
- // TODO menu var is only used on two places, doesn't quite justify the .each
- menu = input.next( that.options.menuElement );
+ this.element
+ .addClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
+ .attr( "role", "menubar" );
+ this._focusable( this.items );
+ this._hoverable( this.items );
+ this.items.siblings( this.options.menuElement )
+ .menu({
+ position: {
+ within: this.options.position.within
+ },
+ select: function( event, ui ) {
+ ui.item.parents( "ul.ui-menu:last" ).hide();
+ that._close();
+ // TODO what is this targetting? there's probably a better way to access it
+ $(event.target).prev().focus();
+ that._trigger( "select", event, ui );
+ },
+ menus: that.options.menuElement
+ })
+ .hide()
+ .attr({
+ "aria-hidden": "true",
+ "aria-expanded": "false"
+ })
+ // TODO use _on
+ .bind( "keydown.menubar", function( event ) {
+ var menu = $( this );
+ if ( menu.is( ":hidden" ) ) {
+ return;
+ }
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.LEFT:
+ that.previous( event );
+ event.preventDefault();
+ break;
+ case $.ui.keyCode.RIGHT:
+ that.next( event );
+ event.preventDefault();
+ break;
+ }
+ });
+ this.items.each(function() {
+ var input = $(this),
+ // TODO menu var is only used on two places, doesn't quite justify the .each
+ menu = input.next( that.options.menuElement );
- // might be a non-menu button
- if ( menu.length ) {
- // TODO use _on
- input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) {
- // ignore triggered focus event
- if ( event.type === "focus" && !event.originalEvent ) {
- return;
- }
- event.preventDefault();
- // TODO can we simplify or extractthis check? especially the last two expressions
- // there's a similar active[0] == menu[0] check in _open
- if ( event.type === "click" && menu.is( ":visible" ) && that.active && that.active[0] === menu[0] ) {
- that._close();
- return;
- }
- if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" || that.options.autoExpand ) {
- if( that.options.autoExpand ) {
- clearTimeout( that.closeTimer );
- }
+ // might be a non-menu button
+ if ( menu.length ) {
+ // TODO use _on
+ input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) {
+ // ignore triggered focus event
+ if ( event.type === "focus" && !event.originalEvent ) {
+ return;
+ }
+ event.preventDefault();
+ // TODO can we simplify or extractthis check? especially the last two expressions
+ // there's a similar active[0] == menu[0] check in _open
+ if ( event.type === "click" && menu.is( ":visible" ) && that.active && that.active[0] === menu[0] ) {
+ that._close();
+ return;
+ }
+ if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" || that.options.autoExpand ) {
+ if( that.options.autoExpand ) {
+ clearTimeout( that.closeTimer );
+ }
- that._open( event, menu );
- }
- })
- // TODO use _on
- .bind( "keydown", function( event ) {
- switch ( event.keyCode ) {
- case $.ui.keyCode.SPACE:
- case $.ui.keyCode.UP:
- case $.ui.keyCode.DOWN:
- that._open( event, $( this ).next() );
- event.preventDefault();
- break;
- case $.ui.keyCode.LEFT:
- that.previous( event );
- event.preventDefault();
- break;
- case $.ui.keyCode.RIGHT:
- that.next( event );
- event.preventDefault();
- break;
- }
- })
- .attr( "aria-haspopup", "true" );
+ that._open( event, menu );
+ }
+ })
+ // TODO use _on
+ .bind( "keydown", function( event ) {
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.SPACE:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.DOWN:
+ that._open( event, $( this ).next() );
+ event.preventDefault();
+ break;
+ case $.ui.keyCode.LEFT:
+ that.previous( event );
+ event.preventDefault();
+ break;
+ case $.ui.keyCode.RIGHT:
+ that.next( event );
+ event.preventDefault();
+ break;
+ }
+ })
+ .attr( "aria-haspopup", "true" );
- // TODO review if these options (menuIcon and buttons) are a good choice, maybe they can be merged
- if ( that.options.menuIcon ) {
- input.addClass( "ui-state-default" ).append( "" );
- input.removeClass( "ui-button-text-only" ).addClass( "ui-button-text-icon-secondary" );
- }
- } else {
- // TODO use _on
- input.bind( "click.menubar mouseenter.menubar", function( event ) {
- if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" ) {
- that._close();
- }
- });
- }
+ // TODO review if these options (menuIcon and buttons) are a good choice, maybe they can be merged
+ if ( that.options.menuIcon ) {
+ input.addClass( "ui-state-default" ).append( "" );
+ input.removeClass( "ui-button-text-only" ).addClass( "ui-button-text-icon-secondary" );
+ }
+ } else {
+ // TODO use _on
+ input.bind( "click.menubar mouseenter.menubar", function( event ) {
+ if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" ) {
+ that._close();
+ }
+ });
+ }
- input
- .addClass( "ui-button ui-widget ui-button-text-only ui-menubar-link" )
- .attr( "role", "menuitem" )
- .wrapInner( "" );
+ input
+ .addClass( "ui-button ui-widget ui-button-text-only ui-menubar-link" )
+ .attr( "role", "menuitem" )
+ .wrapInner( "" );
- if ( that.options.buttons ) {
- input.removeClass( "ui-menubar-link" ).addClass( "ui-state-default" );
- }
- });
- that._on( {
- keydown: function( event ) {
- if ( event.keyCode === $.ui.keyCode.ESCAPE && that.active && that.active.menu( "collapse", event ) !== true ) {
- var active = that.active;
- that.active.blur();
- that._close( event );
- active.prev().focus();
- }
- },
- focusin: function( event ) {
- clearTimeout( that.closeTimer );
- },
- focusout: function( event ) {
- that.closeTimer = setTimeout( function() {
- that._close( event );
- }, 150);
- },
- "mouseleave .ui-menubar-item": function( event ) {
- if ( that.options.autoExpand ) {
- that.closeTimer = setTimeout( function() {
- that._close( event );
- }, 150);
- }
- },
- "mouseenter .ui-menubar-item": function( event ) {
- clearTimeout( that.closeTimer );
- }
- });
+ if ( that.options.buttons ) {
+ input.removeClass( "ui-menubar-link" ).addClass( "ui-state-default" );
+ }
+ });
+ that._on( {
+ keydown: function( event ) {
+ if ( event.keyCode === $.ui.keyCode.ESCAPE && that.active && that.active.menu( "collapse", event ) !== true ) {
+ var active = that.active;
+ that.active.blur();
+ that._close( event );
+ active.prev().focus();
+ }
+ },
+ focusin: function( event ) {
+ clearTimeout( that.closeTimer );
+ },
+ focusout: function( event ) {
+ that.closeTimer = setTimeout( function() {
+ that._close( event );
+ }, 150);
+ },
+ "mouseleave .ui-menubar-item": function( event ) {
+ if ( that.options.autoExpand ) {
+ that.closeTimer = setTimeout( function() {
+ that._close( event );
+ }, 150);
+ }
+ },
+ "mouseenter .ui-menubar-item": function( event ) {
+ clearTimeout( that.closeTimer );
+ }
+ });
- // Keep track of open submenus
- this.openSubmenus = 0;
- },
+ // Keep track of open submenus
+ this.openSubmenus = 0;
+ },
- _destroy : function() {
- this.menuItems
- .removeClass( "ui-menubar-item" )
- .removeAttr( "role" );
+ _destroy : function() {
+ this.menuItems
+ .removeClass( "ui-menubar-item" )
+ .removeAttr( "role" );
- this.element
- .removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
- .removeAttr( "role" )
- .unbind( ".menubar" );
+ this.element
+ .removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
+ .removeAttr( "role" )
+ .unbind( ".menubar" );
- this.items
- .unbind( ".menubar" )
- .removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" )
- .removeAttr( "role" )
- .removeAttr( "aria-haspopup" )
- // TODO unwrap?
- .children( "span.ui-button-text" ).each(function( i, e ) {
- var item = $( this );
- item.parent().html( item.html() );
- })
- .end()
- .children( ".ui-icon" ).remove();
+ this.items
+ .unbind( ".menubar" )
+ .removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-haspopup" )
+ // TODO unwrap?
+ .children( "span.ui-button-text" ).each(function( i, e ) {
+ var item = $( this );
+ item.parent().html( item.html() );
+ })
+ .end()
+ .children( ".ui-icon" ).remove();
- this.element.find( ":ui-menu" )
- .menu( "destroy" )
- .show()
- .removeAttr( "aria-hidden" )
- .removeAttr( "aria-expanded" )
- .removeAttr( "tabindex" )
- .unbind( ".menubar" );
- },
+ this.element.find( ":ui-menu" )
+ .menu( "destroy" )
+ .show()
+ .removeAttr( "aria-hidden" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "tabindex" )
+ .unbind( ".menubar" );
+ },
- _close: function() {
- if ( !this.active || !this.active.length ) {
- return;
- }
- this.active
- .menu( "collapseAll" )
- .hide()
- .attr({
- "aria-hidden": "true",
- "aria-expanded": "false"
- });
- this.active
- .prev()
- .removeClass( "ui-state-active" )
- .removeAttr( "tabIndex" );
- this.active = null;
- this.open = false;
- this.openSubmenus = 0;
- },
+ _close: function() {
+ if ( !this.active || !this.active.length ) {
+ return;
+ }
+ this.active
+ .menu( "collapseAll" )
+ .hide()
+ .attr({
+ "aria-hidden": "true",
+ "aria-expanded": "false"
+ });
+ this.active
+ .prev()
+ .removeClass( "ui-state-active" )
+ .removeAttr( "tabIndex" );
+ this.active = null;
+ this.open = false;
+ this.openSubmenus = 0;
+ },
- _open: function( event, menu ) {
- // on a single-button menubar, ignore reopening the same menu
- if ( this.active && this.active[0] === menu[0] ) {
- return;
- }
- // TODO refactor, almost the same as _close above, but don't remove tabIndex
- if ( this.active ) {
- this.active
- .menu( "collapseAll" )
- .hide()
- .attr({
- "aria-hidden": "true",
- "aria-expanded": "false"
- });
- this.active
- .prev()
- .removeClass( "ui-state-active" );
- }
- // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus)
- var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 );
- this.active = menu
- .show()
- .position( $.extend({
- of: button
- }, this.options.position ) )
- .removeAttr( "aria-hidden" )
- .attr( "aria-expanded", "true" )
- .menu("focus", event, menu.children( ".ui-menu-item" ).first() )
- // TODO need a comment here why both events are triggered
- .focus()
- .focusin();
- this.open = true;
- },
+ _open: function( event, menu ) {
+ // on a single-button menubar, ignore reopening the same menu
+ if ( this.active && this.active[0] === menu[0] ) {
+ return;
+ }
+ // TODO refactor, almost the same as _close above, but don't remove tabIndex
+ if ( this.active ) {
+ this.active
+ .menu( "collapseAll" )
+ .hide()
+ .attr({
+ "aria-hidden": "true",
+ "aria-expanded": "false"
+ });
+ this.active
+ .prev()
+ .removeClass( "ui-state-active" );
+ }
+ // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus)
+ var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 );
+ this.active = menu
+ .show()
+ .position( $.extend({
+ of: button
+ }, this.options.position ) )
+ .removeAttr( "aria-hidden" )
+ .attr( "aria-expanded", "true" )
+ .menu("focus", event, menu.children( ".ui-menu-item" ).first() )
+ // TODO need a comment here why both events are triggered
+ .focus()
+ .focusin();
+ this.open = true;
+ },
- next: function( event ) {
- if ( this.open && this.active.data( "menu" ).active.has( ".ui-menu" ).length ) {
- // Track number of open submenus and prevent moving to next menubar item
- this.openSubmenus++;
- return;
- }
- this.openSubmenus = 0;
- this._move( "next", "first", event );
- },
+ next: function( event ) {
+ if ( this.open && this.active.data( "menu" ).active.has( ".ui-menu" ).length ) {
+ // Track number of open submenus and prevent moving to next menubar item
+ this.openSubmenus++;
+ return;
+ }
+ this.openSubmenus = 0;
+ this._move( "next", "first", event );
+ },
- previous: function( event ) {
- if ( this.open && this.openSubmenus ) {
- // Track number of open submenus and prevent moving to previous menubar item
- this.openSubmenus--;
- return;
- }
- this.openSubmenus = 0;
- this._move( "prev", "last", event );
- },
+ previous: function( event ) {
+ if ( this.open && this.openSubmenus ) {
+ // Track number of open submenus and prevent moving to previous menubar item
+ this.openSubmenus--;
+ return;
+ }
+ this.openSubmenus = 0;
+ this._move( "prev", "last", event );
+ },
- _move: function( direction, filter, event ) {
- var next,
- wrapItem;
- if ( this.open ) {
- next = this.active.closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).first().children( ".ui-menu" ).eq( 0 );
- wrapItem = this.menuItems[ filter ]().children( ".ui-menu" ).eq( 0 );
- } else {
- if ( event ) {
- next = $( event.target ).closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).children( ".ui-menubar-link" ).eq( 0 );
- wrapItem = this.menuItems[ filter ]().children( ".ui-menubar-link" ).eq( 0 );
- } else {
- next = wrapItem = this.menuItems.children( "a" ).eq( 0 );
- }
- }
+ _move: function( direction, filter, event ) {
+ var next,
+ wrapItem;
+ if ( this.open ) {
+ next = this.active.closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).first().children( ".ui-menu" ).eq( 0 );
+ wrapItem = this.menuItems[ filter ]().children( ".ui-menu" ).eq( 0 );
+ } else {
+ if ( event ) {
+ next = $( event.target ).closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).children( ".ui-menubar-link" ).eq( 0 );
+ wrapItem = this.menuItems[ filter ]().children( ".ui-menubar-link" ).eq( 0 );
+ } else {
+ next = wrapItem = this.menuItems.children( "a" ).eq( 0 );
+ }
+ }
- if ( next.length ) {
- if ( this.open ) {
- this._open( event, next );
- } else {
- next.removeAttr( "tabIndex")[0].focus();
- }
- } else {
- if ( this.open ) {
- this._open( event, wrapItem );
- } else {
- wrapItem.removeAttr( "tabIndex")[0].focus();
- }
- }
- }
-});
+ if ( next.length ) {
+ if ( this.open ) {
+ this._open( event, next );
+ } else {
+ next.removeAttr( "tabIndex")[0].focus();
+ }
+ } else {
+ if ( this.open ) {
+ this._open( event, wrapItem );
+ } else {
+ wrapItem.removeAttr( "tabIndex")[0].focus();
+ }
+ }
+ }
+ });
}( jQuery ));