24

I cannot figure out how to use intro.js on dropdown elements.

I found a similar question with no answer there: IntroJS Bootstrap Menu doesnt work

If you want to reproduce the error, follow these steps:

http://recherche.utilitaire.melard.fr/#/carto

You have to click on "Aide" (The green button on the top right), the problem occurs for the second step. on the change event, I do:

$scope.ChangeEvent = function (e) { 
    if (e.id === 'step2') {
        document.getElementById('step1').click();
    } 
    console.log("Change Event called"); 
};

When debugging, everything is working like a charm until that function end: _showElement After that, I get lost in JQuery events, and the dropdown is closed...

If you want to reproduce, just add a breakpoint at the end of the _showElement function and you will understand what I mean...

Community
  • 1
  • 1
Alexandre Mélard
  • 12,229
  • 3
  • 36
  • 46

4 Answers4

14

Here a clearer solution

 function startIntro(){
    var intro = introJs();
      intro.setOptions({
        steps: [
          {
            element: "#mydropdown",
            intro: "This is a dropdown"
          },
          {
            element: '#mydropdownoption',
            intro: "This is an option within a dropdown.",
            position: 'bottom'
          },

        ]
      });

      intro.onbeforechange(function(element) {
        if (this._currentStep === 1) {
          setTimeout(function() {
            $("#mydropdown").addClass("open");
          });
        }
      });
      intro.start();
  };

  $(document).ready(function() {
    setTimeout(startIntro,1500);
  });

Note the setTimeout with no second argument (milliseconds) allows you to queue the function on event loop and run it after all events were processed (including the click closing the dropdown), also, it is better to add the class open to the dropdown if you want to set it to open state

GillesC
  • 10,647
  • 3
  • 40
  • 55
dseminara
  • 11,665
  • 2
  • 20
  • 22
  • 1
    OPs application is based on AngularJS. Your solution is not "Angular Way" and more "jQueriesh". His problem is very simple. – bhantol Sep 13 '14 at 19:05
  • I agree with bhantol, not quite an angularJS solution – Alexandre Mélard Sep 17 '14 at 09:19
  • 1
    For anyone using Bootstrap Version > 4.0 or reading this in 2018, adding the class "open" doesn't seem to work anymore, but there is now the jquery method: `$('#mydropdown').dropdown('toggle');` to open and close it: https://getbootstrap.com/docs/4.0/components/dropdowns/#methods – ffritz Jun 04 '18 at 09:23
2

In your template i.e. in

/views/nav/body-create.html

You have a code where ng-disabled is based on !currentPath.name. And the value of currentPath.name is null. Try inspecting the value on the following element. You will see that it is null.

<button class="dropdown-toggle btn btn-sm btn-default no-radius" ng-disabled="!currentPath.name">
                Niveau{{currentPath.level?": "+currentPath.level:""}} <strong><b class="caret"></b>
                                                          </strong>
</button>

Make sure you have proper name or use different condition - I am not sure what you are trying to do with the condition.

Proof: Inspect the above element in chrome debugger at your recherche.utilitaire.melard.fr/#/carto link. Type the following in console and hit enter.

$scope.currentPath.name='Hello You';

And your "Niveau" menu starts working.

bhantol
  • 9,368
  • 7
  • 44
  • 81
1

I found a workaround, it's quite ugly, but does the job:

$scope.ChangeEvent = function (e) { 
    if (e.id === 'step2') {
        document.getElementById('step1').click();
        setTimeout(function () {
            document.getElementById('step2').style.display = 'block';
        }, 500);
    } 
    console.log("Change Event called"); 
};

I set the display attribute to block just after the click event I added in the change event

When clicking executing the click on the element 1, I noticed that jquery set the state of the style.display of the element 2 to '', so I wait a bit after clicking in order to set it back to 'block', I know it's ugly, but I didn't find anything better at the time

Alexandre Mélard
  • 12,229
  • 3
  • 36
  • 46
0

This happens because of the fixed position.. By using CSS, change the position for the parent item from fixed to absolute and it works perfectly. For example: position of .sidebar is fixed, leave it like that. change position for .sidebar.introjs-fixParent to absolute.

Hope it helps you