1

so I am having a little trouble with this button performing either of these functions on click.....

it isn't great as baseexpand and fullcollapse should be classes but I am not skilled enough to re-write an entire set of functions to accomodate this as they have about 50 dependencies.

Anyway to the point , here is the two functions ....

// Full collapse
$( '#fullcollapse' ).click(function(){
    $( '#menu' ).multilevelpushmenu( 'collapse' );
});

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

they expand and collapse a sidebar-menu .... i have 2 buttons that looks like this ....

    <a id="fullcollapse" class="nav-toggle" role="button" href="#"><span></span></a>

<a id="baseexpand" class="nav-toggle" role="button" href="#"><span></span></a>

I want to make those buttons into one toggle button changing between the id's on each click.

I have been reading documentation for about 6 hours straight now and trying to look into it but am unable to solve this one. Please help

SaidbakR
  • 13,303
  • 20
  • 101
  • 195
havingagoatit
  • 593
  • 4
  • 19
  • yes sorry for the confusion but currently there are two instances of the button with the id of each .... so they do what you are stating, separately... i basically want to combine them into one. – havingagoatit May 22 '15 at 00:10
  • Write a single function that tests whether the menu is open or not. If it's open, then close it; if it's closed, open it. – Barmar May 22 '15 at 00:14
  • is there not some sort of way i could place the buttons in the same place and when one is clicked it fades behind the other and so on – havingagoatit May 22 '15 at 00:22
  • No, first rule in development, don't repeat yourself. The DOM is flexible enough to turn a button into another one without having to have 2 buttons in the first place. Only use 2 buttons if the 2 buttons have to be visible at the same time. – Capsule May 22 '15 at 00:24
  • There's different ways you could do it. See my answer, I just toggled a class. – prograhammer May 22 '15 at 00:24

4 Answers4

2

Try composing your functions with this wrapper

var toggle = function (funcA, funcB) {
    var flag = true;
    return function () {
        if (flag) {
            funcA();
        } else {
            funcB();
        }
        flag = !flag;
    };
};

apply it with

$('#btn').click(toggle (function (){
    $('#menu').multilevelpushmenu( 'collapse' ); // happens 1, 3, 5, 7, ...   time clicked
}, function (){
    $('#menu').multilevelpushmenu( 'expand' );   // happenes  2, 4, 6, 8, ... time clicked
}));

bonus I reimplemented toggle to be able to propogate a return value.

var toggle = function (a, b) {
    var togg = false;
    return function () {
        // passes return value back to caller
        return (togg = !togg) ? a() : b();
    };
};
t3dodson
  • 3,949
  • 2
  • 29
  • 40
  • 1
    i'm having a bash at ti now thanks for the support buddy – havingagoatit May 22 '15 at 00:30
  • w-o-r-k-e-d !! so you have defined a function called toggle that allows for both states to be alternated , smart ! – havingagoatit May 22 '15 at 00:35
  • Lots of repeats and over-engineering with anonymous functions and stuff, maybe not the ideal solution to a newbie but that's my 2 cents. – Capsule May 22 '15 at 00:49
  • This is the most straight forward/elegant way to do it. Javascript newbies need to learn how to pass functions around. – t3dodson May 22 '15 at 00:50
  • Not sure he learned anything here. "it worked" doesn't mean "I learned something today" because from a newbie perspective it's just force-feeding :-) – Capsule May 22 '15 at 01:02
  • __so you have defined a function called toggle that allows for both states to be alternated.__ I think he sees the basic mechanism at work. This solution is also much closer to the description of behavior that he was asking for. __I want to make those buttons into one toggle button.__ – t3dodson May 22 '15 at 01:23
1

See live demo here: https://jsfiddle.net/gpnsmbvk/1/

There's different ways you can achieve what you are asking. Here's a solution that toggles classes:

HTML

<a id="anyofthestates" class="nav-toggle" role="button" href="#"><span>sidebar me</span></a>

Jquery

