r876 - in branches/experimental: tests/visual/menu ui
Author: paul.bakaus
Date: Fri Nov 7 03:54:23 2008
New Revision: 876
Modified:
branches/experimental/tests/visual/menu/menu.html
branches/experimental/ui/ui.core.position.js
branches/experimental/ui/ui.menu.js
Log:
core (experimental): renamed positionTo to positionAround, option relatedTo
to around
menu: implemented drilldown (still needs refactoring, selectCategories
doesn't work fully), browse/select/open/close events
Modified: branches/experimental/tests/visual/menu/menu.html
==============================================================================
--- branches/experimental/tests/visual/menu/menu.html (original)
+++ branches/experimental/tests/visual/menu/menu.html Fri Nov 7 03:54:23
2008
@@ -16,6 +16,7 @@
body,html {
margin: 0;
padding: 0;
+ font-size: 12px;
}
#menu2 {
@@ -29,16 +30,49 @@
$(document).ready(function() {
$('#menu1').menu({
- mode: 'static'
+ mode: 'static',
+ type: 'drilldown',
+ //selectCategories: true,
+ select: function(e, ui) {
+ console.log('Selected item ', ui.item);
+ },
+ browse: function(e, ui) {
+ console.log('Browsing item ', ui.item);
+ }
});
$('button').menu({
- items: '#items2'
+ items: '#items2',
+ //type: 'drilldown',
+ select: function(e, ui) {
+ console.log('Selected item ', ui.item);
+ },
+ browse: function(e, ui) {
+ console.log('Browsing item ', ui.item);
+ },
+ open: function(e, ui) {
+ console.log('Opened menu');
+ },
+ close: function(e, ui) {
+ console.log('Closed menu');
+ }
});
$('#menu2').menu({
items: '#items3',
- mode: 'context'
+ mode: 'context',
+ select: function(e, ui) {
+ console.log('Selected item ', ui.item);
+ },
+ browse: function(e, ui) {
+ console.log('Browsing item ', ui.item);
+ },
+ open: function(e, ui) {
+ console.log('Opened menu');
+ },
+ close: function(e, ui) {
+ console.log('Closed menu');
+ }
});
});
Modified: branches/experimental/ui/ui.core.position.js
==============================================================================
--- branches/experimental/ui/ui.core.position.js (original)
+++ branches/experimental/ui/ui.core.position.js Fri Nov 7 03:54:23 2008
@@ -1,7 +1,7 @@
-$.fn.positionTo = function(e, o) {
+$.fn.positionAround = function(e, o) {
var options = $.extend({
- relativeTo: 'mouse',
+ around: 'mouse',
direction: 'default',
forceDirection: false
}, o);
@@ -20,9 +20,9 @@
};
- if($(options.relativeTo).length && $(options.relativeTo)[0].nodeName) {
//If relativeTo is an element
+ if($(options.around).length && $(options.around)[0].nodeName) { //If
around is an element
- var element = $(options.relativeTo),
+ var element = $(options.around),
offset = element.offset(),
relHeight = element[0].offsetHeight,
relWidth = element[0].offsetWidth
Modified: branches/experimental/ui/ui.menu.js
==============================================================================
--- branches/experimental/ui/ui.menu.js (original)
+++ branches/experimental/ui/ui.menu.js Fri Nov 7 03:54:23 2008
@@ -72,7 +72,7 @@
}
this.items.css('visibility', 'visible');
- if(this.menu.css('position') != 'absolute') //If the position isn't
absolute,
+ if(this.menu.css('position') != 'absolute' &&
this.options.type != 'drilldown') //If the position isn't absolute,
this.menu.css('position', 'absolute').height(this.menu.height()).css('position', 'relative');
//set a hard value for the height
@@ -98,7 +98,161 @@
},
_prepareDrilldown: function() {
+
+ var self = this;
+
+ var breadcrumb = $('<ul class="ui-menu-dd-breadcrumb
ui-component-content"></ul>');
+ var crumbDefaultHeader = $('<li
class="ui-menu-dd-text">'+this.options.crumbDefaultText+'</li>');
+ var firstCrumbText = this.options.backLink ? this.options.backLinkText :
this.options.topLinkText;
+ var firstCrumbClass = this.options.backLink ? 'ui-menu-prev-list
ui-arrow-left-default' : 'ui-menu-all-lists';
+ var firstCrumb = $('<li class="'+firstCrumbClass+'"><a
href="#">'+firstCrumbText+'</a></li>');
+
+ if (!this.items.is('.ui-menu-dd')) {
+
+ this.menu
+ .css({ overflow: 'hidden' })
+ .find('ul').addClass('ui-component-content');
+
+ this.items
+ .addClass('ui-menu-dd ui-menu-current')
+ .find('ul').css({ width: this.options.width });
+
+ // set up links to be split-button (selectable nodes + navigation
links) or single button (navigation only)
+ this.items.find('a').each(function(){
+
+ if($(this).next().is('ul')) {
+ if (self.options.selectCategories) {
+ $(this).addClass('ui-menu-split-btn').html('<span>'+
$(this).text()+'</span>')
+ .after('<a href="#" class="ui-menu-nextlevel"><span
class="'+self.options.nextMenuClass+'">View next level ></span></a>');
+ }
+ else {
+ $(this).addClass('ui-menu-indicator').html('<span
class="'+self.options.nextMenuClass+'">'+ $(this).text()+'</span>');
+ };
+ };
+
+ });
+
+ // standardize all menu heights & widths so that they cover the
previous menu completely
+ var listHeights = [];
+ this.items.find('ul').each(function(i){ listHeights[i] =
$(this).height(); });
+ listHeights.sort(function(a, b) { return b - a; });
+ this.items.find('ul').css({ height: listHeights[0], width:
this.options.width });
+
+ // apply scrollbar to the menu when it exceeds max height
+ if (listHeights[0] > this.options.maxHeight) {
+ this.menu
+ .find('.ui-menu-dd')
+ .addClass('ui-menu-scroll')
+ .css({ height: this.options.maxHeight,
overflow: 'auto', 'overflow-x': 'hidden' })
+ .find('ul')
+ .css({ width: this.options.width - 16 });
+ } else {
+
+ this.menu
+ .find('.ui-menu-dd')
+ .css({ height: listHeights[0] }).find('ul').css({ width:
this.options.width });
+ };
+
+ };
+
+
+ this.options.backLink ?
breadcrumb.addClass('ui-menu-footer').appendTo(this.menu) :
breadcrumb.addClass('ui-menu-header').prependTo(this.menu);
+ breadcrumb.append(crumbDefaultHeader);
+ this.resetDrilldownMenu = function(stayOpen){
+ breadcrumb.empty().append(crumbDefaultHeader);
+ $('.ui-menu-current').removeClass('ui-menu-current');
+ if (!stayOpen) { self.menu.find('.ui-menu-dd ul').css({
visibility: 'hidden' }); }
+ };
+
+ var showNextLevel = function(el, e){
+
+ var thisLink = $(el);
+ var thisList = $(el).parents('ul:eq(0)');
+ var nextList = $(el).next();
+
+ // first breadcrumb link
+ if (breadcrumb.find('li').size() == 1){
+ breadcrumb.empty().append(firstCrumb);
+
+ // 'back' link
+ if (firstCrumb.is('.ui-menu-prev-list')) {
+
+ $('.ui-menu-prev-list a').bind('click.menu', function(){
+
+ $('.ui-menu-current').animate({ left: self.options.width },
self.options.crossSpeed);
+ if ($('.ui-menu-current').parents('ul').eq(0).is('.ui-menu')) {
+ self.resetDrilldownMenu(true);
+ }
+ else {
+ $('.ui-menu-current')
+ .removeClass('ui-menu-current')
+ .parents('ul').eq(0).addClass('ui-menu-current');
+ };
+ return false;
+ });
+
+ } // standard breadcrumb
+ else if (firstCrumb.is('.ui-menu-all-lists')) {
+
+ $('.ui-menu-all-lists a').bind('click.menu', function(){
+
self.menu.find('ul').not('.ui-menu, .ui-menu-dd-breadcrumb').animate({
left: self.options.width }, self.options.crossSpeed);
+ if ($(this).next().is('span')) { $(this).next().remove(); }
+ self.resetDrilldownMenu(true);
+ return false;
+ });
+
+ };
+
+ };
+
+ var addNewCrumb = function() {
+
+ var crumbText = (thisLink.prev().is('a')) ? thisLink.prev().text() :
thisLink.text();
+ var newCrumb = $('<li class="ui-menu-current-crumb" style="display:
none;"><a href="javascript://"
class="ui-menu-crumb">'+crumbText+'</a></li>');
+ $('.ui-menu-current-crumb').removeClass('ui-menu-current-crumb');
+ newCrumb.appendTo(breadcrumb).prev().append(' <span>></span>');
+ newCrumb.show().find('a').click(function(e){
+ if ($(this).parent().is('.ui-menu-current-crumb')){
+ self._trigger('select', e, { item: $(this.parentNode) });
+ return false;
+ }
+ else {
+ nextList.find('ul').animate({ left: self.options.width },
self.options.crossSpeed);
+ $(this).parent().nextAll().css({ visibility: 'hidden'
}).slideUp(self.options.crossSpeed, function(){$(this).remove();});
+
$(this).parent().addClass('ui-menu-current-crumb').find('a').next().remove();
+ self._trigger('browse', e, { item: null }); //TODO: Reference to item
+ return false;
+ };
+ });
+
+ };
+
+ if (!self.options.backLink)
+ addNewCrumb();
+
+ // show the next list
+ $('.ui-menu-current').removeClass('ui-menu-current');
+ nextList.css({ visibility: 'visible', left: self.options.width })
+ .animate({ left: 0 }, self.options.crossSpeed)
+ .addClass('ui-menu-current');
+
+ self._trigger('browse', e, { item: nextList });
+
+ };
+ // end showNextLevel
+
+ self.items.find('a').bind('click.menu', function(e){
+ if ($(this).is('.ui-menu-indicator') ||
$(this).is('.ui-menu-nextlevel')) {
+ showNextLevel(this, e);
+ return false;
+ }
+ else {
+ self._trigger('select', e, { item: $(this.parentNode) });
+ return false;
+ };
+ });
+
},
_prepareFlyout: function() {
@@ -133,10 +287,11 @@
showTimer = setTimeout(function(){
subList.addClass('ui-component-content').show();
- subList.positionTo(e, {
- relativeTo: subList.parent(),
+ subList.positionAround(e, {
+ around: subList.parent(),
direction: 'right'
- });
+ });
+ self._trigger('browse', e, { item: subList });
}, 300);
}, function() {
@@ -160,9 +315,10 @@
);
});
-
- $('a', this.menu).bind('click', function(){
- alert('clicked');
+
+
+ $('a', this.menu).bind('click', function(e){
+ self._trigger('select', e, { item: $(this.parentNode) });
return false;
});
@@ -183,13 +339,14 @@
}
this.menu.show();
- this.menu.positionTo(e, {
- relativeTo: this.options.mode == 'context' ? 'mouse' : this.element,
+ this.menu.positionAround(e, {
+ around: this.options.mode == 'context' ? 'mouse' : this.element,
direction: this.options.direction
});
$.ui.menu.manager.push(this);
this.visible = true;
+ this._trigger('open', e, { });
},
@@ -203,18 +360,19 @@
}
for (var i=0; i < $.ui.menu.manager.length; i++) {
- if(exclusion != $.ui.menu.manager[i]) $.ui.menu.manager[i].close();
+ if(exclusion != $.ui.menu.manager[i])
$.ui.menu.manager[i].close(excludeEvent);
};
},
- close: function() {
+ close: function(e) {
this.menu.hide();
for (var i=0; i < $.ui.menu.manager.length; i++) {
if($.ui.menu.manager[i] == this) $.ui.menu.manager.splice(i,1);
};
this.visible = false;
+ this._trigger('close', e, { });
}
@@ -223,21 +381,27 @@
$.extend($.ui.menu, {
manager: [],
defaults: {
- type: 'normal', //Can be set to either normal, ipod style or toolbar
- mode: 'dropdown', //Can be set to context (open on click) or static
(render into the selected element)
+ type: 'normal', //Can be set to either normal, drilldown or toolbar
+ mode: 'dropdown', //Can be set to context (open on right click),
dropdown or static (render into the selected element)
items: '> ul', //Can be either a jQuery selector, therefore using markup
in the selected node, or a JSON list of menu entries
appendTo: 'body', //Only in case of context/dropdown - where the actual
menu is being appended to,
exclusive: true, //Defines wether only this menu can be shown at the
same time
width: 180,
- height: null, //If height specified and surpassed, up and down arrows at
both ends are shown to navigate up and down,
+ maxHeight: 200, //If height specified and surpassed, scrollbars will be
added to the drilldown
hoverClass: 'ui-hover-state',
hoverClassSecondary: 'ui-component-content',
nextMenuClass: 'ui-arrow-right-default', // class to style the link
(specifically, a span within the link) used in the multi-level menu to show
the next level
- //iPod menu specific
- backLink: true // in the ipod-style menu: instead of breadcrumbs, show
only a 'back' link
+ //drilldown menu specific
+ crossSpeed: 300, // cross-fade speed for multi-level menus
+ backLink: true, // in the drilldown-style menu: instead of breadcrumbs,
show only a 'back' link,
+ backLinkText: 'Back',
+ topLinkText: 'All',
+ crumbDefaultText: ' ',
+ selectCategories: false // set to true if each menu item is a split
button where you can choose either the text (to make a selection) or "next"
arrow (to navigate)
+
}
});