VinceG / twitter-bootstrap-wizard

This twitter bootstrap plugin builds a wizard out of a formatter tabbable structure. It allows to build a wizard functionality using buttons to go through the different wizard steps and using events allows to hook into each step individually.
MIT License
1.39k stars 676 forks source link

using show method from typescript fails #51

Closed ramesees closed 11 years ago

ramesees commented 11 years ago

Hi

I am using the definitely typed bindings to create and manipulate a wizard. I am able to specify the options for my wizard to set things like the next / previous / first selectors and methods to call for onNext and onFirst.

However if I am on the first tab and want to call $('#wizard').show(3) to go to the specified tab instead of the second tab calling the show method as defined here:

interface Wizard { ......... show(index: number) : any; }

doesn't work as I expect.

I would expect it to use the method from bootstrap.wizard.js as defined here:

this.show = function (index) { return element.find('li:eq(' + index + ') a').tab('show'); };

However this doesn't happen - what actually happens is a call is made into the jQueryUI library directly:

show: (function( orig ) { return function( option ) { if ( standardAnimationOption( option ) ) { return orig.apply( this, arguments ); } else { var args = _normalizeArguments.apply( this, arguments ); args.mode = "show"; return this.effect.call( this, args ); } }; })( $.fn.show ),

Am I doing something wrong, and if so can you point me in the right direction, or is this a bug ?

Thanks

anorborg commented 11 years ago

@ramesees In order to call the bootstrapWizard's version of the method, you need to call the method like so (per the documentation):

$('#wizard').bootstrapWizard('show',3);

That is, call the bootstrapWizard method, passing in the method name, followed by the parameter.

ramesees commented 11 years ago

Doesn't that work solely for the javascript implementation ?

Using the typescript bindings there is a show method which takes the index, there is no method on the Wizard interface which takes a string and an index. Attempting to call $('#wizard').bootstrapWizard('show',3); results in being told no such method exists in typescript (which is correct as it is just $('#wizard').bootstrapWizard.show(3);).

I am using the latest jquery.bootstrap.wizard.d.ts file from nuget (v 0.0.3 dated 7th August 2013)

anorborg commented 11 years ago

Sorry about that. I did not see your reference to TypeScript. I'm not familiar with it unfortunately. Doing a little googling, could it be you need to explicitly cast it? i.e ($('#wizard')).show(3)). Maybe because the method technically returns a jQuery object, it conflicts with the interface definition?

anorborg commented 11 years ago

forgot to escape:

(<Wizard>$('#wizard)).show(3));

ramesees commented 11 years ago

That didn't work - although I didn't expect it to.

In a typescript definitely type file (a file with extension .d.ts) you expose methods in an underlying javascript file with the same signature and then at design time you code against the .d.ts file and at run time the call gets passed onto the javascript file. I'm currently working on a large scale SPA using typescript and that's how the other typescript files work.

There must be something else at play here because if I try to use methods such as previousTab() or nextTab() directly from my typescript code on the Wizard object without pressing the Previous or Next buttons I get a "method undefined" error from the javascript engine of my browser.

ramesees commented 11 years ago

To make this easier to envisage I am doing the following:

1) Click my Next button on page 1 of my wizard 2) Inside my Next button have some logic to determine which page should be shown next 3) Call Show(3) to go to page 3 (skipping page 2)

However my Next call is always going to page 2 and not page 3 and I am never hitting the appropriate method in my bootstrap.wizard.js file.

I have no doubt this would work in a pure javascript set up (will try this later and report back). The issue is surrounding the typescript bindings. Apologies for what sounds like I am repeating myself.

anorborg commented 11 years ago

Could you put together a plunker or jsfiddle? it may be helpful to see the code and markup.

ramesees commented 11 years ago

I put together a plunker example here for a pure javascript example: http://plnkr.co/edit/VIRwFRDP5JMvByqJhPej?p=preview which has the idea of skipping to certain pages in the onNext function.

A typescript example will be harder to put together as I'm not sure what supports typescript examples like plunker does for javascript. Would I be right in saying that in the existing javascript code for bootstrap wizard, the wizard is comprised of essentially private methods ? If this is so then the typescript bindings wont be able to work as it cant find the appropriate show or nextTab method at runtime.

ramesees commented 11 years ago

I have solved the problem - it appears that the Typescript .d.ts file is missing the logic to take the name of the method you wish to call and its parameter.

Essentially this needs to be added to the jquery.bootstrap.wizard.d.ts file:

interface JQuery { bootstrapWizard(options?: WizardOptions): Wizard;

** bootstrapWizard(...options: any[]): Wizard; ** 

}

This then allows me to call $('#rootwizard').bootstrapWizard('show', 3); and I go to the correct page.

This issue can now be closed thanks.

pallu commented 8 years ago

I too faced this problem and I did something different. I overloaded the interface like this:

interface JQuery {
    bootstrapWizard(options?: WizardOptions): Wizard;
    bootstrapWizard(command: string, index: number):void; //<-- added
}

This works.