adgsm / multi-level-push-menu

MultiLevelPushMenu jQuery Plugin implementation
http://multi-level-push-menu.dzunic.net
804 stars 212 forks source link

move menu icon out of h2 tags and let it trigger the menu #185

Open alenart91 opened 6 years ago

alenart91 commented 6 years ago

I want to move the menu icon out of the h2 tags so I can position it where I want and add styling outside of the wrapper. Whenever it is moved outside the h2 tags it no longer triggers the menu.

adgsm commented 6 years ago

Hey Alex, You can have your own icon and trigger the menu with click on it, as follows.

var $myDOMElement = $('#myDOMElelemnt');
$myDOMElement.click(function(){
    var $phonemenu = $( '#menu' ).multilevelpushmenu( 'findmenusbytitle' , 'Mobile Phones' ).first();
    $( '#menu' ).multilevelpushmenu( 'expand' , $phonemenu );
});

Take a look at example here.

alenart91 commented 6 years ago

I set up a new Icon to expand the menu with this code

$( '#baseexpand' ).click(function(){
        $( '#menu' ).multilevelpushmenu( 'expand' );
    });

Can't seem to trigger the collapse with the same element though.

adgsm commented 6 years ago
$( '#baseexpand' ).click(function(){
   var expanded = $('#menu').multilevelpushmenu('activemenu');
   if(!expanded){
      $( '#menu' ).multilevelpushmenu( 'expand' );
   }
   else{
      $( '#menu' ).multilevelpushmenu( 'collapse' );
   }
});
alenart91 commented 6 years ago

The code you posted looks good, but it only collapses the menu.

adgsm commented 6 years ago

You're right

    $( '#baseexpand' ).click(function(){
        var expanded = $('#menu').multilevelpushmenu('activemenu').length;
        if(!expanded){
            $( '#menu' ).multilevelpushmenu( 'expand' );
        }
        else{
            $( '#menu' ).multilevelpushmenu( 'collapse' );
        }
    });
alenart91 commented 6 years ago

Works perfectly thank you very much for your help!

waynep16 commented 6 years ago

Do you have a demo of this working? would love to see. Also would be good to have the category text appear running down the menu stripe instead of just the icon clickable

adgsm commented 6 years ago

You have examples of invoking menu events by clicking on external DOM elements here. Menu collapsing/expanding is an simpler example comparing to that.

I agree, category text appear running down the menu stripe would be nice..., but I didn't work much on it after I have developed it ~5 years ago... :(

waynep16 commented 6 years ago

I want to click the whole bar to collapse it also.

On 5 Feb 2018, at 20:22, Momcilo Dzunic notifications@github.com wrote:

You have examples of invoking menu events by clicking on external DOM elements here. Menu collapsing/expanding is an simpler example comparing to that.

I agree, category text appear running down the menu stripe would be nice..., but I didn't work much on it after I have developed it ~5 years ago... :(

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

alenart91 commented 6 years ago

No demo but here's my code. I added an overlay as well. The only problem I've come across if if you swipe the menu or use a method to close the menu by clicking the body it doesn't toggle the classes off and leaves everything mixed up. So I've had to disable swiping and exiting by clicking on the body for now.

<div class="overlay"></div>
 <div class="navi">
                   <div id="menu">
                  <div class="menu-icon"><i id="baseexpand" class="fa fa-reorder"></i></div>
  <nav>
    <h2> Menu</h2>
    <ul>
        <li><a class="nav-link" asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>

                    @if (SignInManager.IsSignedIn(User))
                    {
                        <!-- log out requires a post action, therefore must have a form -->
                        <li><a class="nav-link" asp-controller="Account" asp-action="Manage">Manage</a></li>
                        <li><form method="post"><button type="submit" class="nav-link-logout" asp-controller="Account" asp-action="Logout">Logout</button></form></li>
                    }
                    else
                    {
                        <li><a class="nav-link" asp-area="" asp-controller="Account" asp-action="Login">Login</a></li>
                        <li><a class="nav-link" asp-area="" asp-controller="Account" asp-action="Register">Register</a></li>
                    }
    </ul>
  </nav>
