~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/app/javascript/lazr/wizard/wizard.js

[r=deryck][bug=803954] Bring lazr-js source into lp tree and package
        yui as a dependency

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2010, Canonical Ltd. All rights reserved.
 
2
 *
 
3
 * Display a functioning form in a lazr.formoverlay.
 
4
 *
 
5
 * @module lazr.wizard
 
6
 */
 
7
YUI.add('lazr.wizard', function(Y) {
 
8
 
 
9
    var namespace = Y.namespace("lazr.wizard");
 
10
 
 
11
   /**
 
12
    * The Step class isn't so much a Widget as it is just an Object with
 
13
    * references to perform certain functions. They are used to tell the
 
14
    * Wizard what to do next.
 
15
    *
 
16
    * @class Step
 
17
    * @namespace lazr.wizard
 
18
    */
 
19
    function Step(config) {
 
20
        Step.superclass.constructor.apply(this, arguments);
 
21
    }
 
22
    Step.NAME = "step";
 
23
    Step.ATTRS = {
 
24
        title: {
 
25
            value: ''
 
26
        },
 
27
        form_content: {
 
28
            value: null
 
29
        },
 
30
        funcLoad: {
 
31
            value: function() {}
 
32
        },
 
33
        funcCleanUp: {
 
34
            value: function() {}
 
35
        }
 
36
    };
 
37
 
 
38
    Y.extend(Step, Y.Widget, {
 
39
        load: function() {
 
40
            this.get("funcLoad").apply(this, arguments);
 
41
        }
 
42
    });
 
43
    namespace.Step = Step;
 
44
 
 
45
 
 
46
   /**
 
47
    * The Wizard class builds on the lazr.FormOverlay class
 
48
    * to display form content and extract form data for the callsite.
 
49
    *
 
50
    * @class Wizard
 
51
    * @namespace lazr.wizard
 
52
    */
 
53
    function Wizard(config) {
 
54
        Wizard.superclass.constructor.apply(this, arguments);
 
55
 
 
56
        if (this.get("steps").length == 0) {
 
57
            throw "Cannot create a Wizard with no steps.";
 
58
        }
 
59
        Y.after(this._renderUIWizard, this, "renderUI");
 
60
        Y.after(this._bindUIWizard, this, "bindUI");
 
61
    }
 
62
 
 
63
    Wizard.NAME = "lazr-wizard";
 
64
    Wizard.ATTRS = {
 
65
        current_step_index: {
 
66
            value: -1
 
67
        },
 
68
        previous_step_index: {
 
69
            value: -1
 
70
        },
 
71
        next_step_index: {
 
72
            value: 0
 
73
        },
 
74
        steps: {
 
75
            value: []
 
76
        }
 
77
    }
 
78
 
 
79
    Y.extend(Wizard, Y.lazr.FormOverlay, {
 
80
 
 
81
        initializer: function() {
 
82
            /* Do nothing */
 
83
        },
 
84
 
 
85
        _renderUIWizard: function() {
 
86
            this.next();
 
87
        },
 
88
 
 
89
        _bindUIWizard: function() {
 
90
            Y.on("click",
 
91
                Y.bind(function(e){ this.hide();}, this),
 
92
                this.get("form_cancel_button"));
 
93
        },
 
94
 
 
95
        /**
 
96
         * Add a step to the end of the steps array.
 
97
         *
 
98
         * @method addStep
 
99
         */
 
100
        addStep: function(step) {
 
101
            this.get("steps").push(step);
 
102
            // If the widget is currently on its final step, update the
 
103
            // next_step_index to reflect the fact that we've just added
 
104
            // a new one.
 
105
            if (!this.hasNextStep()) {
 
106
                var current_step_index = this.get("current_step_index");
 
107
                this.set("next_step_index", current_step_index + 1);
 
108
            }
 
109
        },
 
110
 
 
111
        /**
 
112
         * Transition to the step at a given index.
 
113
         *
 
114
         * @method _transitionToStep
 
115
         * @private
 
116
         * @param step_index The index of the step to transition to.
 
117
         */
 
118
        _transitionToStep: function(step_index) {
 
119
            var step = this.get("steps")[step_index];
 
120
            this.set("steptitle", step.get("title"));
 
121
 
 
122
            var step_form_content = step.get("form_content");
 
123
            if (Y.Lang.isValue(step_form_content)) {
 
124
                this.set("form_content", step_form_content);
 
125
                this._setFormContent()
 
126
            }
 
127
 
 
128
            step.load(this);
 
129
            this.fire("wizard:stepChange");
 
130
            this.set("current_step", step);
 
131
            this._updateStepIndices(step_index);
 
132
        },
 
133
 
 
134
        /**
 
135
         * Transition to the next step in the steps array.
 
136
         *
 
137
         * @method next
 
138
         */
 
139
        next: function() {
 
140
            var step_index = this.get("next_step_index");
 
141
            if (step_index < 0) {
 
142
                throw "Wizard is already on its last step.";
 
143
            }
 
144
            this._transitionToStep(step_index);
 
145
        },
 
146
 
 
147
        /**
 
148
         * Transition to the previous step in the steps array.
 
149
         *
 
150
         * @method next
 
151
         */
 
152
        previous: function() {
 
153
            var step_index = this.get("previous_step_index");
 
154
            if (step_index < 0) {
 
155
                throw "Wizard is already on its first step.";
 
156
            }
 
157
            this._transitionToStep(step_index);
 
158
        },
 
159
 
 
160
        /**
 
161
         * Update the step indices based on the current step index.
 
162
         *
 
163
         * @method _updateStepIndices
 
164
         * @private
 
165
         * @param current_step_index The index of the current step.
 
166
         */
 
167
        _updateStepIndices: function(current_step_index) {
 
168
            if (current_step_index > 0) {
 
169
                this.set("previous_step_index", current_step_index - 1);
 
170
            } else {
 
171
                this.set("previous_step_index", -1);
 
172
            }
 
173
 
 
174
            if (this.get("steps").length > current_step_index + 1) {
 
175
                this.set("next_step_index", current_step_index + 1);
 
176
            } else {
 
177
                this.set("next_step_index", -1);
 
178
            }
 
179
 
 
180
            this.set("current_step_index", current_step_index + 1);
 
181
        },
 
182
 
 
183
        /**
 
184
         * Return true if there's another step after the current one.
 
185
         *
 
186
         * @method hasNextStep
 
187
         */
 
188
        hasNextStep: function() {
 
189
            var next_step_index = this.get("next_step_index");
 
190
            return (next_step_index > 0)
 
191
        },
 
192
 
 
193
        /**
 
194
         * Return true if there's a step before the current one.
 
195
         *
 
196
         * @method hasPreviousStep
 
197
         */
 
198
        hasPreviousStep: function() {
 
199
            var previous_step_index = this.get("previous_step_index");
 
200
            return (previous_step_index > -1)
 
201
        },
 
202
 
 
203
        /**
 
204
         * Destroy all the Steps of the widget.
 
205
         *
 
206
         * @method destructor
 
207
         */
 
208
        destructor: function() {
 
209
            // Loop over all the steps and delete them.
 
210
            while(this.get("steps").length > 0) {
 
211
                var step = this.get("steps").pop();
 
212
                delete step;
 
213
            }
 
214
        }
 
215
 
 
216
    });
 
217
 
 
218
    namespace.Wizard = Wizard;
 
219
 
 
220
}, "0.1", {"skinnable": true, "requires": ["lazr.formoverlay"]});