benmarch / angular-ui-tour

Product tour using Angular UI Bootstrap Tooltips
163 stars 49 forks source link

Ever other step not being added #20

Closed dander401 closed 8 years ago

dander401 commented 8 years ago

Through console logging I have traced the issue as far as I can.

//Add step to tour
scope.tourStep = step;
scope.tour = scope.tour || ctrl;

if (ctrl.initialized) {
    configureInheritedProperties();
    ctrl.addStep(step);
} else {
    console.info( step.title +' --- later');
    ctrl.once('init', function () {
        configureInheritedProperties();
        console.info( step.title +' --- now');

        ctrl.addStep(step);
    });
}

console.info( step.title +' --- later'); shows all steps being registered however the --now is only getting called for steps 1,3,5

The html that I have tested with is the following

<div class="userProfile" ui-tour="userProfileTour" ui-tour-backdrop="true" ui-tour-placement="right">
    <div>
        <h1>Account Settings</h1>
    </div>
    <div class="form-horizontal">
        <div class="form-group" tour-step tour-step-title="Username" tour-step-order="0" tour-step-content="You will use this to log on with">
            <label class="col-sm-3 control-label">Username</label>
            <div class="col-sm-8">
                <input class="form-control" name="username" type="string" ng-model="user.username" ng-trim="true" />
            </div>
        </div>
        <div tour-step tour-step-title="Your Name" tour-step-order="1" tour-step-content="This is just so we know who you are">
            <div class="form-group">
                <label class="col-sm-3 control-label">First Name</label>
                <div class="col-sm-8">
                    <input class="form-control" name="firstName" type="string" ng-model="user.firstName" ng-trim="true" />
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-3 control-label">Last Name</label>
                <div class="col-sm-8">
                    <input class="form-control" name="lastName" type="string" ng-model="user.lastName" ng-trim="true" />
                </div>
            </div>
        </div>
        <div tour-step tour-step-title="Email And Organization" tour-step-order="2" tour-step-content="We need to know who are with, and your email. These are used to contact you and automatically add you to certain groups">
            <div class="form-group">
                <label class="col-sm-3 control-label">Email</label>
                <div class="col-sm-8">
                    <input class="form-control" name="email" type="string" ng-model="user.email" ng-trim="true" />
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-3 control-label">Organization</label>
                <div class="col-sm-8">
                    <input class="form-control" name="organization" type="string" ng-model="user.organization" ng-trim="true" />
                </div>
            </div>
        </div>
        <div tour-step tour-step-title="Reason" tour-step-order="3" tour-step-content="What do you use our site for">
            <div class="form-group">
                <label class="col-sm-3 control-label">Reason</label>
                <div class="col-sm-8">
                    <textarea class="form-control" name="reason" type="string" ng-model="user.reason" ng-trim="true"></textarea>
                </div>
            </div>
        </div>
        <div tour-step tour-step-title="Password" tour-step-order="4" tour-step-content="When you want to change your password, you will first need to enter your current password and then enter your new password twice.">
            <div class="form-group">
                <label class="col-sm-3" style="text-align: right;">Old Password</label>
                <div class="col-sm-8">
                    <input class="form-control" name="Password" type="password" ng-model="user.oldPassword" ng-model-options="{updateOn: 'default keyup'}" ng-change="validate()" />
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-3 control-label">New Password</label>
                <div class="col-sm-8">
                    <input class="form-control" name="Password" type="password" ng-model="user.password" ng-model-options="{updateOn: 'default keyup'}" ng-change="validate()" />
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-3 control-label">Password Confirmation</label>
                <div class="col-sm-8">
                    <input class="form-control" name="PasswordConfirmation" type="password" ng-model="passwordConfirmation" ng-model-options="{updateOn: 'default keyup'}" ng-change="validate()" />
                </div>
            </div>
        </div>
    </div>
    <div tour-step tour-step-title="Save or Cancel" tour-step-order="5" tour-step-content="Don't forget to save your changes">
        <div class="form-group">
            <div class="col-sm-offset-3 col-sm-8">
                <button class="btn btn-default cancel" ng-click="cancel()">Cancel</button>
                <button class="btn btn-primary save" ng-click="saveUser()" ng-disabled="!validForm">Save</button>
            </div>
        </div>
    </div>
</div>
benmarch commented 8 years ago

Hmm, can you paste the console output also?

dander401 commented 8 years ago

