1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 
 25 /**
 26  * Creates a new wizard dialog.
 27  * @constructor
 28  * @class
 29  * This class represents a reusable wizard dialog.
 30  * 
 31  * @param {DwtControl}	parent		the parent control
 32  * @param {string}	className		the CSS class name
 33  * @param {string}	title	the dialog title
 34  * @param {number}	w 		the content area width
 35  * @param {number}	h 		the content area height
 36  * 
 37  * @extends		DwtDialog
 38  * 
 39  * @private
 40  */
 41 DwtWizardDialog = function(parent, className, title, w, h) {
 42 	if (arguments.length == 0) { return; }
 43 	className = className || "DwtDialog";
 44 	
 45 	var nextButton = new DwtDialog_ButtonDescriptor(DwtWizardDialog.NEXT_BUTTON, AjxMsg._next, DwtDialog.ALIGN_RIGHT, new AjxCallback(this, this.goNext));
 46 	var prevButton = new DwtDialog_ButtonDescriptor(DwtWizardDialog.PREV_BUTTON, AjxMsg._prev, DwtDialog.ALIGN_RIGHT, new AjxCallback(this, this.goPrev));
 47 	var finishButton = new DwtDialog_ButtonDescriptor(DwtWizardDialog.FINISH_BUTTON, AjxMsg._finish, DwtDialog.ALIGN_RIGHT, new AjxCallback(this, this.finishWizard));
 48 	DwtDialog.call(this, {parent:parent, className:className, standardButtons:[DwtDialog.CANCEL_BUTTON],
 49 						  extraButtons:[prevButton, nextButton, finishButton]});
 50 
 51 	if (!w) {
 52 		this._contentW = "80ex";
 53 	} else {
 54 		this._contentW = w;
 55 	}
 56 	
 57 	if(!h) {
 58 		this._contentH = "100ex";
 59 	} else {
 60 		this._contentH = h;
 61 	}
 62 	
 63 	this._pages = new Array(); 
 64 	this._pageIx = 1;
 65 	this._currentPage = 1;
 66 	this._progressDiv = document.createElement("div");
 67 	this._progressDiv.style.position = DwtControl.STATIC_STYLE;
 68 	this._pageDiv = document.createElement("div");
 69 	this._pageDiv.className = "DwtWizardDialogPageDiv";
 70 	this._pageDiv.style.width = this._contentW;
 71 	this._pageDiv.style.height = this._contentH;
 72 	this._progressBar = new DwtWizProgressBar(this);
 73 	this._createContentHtml();
 74 	this.setTitle(title);
 75 }
 76 
 77 DwtWizardDialog.prototype = new DwtDialog;
 78 DwtWizardDialog.prototype.constructor = DwtWizardDialog;
 79 
 80 //Z-index contants for the tabbed view contents are based on Dwt z-index constants
 81 DwtWizardDialog.Z_ACTIVE_PAGE = Dwt.Z_VIEW+10;
 82 DwtWizardDialog.Z_HIDDEN_PAGE = Dwt.Z_HIDDEN;
 83 DwtWizardDialog.Z_TAB_PANEL = Dwt.Z_VIEW+20;
 84 DwtWizardDialog.Z_CURTAIN = Dwt.Z_CURTAIN;
 85 
 86 DwtWizardDialog.NEXT_BUTTON = 12;
 87 DwtWizardDialog.PREV_BUTTON = 11;
 88 DwtWizardDialog.FINISH_BUTTON = 13;
 89 
 90 //public methods
 91 DwtWizardDialog.prototype.toString = 
 92 function () {
 93 	return "DwtWizardDialog";
 94 }
 95 
 96 DwtWizardDialog.prototype.popdown = 
 97 function () {
 98 	DwtDialog.prototype.popdown.call(this);
 99 	this._hideAllPages();
100 }
101 
102 /*
103  * Makes the dialog visible, and places it. Everything under the dialog will become veiled
104  * if we are modal.
105  *
106  * @param loc	the desired location
107  *//*
108 DwtWizardDialog.prototype.popup =
109 function(loc) {
110 
111 	var thisZ = this._zIndex;
112 	if (this._mode == DwtDialog.MODAL) {
113 		// place veil under this dialog
114 		var dialogZ = this._shell._veilOverlay.dialogZ;
115 		var currentDialogZ = null;
116 		var veilZ;
117 		if (dialogZ.length)
118 			currentDialogZ = dialogZ[dialogZ.length - 1];
119 		if (currentDialogZ) {
120 			thisZ = currentDialogZ + 2;
121 			veilZ = currentDialogZ + 1;
122 		} else {
123 			thisZ = this._zIndex;
124 			veilZ = Dwt.Z_VEIL;
125 		}
126 		this._shell._veilOverlay.veilZ.push(veilZ);
127 		this._shell._veilOverlay.dialogZ.push(thisZ);
128 		Dwt.setZIndex(this._shell._veilOverlay, veilZ);
129 	}
130 	loc = this._loc = loc || this._loc; // use whichever has a value, local has precedence
131 	var sizeShell = this._shell.getSize();
132 	var sizeThis = this.getSize();
133 	var x, y;
134 	if (loc == null) {
135 		// if no location, go for the middle
136 		x = Math.round((sizeShell.x - sizeThis.x) / 2);
137 		y = Math.round((sizeShell.y - sizeThis.y) / 2);
138 	} else {
139 		x = loc.x;
140 		y = loc.y;
141 	}
142 	// try to stay within shell boundaries
143 	if ((x + sizeThis.x) > sizeShell.x)
144 		x = sizeShell.x - sizeThis.x;
145 	if ((y + sizeThis.y) > sizeShell.y)
146 		y = sizeShell.y - sizeThis.y;
147 	this.setLocation(x, y);
148 	
149 	this.setZIndex(thisZ);
150 }
151 */
152 
153 /*
154 * @param pageKey - key to the page to be shown. 
155 * pageKey is the value returned from @link DwtWizardDialog.prototype.addPage method
156 * This method is called by 
157 *	@link DwtWizardPage.prototype.switchToNextPage 
158 *	and 
159 *	@link DwtWizardPage.prototype.switchToPrevPage
160 */
161 DwtWizardDialog.prototype.goPage = 
162 function(pageKey) {
163 	if(this._pages && this._pages[pageKey]) {
164 		this._currentPage = pageKey;
165 		this._showPage(pageKey);
166 		this._progressBar.showStep(pageKey);
167 		this._pages[pageKey].setActive();
168 	}
169 }
170 
171 DwtWizardDialog.prototype.goNext = 
172 function() {
173 	var nextPageKey = this._currentPage + 1;
174 	if(this._pages && this._pages[this._currentPage]) {
175 		this._pages[this._currentPage].switchToNextPage(nextPageKey);
176 	}
177 
178 }
179 
180 DwtWizardDialog.prototype.goPrev = 
181 function() {
182 	var prevPageKey = this._currentPage - 1;
183 	if(this._pages && this._pages[this._currentPage]) {
184 		this._pages[this._currentPage].switchToPrevPage(prevPageKey);
185 	}
186 }
187 
188 DwtWizardDialog.prototype.finishWizard = 
189 function() {
190 	this.popdown();	
191 }
192 
193 /**
194  * 
195  * @param pageKey  the key for the page, returned from {@link #addPage}
196  * @return {DwtPropertyPage}	the view tab
197  * 
198  * @private
199  */
200 DwtWizardDialog.prototype.getPage =
201 function (pageKey) {
202 	if(this._pages && this._pages[pageKey])
203 		return this._pages[pageKey];
204 	else
205 		return null;
206 }
207 
208 /**
209  * @param {DwtPropertyPage}		wizPage 	the wizard page
210  * @return - the key for the added page. This key can be used to retrieve the tab using {@link #getPage}
211  * 
212  * @private
213 */
214 DwtWizardDialog.prototype.addPage =
215 function (wizPage, stepTitle) {
216 	var pageKey = this._pageIx++;	
217 	this._pages[pageKey] = wizPage;
218 	//add a step to the progress bar
219 /*	if(stepTitle == null)
220  		stepTitle = pageKey;*/
221 	this._progressBar.addStep(pageKey, stepTitle);
222 	//add the page 
223 	this._pageDiv.appendChild(this._pages[pageKey].getHtmlElement());
224 	
225 	if(pageKey==1) //show the first tab 
226 		this._pages[pageKey].setZIndex(DwtWizardDialog.Z_ACTIVE_PAGE); 
227 	else {
228 		//hide all the other tabs
229 		this._pages[pageKey].setZIndex(DwtWizardDialog.Z_HIDDEN_PAGE); 
230 		Dwt.setVisible(this._pages[pageKey].getHtmlElement(), false);
231 	}
232 	return pageKey;
233 }
234 
235 //private and protected methods
236 
237 /**
238  * method _createHtm
239  * 
240  * @private
241  */
242 DwtWizardDialog.prototype._createContentHtml =
243 function () {
244 
245 	this._table = document.createElement("table");
246 	this._table.border = 0;
247 	this._table.width = this._contentW;
248 	this._table.cellPadding = this._table.cellSpacing = 0;
249 
250 	this._table.backgroundColor = DwtCssStyle.getProperty(this.parent.getHtmlElement(), "background-color");
251 	
252 	var row1; //_progressBar
253 	var col1;
254 	row1 = this._table.insertRow(0);
255 	row1.align = "left";
256 	row1.vAlign = "middle";
257 	
258 	col1 = row1.insertCell(row1.cells.length);
259 	col1.align = "left";
260 	col1.vAlign = "middle";
261 	col1.noWrap = true;	
262 	col1.width="100%";
263 	col1.className="DwtTabTable";
264 	col1.appendChild(this._progressBar.getHtmlElement());
265 
266 	var rowSep;//separator
267 	var colSep;
268 	rowSep = this._table.insertRow(1);
269 	rowSep.align = "center";
270 	rowSep.vAlign = "middle";
271 	
272 	colSep = rowSep.insertCell(rowSep.cells.length);
273 	colSep.align = "left";
274 	colSep.vAlign = "middle";
275 	colSep.noWrap = true;	
276 	colSep.style.width = this._contentW;
277 	var sepDiv = document.createElement("div");
278 	sepDiv.className = "horizSep";
279 	sepDiv.style.width = this._contentW;
280 	sepDiv.style.height = "5px";
281 	colSep.appendChild(sepDiv);
282 	
283 	var row2; //page
284 	var col2;
285 	row2 = this._table.insertRow(2);
286 	row2.align = "left";
287 	row2.vAlign = "middle";
288 	
289 	col2 = row2.insertCell(row2.cells.length);
290 	col2.align = "left";
291 	col2.vAlign = "middle";
292 	col2.noWrap = true;	
293 	col2.width = this._contentW;
294 	col2.appendChild(this._pageDiv);
295 
296 	this._getContentDiv().appendChild(this._table);
297 }
298 
299 /**
300  * Override addChild method. We need internal control over layout of the children in this class.
301  * Child elements are added to this control in the _createHTML method.
302  * @param child
303  * 
304  * @private
305  */
306 DwtWizardDialog.prototype.addChild =
307 function(child) {
308 	this._children.add(child);
309 }
310 
311 DwtWizardDialog.prototype._showPage = 
312 function(pageKey) {
313 	if(this._pages && this._pages[pageKey]) {
314 		//hide all the tabs
315 		this._hideAllPages();
316 		//make this tab visible
317 		this._pages[pageKey].showMe();
318 		//this._pages[pageKey].setZIndex(DwtWizardDialog.Z_ACTIVE_PAGE);
319 		Dwt.setVisible(this._pages[pageKey].getHtmlElement(), true);
320 	}
321 }
322 
323 DwtWizardDialog.prototype._hideAllPages = 
324 function() {
325 	if(this._pages && this._pages.length) {
326 		for(var curPageKey in this._pages) {
327 			if(this._pages[curPageKey]) {
328 				this._pages[curPageKey].hideMe();
329 				//this._pages[curPageKey].setZIndex(DwtWizardDialog.Z_HIDDEN_PAGE);
330 				Dwt.setVisible(this._pages[curPageKey].getHtmlElement(), false);
331 			}	
332 		}
333 	}
334 }
335 
336 
337 /**
338  * @class
339  * @constructor
340  * DwtWizardpage abstract class for a page in a wizard dialog
341  * tab pages are responsible for creating there own HTML and populating/collecting 
342  * data to/from any form fields that they display
343  * 
344  * @private
345  */
346 DwtWizardPage = function(parent, className) {
347 	if (arguments.length == 0) return;
348 	var clsName = className || "DwtDialog";
349 	DwtPropertyPage.call(this, parent, className, DwtControl.ABSOLUTE_STYLE);
350 }
351 
352 DwtWizardPage.prototype = new DwtTabViewPage;
353 DwtWizardPage.prototype.constructor = DwtWizardPage;
354 
355 DwtWizardPage.prototype.toString = 
356 function() {
357 	return "DwtWizardPage";
358 }
359 
360 /**
361 * setActive is called when the page is activated. 
362 **/
363 DwtWizardPage.prototype.setActive =
364 function () {
365 
366 }
367 
368 /**
369 * @param pageKey - key for the next page
370 * Checks if it is ok to leave go to the next page. 
371 * Default implementation does not check anything.
372 **/
373 DwtWizardPage.prototype.switchToNextPage = 
374 function (pageKey) {
375 	this.parent.goPage(pageKey);
376 }
377 
378 /**
379 * @param pageKey - key for the previous page
380 * Checks if it is ok to leave go to the previous page. 
381 * Default implementation does not check anything.
382 **/
383 DwtWizardPage.prototype.switchToPrevPage = 
384 function (pageKey) {
385 	this.parent.goPage(pageKey);
386 }
387 
388 DwtWizardPage.prototype.showMe = 
389 function() {
390 	this.setZIndex(DwtTabView.Z_ACTIVE_TAB);
391 	/*
392 	DBG.println(AjxDebug.DBG3, "DwtWizardPage.prototype.showMe");
393 	DBG.println(AjxDebug.DBG3, "this.parent.getHtmlElement().offsetHeight: " + this.parent.getHtmlElement().offsetHeight);		
394 	DBG.println(AjxDebug.DBG3, "this.parent.getHtmlElement().clientHeight: " + this.parent.getHtmlElement().clientHeight);				
395 	DBG.println(AjxDebug.DBG3, "this.parent.getHtmlElement().offsetWidth: " + this.parent.getHtmlElement().offsetWidth);		
396 	DBG.println(AjxDebug.DBG3, "this.parent.getHtmlElement().clientWidth: " + this.parent.getHtmlElement().clientWidth);				
397 	DBG.println(AjxDebug.DBG3, "this.parent._contentH: " + this.parent._contentH);					
398 	DBG.println(AjxDebug.DBG3, "this.parent._contentW: " + this.parent._contentW);		
399 	*/
400 	this.getHtmlElement().style.height = this.parent._contentH;
401 	this.getHtmlElement().style.width = this.parent._contentW;
402 	
403 }
404 /**
405  * @class DwtWizProgressBar
406  * @constructor
407  * 
408  * @param parent
409  * 
410  * @private
411  */
412 DwtWizProgressBar = function(parent) {
413 	if (arguments.length == 0) return;
414 	DwtComposite.call(this, {parent:parent, className:"DwtWizProgressBar", posStyle:DwtControl.STATIC_STYLE});
415 	this._table = document.createElement("table");
416 	this._table.border = 0;
417 	this._table.cellPadding = 0;
418 	this._table.cellSpacing = 0;
419 	this.getHtmlElement().appendChild(this._table);
420 	this._table.backgroundColor = DwtCssStyle.getProperty(this.parent.getHtmlElement(), "background-color");
421 	this._stepsNumber = 0; //number of steps
422 	this._steps = new Array();
423 	this._lblHeader = new DwtStepLabel(this);
424 	this._lblHeader.setText("Step 0 of 0");
425 	this._lblHeader.setActive(true);
426 }
427 
428 
429 DwtWizProgressBar.prototype = new DwtComposite;
430 DwtWizProgressBar.prototype.constructor = DwtWizProgressBar;
431 
432 DwtWizProgressBar.prototype.toString = 
433 function() {
434 	return "DwtWizProgressBar";
435 }
436 
437 /**
438 * @param stepKey
439 **/
440 DwtWizProgressBar.prototype.showStep = 
441 function(stepKey) {
442 	var szLabelTxt = "Step " + stepKey + " of " + this._stepsNumber;
443 	if(this._steps[stepKey]) {
444 		szLabelTxt = szLabelTxt + ": " + this._steps[stepKey];
445 	}
446 	this._lblHeader.setText(szLabelTxt);
447 }
448 
449 /**
450 * @param stepKey
451 * @param stepNumber
452 **/
453 DwtWizProgressBar.prototype.addStep =
454 function (stepKey, stepTitle) {
455 	this._steps[stepKey] = stepTitle;
456 	return (++this._stepsNumber);
457 }
458 
459 DwtWizProgressBar.prototype.addChild =
460 function(child) {
461 	this._children.add(child);
462 	var row;
463 	var col;
464 	this._table.width = "100%";
465 	row = (this._table.rows.length != 0) ? this._table.rows[0]: this._table.insertRow(0);
466 	row.align = "center";
467 	row.vAlign = "middle";
468 		
469 	col = row.insertCell(row.cells.length);
470 	col.align = "center";
471 	col.vAlign = "middle";
472 	col.noWrap = true;
473 	col.appendChild(child.getHtmlElement());
474 }
475 
476 
477 /**
478  * @class DwtStepLabel
479  * @constructor
480  * 
481  * @param parent
482  * 
483  * @private
484  */
485 DwtStepLabel = function(parent) {
486 	DwtLabel.call(this, {parent:parent, style:DwtLabel.ALIGN_CENTER, className:"DwtStepLabel"});
487 }
488 
489 DwtStepLabel.prototype = new DwtLabel;
490 DwtStepLabel.prototype.constructor = DwtStepLabel;
491 
492 DwtStepLabel.prototype.toString = 
493 function() {
494 	return "DwtStepLabel";
495 }
496 
497 DwtStepLabel.prototype.setActive = 
498 function(isActive) {
499 	if (isActive) {
500  		this._textCell.className="DwtStepLabelActive";
501  	} else {
502 	 	this._textCell.className="DwtStepLabelInactive";
503  	}
504 }
505 
506