1
/* Copyright (c) 2009, Canonical Ltd. All rights reserved. */
3
YUI.add('lazr.overlay', function(Y) {
6
* LAZR-specific overlay implementation.
13
BOUNDING_BOX = 'boundingBox',
14
CONTENT_BOX = 'contentBox',
19
* An Overlay subclass which draws a rounded-corner, drop-shadow
20
* border around the content.
21
* TODO PrettyOverlay implements an in-page modal dialog box.
22
* The background is blocked using a layer, in order to prevent
23
* clicks on other elements on the page. Pressing Escape or clicking
24
* the close button at the top-right corner dismisses the box.
26
* Note: Classes extending PrettyOverlay must have a corresponding
27
* yui3-widget-name-hidden CSS class in order to allow hiding.
28
* Also, all extending classes must explicitly calls PrettyOverlay's
29
* bindUI method in order to get the event handlers attached.
31
* @class PrettyOverlay
34
var PrettyOverlay = function() {
35
// Check whether the callsite has set a zIndex... if not, set it
36
// to 1000, as the YUI.overlay default is zero.
37
if (arguments[0] && arguments[0].zIndex === undefined){
38
arguments[0].zIndex = 1000;
40
PrettyOverlay.superclass.constructor.apply(this, arguments);
41
Y.after(this._bindUIPrettyOverlay, this, BINDUI);
45
PrettyOverlay.NAME = 'pretty-overlay';
47
PrettyOverlay.ATTRS = {
49
* The value, in percentage, of the progress bar.
60
* Should the progress bar be shown?
61
* (note that if set to true, headerContent must be supplied).
63
* @attribute progressbar
72
* Title for this step, displayed below the progressbar.
73
* (you must have a progressbar to have a steptitle)
75
* @attribute steptitle
84
Y.extend(PrettyOverlay, Y.Overlay, {
86
* The div element shown behind the modal dialog.
89
* @property _blocking_div
95
* The key press handler..
98
* @property _doc_kp_handler
101
_doc_kp_handler: null,
104
* The div displaying the prograss bar.
107
* @property _green_bar
113
* Create the DOM elements needed by the widget.
116
* @method initializer
118
initializer: function() {
119
// The 20% width style is here to force
120
// legacy browsers to include an accessible
122
this._green_bar = Y.Node.create([
123
'<div class="steps">',
124
'<div class="step-on" style="width:20%;">',
125
'</div></div>'].join(""));
127
this._blocking_div = Y.Node.create(
128
'<div class="blocking-div"></div>');
130
this.after("renderedChange", function() {
131
var bounding_box = this.get(BOUNDING_BOX);
132
var content_box = this.get(CONTENT_BOX);
133
var content_box_container = bounding_box.one(
134
".content_box_container");
135
if (content_box_container) {
136
content_box_container.appendChild(content_box);
138
this._setupCloseFacilities();
141
this.after('visibleChange', function(e) {
142
this._setupCloseFacilities();
146
* Fires when the user presses the 'Cancel' button.
149
* @preventable _defCancel
151
this.publish(CANCEL, {
152
defaultFn: this._defaultCancel
157
* Event handler to update HTML when steptitle is set.
160
* @param e {Event.Facade}
161
* @method _afterSteptitleChange
163
_afterSteptitleChange: function(e) {
164
// It's only possible to have a step title
165
// if you also have a progress bar.
166
var progress_bar = this.get(BOUNDING_BOX).one(".steps");
170
var h2 = progress_bar.one("h2");
172
h2 = Y.Node.create("<h2></h2>");
173
progress_bar.appendChild(h2);
174
progress_bar.addClass("contains-steptitle");
176
// We can't just set innerHTML here because Firefox gets it wrong
177
// so remove all existing nodes and add the steptitle as a textnode
178
while (h2.hasChildNodes()) {
179
h2.removeChild(h2.get("firstChild"));
181
h2.appendChild(document.createTextNode(this.get("steptitle")));
185
* Handle the progress change event, adjusting the display
186
* of the progress bar.
189
* @param e {Event.Facade}
190
* @method _afterProgressChange
192
_afterProgressChange: function(e) {
193
var width = parseInt(this.get("progress"), 10);
200
if (this.get("progressbar") &&
201
this.get(CONTENT_BOX).one(".steps")) {
202
// The prograss bar is only being created if
203
// you both ask for it and supply header content
204
var progress_steps = this.get(CONTENT_BOX).one(".step-on");
205
progress_steps.setStyle("width", width + "%");
210
* Hook the events for the escape key press and include
214
* @method _setupCloseFacilities
216
_setupCloseFacilities: function() {
218
var visible = this.get('visible');
220
Y.one('body').appendChild(this._blocking_div);
221
// Handle Escape (code 27) on keydown.
222
this._doc_kp_handler = Y.on('key', function() {
224
}, document, 'down:27');
226
this._removeBlockingDiv();
231
* Remove the HTML for the blocking DIV.
233
* @method _removeBlockingDiv
235
_removeBlockingDiv: function() {
236
if (this._blocking_div) {
237
var blocking_div = Y.one(this._blocking_div);
239
var parent = blocking_div.get('parentNode');
241
parent.removeChild(this._blocking_div);
248
* Destroy the widget (remove its HTML from the page).
252
destructor: function() {
253
this._removeBlockingDiv();
254
if (this._doc_kp_handler) {
255
this._doc_kp_handler.detach();
262
* This method is invoked after bindUI is invoked for the Widget class
263
* using YUI's aop infrastructure.
266
* @method _bindUIPrettyOverlay
269
_bindUIPrettyOverlay: function() {
271
var close_button = this.get(BOUNDING_BOX).one('.close a');
272
close_button.on('click', function(e) {
276
this._blocking_div.on('click', function(e) {
280
// Ensure that when the overlay is clicked, it doesn't stay
281
// focused (with the ugly gray border).
282
var bounding_box = this.get(BOUNDING_BOX);
283
bounding_box.on('click', function(e) {
286
this.after('steptitleChange', this._afterSteptitleChange);
287
this.after('progressChange', this._afterProgressChange);
291
* Event handler for cancel event; hides the widget.
294
* @method _defaultCancel
296
_defaultCancel: function(e) {
298
this._doc_kp_handler.detach();
302
* Overrides the method from WidgetStdMod which creates the separate
303
* sections in the contentBox to also add the progressbar widget
304
* after headerContent.
307
* @method _insertStdModSection
309
_insertStdModSection: function(content_box, section, section_node) {
310
PrettyOverlay.superclass._insertStdModSection.apply(
312
if (section === Y.WidgetStdMod.HEADER &&
313
this.get("progressbar"))
315
var nxt = section_node.next();
317
content_box.insertBefore(this._green_bar, nxt);
319
content_box.appendChild(this._green_bar);
322
this._afterProgressChange();
323
if (this.get('steptitle')) {
324
this._afterSteptitleChange();
330
* The HTML for drawing the border.
332
* The border is implemented using a table. The content area is
333
* marked with the `content_box_container` class so that the widget
334
* can find it and insert the content box into it.
336
* @property BOUNDING_TEMPLATE
338
PrettyOverlay.prototype.BOUNDING_TEMPLATE = [
339
'<div class="pretty-overlay-window">',
340
'<div class="content_box_container" id="yui3-pretty-overlay-modal">',
341
'<div class="close">',
342
'<a href="#" title="Close" class="close-button"></a>',
349
Y.lazr.PrettyOverlay = PrettyOverlay;
351
}, "0.1", {"skinnable": true, "requires": ["oop", "overlay", "event", "widget", "widget-stack", "widget-position"]});