</div>

            </div>
$(document).ready(function(){
    // HTML markup implementation, overlap mode
    $( '#menu' ).css('display' , 'block');
    $( '#menu' ).multilevelpushmenu({
        containersToPush: [$( '.main-content') , $( '.navbar-inverse' ) , $( '.main-footer' ) , $('.copyright')]
    });

    // $( 'body' ).on( 'click' , function( ev ){
    // $('#menu').multilevelpushmenu( 'collapse' );
    // } );

    $( '#baseexpand' ).click(function(){
        $('#baseexpand').toggleClass('baseexpand-open');
        $('.multilevelpushmenu_wrapper h2').toggleClass('multilevelpushmenu_wrapper_open h2');
        $('.overlay').toggleClass('overlay-open');
        $('body').toggleClass('body-open');

        var expanded = $( '#menu' ).multilevelpushmenu( 'activemenu' ).length;
   if(!expanded){
      $( '#menu' ).multilevelpushmenu( 'expand' );
   }
   else{
      $( '#menu' ).multilevelpushmenu( 'collapse' );
   }
});

});
waynep16 commented 6 years ago

This old version

https://tympanus.net/Development/MultiLevelPushMenu/#

lets you click the whole bar to collapse that section - we have to click the small h2 icon at the top to close it down, can somone give a code so it will work like the demo above?

adgsm commented 6 years ago

Hey Wayne,

You can achieve this by making simple tweak (as follow)...

function makeCloseArea(){
    var $inactiveMenus = $( '.levelHolderClass.multilevelpushmenu_inactive' );
    $inactiveMenus.remove( '.close-area' );
    var $closeArea = $( '<div class="close-area" />' );
    $closeArea.css( 'position' , 'absolute' );
    $closeArea.css( 'right' , 0 );
    $closeArea.css( 'top' , 0 );
    $closeArea.css( 'width' , '40px' );
    $closeArea.css( 'height' , '100%' );
    $closeArea.css( 'cursor' , 'pointer' );
    $closeArea.on( 'click' , function( event ){
        $( this ).parents( '.levelHolderClass.multilevelpushmenu_inactive' ).first().find( 'h2 > i' ).first().trigger( 'click' )
    } );
    $inactiveMenus.append( $closeArea );
}
$(document).ready(function(){
    $( '#menu' ).multilevelpushmenu({
        onExpandMenuEnd: function(){
            makeCloseArea();
        },
        onCollapseMenuEnd: function(){
            makeCloseArea();
        }
    });
});

Regards

waynep16 commented 6 years ago

That works great ! I have adaped it to use a class instead of inline css but perfect. It does duplicate the close area div many times which is a small bug here but in general that works for now.

adgsm commented 6 years ago

I am glad to hear that :)

Instead of

$inactiveMenus.remove( '.close-area' );

use following

$( '.levelHolderClass' ).remove( '.close-area' );

to make sure 'close-areas' are removed completely...

waynep16 commented 6 years ago

One last thing to make this complete is to make titles show like this... I have tried using a span and some css but it goes all over the place on each level. Anyone tried or done this before here?

Alt Text

adgsm commented 6 years ago

I am not sure what the question is... If it is about vertical title you can try something like following.

