mendhak / angular-intro.js

AngularJS directives for intro.js
http://code.mendhak.com/angular-intro.js/
GNU Affero General Public License v3.0
503 stars 175 forks source link

introJs doesn't adapt to elements #48

Open Hypercubed opened 9 years ago

Hypercubed commented 9 years ago

Not sure if this is a angular-intro.js problem per se... but definitely more relevant to the dynamic nature of angular.

I have an intro that instructs the user to interact with the webpage in a few places. For example, in one case the user clicks on a button, triggering an ng-click, that adds a new html element it the page (inside an ng-repeat). Later in the introduction steps I refer to the new element. However, because this element did not exist when the intro was started if does not point to the current element. IntroJS appears to create references to the elements at start (https://github.com/usablica/intro.js/blob/master/intro.js#L95). I got around this by adding the following onbeforechange callback:

    $scope.introChange = function() {
      var intro = this;

      for (var i = intro._currentStep+1; i < this._options.steps.length; i++) {
        var currentItem = intro._introItems[i];
        var step = intro._options.steps[i];
        if (step.element) {
          currentItem.element = document.querySelector(step.element);
          currentItem.position = step.position;
        }
      }

    };

I hope this helps others or maybe should be an optional part of angular-intro.js.

CrouseMatthew commented 9 years ago

I was able to solve this issue by putting the directive in the parent index.html file and using the CallMe() callback

directive

<div ng-controller="IntroController">
    <div ng-intro-options="IntroOptions"  ng-intro-method="CallMe"
         ng-intro-autostart="ShouldAutoStart"
         ng-intro-autorefresh="true"></div>
    <div ng-view id='introStep-2'></div>
</div>

end of controller

$scope.ShouldAutoStart = false;
$timeout(function(){$scope.CallMe()},1000);
Hypercubed commented 9 years ago

Sure, but does this work if the DOM changes in the middle of the intro, say due to user interaction?

kmgilbert100 commented 8 years ago

^ - We need a fix for this

shyamal890 commented 8 years ago

+1

tucu-man commented 8 years ago

+1

Muskos commented 8 years ago

+1

chedched commented 7 years ago

+1

miliare commented 7 years ago

+1

mattifh commented 7 years ago

+1

ZhouQunying commented 7 years ago

+1

leepy82 commented 7 years ago

+1

Thanks Hypercubed, this solved my issue.

I couldn't override the higher level onbeforechange callback because I was already overriding it on the step level. What worked for me was invoking this function on the onafterchange of the PRECEEDING step to ensure the target element existed on the following step.

millerscout commented 7 years ago

i don't know if everyone could get this work properly.

when the user interacts with something that will update the view, inside a $timeout, you may call the refresh function, that will re-evaluate queryselector. Now if you still need to work around with onBefore or onAfterchange, i don't think it's the best solutions for us.

A way to properly fix that, it's to rebind the clicks that happens on introjs, into the controller or service, then we'll make the changes that we need and after that we call ngIntroService.next().

if there's anyone in need i may provide that fix, just let me know.

kowsheek commented 7 years ago

@millerscout Yeah that solution would be really helpful, especially on multi-component views.

emecamila commented 6 years ago

El problema es causado ya que el elemento que se pretende referenciar aun no esta creado.

para eso debemos usar la function


$scope.createIntro = function(){
    var IntroOptions = {
        steps:[
            {
                intro: "first msg",
                position: 'auto'
            },
            {
                element: document.querySelector('#btn_step1'),
                intro: "Hello !",
                position: 'left'
            }
        ],
        showStepNumbers: false,
        doneLabel:'Done',
        nextLabel:'Next',
        prevLabel:'Previous'
    };

    ngIntroService.setOptions(IntroOptions);      
    ngIntroService.start();

    ngIntroService.onComplete(function(){
        console.info("complete")
    })

    ngIntroService.onChange(function(targetElement){
        console.info(targetElement.id + " change")
    })
}

setTimeout(function(){ $scope.createIntro(); }, 1000);
avinash03031991 commented 5 years ago

i don't know if everyone could get this work properly.

when the user interacts with something that will update the view, inside a $timeout, you may call the refresh function, that will re-evaluate queryselector. Now if you still need to work around with onBefore or onAfterchange, i don't think it's the best solutions for us.

A way to properly fix that, it's to rebind the clicks that happens on introjs, into the controller or service, then we'll make the changes that we need and after that we call ngIntroService.next().

if there's anyone in need i may provide that fix, just let me know.

HI Millerscout, Please provide this fix for me.