Your Name --- later angular-ui-tour.js:1011 Email And Organization --- later angular-ui-tour.js:1011 Reason --- later angular-ui-tour.js:1011 Password --- later angular-ui-tour.js:1011 Save or Cancel --- later angular-ui-tour.js:1014 Your Name --- now angular-ui-tour.js:323 adding step: undefined Your Name angular-ui-tour.js:1014 Reason --- now angular-ui-tour.js:323 adding step: undefined Reason angular-ui-tour.js:1014 Save or Cancel --- now angular-ui-tour.js:323 adding step: undefined Save or Cancel angular-ui-tour.js:962 1 angular-ui-tour.js:338 removing step: 1 angular-ui-tour.js:323 adding step: 1 Your Name angular-ui-tour.js:962 2 angular-ui-tour.js:962 3 angular-ui-tour.js:338 removing step: 3 angular-ui-tour.js:323 adding step: 3 Reason angular-ui-tour.js:962 4 angular-ui-tour.js:962 5 angular-ui-tour.js:338 removing step: 5 angular-ui-tour.js:323 adding step: 5 Save or Cancel

benmarch commented 8 years ago

Did you add other logging statements as well?

dander401 commented 8 years ago

oh yea sorry, forgot I had theses in the addStep Method

    self.addStep = function (step) {
            if (~stepList.indexOf(step)) {
                console.info( 'skipping step: ' + step.order );
                return;
            }
            console.info( 'adding step: ' + step.order +'   ' + step.title );
            stepList.push(step);
            stepList = $filter('orderBy')(stepList, 'order');
            if (resumeWhenFound) {
                resumeWhenFound(step);
            }
        };

kinda random.... but is there any way for the code insert to keep my formatting when i copy paste?

benmarch commented 8 years ago

Yeah you can use triple back ticks and the type. I updated you initial comment, if you click the edit icon you can see it.

benmarch commented 8 years ago

Sorry, did you add any others? Looks like maybe in removeStep() and one more.

dander401 commented 8 years ago

ive got 6 logs total, let me list them all out

//Pass interpolated values through
TourHelpers.attachInterpolatedValues(attrs, step, options);
orderWatch = attrs.$observe(TourHelpers.getAttrName('order'), function (order) {
    step.order = !isNaN(order*1) ? order*1 : 0;
    console.info( step.order );
    if (ctrl.hasStep(step)) {
        ctrl.reorderStep(step);
    }
});

----

if (ctrl.initialized) {
    configureInheritedProperties();
    ctrl.addStep(step);
} else {
    console.info( step.title +' --- later');
    ctrl.once('init', function () {
        configureInheritedProperties();
        console.info( step.title +' --- now');

        ctrl.addStep(step);
    });
}

----

self.addStep = function (step) {
    if (~stepList.indexOf(step)) {
        console.info( 'skipping step: ' + step.order );
        return;
    }
    console.info( 'adding step: ' + step.order +'   ' + step.title );
    stepList.push(step);
    stepList = $filter('orderBy')(stepList, 'order');
    if (resumeWhenFound) {
        resumeWhenFound(step);
    }
};
----

self.removeStep = function (step) {
    console.info( 'removing step: ' + step.order );
    stepList.splice(stepList.indexOf(step), 1);
};
benmarch commented 8 years ago

Cool, thanks, I'll look this over.

benmarch commented 8 years ago

Ok interesting, it looks like 0, 2, and 4 are never even added...

dander401 commented 8 years ago

Thats what I saw, from my understanding of the code ( mostly flowing stack traces so at best ehh ) it looks like the ctrl.once(init' was to be called and add them but never does

benmarch commented 8 years ago

Ah jeez I think I just realized what the problem is... it's an issue with ezNg's event emitter. I'll have that updated in a few hours and I'll release a new version 0.3.2. Thank you for debugging this, and I'm really sorry about it.

dander401 commented 8 years ago

no problem, never apologize for doing the world a favor and building something open source :) this package is looking awesome

benmarch commented 8 years ago

Ok let's try 0.3.2.

benmarch commented 8 years ago

If 0.3.2 isn't working I'll put your markup in a Fiddle or Plunker and debug it. Unfortunately, I won't be able to get to it until tomorrow. I'll let you know as soon as I find something.

benmarch commented 8 years ago

My mistake, I didn't release 0.3.2 properly so it didn't have the update. I used your markup above and confirmed that it did not work with 0.3.1 or 0.3.2 but it does work now with 0.3.3. Let me know if 0.3.3 works for you.

dander401 commented 8 years ago

Its good now. thanks.

benmarch commented 8 years ago

Awesome! Thanks for helping to debug.

dander401 commented 8 years ago

