From 8c58b9185d121178f0eb9de511d1fd4e8ee1eb6f Mon Sep 17 00:00:00 2001 From: Nao Date: Fri, 7 Mar 2014 00:03:02 +0100 Subject: [PATCH] + Rewrote the main menu system to use hardware-accelerated CSS3 animations instead of jQuery to open menus and animate them. It still works the same in oldIE and other crappy browsers, without the animations of course. It's faster on all other devices, usability is MUCH better (transitions are way more natural delayers than JavaScript timers!), and in exchange for 250 extra bytes of CSS, it saves 100 lines of code for a whopping 1.2KB of JS. It's like early birthday present for me. (script.js, index.css) --- core/javascript/script.js | 84 +++++++++++---------------------------- core/skins/index.css | 17 ++++++-- 2 files changed, 36 insertions(+), 65 deletions(-) diff --git a/core/javascript/script.js b/core/javascript/script.js index db418e97..5671d830 100644 --- a/core/javascript/script.js +++ b/core/javascript/script.js @@ -418,70 +418,32 @@ $.fn.ds = function () $.fn.mm = function () { - var menu_baseId = 0, menu_delay = [], - - // Entering a menu entry? - menu_show_me = function () - { - var - is_top = $(this).parent().hasClass('menu'), - is_visible = $('>ul', this).css('visibility') == 'visible'; - - $('>ul', this).css({ - visibility: 'visible', - opacity: 1, - margin: is_top ? '0 ' + $('span', this).width() + 'px' : 0 - }); - - if (!is_top || !$('>h4', this).addClass('hove').length) - $(this).addClass('hove').parentsUntil('.menu>li').filter('li').addClass('hove'); - - if (!is_visible) - $('>ul', this) - .css(is_top ? { marginTop: 5 } : { marginLeft: 0 }) - .animate(is_top ? { marginTop: 0 } : { marginLeft: -5 }); - - clearTimeout(menu_delay[this.id.slice(2)]); - - $(this).siblings('li').each(function () { menu_hide_children(this.id); }); - }, + this.find('li') + // Entering a menu entry? + .on('mouseenter focus', function () + { + // Start the animation on its child. + $('>ul', this).addClass('anim'); - // Leaving a menu entry? - menu_hide_me = function (e) - { - // The deepest level should hide the hover class immediately. - if (!$(this).children('ul').length) - $(this).children().andSelf().removeClass('hove'); - - // Are we leaving the menu entirely, and thus triggering the time threshold, - // or are we just switching to another non-context menu item? - var id = this.id, target_parent = $(e.relatedTarget).closest('.menu'); - target_parent.length && !target_parent.hasClass('context') ? menu_hide_children(id) : - menu_delay[id.slice(2)] = setTimeout(function () { menu_hide_children(id); }, 300); - }, - - // Hide all children menus. - menu_hide_children = function (id) - { - $('#' + id).children().andSelf().removeClass('hove').find('ul').css({ visibility: 'hidden' }).css(is_ie8down ? '' : 'opacity', 0); - }; + // Add hover effects to this menu entry's parent list. On top-level entries, add effect to the h4 tag only. + if (!$(this).parent().hasClass('menu') || !$('>h4', this).addClass('hove').length) + $(this).addClass('hove').parentsUntil('.menu>li').filter('li').addClass('hove'); - this.each(function () { - var $elem = $(this); - $elem.find('li').each(function () { - $(this).attr('id', 'li' + menu_baseId++) - .on('mouseenter focus', menu_show_me) - .on('mouseleave blur', menu_hide_me) - // Disable double clicks... - .mousedown(false) - // Clicking a link will immediately close the menu -- giving a feeling of responsiveness. - .has('>a,>h4>a') - .click(function () { - $('.hove').removeClass('hove'); - $elem.find('ul').css({ visibility: 'hidden' }).css(is_ie8down ? '' : 'opacity', 0); - }); + $(this).siblings('li').children().andSelf().removeClass('hove anim'); + }) + // Leaving a menu entry? Then hide all of its children. + .on('mouseleave blur', function (e) + { + $(this).children().andSelf().removeClass('hove anim'); + }) + // Disable double clicks and text selection... + .mousedown(false) + // Clicking a link will immediately close the menu -- giving a feeling of responsiveness. + .find('>a,>h4>a') + .click(function () { + $('.hove').removeClass('hove'); + $(this).parentsUntil('.menu').removeClass('anim'); }); - }); // Make menu icons clickable by stealing the link from their neighbor. $('.menu>li>span').each(function () { $(this).wrap($('').attr('href', $(this).next().find('a').attr('href'))); }); diff --git a/core/skins/index.css b/core/skins/index.css index 33a0e179..1b68a1a3 100644 --- a/core/skins/index.css +++ b/core/skins/index.css @@ -869,7 +869,10 @@ input[type=file] font-weight: 400 margin: 0 2px @is (ie7, 0, 10px) 0 // 10px gives more breathing space to the dropdown's arrow... - li ul + ul + opacity: 0 + transition: opacity .3s ease, transform .3s ease, visibility .3s ease + transform: translate3d(0, 5px, 0) display: block clear: left @if !ie[-7] @@ -878,10 +881,9 @@ input[type=file] position: absolute z-index: 42 visibility: hidden - transition: opacity .3s ease margin, padding: 0 border: 1px solid #bbb - @if ie9, chrome, firefox[20-] // Speed matters. + @if ie[9-], chrome, firefox[20-] // Speed matters. background: #fcfcfc box-shadow: inset 0 50px 50px rgba(232, 236, 232, .8), 2px 2px 3px 0 rgba(0,0,0, .2) @else @@ -890,7 +892,8 @@ input[type=file] @endif border-radius: 0 10px 10px 0 - li li ul + ul ul + transform: translate3d(5px, 0, 0) left: @is (ie6, 95%, 100%) top: 0 @@ -920,6 +923,12 @@ input[type=file] margin: 0 white-space: nowrap + ul.anim + visibility: visible + opacity: 1 + transition: opacity .3s ease, transform .3s ease + transform: translate3d(0, 0, 0) + .css > li > ul transition: opacity .15s ease