bootstrap_wizard_rails 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/bootstrap_wizard_rails.rb +4 -0
- data/vendor/assets/javascripts/bootstrap-wizard.js +1171 -0
- data/vendor/assets/stylesheets/bootstrap-wizard.css +182 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cfa55fbc433cdfaaca8f109390f57098faae2a74
|
4
|
+
data.tar.gz: 30fc59864b37f207583ccfed3666460804571e67
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7e598d2220187f0480ffdf303d69818e0f2eb6db123fba360d8b68c849e3703420589af48a179c2f0df4f18787779cc82ec3050a4e7a2f5b87eff9080c5bd974
|
7
|
+
data.tar.gz: dc18b3ea0006c21d61ac541cc20630fb3b9697ed3bf907affcb984387ba1d28ce7968eed4dcea4dea1f2f943697dbd203654ba16acc59ea347731adf393891ba
|
@@ -0,0 +1,1171 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2013 Panopta, Andrew Moffat
|
3
|
+
*
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
9
|
+
* furnished to do so, subject to the following conditions:
|
10
|
+
*
|
11
|
+
* The above copyright notice and this permission notice shall be included in
|
12
|
+
* all copies or substantial portions of the Software.
|
13
|
+
*
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
* SOFTWARE.
|
21
|
+
*/
|
22
|
+
(function ($) {
|
23
|
+
$.fn.wizard = function(args) {
|
24
|
+
return new Wizard(this, args);
|
25
|
+
};
|
26
|
+
|
27
|
+
$.fn.wizard.logging = false;
|
28
|
+
|
29
|
+
var WizardCard = function(wizard, card, index, prev, next) {
|
30
|
+
this.wizard = wizard;
|
31
|
+
this.index = index;
|
32
|
+
this.prev = prev;
|
33
|
+
this.next = next;
|
34
|
+
this.el = card;
|
35
|
+
this.title = card.find("h3").first().text();
|
36
|
+
this.name = card.data("cardname") || this.title;
|
37
|
+
|
38
|
+
this.nav = this._createNavElement(this.title, index);
|
39
|
+
|
40
|
+
this._disabled = false;
|
41
|
+
this._loaded = false;
|
42
|
+
this._events = {};
|
43
|
+
};
|
44
|
+
|
45
|
+
WizardCard.prototype = {
|
46
|
+
select: function() {
|
47
|
+
this.log("selecting");
|
48
|
+
if (!this.isSelected()) {
|
49
|
+
this.nav.addClass("active");
|
50
|
+
this.el.show();
|
51
|
+
|
52
|
+
if (!this._loaded) {
|
53
|
+
this.trigger("loaded");
|
54
|
+
this.reload();
|
55
|
+
}
|
56
|
+
|
57
|
+
this.trigger("selected");
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
/*
|
62
|
+
* this is ugly, but we're handling the changing of the wizard's
|
63
|
+
* buttons here, in the WizardCard select. so when a card is
|
64
|
+
* selected, we're figuring out if we're the first card or the
|
65
|
+
* last card and changing the wizard's buttons via the guts of
|
66
|
+
* the wizard
|
67
|
+
*
|
68
|
+
* ideally this logic should be encapsulated by some wizard methods
|
69
|
+
* that we can call from here, instead of messing with the guts
|
70
|
+
*/
|
71
|
+
var w = this.wizard;
|
72
|
+
|
73
|
+
// The back button is only disabled on this first card...
|
74
|
+
w.backButton.toggleClass("disabled", this.index == 0);
|
75
|
+
|
76
|
+
if (this.index >= w._cards.length-1) {
|
77
|
+
this.log("on last card, changing next button to submit");
|
78
|
+
|
79
|
+
w.changeNextButton(w.args.buttons.submitText, "btn-success");
|
80
|
+
w._readyToSubmit = true;
|
81
|
+
w.trigger("readySubmit");
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
w._readyToSubmit = false;
|
85
|
+
w.changeNextButton(w.args.buttons.nextText, "btn-primary");
|
86
|
+
}
|
87
|
+
|
88
|
+
return this;
|
89
|
+
},
|
90
|
+
|
91
|
+
_createNavElement: function(name, i) {
|
92
|
+
var li = $('<li class="wizard-nav-item"></li>');
|
93
|
+
var a = $('<a class="wizard-nav-link"></a>');
|
94
|
+
a.data("navindex", i);
|
95
|
+
li.append(a);
|
96
|
+
a.append('<span class="glyphicon glyphicon-chevron-right"></span> ');
|
97
|
+
a.append(name);
|
98
|
+
return li;
|
99
|
+
},
|
100
|
+
|
101
|
+
markVisited: function() {
|
102
|
+
this.log("marking as visited");
|
103
|
+
this.nav.addClass("already-visited");
|
104
|
+
this.trigger("markVisited");
|
105
|
+
return this;
|
106
|
+
},
|
107
|
+
|
108
|
+
unmarkVisited: function() {
|
109
|
+
this.log("unmarking as visited");
|
110
|
+
this.nav.removeClass("already-visited");
|
111
|
+
this.trigger("unmarkVisited");
|
112
|
+
return this;
|
113
|
+
},
|
114
|
+
|
115
|
+
deselect: function() {
|
116
|
+
this.nav.removeClass("active");
|
117
|
+
this.el.hide();
|
118
|
+
this.trigger("deselect");
|
119
|
+
return this;
|
120
|
+
},
|
121
|
+
|
122
|
+
enable: function() {
|
123
|
+
this.log("enabling");
|
124
|
+
|
125
|
+
// Issue #38 Hiding navigation link when hide card
|
126
|
+
// Awaiting approval
|
127
|
+
//
|
128
|
+
// this.nav.removeClass('hide');
|
129
|
+
|
130
|
+
this.nav.addClass("active");
|
131
|
+
this._disabled = false;
|
132
|
+
this.trigger("enabled");
|
133
|
+
return this;
|
134
|
+
},
|
135
|
+
|
136
|
+
disable: function(hideCard) {
|
137
|
+
this.log("disabling");
|
138
|
+
this._disabled = true;
|
139
|
+
this.nav.removeClass("active already-visited");
|
140
|
+
if (hideCard) {
|
141
|
+
this.el.hide();
|
142
|
+
// Issue #38 Hiding navigation link when hide card
|
143
|
+
// Awaiting approval
|
144
|
+
//
|
145
|
+
// this.nav.addClass('hide');
|
146
|
+
}
|
147
|
+
this.trigger("disabled");
|
148
|
+
return this;
|
149
|
+
},
|
150
|
+
|
151
|
+
isDisabled: function() {
|
152
|
+
return this._disabled;
|
153
|
+
},
|
154
|
+
|
155
|
+
alreadyVisited: function() {
|
156
|
+
return this.nav.hasClass("already-visited");
|
157
|
+
},
|
158
|
+
|
159
|
+
isSelected: function() {
|
160
|
+
return this.nav.hasClass("active");
|
161
|
+
},
|
162
|
+
|
163
|
+
reload: function() {
|
164
|
+
this._loaded = true;
|
165
|
+
this.trigger("reload");
|
166
|
+
return this;
|
167
|
+
},
|
168
|
+
|
169
|
+
on: function() {
|
170
|
+
return this.wizard.on.apply(this, arguments);
|
171
|
+
},
|
172
|
+
|
173
|
+
trigger: function() {
|
174
|
+
this.callListener("on"+arguments[0]);
|
175
|
+
return this.wizard.trigger.apply(this, arguments);
|
176
|
+
},
|
177
|
+
|
178
|
+
/*
|
179
|
+
* displays an alert box on the current card
|
180
|
+
*/
|
181
|
+
toggleAlert: function(msg, toggle) {
|
182
|
+
this.log("toggling alert to: " + toggle);
|
183
|
+
|
184
|
+
toggle = typeof(toggle) == "undefined" ? true : toggle;
|
185
|
+
|
186
|
+
if (toggle) {this.trigger("showAlert");}
|
187
|
+
else {this.trigger("hideAlert");}
|
188
|
+
|
189
|
+
var div;
|
190
|
+
var alert = this.el.children("h3").first().next("div.alert");
|
191
|
+
|
192
|
+
if (alert.length == 0) {
|
193
|
+
/*
|
194
|
+
* we're hiding anyways, so no need to create anything.
|
195
|
+
* we'll do that if we ever are actually showing the alert
|
196
|
+
*/
|
197
|
+
if (!toggle) {return this;}
|
198
|
+
|
199
|
+
this.log("couldn't find existing alert div, creating one");
|
200
|
+
div = $("<div />");
|
201
|
+
div.addClass("alert");
|
202
|
+
div.addClass("hide");
|
203
|
+
div.insertAfter(this.el.find("h3").first());
|
204
|
+
}
|
205
|
+
else {
|
206
|
+
this.log("found existing alert div");
|
207
|
+
div = alert.first();
|
208
|
+
}
|
209
|
+
|
210
|
+
if (toggle) {
|
211
|
+
if (msg != null) {
|
212
|
+
this.log("setting alert msg to", msg);
|
213
|
+
div.html(msg);
|
214
|
+
}
|
215
|
+
div.show();
|
216
|
+
}
|
217
|
+
else {
|
218
|
+
div.hide();
|
219
|
+
}
|
220
|
+
return this;
|
221
|
+
},
|
222
|
+
|
223
|
+
/*
|
224
|
+
* this looks for event handlers embedded into the html of the
|
225
|
+
* wizard card itself, in the form of a data- attribute
|
226
|
+
*/
|
227
|
+
callListener: function(name) {
|
228
|
+
// a bug(?) in jquery..can't access data-<name> if name is camelCase
|
229
|
+
name = name.toLowerCase();
|
230
|
+
|
231
|
+
this.log("looking for listener " + name);
|
232
|
+
var listener = window[this.el.data(name)];
|
233
|
+
if (listener) {
|
234
|
+
this.log("calling listener " + name);
|
235
|
+
var wizard = this.wizard;
|
236
|
+
|
237
|
+
try {
|
238
|
+
var vret = listener(this);
|
239
|
+
}
|
240
|
+
catch (e) {
|
241
|
+
this.log("exception calling listener " + name + ": ", e);
|
242
|
+
}
|
243
|
+
}
|
244
|
+
else {
|
245
|
+
this.log("didn't find listener " + name);
|
246
|
+
}
|
247
|
+
},
|
248
|
+
|
249
|
+
problem: function(toggle) {
|
250
|
+
this.nav.find("a").toggleClass("wizard-step-error", toggle);
|
251
|
+
},
|
252
|
+
|
253
|
+
validate: function() {
|
254
|
+
var failures = false;
|
255
|
+
var self = this;
|
256
|
+
|
257
|
+
/*
|
258
|
+
* run all the validators embedded on the inputs themselves
|
259
|
+
*/
|
260
|
+
this.el.find("[data-validate]").each(function(i, el) {
|
261
|
+
self.log("validating individiual inputs");
|
262
|
+
el = $(el);
|
263
|
+
|
264
|
+
var v = el.data("validate");
|
265
|
+
if (!v) {return;}
|
266
|
+
|
267
|
+
var ret = {
|
268
|
+
status: true,
|
269
|
+
title: "Error",
|
270
|
+
msg: ""
|
271
|
+
};
|
272
|
+
|
273
|
+
var vret = window[v](el);
|
274
|
+
$.extend(ret, vret);
|
275
|
+
|
276
|
+
// Add-On
|
277
|
+
// This allows the use of a INPUT+BTN used as one according to boostrap layout
|
278
|
+
// for the wizard it is required to add an id with btn-(ID of Input)
|
279
|
+
// this will make sure the popover is drawn on the correct element
|
280
|
+
if ( $('#btn-' + el.attr('id')).length === 1 ) {
|
281
|
+
el = $('#btn-' + el.attr('id'));
|
282
|
+
}
|
283
|
+
|
284
|
+
if (!ret.status) {
|
285
|
+
failures = true;
|
286
|
+
|
287
|
+
// Updated to show error on correct form-group
|
288
|
+
el.parents("div.form-group").toggleClass("has-error", true);
|
289
|
+
|
290
|
+
// This allows the use of a INPUT+BTN used as one according to boostrap layout
|
291
|
+
// for the wizard it is required to add an id with btn-(ID of Input)
|
292
|
+
// this will make sure the popover is drawn on the correct element
|
293
|
+
if ( $('#btn-' + el.attr('id')).length === 1 ) {
|
294
|
+
el = $('#btn-' + el.attr('id'));
|
295
|
+
}
|
296
|
+
|
297
|
+
self.wizard.errorPopover(el, ret.msg);
|
298
|
+
} else {
|
299
|
+
el.parents("div.form-group").toggleClass("has-error", false);
|
300
|
+
|
301
|
+
// This allows the use of a INPUT+BTN used as one according to boostrap layout
|
302
|
+
// for the wizard it is required to add an id with btn-(ID of Input)
|
303
|
+
// this will make sure the popover is drawn on the correct element
|
304
|
+
if ( $('#btn-' + el.attr('id')).length === 1 ) {
|
305
|
+
el = $('#btn-' + el.attr('id'));
|
306
|
+
}
|
307
|
+
|
308
|
+
try {
|
309
|
+
el.popover("destroy");
|
310
|
+
}
|
311
|
+
/*
|
312
|
+
* older versions of bootstrap don't have a destroy call
|
313
|
+
* for popovers
|
314
|
+
*/
|
315
|
+
catch (e) {
|
316
|
+
el.popover("hide");
|
317
|
+
}
|
318
|
+
}
|
319
|
+
});
|
320
|
+
this.log("after validating inputs, failures is", failures);
|
321
|
+
|
322
|
+
/*
|
323
|
+
* run the validator embedded in the card
|
324
|
+
*/
|
325
|
+
var cardValidator = window[this.el.data("validate")];
|
326
|
+
if (cardValidator) {
|
327
|
+
this.log("running html-embedded card validator");
|
328
|
+
var cardValidated = cardValidator(this);
|
329
|
+
if (typeof(cardValidated) == "undefined" || cardValidated == null) {
|
330
|
+
cardValidated = true;
|
331
|
+
}
|
332
|
+
if (!cardValidated) failures = true;
|
333
|
+
this.log("after running html-embedded card validator, failures is", failures);
|
334
|
+
}
|
335
|
+
|
336
|
+
/*
|
337
|
+
* run the validate listener
|
338
|
+
*/
|
339
|
+
this.log("running listener validator");
|
340
|
+
var listenerValidated = this.trigger("validate");
|
341
|
+
if (typeof(listenerValidated) == "undefined" || listenerValidated == null) {
|
342
|
+
listenerValidated = true;
|
343
|
+
}
|
344
|
+
if (!listenerValidated) failures = true;
|
345
|
+
this.log("after running listener validator, failures is", failures);
|
346
|
+
|
347
|
+
var validated = !failures;
|
348
|
+
if (validated) {
|
349
|
+
this.log("validated, calling listeners");
|
350
|
+
this.trigger("validated");
|
351
|
+
}
|
352
|
+
else {
|
353
|
+
this.log("invalid");
|
354
|
+
this.trigger("invalid");
|
355
|
+
}
|
356
|
+
return validated;
|
357
|
+
},
|
358
|
+
|
359
|
+
log: function() {
|
360
|
+
if (!window.console || !$.fn.wizard.logging) {return;}
|
361
|
+
var prepend = "card '"+this.name+"': ";
|
362
|
+
var args = [prepend];
|
363
|
+
args.push.apply(args, arguments);
|
364
|
+
|
365
|
+
console.log.apply(console, args);
|
366
|
+
},
|
367
|
+
|
368
|
+
isActive: function() {
|
369
|
+
return this.nav.hasClass("active");
|
370
|
+
}
|
371
|
+
};
|
372
|
+
|
373
|
+
Wizard = function(markup, args) {
|
374
|
+
|
375
|
+
/* TEMPLATE */
|
376
|
+
this.wizard_template = [
|
377
|
+
'<div class="modal fade wizard">',
|
378
|
+
'<div class="modal-dialog wizard-dialog">',
|
379
|
+
'<div class="modal-content wizard-content">',
|
380
|
+
'<div class="modal-header wizard-header">',
|
381
|
+
'<button type="button" class="close wizard-close" aria-hidden="true">×</button>',
|
382
|
+
'<h3 class="modal-title wizard-title"></h3>',
|
383
|
+
'<span class="wizard-subtitle"></span>',
|
384
|
+
'</div>',
|
385
|
+
'<div class="modal-body wizard-body">',
|
386
|
+
'<div class="pull-left wizard-steps">',
|
387
|
+
'<div class="wizard-nav-container">',
|
388
|
+
'<ul class="nav wizard-nav-list">',
|
389
|
+
'</ul>',
|
390
|
+
'</div>',
|
391
|
+
'<div class="wizard-progress-container">',
|
392
|
+
'<div class="progress progress-striped">',
|
393
|
+
'<div class="progress-bar" style="width: 0%;"></div>',
|
394
|
+
'</div>',
|
395
|
+
'</div>',
|
396
|
+
'</div>',
|
397
|
+
'<form>',
|
398
|
+
'<div class="wizard-cards">',
|
399
|
+
'<div class="wizard-card-container">',
|
400
|
+
'</div>',
|
401
|
+
'<div class="wizard-footer">',
|
402
|
+
'<div class="wizard-buttons-container">',
|
403
|
+
'<button class="btn wizard-cancel wizard-close" type="button">Cancel</button>',
|
404
|
+
'<div class="btn-group-single pull-right">',
|
405
|
+
'<button class="btn wizard-back" type="button">Back</button>',
|
406
|
+
'<button class="btn btn-primary wizard-next" type="button">Next</button>',
|
407
|
+
'</div>',
|
408
|
+
'</div>',
|
409
|
+
'</div>',
|
410
|
+
'</div>',
|
411
|
+
'</form>',
|
412
|
+
'</div>',
|
413
|
+
|
414
|
+
'</div>',
|
415
|
+
'</div>',
|
416
|
+
'</div>'
|
417
|
+
];
|
418
|
+
|
419
|
+
this.args = {
|
420
|
+
keyboard: true,
|
421
|
+
backdrop: true,
|
422
|
+
show: false,
|
423
|
+
submitUrl: "",
|
424
|
+
showCancel: false,
|
425
|
+
showClose: true,
|
426
|
+
progressBarCurrent: false,
|
427
|
+
increaseHeight: 0,
|
428
|
+
contentHeight: 300,
|
429
|
+
contentWidth: 580,
|
430
|
+
buttons: {
|
431
|
+
cancelText: "Cancel",
|
432
|
+
nextText: "Next",
|
433
|
+
backText: "Back",
|
434
|
+
submitText: "Submit",
|
435
|
+
submittingText: "Submitting...",
|
436
|
+
},
|
437
|
+
formClass: "form-horizontal"
|
438
|
+
};
|
439
|
+
|
440
|
+
$.extend(this.args, args || {});
|
441
|
+
|
442
|
+
this._create(markup);
|
443
|
+
};
|
444
|
+
|
445
|
+
Wizard.prototype = {
|
446
|
+
log: function() {
|
447
|
+
if (!window.console || !$.fn.wizard.logging) {return;}
|
448
|
+
var prepend = "wizard "+this.el.id+": ";
|
449
|
+
var args = [prepend];
|
450
|
+
args.push.apply(args, arguments);
|
451
|
+
console.log.apply(console, args);
|
452
|
+
},
|
453
|
+
|
454
|
+
_create: function(markup) {
|
455
|
+
this.markup = $(markup);
|
456
|
+
this.title = this.markup.data('title');
|
457
|
+
this.submitCards = this.markup.find(".wizard-error,.wizard-failure,.wizard-success,.wizard-loading");
|
458
|
+
this.el = $(this.wizard_template.join('\n'));
|
459
|
+
$('body').append(this.el);
|
460
|
+
|
461
|
+
this.modal = this.el.modal({
|
462
|
+
keyboard: this.args.keyboard,
|
463
|
+
show: this.args.show,
|
464
|
+
backdrop: this.args.backdrop
|
465
|
+
});
|
466
|
+
|
467
|
+
this.dimensions = {
|
468
|
+
contentHeight: this.args.contentHeight,
|
469
|
+
contentWidth: this.args.contentWidth
|
470
|
+
};
|
471
|
+
this.dialog = this.modal.find('.wizard-dialog');
|
472
|
+
this.content = this.modal.find('.wizard-content');
|
473
|
+
this.header = this.modal.find('.wizard-header');
|
474
|
+
this.body = this.modal.find('.wizard-body');
|
475
|
+
this.wizardSteps = this.modal.find('.wizard-steps');
|
476
|
+
this.wizardCards = this.modal.find('.wizard-cards');
|
477
|
+
this.wizardCardContainer = this.modal.find('.wizard-card-container');
|
478
|
+
this.wizardCardContainer
|
479
|
+
.append(this.markup.find('.wizard-card'))
|
480
|
+
.append(this.submitCards);
|
481
|
+
this.navContainer = this.modal.find('.wizard-nav-container');
|
482
|
+
this.navList = this.modal.find('.wizard-nav-list');
|
483
|
+
this.progressContainer = this.modal.find('.wizard-progress-container');
|
484
|
+
this.progress = this.progressContainer.find('.progress-bar');
|
485
|
+
this.closeButton = this.modal.find('button.wizard-close.close');
|
486
|
+
this.cardsContainer = this.modal.find('wizard-cards-container');
|
487
|
+
this.form = this.modal.find('form');
|
488
|
+
this.footer = this.modal.find(".wizard-footer");
|
489
|
+
this.cancelButton = this.footer.find(".wizard-cancel");
|
490
|
+
this.backButton = this.footer.find(".wizard-back");
|
491
|
+
this.nextButton = this.footer.find(".wizard-next");
|
492
|
+
|
493
|
+
this._cards = [];
|
494
|
+
this.cards = {};
|
495
|
+
this._readyToSubmit = false;
|
496
|
+
this.percentComplete = 0;
|
497
|
+
this._submitting = false;
|
498
|
+
this._events = {};
|
499
|
+
this._firstShow = true;
|
500
|
+
|
501
|
+
this._createCards();
|
502
|
+
|
503
|
+
this.nextButton.click(this, this._handleNextClick);
|
504
|
+
this.backButton.click(this, this._handleBackClick);
|
505
|
+
|
506
|
+
this.cancelButton.text(this.args.buttons.cancelText);
|
507
|
+
this.backButton.text(this.args.buttons.backText);
|
508
|
+
this.nextButton.text(this.args.buttons.nextText);
|
509
|
+
|
510
|
+
// Apply Form Class(es)
|
511
|
+
this.form.addClass(this.args.formClass);
|
512
|
+
|
513
|
+
// Register Array Holder for popovers
|
514
|
+
this.popovers = [];
|
515
|
+
|
516
|
+
var self = this;
|
517
|
+
var _close = function() {
|
518
|
+
self.reset();
|
519
|
+
self.close();
|
520
|
+
self.trigger("closed");
|
521
|
+
};
|
522
|
+
|
523
|
+
// Register Close Button
|
524
|
+
this.closeButton.click(_close);
|
525
|
+
this.cancelButton.click(_close);
|
526
|
+
|
527
|
+
this.wizardSteps.on("click", "li.already-visited a.wizard-nav-link", this,
|
528
|
+
function(event) {
|
529
|
+
var index = parseInt($(event.target).data("navindex"));
|
530
|
+
event.data.setCard(index);
|
531
|
+
});
|
532
|
+
|
533
|
+
if ( this.title.length != 0 ) {
|
534
|
+
this.setTitle(this.title);
|
535
|
+
}
|
536
|
+
|
537
|
+
this.on("submit", this._defaultSubmit);
|
538
|
+
|
539
|
+
// Set Modal Dimensions
|
540
|
+
this.autoDimensions();
|
541
|
+
},
|
542
|
+
|
543
|
+
autoDimensions: function() {
|
544
|
+
// DO NOT REMOVE DISPLAY ; Temporary display is required for calculation
|
545
|
+
this.modal.css('display', 'block');
|
546
|
+
|
547
|
+
this.dimensions.header = this.header.outerHeight(true);
|
548
|
+
|
549
|
+
// Navigation Pane is dyanmic build on card content
|
550
|
+
// Navigation Pane === BASE Inner Content Height
|
551
|
+
this.dimensions.navigation = this.wizardSteps.outerHeight(true);
|
552
|
+
if ( this.dimensions.navigation < this.dimensions.contentHeight ) {
|
553
|
+
this.dimensions.navigation = this.dimensions.contentHeight;
|
554
|
+
this.navContainer.height( (this.dimensions.contentHeight-30) - this.progressContainer.outerHeight(true));
|
555
|
+
}
|
556
|
+
|
557
|
+
// Dimension Alias ( Body Height === (Navigation Height) )
|
558
|
+
this.dimensions.body = this.dimensions.navigation;
|
559
|
+
|
560
|
+
// Apply OuterHeight of navigation to it's parent wizardSteps
|
561
|
+
this.wizardSteps.height(this.dimensions.body);
|
562
|
+
|
563
|
+
// Modal Height === (Header + Content)
|
564
|
+
this.dimensions.modal = (this.dimensions.header + this.dimensions.navigation);
|
565
|
+
this.content.height(this.dimensions.modal + 'px');
|
566
|
+
this.dialog.width(this.dimensions.contentWidth);
|
567
|
+
|
568
|
+
this.body.height(this.dimensions.body + 'px');
|
569
|
+
this.wizardCards.height(this.dimensions.body + 'px');
|
570
|
+
|
571
|
+
// Footer Height
|
572
|
+
this.dimensions.footer = this.footer.outerHeight(true);
|
573
|
+
|
574
|
+
// Card Container === (Body - Footer)
|
575
|
+
this.dimensions.cardContainer = (this.dimensions.body - this.dimensions.footer);
|
576
|
+
this.wizardCardContainer.height(this.dimensions.cardContainer);
|
577
|
+
|
578
|
+
// Reposition
|
579
|
+
this.dimensions.offset = ($(window).height() - this.dialog.height()) / 2;
|
580
|
+
this.dialog.css({
|
581
|
+
'margin-top': this.dimensions.offset + 'px',
|
582
|
+
'padding-top': 0
|
583
|
+
});
|
584
|
+
|
585
|
+
// DO NOT REMOVE NEXT LINE
|
586
|
+
this.modal.css('display', '');
|
587
|
+
},
|
588
|
+
|
589
|
+
setTitle: function(title) {
|
590
|
+
this.log("setting title to", title);
|
591
|
+
this.modal.find(".wizard-title").first().text(title);
|
592
|
+
return this;
|
593
|
+
},
|
594
|
+
|
595
|
+
setSubtitle: function(title) {
|
596
|
+
this.log("setting subtitle to", title);
|
597
|
+
this.modal.find(".wizard-subtitle").first().text(title);
|
598
|
+
return this;
|
599
|
+
},
|
600
|
+
|
601
|
+
errorPopover: function(el, msg, allowHtml) {
|
602
|
+
this.log("launching popover on", el);
|
603
|
+
allowHtml = typeof allowHtml !== "undefined" ? allowHtml : false;
|
604
|
+
var popover = el.popover({
|
605
|
+
content: msg,
|
606
|
+
trigger: "manual",
|
607
|
+
html: allowHtml,
|
608
|
+
container: el.parents('.form-group')
|
609
|
+
}).addClass("error-popover").popover("show").next(".popover");
|
610
|
+
|
611
|
+
el.parents('.form-group').find('.popover').addClass("error-popover");
|
612
|
+
|
613
|
+
this.popovers.push(el);
|
614
|
+
|
615
|
+
return popover;
|
616
|
+
},
|
617
|
+
|
618
|
+
destroyPopover: function(pop) {
|
619
|
+
pop = $(pop);
|
620
|
+
|
621
|
+
/*
|
622
|
+
* this is the element that the popover was created for
|
623
|
+
*/
|
624
|
+
try {
|
625
|
+
pop.popover("destroy");
|
626
|
+
}
|
627
|
+
/*
|
628
|
+
* older versions of bootstrap don't have a destroy call
|
629
|
+
* for popovers
|
630
|
+
*/
|
631
|
+
catch (e) {
|
632
|
+
pop.popover("hide");
|
633
|
+
}
|
634
|
+
},
|
635
|
+
|
636
|
+
hidePopovers: function(el) {
|
637
|
+
this.log("hiding all popovers");
|
638
|
+
var self = this;
|
639
|
+
|
640
|
+
$.each(this.popovers, function(i, p) {
|
641
|
+
self.destroyPopover(p);
|
642
|
+
});
|
643
|
+
|
644
|
+
this.modal.find('.has-error').removeClass('has-error');
|
645
|
+
this.popovers = [];
|
646
|
+
},
|
647
|
+
|
648
|
+
eachCard: function(fn) {
|
649
|
+
$.each(this._cards, fn);
|
650
|
+
return this;
|
651
|
+
},
|
652
|
+
|
653
|
+
getActiveCard: function() {
|
654
|
+
this.log("getting active card");
|
655
|
+
var currentCard = null;
|
656
|
+
|
657
|
+
$.each(this._cards, function(i, card) {
|
658
|
+
if (card.isActive()) {
|
659
|
+
currentCard = card;
|
660
|
+
return false;
|
661
|
+
}
|
662
|
+
});
|
663
|
+
if (currentCard) {this.log("found active card", currentCard);}
|
664
|
+
else {this.log("couldn't find an active card");}
|
665
|
+
return currentCard;
|
666
|
+
},
|
667
|
+
|
668
|
+
changeNextButton: function(text, cls) {
|
669
|
+
this.log("changing next button, text: " + text, "class: " + cls);
|
670
|
+
if (typeof(cls) != "undefined") {
|
671
|
+
this.nextButton.removeClass("btn-success btn-primary");
|
672
|
+
}
|
673
|
+
|
674
|
+
if (cls) {
|
675
|
+
this.nextButton.addClass(cls);
|
676
|
+
}
|
677
|
+
this.nextButton.text(text);
|
678
|
+
return this;
|
679
|
+
},
|
680
|
+
|
681
|
+
hide: function() {
|
682
|
+
this.log("hiding");
|
683
|
+
this.modal.modal("hide");
|
684
|
+
return this;
|
685
|
+
},
|
686
|
+
|
687
|
+
close: function() {
|
688
|
+
this.log("closing");
|
689
|
+
this.modal.modal("hide");
|
690
|
+
return this;
|
691
|
+
},
|
692
|
+
|
693
|
+
|
694
|
+
show: function(modalOptions) {
|
695
|
+
this.log("showing");
|
696
|
+
if (this._firstShow) {
|
697
|
+
this.setCard(0);
|
698
|
+
this._firstShow = false;
|
699
|
+
}
|
700
|
+
if (this.args.showCancel) {
|
701
|
+
this.cancelButton.show();
|
702
|
+
} else {
|
703
|
+
this.cancelButton.hide();
|
704
|
+
}
|
705
|
+
if (this.args.showClose) { this.closeButton.show(); }
|
706
|
+
this.modal.modal('show');
|
707
|
+
|
708
|
+
return this;
|
709
|
+
},
|
710
|
+
|
711
|
+
on: function(name, fn) {
|
712
|
+
this.log("adding listener to event " + name);
|
713
|
+
this._events[name] = fn;
|
714
|
+
return this;
|
715
|
+
},
|
716
|
+
|
717
|
+
trigger: function() {
|
718
|
+
var name = arguments[0];
|
719
|
+
var args = Array.prototype.slice.call(arguments);
|
720
|
+
args.shift();
|
721
|
+
args.unshift(this);
|
722
|
+
|
723
|
+
this.log("firing event " + name);
|
724
|
+
var handler = this._events[name];
|
725
|
+
if (handler === undefined && this.wizard !== undefined) {
|
726
|
+
handler = this.wizard._events[name];
|
727
|
+
}
|
728
|
+
var ret = null;
|
729
|
+
|
730
|
+
if (typeof(handler) == "function") {
|
731
|
+
this.log("found event handler, calling " + name);
|
732
|
+
try {
|
733
|
+
ret = handler.apply(this, args);
|
734
|
+
}
|
735
|
+
catch (e) {
|
736
|
+
this.log("event handler " + name + " had an exception");
|
737
|
+
}
|
738
|
+
}
|
739
|
+
else {
|
740
|
+
this.log("couldn't find an event handler for " + name);
|
741
|
+
}
|
742
|
+
return ret;
|
743
|
+
},
|
744
|
+
|
745
|
+
|
746
|
+
reset: function() {
|
747
|
+
this.log("resetting");
|
748
|
+
|
749
|
+
this.updateProgressBar(0);
|
750
|
+
this.hideSubmitCards();
|
751
|
+
|
752
|
+
this.setCard(0);
|
753
|
+
this.lockCards();
|
754
|
+
|
755
|
+
this.enableNextButton();
|
756
|
+
this.showButtons();
|
757
|
+
|
758
|
+
this.hidePopovers();
|
759
|
+
|
760
|
+
this.trigger("reset");
|
761
|
+
return this;
|
762
|
+
},
|
763
|
+
|
764
|
+
/*
|
765
|
+
* this handles switching to the next card or previous card, taking
|
766
|
+
* care to skip over disabled cards
|
767
|
+
*/
|
768
|
+
_abstractIncrementStep: function(direction, getNext) {
|
769
|
+
var current = this.getActiveCard();
|
770
|
+
var next;
|
771
|
+
|
772
|
+
if (current) {
|
773
|
+
/*
|
774
|
+
* loop until we find a card that isn't disabled
|
775
|
+
*/
|
776
|
+
this.log("searching for valid next card");
|
777
|
+
while (true) {
|
778
|
+
next = getNext(current);
|
779
|
+
if (next) {
|
780
|
+
this.log("looking at card", next.index);
|
781
|
+
if (next.isDisabled()) {
|
782
|
+
this.log("card " + next.index + " is disabled/locked, continuing");
|
783
|
+
current = next;
|
784
|
+
continue;
|
785
|
+
}
|
786
|
+
else {
|
787
|
+
return this.setCard(current.index+direction);
|
788
|
+
}
|
789
|
+
}
|
790
|
+
else {
|
791
|
+
this.log("next card is not defined, breaking");
|
792
|
+
break;
|
793
|
+
}
|
794
|
+
}
|
795
|
+
}
|
796
|
+
else {
|
797
|
+
this.log("current card is undefined");
|
798
|
+
}
|
799
|
+
},
|
800
|
+
|
801
|
+
|
802
|
+
incrementCard: function() {
|
803
|
+
this.log("incrementing card");
|
804
|
+
var card = this._abstractIncrementStep(1, function(current){return current.next;});
|
805
|
+
this.trigger("incrementCard");
|
806
|
+
return card;
|
807
|
+
},
|
808
|
+
|
809
|
+
decrementCard: function() {
|
810
|
+
this.log("decrementing card");
|
811
|
+
var card = this._abstractIncrementStep(-1, function(current){return current.prev;});
|
812
|
+
this.trigger("decrementCard");
|
813
|
+
return card;
|
814
|
+
},
|
815
|
+
|
816
|
+
setCard: function(i) {
|
817
|
+
this.log("setting card to " + i);
|
818
|
+
this.hideSubmitCards();
|
819
|
+
var currentCard = this.getActiveCard();
|
820
|
+
|
821
|
+
if (this._submitting) {
|
822
|
+
this.log("we're submitting the wizard already, can't change cards");
|
823
|
+
return currentCard;
|
824
|
+
}
|
825
|
+
|
826
|
+
var newCard = this._cards[i];
|
827
|
+
if (newCard) {
|
828
|
+
if (newCard.isDisabled()) {
|
829
|
+
this.log("new card is currently disabled, returning");
|
830
|
+
return currentCard;
|
831
|
+
}
|
832
|
+
|
833
|
+
if (currentCard) {
|
834
|
+
|
835
|
+
/*
|
836
|
+
* here, we're only validating if we're going forward,
|
837
|
+
* not if we're going backwards in a step
|
838
|
+
*/
|
839
|
+
if (i > currentCard.index) {
|
840
|
+
var cardToValidate = currentCard;
|
841
|
+
var ok = false;
|
842
|
+
|
843
|
+
/*
|
844
|
+
* we need to loop over every card between our current
|
845
|
+
* card and the card that we clicked, and re-validate
|
846
|
+
* them. if there's an error, we need to select the
|
847
|
+
* first card to have an error
|
848
|
+
*/
|
849
|
+
while (cardToValidate.index != newCard.index) {
|
850
|
+
/*
|
851
|
+
* unless we're validating the card that we're
|
852
|
+
* leaving, we need to select the card, so that
|
853
|
+
* any validators that trigger errorPopovers can
|
854
|
+
* display correctly
|
855
|
+
*/
|
856
|
+
if (cardToValidate.index != currentCard.index) {
|
857
|
+
cardToValidate.prev.deselect();
|
858
|
+
cardToValidate.prev.markVisited();
|
859
|
+
cardToValidate.select();
|
860
|
+
}
|
861
|
+
ok = cardToValidate.validate();
|
862
|
+
if (!ok) {
|
863
|
+
return cardToValidate;
|
864
|
+
}
|
865
|
+
cardToValidate = cardToValidate.next;
|
866
|
+
}
|
867
|
+
|
868
|
+
cardToValidate.prev.deselect();
|
869
|
+
cardToValidate.prev.markVisited();
|
870
|
+
}
|
871
|
+
|
872
|
+
currentCard.deselect();
|
873
|
+
currentCard.markVisited();
|
874
|
+
}
|
875
|
+
|
876
|
+
newCard.select();
|
877
|
+
|
878
|
+
if (this.args.progressBarCurrent) {
|
879
|
+
this.percentComplete = i * 100.0 / this._cards.length;
|
880
|
+
this.updateProgressBar(this.percentComplete);
|
881
|
+
}
|
882
|
+
else {
|
883
|
+
var lastPercent = this.percentComplete;
|
884
|
+
this.percentComplete = i * 100.0 / this._cards.length;
|
885
|
+
this.percentComplete = Math.max(lastPercent, this.percentComplete);
|
886
|
+
this.updateProgressBar(this.percentComplete);
|
887
|
+
}
|
888
|
+
|
889
|
+
return newCard;
|
890
|
+
}
|
891
|
+
else {
|
892
|
+
this.log("couldn't find card " + i);
|
893
|
+
}
|
894
|
+
},
|
895
|
+
|
896
|
+
updateProgressBar: function(percent) {
|
897
|
+
this.log("updating progress to " + percent + "%");
|
898
|
+
this.progress.css({width: percent + "%"});
|
899
|
+
this.percentComplete = percent;
|
900
|
+
|
901
|
+
this.trigger("progressBar", percent);
|
902
|
+
|
903
|
+
if (percent == 100) {
|
904
|
+
this.log("progress is 100, animating progress bar");
|
905
|
+
this.progressContainer.find('.progress').addClass("active");
|
906
|
+
}
|
907
|
+
else if (percent == 0) {
|
908
|
+
this.log("progress is 0, disabling animation");
|
909
|
+
this.progressContainer.find('.progress').removeClass("active");
|
910
|
+
}
|
911
|
+
},
|
912
|
+
|
913
|
+
getNextCard: function() {
|
914
|
+
var currentCard = this.getActiveCard();
|
915
|
+
if (currentCard) return currentCard.next;
|
916
|
+
},
|
917
|
+
|
918
|
+
lockCards: function() {
|
919
|
+
this.log("locking nav cards");
|
920
|
+
this.eachCard(function(i,card){card.unmarkVisited();});
|
921
|
+
return this;
|
922
|
+
},
|
923
|
+
|
924
|
+
disableCards: function() {
|
925
|
+
this.log("disabling all nav cards");
|
926
|
+
this.eachCard(function(i,card){card.disable();});
|
927
|
+
return this;
|
928
|
+
},
|
929
|
+
|
930
|
+
enableCards: function() {
|
931
|
+
this.log("enabling all nav cards");
|
932
|
+
this.eachCard(function(i,card){card.enable();});
|
933
|
+
return this;
|
934
|
+
},
|
935
|
+
|
936
|
+
hideCards: function() {
|
937
|
+
this.log("hiding cards");
|
938
|
+
this.eachCard(function(i,card){card.deselect();});
|
939
|
+
this.hideSubmitCards();
|
940
|
+
return this;
|
941
|
+
},
|
942
|
+
|
943
|
+
hideButtons: function() {
|
944
|
+
this.log("hiding buttons");
|
945
|
+
this.cancelButton.hide();
|
946
|
+
this.closeButton.hide();
|
947
|
+
this.nextButton.hide();
|
948
|
+
this.backButton.hide();
|
949
|
+
return this;
|
950
|
+
},
|
951
|
+
|
952
|
+
showButtons: function() {
|
953
|
+
this.log("showing buttons");
|
954
|
+
if (this.args.showCancel) {
|
955
|
+
this.cancelButton.show();
|
956
|
+
} else {
|
957
|
+
this.cancelButton.hide();
|
958
|
+
}
|
959
|
+
if (this.args.showClose) { this.closeButton.show(); };
|
960
|
+
this.nextButton.show();
|
961
|
+
this.backButton.show();
|
962
|
+
return this;
|
963
|
+
},
|
964
|
+
|
965
|
+
getCard: function(el) {
|
966
|
+
var cardDOMEl = $(el).parents(".wizard-card").first()[0];
|
967
|
+
if (cardDOMEl) {
|
968
|
+
var foundCard = null;
|
969
|
+
this.eachCard(function(i, card) {
|
970
|
+
if (cardDOMEl == card.el[0]) {
|
971
|
+
foundCard = card;
|
972
|
+
return false;
|
973
|
+
}
|
974
|
+
return true;
|
975
|
+
});
|
976
|
+
return foundCard;
|
977
|
+
}
|
978
|
+
else {
|
979
|
+
return null;
|
980
|
+
}
|
981
|
+
},
|
982
|
+
|
983
|
+
_createCards: function() {
|
984
|
+
var prev = null;
|
985
|
+
var next = null;
|
986
|
+
var currentCard = null;
|
987
|
+
var wizard = this;
|
988
|
+
var self = this;
|
989
|
+
|
990
|
+
self.log("Creating Cards");
|
991
|
+
|
992
|
+
var cards = this.modal.find(".wizard-cards .wizard-card");
|
993
|
+
$.each(cards, function(i, card) {
|
994
|
+
card = $(card);
|
995
|
+
|
996
|
+
prev = currentCard;
|
997
|
+
currentCard = new WizardCard(wizard, card, i, prev, next);
|
998
|
+
self._cards.push(currentCard);
|
999
|
+
if (currentCard.name) {
|
1000
|
+
self.cards[currentCard.name] = currentCard;
|
1001
|
+
}
|
1002
|
+
if (prev) {prev.next = currentCard;}
|
1003
|
+
|
1004
|
+
self.modal.find(".wizard-steps .wizard-nav-list").append(currentCard.nav);
|
1005
|
+
});
|
1006
|
+
},
|
1007
|
+
|
1008
|
+
showSubmitCard: function(name) {
|
1009
|
+
this.log("showing "+name+" submit card");
|
1010
|
+
|
1011
|
+
var card = this.el.find(".wizard-"+name);
|
1012
|
+
if (card.length) {
|
1013
|
+
this.hideCards();
|
1014
|
+
this.el.find(".wizard-"+name).show();
|
1015
|
+
}
|
1016
|
+
else {
|
1017
|
+
this.log("couldn't find submit card "+name);
|
1018
|
+
}
|
1019
|
+
},
|
1020
|
+
|
1021
|
+
hideSubmitCard: function(name) {
|
1022
|
+
this.log("hiding "+name+" submit card");
|
1023
|
+
this.el.find(".wizard-"+name).hide();
|
1024
|
+
},
|
1025
|
+
|
1026
|
+
hideSubmitCards: function() {
|
1027
|
+
var wizard = this;
|
1028
|
+
$.each(["success", "error", "failure", "loading"], function(i, name) {
|
1029
|
+
wizard.hideSubmitCard(name);
|
1030
|
+
});
|
1031
|
+
},
|
1032
|
+
|
1033
|
+
enableNextButton: function() {
|
1034
|
+
this.log("enabling next button");
|
1035
|
+
this.nextButton.removeAttr("disabled");
|
1036
|
+
return this;
|
1037
|
+
},
|
1038
|
+
|
1039
|
+
disableNextButton: function() {
|
1040
|
+
this.log("disabling next button");
|
1041
|
+
this.nextButton.attr("disabled", "disabled");
|
1042
|
+
return this;
|
1043
|
+
},
|
1044
|
+
|
1045
|
+
serializeArray: function() {
|
1046
|
+
var form = this.form.serializeArray();
|
1047
|
+
this.form.find('input[disabled][data-serialize="1"]').each(function() {
|
1048
|
+
formObj = {
|
1049
|
+
name: $(this).attr('name'),
|
1050
|
+
value: $(this).val()
|
1051
|
+
};
|
1052
|
+
|
1053
|
+
form.push(formObj);
|
1054
|
+
});
|
1055
|
+
|
1056
|
+
return form;
|
1057
|
+
},
|
1058
|
+
|
1059
|
+
serialize: function() {
|
1060
|
+
var form = this.form.serialize();
|
1061
|
+
this.form.find('input[disabled][data-serialize="1"]').each(function() {
|
1062
|
+
form = form + '&' + $(this).attr('name') + '=' + $(this).val();
|
1063
|
+
});
|
1064
|
+
|
1065
|
+
return form;
|
1066
|
+
},
|
1067
|
+
|
1068
|
+
find: function(selector) {
|
1069
|
+
return this.modal.find(selector);
|
1070
|
+
},
|
1071
|
+
|
1072
|
+
|
1073
|
+
/*
|
1074
|
+
* the next 3 functions are to be called by the custom submit event
|
1075
|
+
* handler. the idea is that after you make an ajax call to submit
|
1076
|
+
* your wizard data (or whatever it is you want to do at the end of
|
1077
|
+
* the wizard), you call one of these 3 handlers to display a specific
|
1078
|
+
* card for either success, failure, or error
|
1079
|
+
*/
|
1080
|
+
submitSuccess: function() {
|
1081
|
+
this.log("submit success");
|
1082
|
+
this._submitting = false;
|
1083
|
+
this.showSubmitCard("success");
|
1084
|
+
this.trigger("submitSuccess");
|
1085
|
+
},
|
1086
|
+
|
1087
|
+
submitFailure: function() {
|
1088
|
+
this.log("submit failure");
|
1089
|
+
this._submitting = false;
|
1090
|
+
this.showSubmitCard("failure");
|
1091
|
+
this.trigger("submitFailure");
|
1092
|
+
},
|
1093
|
+
|
1094
|
+
submitError: function() {
|
1095
|
+
this.log("submit error");
|
1096
|
+
this._submitting = false;
|
1097
|
+
this.showSubmitCard("error");
|
1098
|
+
this.trigger("submitError");
|
1099
|
+
},
|
1100
|
+
|
1101
|
+
|
1102
|
+
_submit: function() {
|
1103
|
+
this.log("submitting wizard");
|
1104
|
+
this._submitting = true;
|
1105
|
+
|
1106
|
+
this.lockCards();
|
1107
|
+
this.cancelButton.hide();
|
1108
|
+
this.closeButton.hide();
|
1109
|
+
this.backButton.hide();
|
1110
|
+
|
1111
|
+
this.showSubmitCard("loading");
|
1112
|
+
this.updateProgressBar(100);
|
1113
|
+
|
1114
|
+
this.changeNextButton(this.args.buttons.submittingText, false);
|
1115
|
+
this.disableNextButton();
|
1116
|
+
|
1117
|
+
var ret = this.trigger("submit");
|
1118
|
+
this.trigger("loading");
|
1119
|
+
},
|
1120
|
+
|
1121
|
+
_onNextClick: function() {
|
1122
|
+
this.log("handling 'next' button click");
|
1123
|
+
var currentCard = this.getActiveCard();
|
1124
|
+
if (this._readyToSubmit && currentCard.validate()) {
|
1125
|
+
this._submit();
|
1126
|
+
}
|
1127
|
+
else {
|
1128
|
+
currentCard = this.incrementCard();
|
1129
|
+
}
|
1130
|
+
},
|
1131
|
+
|
1132
|
+
_onBackClick: function() {
|
1133
|
+
this.log("handling 'back' button click");
|
1134
|
+
var currentCard = this.decrementCard();
|
1135
|
+
},
|
1136
|
+
|
1137
|
+
_handleNextClick: function(event) {
|
1138
|
+
var wizard = event.data;
|
1139
|
+
wizard._onNextClick.call(wizard);
|
1140
|
+
},
|
1141
|
+
|
1142
|
+
_handleBackClick: function(event) {
|
1143
|
+
var wizard = event.data;
|
1144
|
+
wizard._onBackClick.call(wizard);
|
1145
|
+
},
|
1146
|
+
|
1147
|
+
|
1148
|
+
/*
|
1149
|
+
* this function is attached by default to the wizard's "submit" event.
|
1150
|
+
* if you choose to implement your own custom submit logic, you should
|
1151
|
+
* copy how this function works
|
1152
|
+
*/
|
1153
|
+
_defaultSubmit: function(wizard) {
|
1154
|
+
$.ajax({
|
1155
|
+
type: "POST",
|
1156
|
+
url: wizard.args.submitUrl,
|
1157
|
+
data: wizard.serialize(),
|
1158
|
+
dataType: "json"
|
1159
|
+
}).done(function(response) {
|
1160
|
+
wizard.submitSuccess();
|
1161
|
+
wizard.hideButtons();
|
1162
|
+
wizard.updateProgressBar(0);
|
1163
|
+
}).fail(function() {
|
1164
|
+
wizard.submitFailure();
|
1165
|
+
wizard.hideButtons();
|
1166
|
+
});
|
1167
|
+
}
|
1168
|
+
};
|
1169
|
+
|
1170
|
+
|
1171
|
+
}(window.jQuery));
|