Ive got one more issue with a step not being added. I have an empty div that id like to put a tour step on but it doesnt seem to add. ( I generate the content for the div ). Do I need to just add and remove the tour step each time I change its content?

benmarch commented 8 years ago

Is the tour step statically on the div or are you adding the attributes dynamically as well?

dander401 commented 8 years ago

static looks like this

<div id="chartDownloadContainer" tour-step-title="Preview" tour-step-order="3" tour-step-content="Preview how the chart will look at your desired size. If the download buttons fail, you can right click the chart and click 'Save As' to export it manually " tour-step-placement="bottom"></div>
benmarch commented 8 years ago

Looks like it is missing the tour-step attribute.

dander401 commented 8 years ago

that would be my bad at re adding it here... i do have the tour step... like this one which doesnt work

<div id="chartDownloadContainer" tour-step tour-step-title="Preview" tour-step-order="3" tour-step-content="Preview how the chart will look at your desired size. If the download buttons fail, you can right click the chart and click 'Save As' to export it manually " tour-step-placement="bottom"></div>

just so you know.

benmarch commented 8 years ago

I just added it to my test environment and it displayed as expected. I think I would need more context. I'll reopen this issue.

dander401 commented 8 years ago

sorry i just noticed my just so you know was empty.... i meant to put in what I was doing.

I have svg charts, that Im converting to images for downloads and showing the preview in a canvas element ( which is also used as a fallback for when auto downloads fail )

this tour-step is on the item that is loosing and having its inner content regenerated every time the size changes ( to generate a new png or jpeg )

In short the controller that modifies the div looks something like this

var canvasEle = myMagicSvgToCanvas( svgEle );
var preview = window.document.getElementById( 'chartDownloadContainer' );
preview = angular.element( preview );
 preview.html( '' );
preview.append(canvasEle);
benmarch commented 8 years ago

Ah ok, it might have something to do with event handlers getting lost. Try wrapping "#chartDownloadContainer" with another div and moving the tour step to that div. That way there won't be any conflict.

dander401 commented 8 years ago

Alright, that worked.... except it draws an empty canvas... honestly I don't know a lot about the magic canvas... Just incase this this helps here how I crate it from a svg element.

function svgToCanvas( source ) {
            var style = window.getComputedStyle( window.document.body );
            var q = $q.defer();
            var img = new window.Image();

            var ele = angular.element( source ).clone();
            ele.attr('font-family', style.fontFamily);
            var xml = new window.XMLSerializer().serializeToString( ele[ 0 ] );

            // make it base64
            // set it as the source of the img element
            var imgSrc = 'data:image/svg+xml;base64,' + window.btoa( xml );

            //be sure to set onload before src
            img.onload = function drawImage() {
                var canvasEle = angular.element( '<canvas></canvas>' );
                canvasEle.attr( 'height', ele.attr( 'height' ) );
                canvasEle.attr( 'width', ele.attr( 'width' ) );
                // draw the image onto the canvas
                canvasEle[ 0 ].getContext( '2d' ).drawImage( img, 0, 0 );
                q.resolve( canvasEle );
            };
            img.onerror = function () {
                throw 'Something when wrong converting svg to canvas';
            };
            img.src = imgSrc;
            return q.promise;
        };
dander401 commented 8 years ago

Just fyi... i do have a backdrop, and the popover is appended to body

benmarch commented 8 years ago

Cool, that var ele = angular.element( source ).clone(); is probably what was breaking it before, but I'm not 100% certain on that. I'm not really sure if I can help with the empty canvas, does it display the canvas if you remove the tour-step attribute?

dander401 commented 8 years ago

good call on the ele.clone that makes sense.

It does display the canvas drawn, just the popover doesnt... which i guess is expected because its pointed to the orginal element. hmmm... looks like have something fun to try to work around then. Thanks for point out how i was breaking it.

btw... i really appreciate your quick and helpful responses

dander401 commented 8 years ago

well wait... the cloned element is just used to create the image the is placed in the original element. hmmm... so i may need to get the canvas in the popover and redraw the image there...

Can i get a reference to the current step popup with the tours onShow?

dander401 commented 8 years ago

I decided to just do this tour without a backdrop which allows the popovers to just point to the uncloned elements. this makes it a non issue for me. I'm good to close this issue.

benmarch commented 8 years ago

Ok cool, sorry it doesn't work exactly as desired. The backdrops in general are known to be problematic, and I would rather not spend too much extra time on them. If you want to try to work on the backdrop service and create a PR that would be awesome, but there probably isn't a great universal solution. Closing this issue now.