function makeCloseArea(){
    var $inactiveMenus = $( '.levelHolderClass.multilevelpushmenu_inactive' );
    $( '.levelHolderClass .close-area' ).remove();
    $inactiveMenus.each( function( index , element ){
        var $closeArea = $( '<div class="close-area" />' );
        $closeArea.css( 'display' , 'block' );
        $closeArea.css( 'position' , 'absolute' );
        $closeArea.css( 'right' , 0 );
        $closeArea.css( 'top' , 0 );
        $closeArea.css( 'width' , '40px' );
        $closeArea.css( 'height' , '100%' );
        $closeArea.css( 'cursor' , 'pointer' );
        $closeArea.on( 'click' , function( event ){
            $( this ).parents( '.levelHolderClass.multilevelpushmenu_inactive' ).first().find( 'h2 > i' ).first().trigger( 'click' )
        } );
        $( element ).append( $closeArea );

        var $spanText = $( '<span />' );
        $spanText.css( 'display' , 'block' );
        $spanText.css( 'position' , 'relative' );
        $spanText.css( 'margin-top' , '6.5em' );
        $spanText.css( 'color' , '#fff' );
        $spanText.css( 'white-space' , 'nowrap' );
        $spanText.css( '-webkit-transform' , 'rotate(270deg)' );
        $spanText.css( '-moz-transform' , 'rotate(270deg)' );
        $spanText.css( '-ms-transform' , 'rotate(270deg)' );
        $spanText.css( '-o-transform' , 'rotate(270deg)' );
        $spanText.css( 'transform' , 'rotate(270deg)' );
        $spanText.text( $( element ).find( 'h2' ).first().text() );
        $( element ).find( '.close-area' ).first().append( $spanText );
    } );
}
$(document).ready(function(){
    $( '#menu' ).multilevelpushmenu({
        onExpandMenuEnd: function(){
            makeCloseArea();
        },
        onCollapseMenuEnd: function(){
            makeCloseArea();
        }
    });
});
waynep16 commented 6 years ago

You've done it again :) amazing :+1: Just a small small issue when going back in the menu, the span stays there too long and overlaps the menu a little bit.

see video here to explain - https://ufile.io/1ztzv (sorry for free mp4 upload hosting here GIT doesnt support mp4)

adgsm commented 6 years ago

I didn't download the video but I guess I understand the issue. The situation is a bit more complicated here. First you need to tweak jquery.multilevelpushmenu.js as follows.

At line 636 replace

instance.settings.onCollapseMenuStart.apply(this, Array.prototype.slice.call([instance.settings]));

with following

instance.settings.onCollapseMenuStart.apply(this, Array.prototype.slice.call([instance.settings, arguments[0]]));

This will expose collapse level as second argument in onCollapseMenuStart event callback.

Now add onCollapseMenuStart callback in your code as follows.

function makeCloseArea(){
    var $inactiveMenus = $( '.levelHolderClass.multilevelpushmenu_inactive' );
    $( '.levelHolderClass .close-area' ).remove();
    $inactiveMenus.each( function( index , element ){
        var $closeArea = $( '<div class="close-area" />' );
        $closeArea.css( 'display' , 'block' );
        $closeArea.css( 'position' , 'absolute' );
        $closeArea.css( 'right' , 0 );
        $closeArea.css( 'top' , 0 );
        $closeArea.css( 'width' , '40px' );
        $closeArea.css( 'height' , '100%' );
        $closeArea.css( 'cursor' , 'pointer' );
        $closeArea.on( 'click' , function( event ){
            $( this ).parents( '.levelHolderClass.multilevelpushmenu_inactive' ).first().find( 'h2 > i' ).first().trigger( 'click' );
        } );
        $( element ).append( $closeArea );

        var $spanText = $( '<span />' );
        $spanText.css( 'display' , 'block' );
        $spanText.css( 'position' , 'relative' );
        $spanText.css( 'margin-top' , '6.5em' );
        $spanText.css( 'color' , '#fff' );
        $spanText.css( 'white-space' , 'nowrap' );
        $spanText.css( '-webkit-transform' , 'rotate(270deg)' );
        $spanText.css( '-moz-transform' , 'rotate(270deg)' );
        $spanText.css( '-ms-transform' , 'rotate(270deg)' );
        $spanText.css( '-o-transform' , 'rotate(270deg)' );
        $spanText.css( 'transform' , 'rotate(270deg)' );
        $spanText.text( $( element ).find( 'h2' ).first().text() );
        $( element ).find( '.close-area' ).first().append( $spanText );
    } );
}
$(document).ready(function(){
    $( '#menu' ).multilevelpushmenu({
        onExpandMenuEnd: function(){
            makeCloseArea();
        },
        onCollapseMenuEnd: function(){
            makeCloseArea();
        },
        onCollapseMenuStart: function( settings , collapseLevel ){
            if( !collapseLevel ){
                $( '.levelHolderClass' ).find( '.close-area' ).remove();
            }
            else{
                $( '.levelHolderClass.multilevelpushmenu_inactive' ).each( function( index , element ) {
                    if( parseInt( $( element ).attr( 'data-level' ) , 10 ) >= collapseLevel ){
                        $( element ).find( '.close-area' ).remove();
                    }
                } );
            }
        }
    });
});

