Extension:GuidedTour/Refactoring brainstorming


  • Easy for extension developers to use
  • Easy for admins to use
  • Easy to maintain and enhance
  • Clear and concise, without unused code or features
  • Allow tours to run setup code every time the tour is re-started (passing some setup callback to defineTour)? Currently, they can only run at page load, which for VE can make a difference in some edge cases. This could become more of an issue as no-reload interfaces become more common. See https://gerrit.wikimedia.org/r/#/c/72682/7/resources/tours/gettingstartedtasktoolbarve.js
  • Point to correct selectors when VE is enabled (e.g. they appropriate ca-edit, and wikitext becomes ca-editsource). There could potentially be a mini-library of selectors GuidedTour helps you with (you could still use arbitrary ones when needed) .Done right, this could potentially handle both VE and skin-specific variations for standard features
    The same applies to text. For example, the wikitext edit tab is visualeditor-ca-editsource with VisualEditor enabled, but vector-view-edit otherwise (at least assuming Vector, but it's the same text for Monobook).
  • shouldSkip array so they can easily combine (OR/AND)
  • Names for steps so they can point to each other, with possible special 'next' and 'end'
  • Add non-linear?
  • Right now GuidedTour handles hooks, and shouldSkip uses simple boolean functions
    • Cut out the middle man and let tour writers use hooks directly? .listenFor could take a list of hooks, any of which firing triggers a call to proceedTo. proceedTo would pass the hook that just fired, if any.
  • Let tours seamlessly point to each other? This ties well to the non-linear. For example, a tour could send people off to another tour in some cases.
  • With non-linearity and more powerful options, nesting may get too deep currently.
    • Take more of a DSL approach
    • var otherStep = tour.step( ... )
    • startWith( step ), proceedTo( ) (takes a function and returns the next step)
    • then with implicit next button?
    • .next implicitly chains together with next buttons (necessary?)
    • then/proceedTo passes in an object that you call for the "shouldSkip" helpers (maybe the tour object). If proceedTo/then doesn't return anything/returning undefined, it doesn't skip.
    • Global transitions if the user does something not covered by local transition (click "Edit source" in the middle of a VE tour)
  • Allow functions instead of strings in some cases
  • Do a test branch of GuidedTour for this new interface. This should include reimplementing test.js. Also, use this test branch in a test branch of GettingStarted, to reimplement gettingstartedtasktoolbarve.
  • Pass tourState to then()/step()/proceedTo() functions.
  • Have tour cookie track which steps have been shown? Currently it acts as a high-water mark, which won't work as well for non-linear tours. (Instead you could launch separate tours for each sub-subject, each maintaining its own current step.)
  • Steps that deliberately don't show anything and are just there as part of the flow?



listenFor can be called on either the step or the tour. listenFor can be at the tour level even if proceedTo as at the step level. It will cause GuidedTour to listen for the specified event in that context. When the event is triggered, GuidedTour will then determine if anything should be done.

step.listenFor( function ( helper ) {
  helper.$( 'someButton' ).on( 'click' );
  helper.mw.hook( 've.activationComplete' );
} );

This lets built-in hooks and events have parity with user-defined ones. The idea is that either will simply trigger proceedTo. However, we need to make sure this decoupling is useful, not annoying.

This proposed API also requires mirroring some of the jQuery API (probably just on, though that itself has multiple variants); the idea is to make it very familiar. The idea is also that they could simly call the helpers more than once for multiple events (there could maybe be a varargs version for mw.hook to specify more than one hook at once).



The function passed to proceedTo is in charge of deciding where (if anywhere) to go next. It is triggered by certain events or hooks. Some sort of state should be passed to proceedTo, so it knows what just happened (e.g. doc ready fired, or someButton was clicked), without having to call shouldSkip helpers. The shouldSkip helpers will still be available, but they will not be needed for all use cases.

Use cases