$(function(){

    $('#anyofthestates').click(function(){
        $(this).toggleClass('expand');

        if($(this).hasClass('expand')){
            alert('baseexpand');
            // $( '#menu' ).multilevelpushmenu( 'expand' );
        }
        else{
            alert('fullcollapse');
            // $( '#menu' ).multilevelpushmenu( 'collapse' );
        }
    });

});
prograhammer
  • 20,132
  • 13
  • 91
  • 118
  • That's a nice variant of my answer but you should use the ternary operator to avoid repeating `$( '#menu' ).multilevelpushmenu( something )` – Capsule May 22 '15 at 00:26
  • Yeah I was thinking of going the `data` route, but decided for toggling classes. I don't like to use the ternary too much, but that's just my preference. :-) – prograhammer May 22 '15 at 00:28
  • also while it works with an alert changing the state based on an id is pants from what i understand .... I am in a bind with this one though as i can't rewrite the functions to be classes instead .... that would make things so much easier – havingagoatit May 22 '15 at 00:29
  • Hmmm.. these are some strange things you have going on. We are probably playing too much of a guessing game without more code/information/etc. – prograhammer May 22 '15 at 00:34
  • You really should use the ternary operator, otherwise you'll never be able to DRY ;-) – Capsule May 22 '15 at 00:35
  • yeah and a bit of a catch 22 really because i din't want to give too much as to be generic and not to the point as per the house rules (as i am learning slowly) ..... Tommy DDD gave a response that seems to work by setting up a toggle for the id states, really appreciate your input on this – havingagoatit May 22 '15 at 00:40
  • Yeah I could make it more DRY, and I should do it here. But it's interesting sometimes how we as programmers can actually overdue this DRY concept in an application, and we could end up increasing maintenance work. ;-p – prograhammer May 22 '15 at 00:41
  • BTW @havingagoatit you don't have to rewrite those functions, you can trigger them (if that's what you are saying). For example, use `$('#baseexpand').click();` and it will trigger the click and function as if you had clicked it. – prograhammer May 22 '15 at 00:45
  • It will never increase maintenance work while it could potentially decrease flexibility in case of changes, but that's another discussion ;-) – Capsule May 22 '15 at 00:46
  • its amazing appreciating the complexities of what actually happens behind the scenes, the button in question is a hamburger trigger for opening and closign the menu ... should of been less of a pain but tommy DDD came up with that toggle function which seemed to work well .... thanks for your input I voted you up – havingagoatit May 22 '15 at 00:48
  • Yup, another discussion that involves unit tests, business domain discussion, etc, etc. I just find that DRY seems like its the best way to go, and mostly it is, but because you can remove a repetition doesn't 100% mean you should always in OOP. Yeah, another discussion though. – prograhammer May 22 '15 at 00:48
0

I would change a data attribute on the button itself (the state could be stored anywhere else in the DOM tho, like on the menu) and toggle between the 2 states at each click:

$('.nav-toggle').click(function(e){
    e.preventDefault();

    $('#menu').multilevelpushmenu($(this).data('action'));
    $(this).data('action', ($(this).data('action') == 'fullcollapse' ? 'basexpand' : 'fullcollapse'));
});

HTML:

<a data-action="fullcollapse" class="nav-toggle" role="button"><span></span></a>

The data-action you set in your HTML should be the action you want on the first click.

Example with a generic multilevelpushmenu function: https://jsfiddle.net/q3c117yr/

Capsule
  • 6,118
  • 1
  • 20
  • 27
  • 1
    He wants to combine the expand and collapse buttons into a single toggle button. – Barmar May 22 '15 at 00:14
  • I don't know how you define your `multiplepushmenu` function but if I don't associate this to `$('#menu')` it works quite well: https://jsfiddle.net/q3c117yr/ – Capsule May 22 '15 at 00:33
  • I am a novice and unfamiliar with the data-action but in a sense maybe it isn't registering as the defined functions are id's .... unless data-action refers to id's .... or maybe i'm just a bit of a thicko – havingagoatit May 22 '15 at 00:38
  • Did you add a default `data-action` to your button? It won't work on the first click without it. About being a novice, if you keep repeating you're one without trying to understand why or not it's working, you sure will stay this way ;-) – Capsule May 22 '15 at 00:39
  • ah yes indeed sorry for moaning about my incompetence it's 2am and i have monitor eyes.... i set the data-action by default to baseexpand , that would logically be the initial state to go for as the menu will be closed on startup – havingagoatit May 22 '15 at 00:42
  • Downvoters, please provide a valid explanation, or maybe it's @devkaoru, that would be so lame, but not surprising – Capsule May 22 '15 at 06:02
0

assuming you only have those two buttons with nav-toggle the DOM.

html:

<a id="fullcollapse" class="nav-toggle" role="button" href="#"><span></span></a>

<a id="baseexpand" class="nav-toggle" role="button" href="#"><span></span></a>

js:

$(function () {
  var expand = false;
  $('.nav-toggle').on('click', function (e) {
    // not preventing default in case other things are listening if not then prevent it here.

     expand = !expand;
     var action = expand ? 'expand' : 'collapse';
     $('#menu').multilevelpushmenu(action);
  });
});

The reason why using data won't work is because data properties are bound to the element you are selecting. Each button will have it's own data property and thus you cannot sync the two buttons by this one value. You need to have a separate value that can be accessed by both in order to keep their state in sync.

devkaoru
  • 1,142
  • 9
  • 7
  • data will work when only using one button, which is what the OP wants: `I want to make those buttons into one toggle button`, and you still come with a 2 buttons solution – Capsule May 22 '15 at 00:51