That's it.

waynep16 commented 6 years ago

You're a magician. That works beautifully and i cant thank you enough.

waynep16 commented 6 years ago

However - small issue here with headings that have a long title, it overlaps? any ideas ? thanks

image

adgsm commented 6 years ago

Unfortunately css overflow:hidden won't work for you since it will take width of the parent element for transformed span (40px in your case)... The only thing that comes to my mind is to crop title text to certain number of characters which won't exceed size of the vertical bar, e.g. as follows...

function cropText( text , len , sufix ) {
    var sufixLength = ( sufix && sufix.length < text.length ) ? sufix.length : 0,
        sufixText = ( sufix && sufixLength ) ? sufix : '';
    if ( text && len && text.length > len )
        return text.substring( 0 , len - sufixLength ) + sufixText;

    return text;
}

function makeCloseArea() {
    var $inactiveMenus = $('.levelHolderClass.multilevelpushmenu_inactive');
    $('.levelHolderClass .close-area').remove();
    $inactiveMenus.each(function (index, element) {
        var $closeArea = $('<div class="close-area" />');
        $closeArea.css('display', 'block');
        $closeArea.css('position', 'absolute');
        $closeArea.css('right', 0);
        $closeArea.css('top', 0);
        $closeArea.css('width', '40px');
        $closeArea.css('height', '100%');
        $closeArea.css('cursor', 'pointer');
        $closeArea.on('click', function (event) {
            $(this).parents('.levelHolderClass.multilevelpushmenu_inactive').first().find('h2 > i').first().trigger('click');
        });
        $(element).append($closeArea);

        var $spanText = $('<span />');
        $spanText.css('display', 'block');
        $spanText.css('position', 'relative');
        $spanText.css('margin-top', '6.5em');
        $spanText.css('max-width', '5em');
        $spanText.css('color', '#fff');
        $spanText.css('white-space', 'nowrap');
        $spanText.css('-webkit-transform', 'rotate(270deg)');
        $spanText.css('-moz-transform', 'rotate(270deg)');
        $spanText.css('-ms-transform', 'rotate(270deg)');
        $spanText.css('-o-transform', 'rotate(270deg)');
        $spanText.css('transform', 'rotate(270deg)');
        var text = cropText( $(element).find('h2').first().text() , 30 , '...' ); // adjust no of characters here per your needs
        $spanText.text( text );
        $(element).find('.close-area').first().append( $spanText );
    });
}
$(document).ready(function () {
    $('#menu').multilevelpushmenu({
        onExpandMenuEnd: function () {
            makeCloseArea();
        },
        onCollapseMenuEnd: function () {
            makeCloseArea();
        },
        onCollapseMenuStart: function (settings, collapseLevel) {
            if (!collapseLevel) {
                $('.levelHolderClass').find('.close-area').remove();
            } else {
                $('.levelHolderClass.multilevelpushmenu_inactive').each(function (index, element) {
                    if (parseInt($(element).attr('data-level'), 10) >= collapseLevel) {
                        $(element).find('.close-area').remove();
                    }
                });
            }
        }
    });
});
rivertim commented 6 years ago

@adgsm Hey. I know this is an old thread, but I'm trying to implement the code you suggested here:

function makeCloseArea(){ etc…

I cannot make it work at all! Where exactly should I be inserting this code? Should the function and the document.ready be split up into different files? I have tried putting it in expandcollapse.js , jquery.multilevelpushmenu.min.js, or even my html page.

Could you please show a working example?

Such a great menu – thank you!

Tim

rivertim commented 6 years ago

@waynep16 Sorry to bother you with an old thread. Would you still have the 'whole-bar collapse' code for the mlp menu? I can't get the owner's code to work at all. A working example to examine would be great. Many thanks.

waynep16 commented 6 years ago

@rivertim I added the code under my original MMmenu call from here

https://github.com/adgsm/multi-level-push-menu/issues/185#issuecomment-373394265

to make the whole bar close on click of whole bar....

rivertim commented 6 years ago

@waynep16 Hey. Thanks for the speedy reply! :) Sorry to be thick, but I don't see your code. I see the owner's suggested code – which I just can't make work! Maybe I'm missing something simple here. Would you by any chance have the complete code of your working example?

waynep16 commented 6 years ago

Code was on that comment but i think you need to add the following CSS Also

` .close-area { position: absolute; right: 0px; top: 0px; width: 40px; height: 100%; cursor: pointer; }

#menu .multilevelpushmenu_wrapper .close-area span {
    display: block;
    position: relative;
    color: rgb(255, 255, 255);
    white-space: nowrap;
    transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    top: 19%;
    right: 126px;
    text-overflow: ellipsis;
    width: 294px;
    overflow: hidden;
}`
rivertim commented 6 years ago

@waynep16 Wayne, thanks for the css. But I still don't see the js code attached to any of your comments in this thread. Am I missing something?

waynep16 commented 6 years ago

Its in this comment here

https://github.com/adgsm/multi-level-push-menu/issues/185#issuecomment-373394265 <<<

rivertim commented 6 years ago

@waynep16 This? I thought this was the creator of the menu's code?

function makeCloseArea(){ var $inactiveMenus = $( '.levelHolderClass.multilevelpushmenu_inactive' ); $inactiveMenus.remove( '.close-area' ); var $closeArea = $( '

' ); $closeArea.css( 'position' , 'absolute' ); $closeArea.css( 'right' , 0 ); $closeArea.css( 'top' , 0 ); $closeArea.css( 'width' , '40px' ); $closeArea.css( 'height' , '100%' ); $closeArea.css( 'cursor' , 'pointer' ); $closeArea.on( 'click' , function( event ){ $( this ).parents( '.levelHolderClass.multilevelpushmenu_inactive' ).first().find( 'h2 > i' ).first().trigger( 'click' ) } ); $inactiveMenus.append( $closeArea ); } $(document).ready(function(){ $( '#menu' ).multilevelpushmenu({ onExpandMenuEnd: function(){ makeCloseArea(); }, onCollapseMenuEnd: function(){ makeCloseArea(); } }); });

If so, I can't make this work at all! Not sure whether this code should be in the main js file or in the html source. Any pointers would be appreciated. Thanks.

waynep16 commented 6 years ago

Thats it... it goes below where you are calling the main menu code

rivertim commented 6 years ago

@waynep16 In the jquery.multilevelpushmenu.min.js or my html page?

rivertim commented 6 years ago

@waynep16 Thanks for your help, but I can't get this code working wherever I put it. It never creates the vital .close-area div in the source… If you have a moment sometime I'd love to see a working example of this!

waynep16 commented 6 years ago

The site this was for is no longer in production but literally i pasted the code above and it worked 1st time (providing the initial set up was working fine initially )

rivertim commented 6 years ago

@waynep16 Thanks for your help anyway. My existing setup is also working fine. But when I add the code above it doesn't function as it should. C'est la vie!