]> jfr.im git - irc/quakenet/qwebirc.git/blame - static/js/mocha.js
Merge.
[irc/quakenet/qwebirc.git] / static / js / mocha.js
CommitLineData
cfd8616d
CP
1/*
2
3Script: Core.js
4 MochaUI - A Web Applications User Interface Framework.
5
6Copyright:
7 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
8
9License:
10 MIT-style license.
11
12Contributors:
13 - Scott F. Frederick
14 - Joel Lindau
15
16Note:
17 This documentation is taken directly from the javascript source files. It is built using Natural Docs.
18
19*/
20
21var MochaUI = new Hash({
22 options: new Hash({
23 useEffects: true, // Toggles the majority of window fade and move effects.
24 useLoadingIcon: true // Toggles whether or not the ajax spinners are displayed in window footers.
25
26 }),
27 Windows: {
28 instances: new Hash(),
29 indexLevel: 100, // Used for z-Index
30 windowIDCount: 0, // Used for windows without an ID defined by the user
31 windowsVisible: true // Ctrl-Alt-Q to toggle window visibility
32 },
33 ieSupport: 'excanvas', // Makes it easier to switch between Excanvas and Moocanvas for testing
34 focusingWindow: 'false',
35 /*
36
37 Function: updateContent
38 Replace the content of a window.
39
40 Arguments:
41 windowEl, content, url
42
43 */
44 updateContent: function(windowEl, content, url, element, loadMethod){
45
46 if (!windowEl) return;
47
48 //alert('test');
49
50 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
51 var contentEl = currentInstance.contentEl;
52 var options = currentInstance.options;
53 if (element != null){
54 var contentContainer = element;
55 }
56 else {
57 var contentContainer = currentInstance.contentEl;
58 }
59 var canvasIconEl = currentInstance.canvasIconEl;
60
61 // Remove old content.
62 if (contentContainer == contentEl){
63 currentInstance.contentEl.empty();
64 }
65
66 //alert(loadMethod);
67 var loadMethod = loadMethod ? loadMethod : currentInstance.options.loadMethod;
68
69 // Load new content.
70 switch(loadMethod) {
71 case 'xhr':
72 new Request.HTML({
73 url: url,
74 update: contentContainer,
75 evalScripts: options.evalScripts,
76 evalResponse: options.evalResponse,
77 onRequest: function(){
78 if (contentContainer == contentEl){
79 currentInstance.showLoadingIcon(canvasIconEl);
80 }
81 }.bind(this),
82 onFailure: function(){
83 if (contentContainer == contentEl){
84 contentContainer.set('html','<p><strong>Error Loading XMLHttpRequest</strong></p>');
85 currentInstance.hideLoadingIcon(canvasIconEl);
86 }
87 }.bind(this),
88 onSuccess: function() {
89 if (contentContainer == contentEl){
90 currentInstance.hideLoadingIcon(canvasIconEl);
91 currentInstance.fireEvent('onContentLoaded', windowEl);
92 }
93 }.bind(this)
94 }).get();
95 break;
96 case 'iframe': // May be able to streamline this if the iframe already exists.
97 if ( options.contentURL == '' || contentContainer != contentEl) {
98 break;
99 }
100 currentInstance.iframeEl = new Element('iframe', {
101 'id': currentInstance.options.id + '_iframe',
102 'name': currentInstance.options.id + '_iframe',
103 'class': 'mochaIframe',
104 'src': url,
105 'marginwidth': 0,
106 'marginheight': 0,
107 'frameBorder': 0,
108 'scrolling': 'auto',
109 'styles': {
110 'height': currentInstance.contentWrapperEl.offsetHeight
111 }
112 }).injectInside(contentEl);
113
114 // Add onload event to iframe so we can stop the loading icon and run onContentLoaded()
115 currentInstance.iframeEl.addEvent('load', function(e) {
116 currentInstance.hideLoadingIcon.delay(150, currentInstance, canvasIconEl);
117 currentInstance.fireEvent('onContentLoaded', windowEl);
118 }.bind(this));
119 currentInstance.showLoadingIcon(canvasIconEl);
120 break;
121 case 'html':
122 default:
123 // Need to test injecting elements as content.
124 var elementTypes = new Array('element', 'textnode', 'whitespace', 'collection');
125 if (elementTypes.contains($type(content))) {
126 content.inject(contentContainer);
127 } else {
128 contentContainer.set('html', content);
129 }
130 currentInstance.fireEvent('onContentLoaded', windowEl);
131 break;
132 }
133
134 },
135 collapseToggle: function(windowEl){
136 var instances = MochaUI.Windows.instances;
137 var currentInstance = instances.get(windowEl.id);
138 var handles = currentInstance.windowEl.getElements('.handle');
139 if (currentInstance.isCollapsed == false) {
140 currentInstance.isCollapsed = true;
141 handles.setStyle('display', 'none');
142 if ( currentInstance.iframe ) {
143 currentInstance.iframeEl.setStyle('visibility', 'hidden');
144 }
145 currentInstance.contentBorderEl.setStyles({
146 visibility: 'hidden',
147 position: 'absolute',
148 top: -10000,
149 left: -10000
150 });
151 if(currentInstance.toolbarWrapperEl){
152 currentInstance.toolbarWrapperEl.setStyles({
153 visibility: 'hidden',
154 position: 'absolute',
155 top: -10000,
156 left: -10000
157 });
158 }
159 currentInstance.drawWindowCollapsed(windowEl);
160 }
161 else {
162 currentInstance.isCollapsed = false;
163 currentInstance.drawWindow(windowEl);
164 currentInstance.contentBorderEl.setStyles({
165 visibility: 'visible',
166 position: null,
167 top: null,
168 left: null
169 });
170 if(currentInstance.toolbarWrapperEl){
171 currentInstance.toolbarWrapperEl.setStyles({
172 visibility: 'visible',
173 position: null,
174 top: null,
175 left: null
176 });
177 }
178 if ( currentInstance.iframe ) {
179 currentInstance.iframeEl.setStyle('visibility', 'visible');
180 }
181 handles.setStyle('display', 'block');
182 }
183 },
184 /*
185
186 Function: closeWindow
187 Closes a window.
188
189 Syntax:
190 (start code)
191 MochaUI.closeWindow();
192 (end)
193
194 Arguments:
195 windowEl - the ID of the window to be closed
196
197 Returns:
198 true - the window was closed
199 false - the window was not closed
200
201 */
202 closeWindow: function(windowEl){
203 // Does window exist and is not already in process of closing ?
204
205 var instances = MochaUI.Windows.instances;
206 var currentInstance = instances.get(windowEl.id);
207 if (windowEl != $(windowEl) || currentInstance.isClosing) return;
208
209 currentInstance.isClosing = true;
210 currentInstance.fireEvent('onClose', windowEl);
211
212 if (MochaUI.options.useEffects == false){
213 if (currentInstance.options.type == 'modal'){
214 $('modalOverlay').setStyle('opacity', 0);
215 if (Browser.Engine.trident4) {
216 $('modalFix').setStyle('display', 'block');
217 }
218 }
219 this.closingJobs(windowEl);
220 return true;
221 }
222 else {
223 // Redraws IE windows without shadows since IE messes up canvas alpha when you change element opacity
224 if (Browser.Engine.trident) currentInstance.drawWindow(windowEl, false);
225 if (currentInstance.options.type == 'modal'){
226 MochaUI.Modal.modalOverlayCloseMorph.start({
227 'opacity': 0
228 });
229 }
230 var closeMorph = new Fx.Morph(windowEl, {
231 duration: 180,
232 onComplete: function(){
233 MochaUI.closingJobs(windowEl);
234 return true;
235 }.bind(this)
236 });
237 closeMorph.start({
238 'opacity': .4
239 });
240 }
241
242 if (currentInstance.check) currentInstance.check.destroy();
243 },
244 closingJobs: function(windowEl){
245
246 windowEl.destroy();
247 var instances = MochaUI.Windows.instances;
248 var currentInstance = instances.get(windowEl.id);
249 currentInstance.fireEvent('onCloseComplete');
250
251 if (this.options.type != 'modal' && this.options.type != 'notification') {
252 var newFocus = this.getWindowWithHighestZindex();
253 this.focusWindow(newFocus);
254 }
255
256 instances.erase(currentInstance.options.id);
257 if (this.loadingWorkspace == true) {
258 this.windowUnload();
259 }
260
261 if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {
262 currentButton = $(currentInstance.options.id + '_dockTab');
263 MochaUI.Dock.dockSortables.removeItems(currentButton).destroy();
264 // Need to resize everything in case the dock becomes smaller when a tab is removed
265 MochaUI.Desktop.setDesktopSize();
266 }
267 },
268 /*
269
270 Function: closeAll
271 Close all open windows.
272
273 */
274 closeAll: function() {
275 $$('div.mocha').each(function(windowEl){
276 this.closeWindow(windowEl);
277 }.bind(this));
278 },
279 /*
280
281 Function: toggleWindowVisibility
282 Toggle window visibility with Ctrl-Alt-Q.
283
284 */
285 toggleWindowVisibility: function(){
286 MochaUI.Windows.instances.each(function(instance){
287 if (instance.options.type == 'modal' || instance.isMinimized == true) return;
288 var id = $(instance.options.id);
289 if (id.getStyle('visibility') == 'visible'){
290 if (instance.iframe){
291 instance.iframeEl.setStyle('visibility', 'hidden');
292 }
293 if (instance.toolbarEl){
294 instance.toolbarWrapperEl.setStyle('visibility', 'hidden');
295 }
296 instance.contentBorderEl.setStyle('visibility', 'hidden');
297 id.setStyle('visibility', 'hidden');
298 MochaUI.Windows.windowsVisible = false;
299 }
300 else {
301 id.setStyle('visibility', 'visible');
302 instance.contentBorderEl.setStyle('visibility', 'visible');
303 if (instance.iframe){
304 instance.iframeEl.setStyle('visibility', 'visible');
305 }
306 if (instance.toolbarEl){
307 instance.toolbarWrapperEl.setStyle('visibility', 'visible');
308 }
309 MochaUI.Windows.windowsVisible = true;
310 }
311 }.bind(this));
312
313 },
314 focusWindow: function(windowEl, fireEvent){
315
316 // This is used with blurAll
317 MochaUI.focusingWindow = 'true';
318 var windowClicked = function(){
319 MochaUI.focusingWindow = 'false';
320 }
321 windowClicked.delay(170, this);
322
323 // Only focus when needed
324 if (windowEl != $(windowEl) || windowEl.hasClass('isFocused')) return;
325
326 var instances = MochaUI.Windows.instances;
327 var currentInstance = instances.get(windowEl.id);
328
329 MochaUI.Windows.indexLevel++;
330 windowEl.setStyle('zIndex', MochaUI.Windows.indexLevel);
331
332 // Fire onBlur for the window that lost focus.
333 instances.each(function(instance){
334 if (instance.windowEl.hasClass('isFocused')){
335 instance.fireEvent('onBlur', instance.windowEl);
336 }
337 instance.windowEl.removeClass('isFocused');
338 });
339
340 if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {
341 MochaUI.Dock.makeActiveTab();
342 }
343 currentInstance.windowEl.addClass('isFocused');
344
345 if (fireEvent != false){
346 currentInstance.fireEvent('onFocus', windowEl);
347 }
348
349 },
350 getWindowWithHighestZindex: function(){
351 this.highestZindex = 0;
352 $$('div.mocha').each(function(element){
353 this.zIndex = element.getStyle('zIndex');
354 if (this.zIndex >= this.highestZindex) {
355 this.highestZindex = this.zIndex;
356 }
357 }.bind(this));
358 $$('div.mocha').each(function(element){
359 if (element.getStyle('zIndex') == this.highestZindex) {
360 this.windowWithHighestZindex = element;
361 }
362 }.bind(this));
363 return this.windowWithHighestZindex;
364 },
365 blurAll: function(){
366 //alert(MochaUI.focusingWindow);
367 if (MochaUI.focusingWindow == 'false') {
368 $$('.mocha').each(function(windowEl){
369 var instances = MochaUI.Windows.instances;
370 var currentInstance = instances.get(windowEl.id);
371 windowEl.removeClass('isFocused');
372 });
373 $$('div.dockTab').removeClass('activeDockTab');
374 }
375 },
376 roundedRect: function(ctx, x, y, width, height, radius, rgb, a){
377 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
378 ctx.beginPath();
379 ctx.moveTo(x, y + radius);
380 ctx.lineTo(x, y + height - radius);
381 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
382 ctx.lineTo(x + width - radius, y + height);
383 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
384 ctx.lineTo(x + width, y + radius);
385 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
386 ctx.lineTo(x + radius, y);
387 ctx.quadraticCurveTo(x, y, x, y + radius);
388 ctx.fill();
389 },
390 triangle: function(ctx, x, y, width, height, rgb, a){
391 ctx.beginPath();
392 ctx.moveTo(x + width, y);
393 ctx.lineTo(x, y + height);
394 ctx.lineTo(x + width, y + height);
395 ctx.closePath();
396 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
397 ctx.fill();
398 },
399 circle: function(ctx, x, y, diameter, rgb, a){
400 ctx.beginPath();
401 ctx.moveTo(x, y);
402 ctx.arc(x, y, diameter, 0, Math.PI*2, true);
403 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
404 ctx.fill();
405 },
406 /*
407
408 Function: centerWindow
409 Center a window in it's container. If windowEl is undefined it will center the window that has focus.
410
411 */
412 centerWindow: function(windowEl){
413
414 if(!windowEl){
415 MochaUI.Windows.instances.each(function(instance){
416 if (instance.windowEl.hasClass('isFocused')){
417 windowEl = instance.windowEl;
418 }
419 });
420 }
421
422 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
423 var options = currentInstance.options;
424 var dimensions = options.container.getCoordinates();
425 var windowPosTop = (dimensions.height * .5) - ((options.height + currentInstance.headerFooterShadow) * .5);
426 var windowPosLeft = (dimensions.width * .5) - (options.width * .5);
427
428 if (MochaUI.options.useEffects == true){
429 currentInstance.morph.start({
430 'top': windowPosTop,
431 'left': windowPosLeft
432 });
433 }
434 else {
435 windowEl.setStyles({
436 'top': windowPosTop,
437 'left': windowPosLeft
438 });
439 }
440 },
441 /*
442
443 Function: dynamicResize
444 Use with a timer to resize a window as the window's content size changes, such as with an accordian.
445
446 */
447 dynamicResize: function(windowEl){
448 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
449 var contentWrapperEl = currentInstance.contentWrapperEl;
450 var contentEl = currentInstance.contentEl;
451
452 contentWrapperEl.setStyle('height', contentEl.offsetHeight);
453 contentWrapperEl.setStyle('width', contentEl.offsetWidth);
454 currentInstance.drawWindow(windowEl);
455 },
456 /*
457
458 Function: garbageCleanUp
459 Empties all windows of their children, and removes and garbages the windows. It is does not trigger onClose() or onCloseComplete(). This is useful to clear memory before the pageUnload.
460
461 Syntax:
462 (start code)
463 MochaUI.garbageCleanUp();
464 (end)
465
466 */
467 garbageCleanUp: function(){
468 $$('div.mocha').each(function(el){
469 el.destroy();
470 }.bind(this));
471 }
472});
473
474// Toggle window visibility with Ctrl-Alt-Q
475document.addEvent('keydown', function(event){
476 if (event.key == 'q' && event.control && event.alt) {
477 MochaUI.toggleWindowVisibility();
478 }
479});
480
481// Blur all windows if user clicks anywhere else on the page
482document.addEvent('click', function(event){
483 MochaUI.blurAll.delay(50);
484});
485/*
486
487Script: Window.js
488 Build windows.
489
490Copyright:
491 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
492
493License:
494 MIT-style license.
495
496Requires:
497 Core.js
498
499*/
500
501/*
502Class: Window
503 Creates a single MochaUI window.
504
505Syntax:
506 (start code)
507 new MochaUI.Window(options);
508 (end)
509
510Arguments:
511 options
512
513Options:
514 id - The ID of the window. If not defined, it will be set to 'win' + windowIDCount.
515 title - The title of the window.
516 type - ('window', 'modal' or 'notification') Defaults to 'window'.
517 loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html'.
518 contentURL - Used if loadMethod is set to 'xhr' or 'iframe'.
519 evalScripts - (boolean) An xhr loadMethod option. Defaults to true.
520 evalResponse - (boolean) An xhr loadMethod option. Defaults to false.
521 content - (string or element) An html loadMethod option.
522 toolbar - (boolean) Create window toolbar. Defaults to false. This can be used for tabs, media controls, and so forth.
523 toolbarPosition - ('top' or 'bottom') Defaults to top.
524 toolbarHeight - (number)
525 toolbarURL - (url) Defaults to 'pages/lipsum.html'.
526 toolbarContent - (string)
527 container - (element ID) Element the window is injected in. The container defaults to 'desktop'. If no desktop then to document.body. Use 'pageWrapper' if you don't want the windows to overlap the toolbars.
528 restrict - (boolean) Restrict window to container when dragging.
529 shape - ('box' or 'gauge') Shape of window. Defaults to 'box'.
530 collapsible - (boolean) Defaults to true.
531 minimizable - (boolean) Requires MochaUI.Desktop and MochaUI.Dock. Defaults to true if dependenices are met.
532 maximizable - (boolean) Requires MochaUI.Desktop. Defaults to true if dependenices are met.
533 closable - (boolean) Defaults to true.
534 draggable - (boolean) Defaults to false for modals; otherwise true.
535 draggableGrid - (false or number) Distance in pixels for snap-to-grid dragging. Defaults to false.
536 draggableLimit - (false or number) An object with x and y properties used to limit the movement of the Window. Defaults to false.
537 draggableSnap - (boolean) The distance to drag before the Window starts to respond to the drag. Defaults to false.
538 resizable - (boolean) Defaults to false for modals, notifications and gauges; otherwise true.
539 resizeLimit - (object) Minimum and maximum width and height of window when resized.
540 addClass - (string) Add a class to your window to give you more control over styling.
541 width - (number) Width of content area.
542 height - (number) Height of content area.
543 x - (number) If x and y are left undefined the window is centered on the page.
544 y - (number)
545 scrollbars - (boolean)
546 padding - (object)
547 shadowBlur -(number) Width of shadows.
548 headerHeight - (number) Height of window titlebar.
549 footerHeight - (number) Height of window footer.
550 cornerRadius - (number)
551 contentBgColor - (hex) Body background color
552 headerStartColor - ([r,g,b,]) Titlebar gradient's top color
553 headerStopColor - ([r,g,b,]) Titlebar gradient's bottom color
554 bodyBgColor - ([r,g,b,]) Background color of the main canvas shape
555 minimizeBgColor - ([r,g,b,]) Minimize button background color
556 minimizeColor - ([r,g,b,]) Minimize button color
557 maximizeBgColor - ([r,g,b,]) Maximize button background color
558 maximizeColor - ([r,g,b,]) Maximize button color
559 closeBgColor - ([r,g,b,]) Close button background color
560 closeColor - ([r,g,b,]) Close button color
561 resizableColor - ([r,g,b,]) Resizable icon color
562 onBeforeBuild - (function) Fired just before the window is built.
563 onContentLoaded - (function) Fired when content is successfully loaded via XHR or Iframe.
564 onFocus - (function) Fired when the window is focused.
565 onBlur - (function) Fired when window loses focus.
566 onResize - (function) Fired when the window is resized.
567 onMinimize - (function) Fired when the window is minimized.
568 onMaximize - (function) Fired when the window is maximized.
569 onRestore - (function) Fired when a window is restored from minimized or maximized.
570 onClose - (function) Fired just before the window is closed.
571 onCloseComplete - (function) Fired after the window is closed.
572
573Returns:
574 Window object.
575
576Example:
577 Define a window. It is suggested you name the function the same as your window ID + "Window".
578 (start code)
579 var mywindowWindow = function(){
580 new MochaUI.Window({
581 id: 'mywindow',
582 title: 'My Window',
583 loadMethod: 'xhr',
584 contentURL: 'pages/lipsum.html',
585 width: 340,
586 height: 150
587 });
588 }
589 (end)
590
591Example:
592 Create window onDomReady.
593 (start code)
594 window.addEvent('domready', function(){
595 mywindow();
596 });
597 (end)
598
599Example:
600 Add link events to build future windows. It is suggested you give your anchor the same ID as your window + "WindowLink" or + "WindowLinkCheck". Use the latter if it is a link in the menu toolbar.
601
602 If you wish to add links in windows that open other windows remember to add events to those links when the windows are created.
603
604 (start code)
605 // Javascript:
606 if ($('mywindowLink')){
607 $('mywindowLink').addEvent('click', function(e) {
608 new Event(e).stop();
609 mywindow();
610 });
611 }
612
613 // HTML:
614 <a id="mywindowLink" href="pages/lipsum.html">My Window</a>
615 (end)
616
617
618 Loading Content with an XMLHttpRequest(xhr):
619 For content to load via xhr all the files must be online and in the same domain. If you need to load content from another domain or wish to have it work offline, load the content in an iframe instead of using the xhr option.
620
621 Iframes:
622 If you use the iframe loadMethod your iframe will automatically be resized when the window it is in is resized. If you want this same functionality when using one of the other load options simply add class="mochaIframe" to those iframes and they will be resized for you as well.
623
624*/
625
626// Having these options outside of the Class allows us to add, change, and remove
627// individual options without rewriting all of them.
628
629MochaUI.Windows.windowOptions = {
630 id: null,
631 title: 'New Window',
632 icon: false,
633 type: 'window',
634
635 loadMethod: 'html',
636 contentURL: 'pages/lipsum.html',
637
638 closeAfter: false, // Close the window after a certain period of time in milliseconds. This is particularly useful for notifications.
639
640 // xhr options
641 evalScripts: true,
642 evalResponse: false,
643
644 // html options
645 content: 'Window content',
646
647 // Toolbar
648 toolbar: false,
649 toolbarPosition: 'top',
650 toolbarHeight: 29,
651 toolbarURL: 'pages/lipsum.html',
652 toolbarContent: '',
653
654 // Container options
655 container: null,
656 restrict: true,
657 shape: 'box',
658
659 // Window Controls
660 collapsible: true,
661 minimizable: true,
662 maximizable: true,
663 closable: true,
664
665 // Draggable
666 draggable: null,
667 draggableGrid: false,
668 draggableLimit: false,
669 draggableSnap: false,
670
671 // Resizable
672 resizable: null,
673 resizeLimit: {'x': [250, 2500], 'y': [125, 2000]},
674
675 // Style options:
676 addClass: '',
677 width: 300,
678 height: 125,
679 x: null,
680 y: null,
681 scrollbars: true,
682 padding: { top: 10, right: 12, bottom: 10, left: 12 },
683 shadowBlur: 5,
684 shadowOffset: {'x': 0, 'y': 1}, // Should be positive and not be greater than the ShadowBlur.
685 controlsOffset: {'right': 6, 'top': 6}, // Change this if you want to reposition the window controls.
686 useCanvasControls: true, // Set this to false if you wish to use images for the buttons.
687
688 // Color options:
689 headerHeight: 25,
690 footerHeight: 25,
691 cornerRadius: 10,
692 contentBgColor: '#fff',
693 headerStartColor: [250, 250, 250],
694 headerStopColor: [229, 229, 229],
695 bodyBgColor: [229, 229, 229],
696 minimizeBgColor: [255, 255, 255],
697 minimizeColor: [0, 0, 0],
698 maximizeBgColor: [255, 255, 255],
699 maximizeColor: [0, 0, 0],
700 closeBgColor: [255, 255, 255],
701 closeColor: [0, 0, 0],
702 resizableColor: [254, 254, 254],
703
704 // Events
705 onBeforeBuild: $empty,
706 onContentLoaded: $empty,
707 onFocus: $empty,
708 onBlur: $empty,
709 onResize: $empty,
710 onMinimize: $empty,
711 onMaximize: $empty,
712 onRestore: $empty,
713 onMove: $empty, // NOT YET IMPLEMENTED
714 onClose: $empty,
715 onCloseComplete: $empty
716};
717
718MochaUI.Window = new Class({
719 options: MochaUI.Windows.windowOptions,
720 initialize: function(options){
721 this.setOptions(options);
722
723 // Shorten object chain
724 var options = this.options;
725
726 $extend(this, {
727 accordianTimer: '', // Used with accordian - should go somewhere else maybe?
728 mochaControlsWidth: 0,
729 minimizebuttonX: 0, // Minimize button horizontal position
730 maximizebuttonX: 0, // Maximize button horizontal position
731 closebuttonX: 0, // Close button horizontal position
732 headerFooterShadow: options.headerHeight + options.footerHeight + (options.shadowBlur * 2),
733 oldTop: 0,
734 oldLeft: 0,
735 iframe: options.loadMethod == 'iframe' ? true : false,
736 isMaximized: false,
737 isMinimized: false,
738 isCollapsed: false,
739 timestamp: $time()
740 });
741
742 // May be better to use if type != window
743 if (options.type == 'modal' || options.type == 'notification'){
744 options.container = document.body;
745 options.minimizable = false;
746 }
747 if (!options.container){
748 options.container = MochaUI.Desktop.desktop ? MochaUI.Desktop.desktop : document.body;
749 }
750
751 // Set this.options.resizable to default if it was not defined
752 if (options.resizable == null){
753 if (options.type == 'modal' || options.shape == 'gauge' || options.type == 'notification'){
754 options.resizable = false;
755 }
756 else {
757 options.resizable = true;
758 }
759 }
760
761 // Set this.options.draggable if it was not defined
762 if (options.draggable == null){
763 if (options.type == 'modal' || options.type == 'notification'){
764 options.draggable = false;
765 }
766 else {
767 options.draggable = true;
768 }
769 }
770
771 // Gauges are not maximizable or resizable
772 if (options.shape == 'gauge' || options.type == 'notification'){
773 options.collapsible = false;
774 options.maximizable = false;
775 options.contentBgColor = 'transparent';
776 options.scrollbars = false;
777 options.footerHeight = 0;
778 }
779 if (options.type == 'notification'){
780 options.closable = false;
781 options.headerHeight = 0;
782 }
783
784 // Minimizable, dock is required and window cannot be modal
785 if (MochaUI.Dock){
786 if (MochaUI.Dock.dock && options.type != 'modal'){
787 options.minimizable = options.minimizable;
788 }
789 }
790 else {
791 options.minimizable = false;
792 }
793
794 // Maximizable, desktop is required
795 options.maximizable = MochaUI.Desktop.desktop && options.maximizable && options.type != 'modal';
796
797 // If window has no ID, give it one.
798 if (options.id == null){
799 options.id = 'win' + (++MochaUI.Windows.windowIDCount);
800 }
801 this.windowEl = $(options.id);
802
803 this.newWindow();
804
805 // Return window object
806 return this;
807 },
808 saveValues: function(){
809 var coordinates = this.windowEl.getCoordinates();
810 this.options.x = coordinates.left.toInt();
811 this.options.y = coordinates.top.toInt();
812 },
813 /*
814
815 Internal Function: newWindow
816
817 Arguments:
818 properties
819
820 */
821 newWindow: function(properties){ // options is not doing anything
822
823 // Shorten object chain
824 var instances = MochaUI.Windows.instances;
825 var instanceID = instances.get(this.options.id);
826
827 // Here we check to see if there is already a class instance for this window
828 if (instanceID){
829 var currentInstance = instanceID;
830 }
831
832 // Check if window already exists and is not in progress of closing
833 if ( this.windowEl && !this.isClosing ) {
834 // Restore if minimized
835 if (currentInstance.isMinimized) {
836 MochaUI.Dock.restoreMinimized(this.windowEl);
837 }
838 // Expand and focus if collapsed
839 if (currentInstance.isCollapsed) {
840 MochaUI.collapseToggle(this.windowEl);
841 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);
842 }
843 // Else focus
844 else {
845 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);
846 }
847 return;
848 }
849 else {
850 instances.set(this.options.id, this);
851 }
852
853 this.isClosing = false;
854 this.fireEvent('onBeforeBuild');
855
856 // Create window div
857 MochaUI.Windows.indexLevel++;
858 this.windowEl = new Element('div', {
859 'class': 'mocha',
860 'id': this.options.id,
861 'styles': {
862 'width': this.options.width,
863 'height': this.options.height,
864 'display': 'block',
865 'opacity': 0,
866 'zIndex': MochaUI.Windows.indexLevel
867 }
868 });
869
870 this.windowEl.addClass(this.options.addClass);
871
872 // Fix a mouseover issue with gauges in IE7
873 if ( Browser.Engine.trident && this.options.shape == 'gauge') {
874 this.windowEl.setStyle('background', 'url(../images/spacer.gif)');
875 }
876
877 if ((this.options.type == 'modal' && !Browser.Engine.gecko && !Browser.Engine.trident) || (Browser.Platform.mac && Browser.Engine.gecko)){
878 this.windowEl.setStyle('position', 'fixed');
879 }
880
881 if (this.options.loadMethod == 'iframe') {
882 // Iframes have their own scrollbars and padding.
883 this.options.scrollbars = false;
884 this.options.padding = { top: 0, right: 0, bottom: 0, left: 0 };
885 }
886
887 // Insert sub elements inside windowEl
888 this.insertWindowElements();
889
890 // Set title
891 this.titleEl.set('html',this.options.title);
892
893 // Set scrollbars, always use 'hidden' for iframe windows
894 this.contentWrapperEl.setStyles({
895 'overflow': this.options.scrollbars && !this.options.iframe ? 'auto' : 'hidden',
896 'background': this.options.contentBgColor
897 });
898
899 this.contentEl.setStyles({
900 'padding-top': this.options.padding.top,
901 'padding-bottom': this.options.padding.bottom,
902 'padding-left': this.options.padding.left,
903 'padding-right': this.options.padding.right
904 });
905
906
907 if (this.options.shape == 'gauge'){
908 if (this.options.useCanvasControls){
909 this.canvasControlsEl.setStyle('display', 'none');
910 }
911 else {
912 this.controlsEl.setStyle('display', 'none');
913 }
914 this.windowEl.addEvent('mouseover', function(){
915 this.mouseover = true;
916 var showControls = function(){
917 if (this.mouseover != false){
918 if (this.options.useCanvasControls){
919 this.canvasControlsEl.setStyle('display', 'block');
920 }
921 else {
922 this.controlsEl.setStyle('display', 'block');
923 }
924 this.canvasHeaderEl.setStyle('display', 'block');
925 this.titleEl.setStyle('display', 'block');
926 }
927 };
928 showControls.delay(150, this);
929
930 }.bind(this));
931 this.windowEl.addEvent('mouseleave', function(){
932 this.mouseover = false;
933 if (this.options.useCanvasControls){
934 this.canvasControlsEl.setStyle('display', 'none');
935 }
936 else {
937 this.controlsEl.setStyle('display', 'none');
938 }
939 this.canvasHeaderEl.setStyle('display', 'none');
940 this.titleEl.setStyle('display', 'none');
941 }.bind(this));
942 }
943
944 // Inject window into DOM
945 this.windowEl.injectInside(this.options.container);
946
947 if (this.options.type != 'notification'){
948 this.setMochaControlsWidth();
949 }
950
951 // Add content to window.
952 MochaUI.updateContent(this.windowEl, this.options.content, this.options.contentURL);
953
954 // Add content to window toolbar.
955 if (this.options.toolbar == true){
956 /* SLUG */
957 //MochaUI.updateContent(this.windowEl, this.options.toolbarContent, this.options.toolbarURL, this.toolbarEl, 'xhr');
958 MochaUI.updateContent(this.windowEl, this.options.toolbarContent, this.options.toolbarURL, this.toolbarEl, this.options.toolbarContent==undefined?'xhr':'html');
959 }
960
961 this.drawWindow(this.windowEl);
962
963 // Attach events to the window
964 this.attachDraggable(this.windowEl);
965 this.attachResizable(this.windowEl);
966 this.setupEvents(this.windowEl);
967
968 if (this.options.resizable){
969 this.adjustHandles();
970 }
971
972 // Move window into position. If position not specified by user then center the window on the page.
973 if (this.options.container == document.body || this.options.container == MochaUI.Desktop.desktop){
974 var dimensions = window.getSize();
975 }
976 else {
977 var dimensions = $(this.options.container).getSize();
978 }
979
980 if (!this.options.y) {
981 var y = (dimensions.y * .5) - ((this.options.height + this.headerFooterShadow) * .5);
982 }
983 else {
984 var y = this.options.y - this.options.shadowBlur;
985 }
986
987 if (!this.options.x) {
988 var x = (dimensions.x * .5) - (this.options.width * .5);
989 }
990 else {
991 var x = this.options.x - this.options.shadowBlur;
992 }
993
994 this.windowEl.setStyles({
995 'top': y,
996 'left': x
997 });
998
999 // Create opacityMorph
1000 if (MochaUI.options.useEffects == true){
1001 // IE cannot handle both element opacity and VML alpha at the same time.
1002 if (Browser.Engine.trident){
1003 this.drawWindow(this.windowEl, false);
1004 }
1005 this.opacityMorph = new Fx.Morph(this.windowEl, {
1006 'duration': 500,
1007 onComplete: function(){
1008 if (Browser.Engine.trident){
1009 this.drawWindow(this.windowEl);
1010 }
1011 }.bind(this)
1012 });
1013 }
1014
1015 if (this.options.type == 'modal') {
1016 if (Browser.Engine.trident4){
1017 $('modalFix').setStyle('display', 'block');
1018 }
1019 $('modalOverlay').setStyle('display', 'block');
1020 if (MochaUI.options.useEffects == false){
1021 $('modalOverlay').setStyle('opacity', .55);
1022 this.windowEl.setStyles({
1023 'zIndex': 11000,
1024 'opacity': 1
1025 });
1026 }
1027 else {
1028 MochaUI.Modal.modalOverlayCloseMorph.cancel();
1029 MochaUI.Modal.modalOverlayOpenMorph.start({
1030 'opacity': .55
1031 });
1032 this.windowEl.setStyles({
1033 'zIndex': 11000
1034 });
1035 this.opacityMorph.start({
1036 'opacity': 1
1037 });
1038 }
1039
1040 $$('.dockTab').removeClass('activeDockTab');
1041 $$('.mocha').removeClass('isFocused');
1042 this.windowEl.addClass('isFocused');
1043
1044 }
1045 else if (MochaUI.options.useEffects == false){
1046 this.windowEl.setStyle('opacity', 1);
1047 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);
1048 }
1049 else {
1050 this.opacityMorph.start({
1051 'opacity': 1
1052 });
1053 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);
1054 }
1055
1056 // This is a generic morph that can be reused later by functions like centerWindow()
1057 this.morph = new Fx.Morph(this.windowEl, {
1058 'duration': 200
1059 });
1060
1061 // Add check mark to menu if link exists in menu
1062 // Need to make sure the check mark is not added to links not in menu
1063
1064 if ($(this.windowEl.id + 'LinkCheck')){
1065 this.check = new Element('div', {
1066 'class': 'check',
1067 'id': this.options.id + '_check'
1068 }).injectInside(this.windowEl.id + 'LinkCheck');
1069 }
1070
1071 if (this.options.closeAfter != false){
1072 MochaUI.closeWindow.delay(this.options.closeAfter, this, this.windowEl);
1073 }
1074
1075 if (MochaUI.Dock && $(MochaUI.options.dock) && this.options.type == 'window' ) {
1076 MochaUI.Dock.createDockTab(this.windowEl);
1077 }
1078
1079 },
1080 setupEvents: function(windowEl) {
1081
1082 // Set events
1083 // Note: if a button does not exist, its due to properties passed to newWindow() stating otherwice
1084 if (this.closeButtonEl){
1085 this.closeButtonEl.addEvent('click', function(e) {
1086 new Event(e).stop();
1087 MochaUI.closeWindow(windowEl);
1088 }.bind(this));
1089 }
1090
1091 if (this.options.type == 'window'){
1092 windowEl.addEvent('click', function() {
1093 MochaUI.focusWindow(windowEl);
1094 }.bind(this));
1095 }
1096
1097 if (this.minimizeButtonEl) {
1098 this.minimizeButtonEl.addEvent('click', function(e) {
1099 new Event(e).stop();
1100 MochaUI.Dock.minimizeWindow(windowEl);
1101 }.bind(this));
1102 }
1103
1104 if (this.maximizeButtonEl) {
1105 this.maximizeButtonEl.addEvent('click', function(e) {
1106 new Event(e).stop();
1107 if (this.isMaximized) {
1108 MochaUI.Desktop.restoreWindow(windowEl);
1109 } else {
1110 MochaUI.Desktop.maximizeWindow(windowEl);
1111 }
1112 }.bind(this));
1113 }
1114
1115 if (this.options.collapsible == true){
1116 // Keep titlebar text from being selected on double click in Safari.
1117 this.titleEl.addEvent('selectstart', function(e) {
1118 e = new Event(e).stop();
1119 }.bind(this));
1120 // Keep titlebar text from being selected on double click in Opera.
1121 this.titleBarEl.addEvent('mousedown', function(e) {
1122 e = new Event(e).stop();
1123 }.bind(this));
1124 this.titleBarEl.addEvent('dblclick', function(e) {
1125 e = new Event(e).stop();
1126 MochaUI.collapseToggle(this.windowEl);
1127 }.bind(this));
1128 }
1129
1130 },
1131 /*
1132
1133 Internal Function: attachDraggable()
1134 Make window draggable.
1135
1136 Arguments:
1137 windowEl
1138
1139 */
1140 attachDraggable: function(windowEl){
1141 if (!this.options.draggable) return;
1142 this.windowDrag = new Drag.Move(windowEl, {
1143 handle: this.titleBarEl,
1144 container: this.options.restrict == true ? $(this.options.container) : false,
1145 grid: this.options.draggableGrid,
1146 limit: this.options.draggableLimit,
1147 snap: this.options.draggableSnap,
1148 onStart: function() {
1149 if (this.options.type != 'modal'){
1150 MochaUI.focusWindow(windowEl);
1151 }
1152 if ( this.iframe )
1153 this.iframeEl.setStyle('visibility', 'hidden');
1154 }.bind(this),
1155 onComplete: function() {
1156 if ( this.iframe ){
1157 this.iframeEl.setStyle('visibility', 'visible');
1158 }
1159 // Store new position in options.
1160 this.saveValues();
1161 }.bind(this)
1162 });
1163 },
1164 /*
1165
1166 Internal Function: attachResizable
1167 Make window resizable.
1168
1169 Arguments:
1170 windowEl
1171
1172 */
1173 attachResizable: function(windowEl){
1174 if (!this.options.resizable) return;
1175 this.windowEl.makeResizable({
1176 handle: [this.n, this.ne, this.nw],
1177 limit: {
1178 y: [
1179 function(){
1180 return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[1];
1181 }.bind(this),
1182 function(){
1183 return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[0];
1184 }.bind(this)
1185 ]
1186 },
1187 modifiers: {x: false, y: 'top'},
1188 onBeforeStart: function(){
1189 this.resizeOnBeforeStart();
1190 }.bind(this),
1191 onStart: function(){
1192 this.coords = this.contentWrapperEl.getCoordinates();
1193 this.y2 = this.coords.top.toInt() + this.contentWrapperEl.offsetHeight;
1194 }.bind(this),
1195 onDrag: function(){
1196 this.coords = this.contentWrapperEl.getCoordinates();
1197 this.contentWrapperEl.setStyle('height', this.y2 - this.coords.top.toInt());
1198 this.drawWindow(windowEl);
1199 this.adjustHandles();
1200 }.bind(this),
1201 onComplete: function(){
1202 this.resizeOnComplete();
1203 }.bind(this)
1204 });
1205
1206 this.contentWrapperEl.makeResizable({
1207 handle: [this.e, this.ne],
1208 limit: {
1209 x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ]
1210 },
1211 modifiers: {x: 'width', y: false},
1212 onBeforeStart: function(){
1213 this.resizeOnBeforeStart();
1214 }.bind(this),
1215 onDrag: function(){
1216 this.drawWindow(windowEl);
1217 this.adjustHandles();
1218 }.bind(this),
1219 onComplete: function(){
1220 this.resizeOnComplete();
1221 }.bind(this)
1222 });
1223
1224 this.contentWrapperEl.makeResizable({
1225 container: this.options.restrict == true ? $(this.options.container) : false,
1226 handle: this.se,
1227 limit: {
1228 x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ],
1229 y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]
1230 },
1231 modifiers: {x: 'width', y: 'height'},
1232 onBeforeStart: function(){
1233 this.resizeOnBeforeStart();
1234 }.bind(this),
1235 onDrag: function(){
1236 this.drawWindow(windowEl);
1237 this.adjustHandles();
1238 }.bind(this),
1239 onComplete: function(){
1240 this.resizeOnComplete();
1241 }.bind(this)
1242 });
1243
1244 this.contentWrapperEl.makeResizable({
1245 handle: [this.s, this.sw],
1246 limit: {
1247 y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]
1248 },
1249 modifiers: {x: false, y: 'height'},
1250 onBeforeStart: function(){
1251 this.resizeOnBeforeStart();
1252 }.bind(this),
1253 onDrag: function(){
1254 this.drawWindow(windowEl);
1255 this.adjustHandles();
1256 }.bind(this),
1257 onComplete: function(){
1258 this.resizeOnComplete();
1259 }.bind(this)
1260 });
1261
1262 this.windowEl.makeResizable({
1263 handle: [this.w, this.sw, this.nw],
1264 limit: {
1265 x: [
1266 function(){
1267 return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[1];
1268 }.bind(this),
1269 function(){
1270 return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[0];
1271 }.bind(this)
1272 ]
1273 },
1274 modifiers: {x: 'left', y: false},
1275 onBeforeStart: function(){
1276 this.resizeOnBeforeStart();
1277 }.bind(this),
1278 onStart: function(){
1279 this.coords = this.contentWrapperEl.getCoordinates();
1280 this.x2 = this.coords.left.toInt() + this.contentWrapperEl.offsetWidth;
1281 }.bind(this),
1282 onDrag: function(){
1283 this.coords = this.contentWrapperEl.getCoordinates();
1284 this.contentWrapperEl.setStyle('width', this.x2 - this.coords.left.toInt());
1285 this.drawWindow(windowEl);
1286 this.adjustHandles();
1287 }.bind(this),
1288 onComplete: function(){
1289 this.resizeOnComplete();
1290 }.bind(this)
1291 });
1292
1293 },
1294 resizeOnBeforeStart: function(){
1295 if (this.iframeEl){
1296 this.iframeEl.setStyle('visibility', 'hidden');
1297 }
1298 },
1299 resizeOnComplete: function(){
1300 if (this.iframeEl){
1301 this.iframeEl.setStyle('visibility', 'visible');
1302 }
1303 this.fireEvent('onResize', this.windowEl);
1304 },
1305 adjustHandles: function(){
1306
1307 var shadowBlur = this.options.shadowBlur;
1308 var shadowBlur2x = shadowBlur * 2;
1309 var shadowOffset = this.options.shadowOffset;
1310 var top = shadowBlur - shadowOffset.y - 1;
1311 var right = shadowBlur + shadowOffset.x - 1;
1312 var bottom = shadowBlur + shadowOffset.y - 1;
1313 var left = shadowBlur - shadowOffset.x - 1;
1314
1315 var coordinates = this.windowEl.getCoordinates();
1316 var width = coordinates.width - shadowBlur2x + 2;
1317 var height = coordinates.height - shadowBlur2x + 2;
1318
1319 this.n.setStyles({
1320 'top': top,
1321 'left': left + 10,
1322 'width': width - 20
1323 });
1324 this.e.setStyles({
1325 'top': top + 10,
1326 'right': right,
1327 'height': height - 30
1328 });
1329 this.s.setStyles({
1330 'bottom': bottom,
1331 'left': left + 10,
1332 'width': width - 30
1333 });
1334 this.w.setStyles({
1335 'top': top + 10,
1336 'left': left,
1337 'height': height - 20
1338 });
1339 this.ne.setStyles({
1340 'top': top,
1341 'right': right
1342 });
1343 this.se.setStyles({
1344 'bottom': bottom,
1345 'right': right
1346 });
1347 this.sw.setStyles({
1348 'bottom': bottom,
1349 'left': left
1350 });
1351 this.nw.setStyles({
1352 'top': top,
1353 'left': left
1354 });
1355 },
1356 /*
1357
1358 Internal Function: insertWindowElements
1359
1360 Arguments:
1361 windowEl
1362
1363 */
1364 insertWindowElements: function(){
1365
1366 var options = this.options;
1367 var height = options.height;
1368 var width = options.width;
1369 var id = options.id;
1370
1371 var cache = {};
1372
1373 if (Browser.Engine.trident4){
1374 cache.zIndexFixEl = new Element('iframe', {
1375 'id': id + '_zIndexFix',
1376 'class': 'zIndexFix',
1377 'scrolling': 'no',
1378 'marginWidth': 0,
1379 'marginHeight': 0,
1380 'src': ''
1381 }).inject(this.windowEl);
1382 }
1383
1384 cache.overlayEl = new Element('div', {
1385 'id': id + '_overlay',
1386 'class': 'mochaOverlay'
1387 }).inject(this.windowEl);
1388
1389 cache.titleBarEl = new Element('div', {
1390 'id': id + '_titleBar',
1391 'class': 'mochaTitlebar',
1392 'styles': {
1393 'cursor': options.draggable ? 'move' : 'default'
1394 }
1395 }).inject(cache.overlayEl, 'top');
1396
1397 cache.titleEl = new Element('h3', {
1398 'id': id + '_title',
1399 'class': 'mochaTitle'
1400 }).inject(cache.titleBarEl);
1401
1402 if (options.icon != false){
1403 cache.titleBarEl.setStyles({
1404 'padding-left': 15,
1405 'background': 'url(' + options.icon + ') 5px 5px no-repeat'
1406 })
1407 }
1408
1409 cache.contentBorderEl = new Element('div', {
1410 'id': id + '_contentBorder',
1411 'class': 'mochaContentBorder'
1412 }).inject(cache.overlayEl);
1413
1414 if (options.toolbar){
1415 cache.toolbarWrapperEl = new Element('div', {
1416 'id': id + '_toolbarWrapper',
1417 'class': 'mochaToolbarWrapper'
1418 }).inject(cache.contentBorderEl, options.toolbarPosition == 'bottom' ? 'after' : 'before');
1419
1420 cache.toolbarEl = new Element('div', {
1421 'id': id + '_toolbar',
1422 'class': 'mochaToolbar'
1423 }).inject(cache.toolbarWrapperEl);
1424
1425 }
1426
1427 cache.contentWrapperEl = new Element('div', {
1428 'id': id + '_contentWrapper',
1429 'class': 'mochaContentWrapper',
1430 'styles': {
1431 'width': width + 'px',
1432 'height': height + 'px'
1433 }
1434 }).inject(cache.contentBorderEl);
1435
1436 if (this.options.shape == 'gauge'){
1437 cache.contentBorderEl.setStyle('borderWidth', 0);
1438 }
1439
1440 cache.contentEl = new Element('div', {
1441 'id': id + '_content',
1442 'class': 'mochaContent'
1443 }).inject(cache.contentWrapperEl);
1444
1445 cache.canvasEl = new Element('canvas', {
1446 'id': id + '_canvas',
1447 'class': 'mochaCanvas',
1448 'width': 1,
1449 'height': 1
1450 }).inject(this.windowEl);
1451
1452 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
1453 G_vmlCanvasManager.initElement(cache.canvasEl);
1454 cache.canvasEl = this.windowEl.getElement('.mochaCanvas');
1455 }
1456
1457 cache.controlsEl = new Element('div', {
1458 'id': id + '_controls',
1459 'class': 'mochaControls'
1460 }).inject(cache.overlayEl, 'after');
1461
1462 if (options.useCanvasControls == true){
1463 cache.canvasControlsEl = new Element('canvas', {
1464 'id': id + '_canvasControls',
1465 'class': 'mochaCanvasControls',
1466 'width': 14,
1467 'height': 14
1468 }).inject(this.windowEl);
1469
1470 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
1471 G_vmlCanvasManager.initElement(cache.canvasControlsEl);
1472 cache.canvasControlsEl = this.windowEl.getElement('.mochaCanvasControls');
1473 }
1474 }
1475
1476 if (options.closable){
1477 cache.closeButtonEl = new Element('div', {
1478 'id': id + '_closeButton',
1479 'class': 'mochaCloseButton',
1480 'title': 'Close'
1481 }).inject(cache.controlsEl);
1482 if (options.useCanvasControls == true){
1483 cache.closeButtonEl.setStyle('background', 'none');
1484 }
1485 }
1486
1487 if (options.maximizable){
1488 cache.maximizeButtonEl = new Element('div', {
1489 'id': id + '_maximizeButton',
1490 'class': 'mochaMaximizeButton',
1491 'title': 'Maximize'
1492 }).inject(cache.controlsEl);
1493 if (options.useCanvasControls == true){
1494 cache.maximizeButtonEl.setStyle('background', 'none');
1495 }
1496 }
1497
1498 if (options.minimizable){
1499 cache.minimizeButtonEl = new Element('div', {
1500 'id': id + '_minimizeButton',
1501 'class': 'mochaMinimizeButton',
1502 'title': 'Minimize'
1503 }).inject(cache.controlsEl);
1504 if (options.useCanvasControls == true){
1505 cache.minimizeButtonEl.setStyle('background', 'none');
1506 }
1507 }
1508
1509 if (options.shape != 'gauge' && options.type != 'notification'){
1510 cache.canvasIconEl = new Element('canvas', {
1511 'id': id + '_canvasIcon',
1512 'class': 'mochaLoadingIcon',
1513 'width': 18,
1514 'height': 18
1515 }).inject(this.windowEl, 'bottom');
1516
1517 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
1518 G_vmlCanvasManager.initElement(cache.canvasIconEl);
1519 cache.canvasIconEl = this.windowEl.getElement('.mochaLoadingIcon');
1520 }
1521 }
1522
1523 if (this.options.shape == 'gauge'){
1524 cache.canvasHeaderEl = new Element('canvas', {
1525 'id': id + '_canvasHeader',
1526 'class': 'mochaCanvasHeader',
1527 'width': this.options.width,
1528 'height': 26
1529 }).inject(this.windowEl, 'bottom');
1530
1531 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
1532 G_vmlCanvasManager.initElement(cache.canvasHeaderEl);
1533 cache.canvasHeaderEl = this.windowEl.getElement('.mochaCanvasHeader');
1534 }
1535 }
1536
1537 if ( Browser.Engine.trident ) {
1538 cache.overlayEl.setStyle('zIndex', 2);
1539 }
1540
1541 // For Mac Firefox 2 to help reduce scrollbar bugs in that browser
1542 if (Browser.Platform.mac && Browser.Engine.gecko) {
1543 cache.overlayEl.setStyle('overflow', 'auto');
1544 }
1545
1546 if (options.resizable){
1547 cache.n = new Element('div', {
1548 'id': id + '_resizeHandle_n',
1549 'class': 'handle',
1550 'styles': {
1551 'top': 0,
1552 'left': 10,
1553 'cursor': 'n-resize'
1554 }
1555 }).inject(cache.overlayEl, 'after');
1556
1557 cache.ne = new Element('div', {
1558 'id': id + '_resizeHandle_ne',
1559 'class': 'handle corner',
1560 'styles': {
1561 'top': 0,
1562 'right': 0,
1563 'cursor': 'ne-resize'
1564 }
1565 }).inject(cache.overlayEl, 'after');
1566
1567 cache.e = new Element('div', {
1568 'id': id + '_resizeHandle_e',
1569 'class': 'handle',
1570 'styles': {
1571 'top': 10,
1572 'right': 0,
1573 'cursor': 'e-resize'
1574 }
1575 }).inject(cache.overlayEl, 'after');
1576
1577 cache.se = new Element('div', {
1578 'id': id + '_resizeHandle_se',
1579 'class': 'handle cornerSE',
1580 'styles': {
1581 'bottom': 0,
1582 'right': 0,
1583 'cursor': 'se-resize'
1584 }
1585 }).inject(cache.overlayEl, 'after');
1586
1587 cache.s = new Element('div', {
1588 'id': id + '_resizeHandle_s',
1589 'class': 'handle',
1590 'styles': {
1591 'bottom': 0,
1592 'left': 10,
1593 'cursor': 's-resize'
1594 }
1595 }).inject(cache.overlayEl, 'after');
1596
1597 cache.sw = new Element('div', {
1598 'id': id + '_resizeHandle_sw',
1599 'class': 'handle corner',
1600 'styles': {
1601 'bottom': 0,
1602 'left': 0,
1603 'cursor': 'sw-resize'
1604 }
1605 }).inject(cache.overlayEl, 'after');
1606
1607 cache.w = new Element('div', {
1608 'id': id + '_resizeHandle_w',
1609 'class': 'handle',
1610 'styles': {
1611 'top': 10,
1612 'left': 0,
1613 'cursor': 'w-resize'
1614 }
1615 }).inject(cache.overlayEl, 'after');
1616
1617 cache.nw = new Element('div', {
1618 'id': id + '_resizeHandle_nw',
1619 'class': 'handle corner',
1620 'styles': {
1621 'top': 0,
1622 'left': 0,
1623 'cursor': 'nw-resize'
1624 }
1625 }).inject(cache.overlayEl, 'after');
1626 }
1627 $extend(this, cache);
1628
1629 },
1630 /*
1631
1632 Internal function: drawWindow
1633 This is where we create the canvas GUI
1634
1635 Arguments:
1636 windowEl: the $(window)
1637 shadows: (boolean) false will draw a window without shadows
1638
1639 */
1640 drawWindow: function(windowEl, shadows) {
1641
1642 if (this.isCollapsed){
1643 this.drawWindowCollapsed(windowEl, shadows);
1644 return;
1645 }
1646
1647 var options = this.options;
1648 var shadowBlur = options.shadowBlur;
1649 var shadowBlur2x = shadowBlur * 2;
1650 var shadowOffset = this.options.shadowOffset;
1651
1652 /*
1653 var borderHeight = 0;
1654 var styleDimensions = this.contentBorderEl.getStyles('margin-top', 'margin-bottom', 'border-top', 'border-bottom');
1655 for(var style in styleDimensions){
1656 borderHeight += styleDimensions[style].toInt();
1657 }
1658
1659 var borderWidth = 0;
1660 var styleDimensions = this.contentBorderEl.getStyles('margin-left', 'margin-right', 'border-left', 'border-right');
1661 for(var style in styleDimensions){
1662 borderWidth += styleDimensions[style].toInt();
1663 }
1664 */
1665
1666 this.overlayEl.setStyles({
1667 'width': this.contentWrapperEl.offsetWidth
1668 });
1669
1670 // Resize iframe when window is resized
1671 if (this.iframe) {
1672 this.iframeEl.setStyles({
1673 'height': this.contentWrapperEl.offsetHeight
1674 });
1675 }
1676
1677 var borderHeight = this.contentBorderEl.getStyle('border-top').toInt() + this.contentBorderEl.getStyle('border-bottom').toInt();
1678 var toolbarHeight = this.toolbarWrapperEl ? this.toolbarWrapperEl.getStyle('height').toInt() + this.toolbarWrapperEl.getStyle('border-top').toInt() : 0;
1679
1680 this.headerFooterShadow = options.headerHeight + options.footerHeight + shadowBlur2x;
1681 var height = this.contentWrapperEl.getStyle('height').toInt() + this.headerFooterShadow + toolbarHeight + borderHeight;
1682 var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;
1683 this.windowEl.setStyles({
1684 'height': height,
1685 'width': width
1686 });
1687
1688 this.overlayEl.setStyles({
1689 'height': height,
1690 'top': shadowBlur - shadowOffset.y,
1691 'left': shadowBlur - shadowOffset.x
1692 });
1693
1694 // Opera requires the canvas height and width be set this way when resizing:
1695 this.canvasEl.height = height;
1696 this.canvasEl.width = width;
1697
1698 // Part of the fix for IE6 select z-index bug and FF on Mac scrollbar z-index bug
1699 if (Browser.Engine.trident4){
1700 this.zIndexFixEl.setStyles({
1701 'width': width,
1702 'height': height
1703 })
1704 }
1705
1706 this.titleBarEl.setStyles({
1707 'width': width - shadowBlur2x,
1708 'height': options.headerHeight
1709 });
1710
1711 // Make sure loading icon is placed correctly.
1712 if (options.shape != 'gauge' && options.type != 'notification'){
1713 this.canvasIconEl.setStyles({
1714 'left': shadowBlur - shadowOffset.x + 3,
1715 'bottom': shadowBlur + shadowOffset.y + 4
1716 });
1717 }
1718
1719 // Draw Window
1720 var ctx = this.canvasEl.getContext('2d');
1721 ctx.clearRect(0, 0, width, height);
1722
1723 switch(options.shape) {
1724 case 'box':
1725 this.drawBox(ctx, width, height, shadowBlur, shadowOffset, shadows);
1726 break;
1727 case 'gauge':
1728 this.drawGauge(ctx, width, height, shadowBlur, shadowOffset, shadows);
1729 break;
1730 }
1731
1732 if (options.type != 'notification' && options.useCanvasControls == true){
1733 this.drawControls(width, height, shadows);
1734 }
1735
1736 if (options.resizable){
1737 MochaUI.triangle(
1738 ctx,
1739 width - (shadowBlur + shadowOffset.x + 17),
1740 height - (shadowBlur + shadowOffset.y + 18),
1741 11,
1742 11,
1743 options.resizableColor,
1744 1.0
1745 );
1746 }
1747
1748 // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7
1749 if (Browser.Engine.trident){
1750 MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);
1751 }
1752
1753 },
1754 drawWindowCollapsed: function(windowEl, shadows) {
1755
1756 var options = this.options;
1757 var shadowBlur = options.shadowBlur;
1758 var shadowBlur2x = shadowBlur * 2;
1759 var shadowOffset = options.shadowOffset;
1760
1761 var headerShadow = options.headerHeight + shadowBlur2x + 2;
1762 var height = headerShadow;
1763 var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;
1764 this.windowEl.setStyle('height', height);
1765
1766 this.overlayEl.setStyles({
1767 'height': height,
1768 'top': shadowBlur - shadowOffset.y,
1769 'left': shadowBlur - shadowOffset.x
1770 });
1771
1772 // Opera height and width must be set like this, when resizing:
1773 this.canvasEl.height = height;
1774 this.canvasEl.width = width;
1775
1776 // Part of the fix for IE6 select z-index bug and FF on Mac scrollbar z-index bug
1777 if (Browser.Engine.trident4){
1778 this.zIndexFixEl.setStyles({
1779 'width': width,
1780 'height': height
1781 });
1782 }
1783
1784 // Set width
1785 this.windowEl.setStyle('width', width);
1786 this.overlayEl.setStyle('width', width);
1787 this.titleBarEl.setStyles({
1788 'width': width - shadowBlur2x,
1789 'height': options.headerHeight
1790 });
1791
1792 // Draw Window
1793 var ctx = this.canvasEl.getContext('2d');
1794 ctx.clearRect(0, 0, width, height);
1795
1796 this.drawBoxCollapsed(ctx, width, height, shadowBlur, shadowOffset, shadows);
1797 if (options.useCanvasControls == true){
1798 this.drawControls(width, height, shadows);
1799 }
1800
1801 // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7
1802 if ( Browser.Engine.trident ){
1803 MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);
1804 }
1805
1806 },
1807 drawControls : function(width, height, shadows){
1808 var options = this.options;
1809 var shadowBlur = options.shadowBlur;
1810 var shadowOffset = options.shadowOffset;
1811 var controlsOffset = options.controlsOffset;
1812
1813 // Make sure controls are placed correctly.
1814 this.controlsEl.setStyles({
1815 'right': shadowBlur + shadowOffset.x + controlsOffset.right,
1816 'top': shadowBlur - shadowOffset.y + controlsOffset.top
1817 });
1818
1819 this.canvasControlsEl.setStyles({
1820 'right': shadowBlur + shadowOffset.x + controlsOffset.right,
1821 'top': shadowBlur - shadowOffset.y + controlsOffset.top
1822 });
1823
1824 // Calculate X position for controlbuttons
1825 //var mochaControlsWidth = 52;
1826 this.closebuttonX = options.closable ? this.mochaControlsWidth - 7 : this.mochaControlsWidth + 12;
1827 this.maximizebuttonX = this.closebuttonX - (options.maximizable ? 19 : 0);
1828 this.minimizebuttonX = this.maximizebuttonX - (options.minimizable ? 19 : 0);
1829
1830 var ctx2 = this.canvasControlsEl.getContext('2d');
1831 ctx2.clearRect(0, 0, 100, 100);
1832
1833 if (this.options.closable){
1834 this.closebutton(
1835 ctx2,
1836 this.closebuttonX,
1837 7,
1838 options.closeBgColor,
1839 1.0,
1840 options.closeColor,
1841 1.0
1842 );
1843 }
1844 if (this.options.maximizable){
1845 this.maximizebutton(
1846 ctx2,
1847 this.maximizebuttonX,
1848 7,
1849 options.maximizeBgColor,
1850 1.0,
1851 options.maximizeColor,
1852 1.0
1853 );
1854 }
1855 if (this.options.minimizable){
1856 this.minimizebutton(
1857 ctx2,
1858 this.minimizebuttonX,
1859 7,
1860 options.minimizeBgColor,
1861 1.0,
1862 options.minimizeColor,
1863 1.0
1864 );
1865 }
1866
1867 },
1868 drawBox: function(ctx, width, height, shadowBlur, shadowOffset, shadows){
1869
1870 var shadowBlur2x = shadowBlur * 2;
1871 var cornerRadius = this.options.cornerRadius;
1872
1873 // This is the drop shadow. It is created onion style.
1874 if ( shadows != false ) {
1875 for (var x = 0; x <= shadowBlur; x++){
1876 MochaUI.roundedRect(
1877 ctx,
1878 shadowOffset.x + x,
1879 shadowOffset.y + x,
1880 width - (x * 2) - shadowOffset.x,
1881 height - (x * 2) - shadowOffset.y,
1882 cornerRadius + (shadowBlur - x),
1883 [0, 0, 0],
1884 x == shadowBlur ? .29 : .065 + (x * .01)
1885 );
1886 }
1887 }
1888 // Window body.
1889 this.bodyRoundedRect(
1890 ctx, // context
1891 shadowBlur - shadowOffset.x, // x
1892 shadowBlur - shadowOffset.y, // y
1893 width - shadowBlur2x, // width
1894 height - shadowBlur2x, // height
1895 cornerRadius, // corner radius
1896 this.options.bodyBgColor // Footer color
1897 );
1898
1899 if (this.options.type != 'notification'){
1900 // Window header.
1901 this.topRoundedRect(
1902 ctx, // context
1903 shadowBlur - shadowOffset.x, // x
1904 shadowBlur - shadowOffset.y, // y
1905 width - shadowBlur2x, // width
1906 this.options.headerHeight, // height
1907 cornerRadius, // corner radius
1908 this.options.headerStartColor, // Header gradient's top color
1909 this.options.headerStopColor // Header gradient's bottom color
1910 );
1911 }
1912 },
1913 drawBoxCollapsed: function(ctx, width, height, shadowBlur, shadowOffset, shadows){
1914
1915 var options = this.options;
1916 var shadowBlur2x = shadowBlur * 2;
1917 var cornerRadius = options.cornerRadius;
1918
1919 // This is the drop shadow. It is created onion style.
1920 if ( shadows != false ) {
1921 for (var x = 0; x <= shadowBlur; x++){
1922 MochaUI.roundedRect(
1923 ctx,
1924 shadowOffset.x + x,
1925 shadowOffset.y + x,
1926 width - (x * 2) - shadowOffset.x,
1927 height - (x * 2) - shadowOffset.y,
1928 cornerRadius + (shadowBlur - x),
1929 [0, 0, 0],
1930 x == shadowBlur ? .3 : .06 + (x * .01)
1931 );
1932 }
1933 }
1934
1935 // Window header
1936 this.topRoundedRect2(
1937 ctx, // context
1938 shadowBlur - shadowOffset.x, // x
1939 shadowBlur - shadowOffset.y, // y
1940 width - shadowBlur2x, // width
1941 options.headerHeight + 2, // height
1942 cornerRadius, // corner radius
1943 options.headerStartColor, // Header gradient's top color
1944 options.headerStopColor // Header gradient's bottom color
1945 );
1946
1947 },
1948 drawGauge: function(ctx, width, height, shadowBlur, shadowOffset, shadows){
1949 var options = this.options;
1950 var radius = (width * .5) - (shadowBlur) + 16;
1951 if (shadows != false) {
1952 for (var x = 0; x <= shadowBlur; x++){
1953 MochaUI.circle(
1954 ctx,
1955 width * .5 + shadowOffset.x,
1956 (height + options.headerHeight) * .5 + shadowOffset.x,
1957 (width *.5) - (x * 2) - shadowOffset.x,
1958 [0, 0, 0],
1959 x == shadowBlur ? .7 : .08 + (x * .04)
1960 );
1961 }
1962 }
1963 MochaUI.circle(
1964 ctx,
1965 width * .5 - shadowOffset.x,
1966 (height + options.headerHeight) * .5 - shadowOffset.y,
1967 (width *.5) - shadowBlur,
1968 options.bodyBgColor,
1969 1
1970 );
1971
1972 // Draw gauge header
1973 this.canvasHeaderEl.setStyles({
1974 'top': shadowBlur - shadowOffset.y,
1975 'left': shadowBlur - shadowOffset.x
1976 });
1977 var ctx = this.canvasHeaderEl.getContext('2d');
1978 ctx.clearRect(0, 0, width, 100);
1979 ctx.beginPath();
1980 ctx.lineWidth = 24;
1981 ctx.lineCap = 'round';
1982 ctx.moveTo(13, 13);
1983 ctx.lineTo(width - (shadowBlur*2) - 13, 13);
1984 ctx.strokeStyle = 'rgba(0, 0, 0, .25)';
1985 ctx.stroke();
1986 },
1987 bodyRoundedRect: function(ctx, x, y, width, height, radius, rgb){
1988 ctx.fillStyle = 'rgba(' + rgb.join(',') + ', 100)';
1989 ctx.beginPath();
1990 ctx.moveTo(x, y + radius);
1991 ctx.lineTo(x, y + height - radius);
1992 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
1993 ctx.lineTo(x + width - radius, y + height);
1994 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
1995 ctx.lineTo(x + width, y + radius);
1996 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
1997 ctx.lineTo(x + radius, y);
1998 ctx.quadraticCurveTo(x, y, x, y + radius);
1999 ctx.fill();
2000
2001 },
2002 topRoundedRect: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){
2003 var lingrad = ctx.createLinearGradient(0, 0, 0, height);
2004 lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');
2005 lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)');
2006 ctx.fillStyle = lingrad;
2007 ctx.beginPath();
2008 ctx.moveTo(x, y);
2009 ctx.lineTo(x, y + height);
2010 ctx.lineTo(x + width, y + height);
2011 ctx.lineTo(x + width, y + radius);
2012 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
2013 ctx.lineTo(x + radius, y);
2014 ctx.quadraticCurveTo(x, y, x, y + radius);
2015 ctx.fill();
2016 /*
2017 ctx.beginPath();
2018 ctx.strokeStyle = '#000';
2019 ctx.lineWidth = 1;
2020 ctx.moveTo(x, y + height + .5);
2021 ctx.lineTo(x + width, y + height + .5);
2022 ctx.stroke();
2023 */
2024
2025 },
2026 topRoundedRect2: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){
2027 var lingrad = ctx.createLinearGradient(0, this.options.shadowBlur - 1, 0, height + this.options.shadowBlur + 3);
2028 lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');
2029 lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)');
2030 ctx.fillStyle = lingrad;
2031 ctx.beginPath();
2032 ctx.moveTo(x, y + radius);
2033 ctx.lineTo(x, y + height - radius);
2034 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
2035 ctx.lineTo(x + width - radius, y + height);
2036 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
2037 ctx.lineTo(x + width, y + radius);
2038 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
2039 ctx.lineTo(x + radius, y);
2040 ctx.quadraticCurveTo(x, y, x, y + radius);
2041 ctx.fill();
2042 },
2043 maximizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
2044 // Circle
2045 ctx.beginPath();
2046 ctx.moveTo(x, y);
2047 ctx.arc(x, y, 7, 0, Math.PI*2, true);
2048 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
2049 ctx.fill();
2050 // X sign
2051 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
2052 ctx.beginPath();
2053 ctx.moveTo(x, y - 4);
2054 ctx.lineTo(x, y + 4);
2055 ctx.stroke();
2056 ctx.beginPath();
2057 ctx.moveTo(x - 4, y);
2058 ctx.lineTo(x + 4, y);
2059 ctx.stroke();
2060 },
2061 closebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
2062 // Circle
2063 ctx.beginPath();
2064 ctx.moveTo(x, y);
2065 ctx.arc(x, y, 7, 0, Math.PI*2, true);
2066 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
2067 ctx.fill();
2068 // Plus sign
2069 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
2070 ctx.beginPath();
2071 ctx.moveTo(x - 3, y - 3);
2072 ctx.lineTo(x + 3, y + 3);
2073 ctx.stroke();
2074 ctx.beginPath();
2075 ctx.moveTo(x + 3, y - 3);
2076 ctx.lineTo(x - 3, y + 3);
2077 ctx.stroke();
2078 },
2079 minimizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
2080 // Circle
2081 ctx.beginPath();
2082 ctx.moveTo(x,y);
2083 ctx.arc(x,y,7,0,Math.PI*2,true);
2084 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
2085 ctx.fill();
2086 // Minus sign
2087 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
2088 ctx.beginPath();
2089 ctx.moveTo(x - 4, y);
2090 ctx.lineTo(x + 4, y);
2091 ctx.stroke();
2092 },
2093 /*
2094
2095 Function: hideLoadingIcon
2096 Hides the spinner.
2097
2098 */
2099 hideLoadingIcon: function(canvas) {
2100 if (!MochaUI.options.useLoadingIcon || this.options.shape == 'gauge' || this.options.type == 'notification') return;
2101 $(canvas).setStyle('display', 'none');
2102 $clear(canvas.iconAnimation);
2103 },
2104 /*
2105
2106 Function: showLoadingIcon
2107 Shows the spinner.
2108
2109 */
2110 showLoadingIcon: function(canvas) {
2111 if (!MochaUI.options.useLoadingIcon || this.options.shape == 'gauge' || this.options.type == 'notification') return;
2112 $(canvas).setStyles({
2113 'display': 'block'
2114 });
2115 var t = 1;
2116 var iconAnimation = function(canvas){
2117 var ctx = $(canvas).getContext('2d');
2118 ctx.clearRect(0, 0, 18, 18);
2119 ctx.save();
2120 ctx.translate(9, 9);
2121 ctx.rotate(t*(Math.PI / 8));
2122 var color = 0;
2123 for (var i=0; i < 8; i++){
2124 color = Math.floor(255 / 8 * i);
2125 ctx.fillStyle = "rgb(" + color + "," + color + "," + color + ")";
2126 ctx.rotate(-Math.PI / 4);
2127 ctx.beginPath();
2128 ctx.arc(0, 7, 2, 0, Math.PI*2, true);
2129 ctx.fill();
2130 }
2131 ctx.restore();
2132 t++;
2133 }.bind(this);
2134 canvas.iconAnimation = iconAnimation.periodical(125, this, canvas);
2135 },
2136 setMochaControlsWidth: function(){
2137 this.mochaControlsWidth = 0;
2138 var options = this.options;
2139 if (options.minimizable){
2140 this.mochaControlsWidth += (this.minimizeButtonEl.getStyle('margin-left').toInt() + this.minimizeButtonEl.getStyle('width').toInt());
2141 }
2142 if (options.maximizable){
2143 this.mochaControlsWidth += (this.maximizeButtonEl.getStyle('margin-left').toInt() + this.maximizeButtonEl.getStyle('width').toInt());
2144 }
2145 if (options.closable){
2146 this.mochaControlsWidth += (this.closeButtonEl.getStyle('margin-left').toInt() + this.closeButtonEl.getStyle('width').toInt());
2147 }
2148 this.controlsEl.setStyle('width', this.mochaControlsWidth);
2149 if (options.useCanvasControls == true){
2150 this.canvasControlsEl.setProperty('width', this.mochaControlsWidth);
2151 }
2152 }
2153});
2154MochaUI.Window.implement(new Options, new Events);
2155/*
2156
2157Script: Modal.js
2158 Create modal dialog windows.
2159
2160Copyright:
2161 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2162
2163License:
2164 MIT-style license.
2165
2166Requires:
2167 Core.js, Window.js
2168
2169See Also:
2170 <Window>
2171
2172*/
2173
2174MochaUI.Modal = new Class({
2175
2176 Extends: MochaUI.Window,
2177
2178 Implements: [Events, Options],
2179
2180 initialize: function(options){
2181 this.modalInitialize();
2182 this.installed = true;
2183
2184 window.addEvent('resize', function(){
2185 this.setModalSize();
2186 }.bind(this));
2187
2188 },
2189 modalInitialize: function(){
2190 var modalOverlay = new Element('div', {
2191 'id': 'modalOverlay',
2192 'styles': {
2193 'height': document.getCoordinates().height
2194 }
2195 });
2196 modalOverlay.inject(document.body);
2197
2198 if (Browser.Engine.trident4){
2199 var modalFix = new Element('iframe', {
2200 'id': 'modalFix',
2201 'scrolling': 'no',
2202 'marginWidth': 0,
2203 'marginHeight': 0,
2204 'src': '',
2205 'styles': {
2206 'height': document.getCoordinates().height
2207 }
2208 }).inject(document.body);
2209 }
2210
2211 modalOverlay.setStyle('opacity', .4);
2212 this.modalOverlayOpenMorph = new Fx.Morph($('modalOverlay'), {
2213 'duration': 200
2214 });
2215 this.modalOverlayCloseMorph = new Fx.Morph($('modalOverlay'), {
2216 'duration': 200,
2217 onComplete: function(){
2218 $('modalOverlay').setStyle('display', 'none');
2219 if (Browser.Engine.trident4){
2220 $('modalFix').setStyle('display', 'none');
2221 }
2222 }.bind(this)
2223 });
2224 },
2225 setModalSize: function(){
2226 $('modalOverlay').setStyle('height', document.getCoordinates().height);
2227 if (Browser.Engine.trident4){
2228 $('modalFix').setStyle('height', document.getCoordinates().height);
2229 }
2230 }
2231});
2232MochaUI.Modal.implement(new Options, new Events);
2233/*
2234
2235Script: Windows-from-html.js
2236 Create windows from html markup in page.
2237
2238Copyright:
2239 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2240
2241License:
2242 MIT-style license.
2243
2244Requires:
2245 Core.js, Window.js
2246
2247Example:
2248 HTML markup.
2249 (start code)
2250<div class="mocha" id="mywindow" style="width:300px;height:255px;top:50px;left:350px">
2251 <h3 class="mochaTitle">My Window</h3>
2252 <p>My Window Content</p>
2253</div>
2254 (end)
2255
2256See Also:
2257 <Window>
2258
2259*/
2260
2261MochaUI.extend({
2262 NewWindowsFromHTML: function(){
2263 $$('div.mocha').each(function(el) {
2264 // Get the window title and destroy that element, so it does not end up in window content
2265 if ( Browser.Engine.presto || Browser.Engine.trident5 ){
2266 el.setStyle('display','block'); // Required by Opera, and probably IE7
2267 }
2268 var title = el.getElement('h3.mochaTitle');
2269 var elDimensions = el.getStyles('height', 'width');
2270 var properties = {
2271 id: el.getProperty('id'),
2272 height: elDimensions.height.toInt(),
2273 width: elDimensions.width.toInt(),
2274 x: el.getStyle('left').toInt(),
2275 y: el.getStyle('top').toInt()
2276 };
2277 // If there is a title element, set title and destroy the element so it does not end up in window content
2278 if ( title ) {
2279 properties.title = title.innerHTML;
2280 title.destroy();
2281 }
2282
2283 // Get content and destroy the element
2284 properties.content = el.innerHTML;
2285 el.destroy();
2286
2287 // Create window
2288 new MochaUI.Window(properties, true);
2289 }.bind(this));
2290 }
2291});
2292/*
2293
2294Script: Windows-from-json.js
2295 Create one or more windows from JSON data. You can define all the same properties as you can for new MochaUI.Window(). Undefined properties are set to their defaults.
2296
2297Copyright:
2298 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2299
2300License:
2301 MIT-style license.
2302
2303Syntax:
2304 (start code)
2305 MochaUI.newWindowsFromJSON(properties);
2306 (end)
2307
2308Example:
2309 (start code)
2310 MochaUI.jsonWindows = function(){
2311 var url = 'data/json-windows-data.js';
2312 var request = new Request.JSON({
2313 url: url,
2314 method: 'get',
2315 onComplete: function(properties) {
2316 MochaUI.newWindowsFromJSON(properties.windows);
2317 }
2318 }).send();
2319 }
2320 (end)
2321
2322See Also:
2323 <Window>
2324
2325*/
2326
2327MochaUI.extend({
2328 newWindowsFromJSON: function(properties){
2329 properties.each(function(properties) {
2330 new MochaUI.Window(properties);
2331 }.bind(this));
2332 }
2333});
2334/*
2335
2336Script: Arrange-cascade.js
2337 Cascade windows.
2338
2339Copyright:
2340 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2341
2342License:
2343 MIT-style license.
2344
2345Requires:
2346 Core.js, Window.js
2347
2348Syntax:
2349 (start code)
2350 MochaUI.arrangeCascade();
2351 (end)
2352
2353*/
2354
2355MochaUI.options.extend({
2356 desktopTopOffset: 30, // Use a negative number if neccessary to place first window where you want it
2357 desktopLeftOffset: 20,
2358 mochaTopOffset: 50, // Initial vertical spacing of each window
2359 mochaLeftOffset: 40 // Initial horizontal spacing of each window
2360});
2361
2362MochaUI.extend({
2363 arrangeCascade: function(){
2364 var x = this.options.desktopLeftOffset;
2365 var y = this.options.desktopTopOffset;
2366 $$('div.mocha').each(function(windowEl){
2367 var currentWindowClass = MochaUI.Windows.instances.get(windowEl.id);
2368 if (!currentWindowClass.isMinimized && !currentWindowClass.isMaximized){
2369 id = windowEl.id;
2370 MochaUI.focusWindow(windowEl);
2371 x += this.options.mochaLeftOffset;
2372 y += this.options.mochaTopOffset;
2373
2374 if (MochaUI.options.useEffects == false){
2375 windowEl.setStyles({
2376 'top': y,
2377 'left': x
2378 });
2379 }
2380 else {
2381 var cascadeMorph = new Fx.Morph(windowEl, {
2382 'duration': 550
2383 });
2384 cascadeMorph.start({
2385 'top': y,
2386 'left': x
2387 });
2388 }
2389 }
2390 }.bind(this));
2391 }
2392});
2393/*
2394
2395Script: Arrange-tile.js
2396 Cascade windows.
2397
2398Authors:
2399 Harry Roberts and Greg Houston
2400
2401License:
2402 MIT-style license.
2403
2404Requires:
2405 Core.js, Window.js
2406
2407Syntax:
2408 (start code)
2409 MochaUI.arrangeTile();
2410 (end)
2411
2412*/
2413
2414MochaUI.extend({
2415 arrangeTile: function(){
2416 var x = 10;
2417 var y = 10;
2418
2419 var instances = MochaUI.Windows.instances;
2420
2421 var windowsNum = 0;
2422
2423 instances.each(function(instance){
2424 if (!instance.isMinimized && !instance.isMaximized){
2425 windowsNum++;
2426 }
2427 });
2428
2429 var cols = 3;
2430 var rows = Math.ceil(windowsNum / cols);
2431
2432 var coordinates = document.getCoordinates();
2433
2434 var col_width = ((coordinates.width - this.options.desktopLeftOffset) / cols);
2435 var col_height = ((coordinates.height - this.options.desktopTopOffset) / rows);
2436
2437 var row = 0;
2438 var col = 0;
2439
2440 instances.each(function(instance){
2441 if (!instance.isMinimized && !instance.isMaximized){
2442
2443 var content = instance.contentWrapperEl;
2444 var content_coords = content.getCoordinates();
2445 var window_coords = instance.windowEl.getCoordinates();
2446
2447 // Calculate the amount of padding around the content window
2448 var padding_top = content_coords.top - window_coords.top;
2449 var padding_bottom = window_coords.height - content_coords.height - padding_top;
2450 var padding_left = content_coords.left - window_coords.left;
2451 var padding_right = window_coords.width - content_coords.width - padding_left;
2452
2453 if (instance.options.shape != 'gauge' && instance.options.resizable == true){
2454 var width = (col_width - 3 - padding_left - padding_right);
2455 var height = (col_height - 3 - padding_top - padding_bottom);
2456
2457 if (width > instance.options.resizeLimit.x[0] && width < instance.options.resizeLimit.x[1]){
2458 content.setStyle('width', width);
2459 }
2460 if (height > instance.options.resizeLimit.y[0] && height < instance.options.resizeLimit.y[1]){
2461 content.setStyle('height', height);
2462 }
2463
2464 }
2465
2466 var left = (x + (col * col_width));
2467 var top = (y + (row * col_height));
2468
2469 instance.windowEl.setStyles({
2470 'left': left,
2471 'top': top
2472 });
2473
2474 instance.drawWindow(instance.windowEl);
2475
2476 MochaUI.focusWindow(instance.windowEl);
2477
2478 if (++col === cols) {
2479 row++;
2480 col = 0;
2481 }
2482 }
2483 }.bind(this));
2484 }
2485});/*
2486
2487Script: Tabs.js
2488 Functionality for window tabs.
2489
2490Copyright:
2491 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2492
2493License:
2494 MIT-style license.
2495
2496Requires:
2497 Core.js, Window.js
2498
2499To do:
2500 - Move to Window
2501
2502*/
2503
2504MochaUI.extend({
2505 /*
2506
2507 Function: initializeTabs
2508 Add click event to each list item that fires the selected function.
2509
2510 */
2511 initializeTabs: function(el){
2512 $(el).getElements('li').each(function(listitem){
2513 listitem.addEvent('click', function(e){
2514 MochaUI.selected(this, el);
2515 });
2516 });
2517 },
2518 /*
2519
2520 Function: selected
2521 Add "selected" class to current list item and remove it from sibling list items.
2522
2523 Syntax:
2524 (start code)
2525 selected(el, parent);
2526 (end)
2527
2528Arguments:
2529 el - the list item
2530 parent - the ul
2531
2532 */
2533 selected: function(el, parent){
2534 $(parent).getChildren().each(function(listitem){
2535 listitem.removeClass('selected');
2536 });
2537 el.addClass('selected');
2538 }
2539});
2540
2541/*
2542
2543Script: Desktop.js
2544 Creates a desktop. Enables window maximize.
2545
2546Copyright:
2547 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
2548
2549License:
2550 MIT-style license.
2551
2552Requires:
2553 Core.js, Window.js
2554
2555Options:
2556 sidebarLimitX - Sidebar minimum and maximum widths when resizing.
2557
2558*/
2559
2560MochaUI.Desktop = new Class({
2561
2562 Extends: MochaUI.Window,
2563
2564 Implements: [Events, Options],
2565
2566 options: {
2567 // Naming options:
2568 // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.
2569 desktop: 'desktop',
2570 desktopHeader: 'desktopHeader',
2571 desktopNavBar: 'desktopNavbar',
2572 pageWrapper: 'pageWrapper',
2573 page: 'page',
2574 desktopFooter: 'desktopFooterWrapper',
2575 sidebarWrapper: 'sidebarWrapper',
2576 sidebar: 'sidebar',
2577 sidebarContentWrapper: 'sidebarContentWrapper',
2578 sidebarMinimize: 'sidebarControl',
2579 sidebarHandle: 'sidebarHandle',
2580 // Sidebar options:
2581 sidebarLimitX: [180, 280] // Sidebar minimum and maximum widths when resizing.
2582 },
2583 initialize: function(options){
2584 this.setOptions(options);
2585 this.desktop = $(this.options.desktop);
2586 this.desktopHeader = $(this.options.desktopHeader);
2587 this.desktopNavBar = $(this.options.desktopNavBar);
2588 this.pageWrapper = $(this.options.pageWrapper);
2589 this.page = $(this.options.page);
2590 this.desktopFooter = $(this.options.desktopFooter);
2591 this.sidebarWrapper = $(this.options.sidebarWrapper);
2592 this.sidebar = $(this.options.sidebar);
2593 this.sidebarContentWrapper = $(this.options.sidebarContentWrapper);
2594 this.sidebarMinimize = $(this.options.sidebarMinimize);
2595 this.sidebarHandle = $(this.options.sidebarHandle);
2596
2597 this.setDesktopSize();
2598 this.menuInitialize();
2599
2600 if(this.sidebar){
2601 this.sidebarInitialize();
2602 }
2603
2604 // Resize desktop, page wrapper, modal overlay, and maximized windows when browser window is resized
2605 window.addEvent('resize', function(){
2606 this.onBrowserResize();
2607 }.bind(this));
2608 },
2609 menuInitialize: function(){
2610 // Fix for dropdown menus in IE6
2611 if (Browser.Engine.trident4 && this.desktopNavBar){
2612 this.desktopNavBar.getElements('li').each(function(element) {
2613 element.addEvent('mouseenter', function(){
2614 this.addClass('ieHover');
2615 });
2616 element.addEvent('mouseleave', function(){
2617 this.removeClass('ieHover');
2618 });
2619 });
2620 };
2621 },
2622 onBrowserResize: function(){
2623 this.setDesktopSize();
2624 // Resize maximized windows to fit new browser window size
2625 setTimeout( function(){
2626 MochaUI.Windows.instances.each(function(instance){
2627 if (instance.isMaximized) {
2628
2629 // Hide iframe while resize for better performance
2630 if ( instance.iframeEl ) {
2631 instance.iframeEl.setStyle('visibility', 'hidden');
2632 }
2633
2634 var coordinates = document.getCoordinates();
2635 var borderHeight = instance.contentBorderEl.getStyle('border-top').toInt() + instance.contentBorderEl.getStyle('border-bottom').toInt();
2636 var toolbarHeight = instance.toolbarWrapperEl ? instance.toolbarWrapperEl.getStyle('height').toInt() + instance.toolbarWrapperEl.getStyle('border-top').toInt() : 0;
2637 instance.contentWrapperEl.setStyles({
2638 'height': coordinates.height - instance.options.headerHeight - instance.options.footerHeight - borderHeight - toolbarHeight,
2639 'width': coordinates.width
2640 });
2641
2642 instance.drawWindow($(instance.options.id));
2643 if ( instance.iframeEl ) {
2644 instance.iframeEl.setStyles({
2645 'height': instance.contentWrapperEl.getStyle('height')
2646 });
2647 instance.iframeEl.setStyle('visibility', 'visible');
2648 }
2649
2650 }
2651 }.bind(this));
2652 }.bind(this), 100);
2653 },
2654 setDesktopSize: function(){
2655 var windowDimensions = window.getCoordinates();
2656
2657 // var dock = $(MochaUI.options.dock);
2658 var dockWrapper = $(MochaUI.options.dockWrapper);
2659
2660 // Setting the desktop height may only be needed by IE7
2661 if (this.desktop){
2662 this.desktop.setStyle('height', windowDimensions.height);
2663 }
2664
2665 // Set pageWrapper height so the dock doesn't cover the pageWrapper scrollbars.
2666 if (this.pageWrapper && this.desktopHeader) {
2667
2668 var dockOffset = MochaUI.dockVisible ? dockWrapper.offsetHeight : 0;
2669 var pageWrapperHeight = windowDimensions.height - this.desktopHeader.offsetHeight - this.desktopFooter.offsetHeight - dockOffset;
2670
2671 if ( pageWrapperHeight < 0 ) {
2672 pageWrapperHeight = 0;
2673 }
2674 this.pageWrapper.setStyle('height', pageWrapperHeight + 'px');
2675 }
2676
2677 if (this.sidebar){
2678 var sidebarBorderOffset = Browser.Engine.trident4 ? 3 : 2;
2679 this.sidebarContentWrapper.setStyle('height', pageWrapperHeight - sidebarBorderOffset + 'px');
2680 this.sidebarMinimize.setStyle('top', ((pageWrapperHeight * .5) - (this.sidebarMinimize.offsetHeight * .5)) + 'px');
2681 this.sidebarHandle.setStyle('height', pageWrapperHeight - sidebarBorderOffset + 'px');
2682 }
2683 },
2684 /*
2685
2686 Function: maximizeWindow
2687 Maximize a window.
2688
2689 Syntax:
2690 (start code)
2691 MochaUI.Desktop.maximizeWindow(windowEl);
2692 (end)
2693SLUG
2694 */
2695 maximizeWindow: function(windowEl) {
2696
2697 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
2698 var windowDrag = currentInstance.windowDrag;
2699
2700 // If window no longer exists or is maximized, stop
2701 if (windowEl != $(windowEl) || currentInstance.isMaximized ) return;
2702
2703 if (currentInstance.isCollapsed){
2704 MochaUI.collapseToggle(windowEl);
2705 }
2706
2707 currentInstance.isMaximized = true;
2708
2709 // If window is restricted to a container, it should not be draggable when maximized.
2710 if (currentInstance.options.restrict){
2711 windowDrag.detach();
2712 currentInstance.titleBarEl.setStyle('cursor', 'default');
2713 }
2714
2715 // If the window has a container that is not the desktop
2716 // temporarily move the window to the desktop while it is minimized.
2717 if (currentInstance.options.container != this.desktop){
2718 this.desktop.grab(windowEl);
2719 if (this.options.restrict){
2720 windowDrag.container = this.desktop;
2721 }
2722 }
2723
2724 // Save original position
2725 currentInstance.oldTop = windowEl.getStyle('top');
2726 currentInstance.oldLeft = windowEl.getStyle('left');
2727
2728 var contentWrapperEl = currentInstance.contentWrapperEl;
2729
2730 // Save original dimensions
2731 contentWrapperEl.oldWidth = contentWrapperEl.getStyle('width');
2732 contentWrapperEl.oldHeight = contentWrapperEl.getStyle('height');
2733
2734 // Hide iframe
2735 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
2736 if ( currentInstance.iframe ) {
2737 currentInstance.iframeEl.setStyle('visibility', 'hidden');
2738 }
2739
2740 //var windowDimensions = document.getCoordinates();
2741 var windowDimensions = currentInstance.options.container.getCoordinates();
2742 var options = currentInstance.options;
2743 var shadowBlur = options.shadowBlur;
2744 var shadowOffset = options.shadowOffset;
2745
2746 if (MochaUI.options.useEffects == false){
2747 windowEl.setStyles({
2748 'top': shadowOffset.y - shadowBlur + windowDimensions.top,
2749 'left': shadowOffset.x - shadowBlur + windowDimensions.left
2750 });
2751 currentInstance.contentWrapperEl.setStyles({
2752 'height': windowDimensions.height - options.headerHeight - options.footerHeight - options.toolbarHeight,
2753 'width': windowDimensions.width
2754 });
2755 currentInstance.drawWindow(windowEl);
2756 // Show iframe
2757 if ( currentInstance.iframe ) {
2758 currentInstance.iframeEl.setStyle('visibility', 'visible');
2759 }
2760 currentInstance.fireEvent('onMaximize', windowEl);
2761 }
2762 else {
2763
2764 // Todo: Initialize the variables for these morphs once in an initialize function and reuse them
2765
2766 var maximizeMorph = new Fx.Elements([contentWrapperEl, windowEl], {
2767 duration: 70,
2768 onStart: function(windowEl){
2769 currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);
2770 }.bind(this),
2771 onComplete: function(windowEl){
2772 $clear(currentInstance.maximizeAnimation);
2773 currentInstance.drawWindow(windowEl);
2774 // Show iframe
2775 if ( currentInstance.iframe ) {
2776 currentInstance.iframeEl.setStyle('visibility', 'visible');
2777 }
2778 currentInstance.fireEvent('onMaximize', windowEl);
2779 }.bind(this)
2780 });
2781 maximizeMorph.start({
2782 '0': { 'height': function(){ return windowDimensions.height - options.headerHeight - options.footerHeight - currentInstance.contentBorderEl.getStyle('border-top').toInt() - currentInstance.contentBorderEl.getStyle('border-bottom').toInt() - ( currentInstance.toolbarWrapperEl ? currentInstance.toolbarWrapperEl.getStyle('height').toInt() + currentInstance.toolbarWrapperEl.getStyle('border-top').toInt() : 0)},
2783 'width': windowDimensions.width
2784 },
2785 '1': { 'top': shadowOffset.y - shadowBlur,
2786 'left': shadowOffset.x - shadowBlur
2787 }
2788 });
2789 }
2790 currentInstance.maximizeButtonEl.setProperty('title', 'Restore');
2791 MochaUI.focusWindow(windowEl);
2792
2793 },
2794 /*
2795
2796 Function: restoreWindow
2797 Restore a maximized window.
2798
2799 Syntax:
2800 (start code)
2801 MochaUI.Desktop.restoreWindow(windowEl);
2802 (end)
2803
2804 */
2805 restoreWindow: function(windowEl) {
2806
2807 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
2808
2809 // Window exists and is maximized ?
2810 if (windowEl != $(windowEl) || !currentInstance.isMaximized) return;
2811
2812 var options = currentInstance.options;
2813 currentInstance.isMaximized = false;
2814
2815 if (options.restrict){
2816 currentInstance.windowDrag.attach();
2817 currentInstance.titleBarEl.setStyle('cursor', 'move');
2818 }
2819
2820 // Hide iframe
2821 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
2822 if ( currentInstance.iframe ) {
2823 currentInstance.iframeEl.setStyle('visibility', 'hidden');
2824 }
2825
2826 var contentWrapperEl = currentInstance.contentWrapperEl;
2827
2828 if (MochaUI.options.useEffects == false){
2829 contentWrapperEl.setStyles({
2830 'width': contentWrapperEl.oldWidth,
2831 'height': contentWrapperEl.oldHeight
2832 });
2833 currentInstance.drawWindow(windowEl);
2834 windowEl.setStyles({
2835 'top': currentInstance.oldTop,
2836 'left': currentInstance.oldLeft
2837 });
2838 if (currentInstance.container != this.desktop){
2839 $(options.container).grab(windowEl);
2840 if (options.restrict){
2841 currentInstance.windowDrag.container = $(options.container);
2842 }
2843 }
2844 currentInstance.fireEvent('onRestore', windowEl);
2845 }
2846 else {
2847 var restoreMorph = new Fx.Elements([contentWrapperEl, windowEl], {
2848 'duration': 150,
2849 'onStart': function(windowEl){
2850 currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);
2851 }.bind(this),
2852 'onComplete': function(el){
2853 $clear(currentInstance.maximizeAnimation);
2854 currentInstance.drawWindow(windowEl);
2855 if ( currentInstance.iframe ) {
2856 currentInstance.iframeEl.setStyle('visibility', 'visible');
2857 }
2858 if (options.container != this.desktop){
2859 $(options.container).grab(windowEl);
2860 if (options.restrict){
2861 currentInstance.windowDrag.container = $(options.container);
2862 }
2863 }
2864 currentInstance.fireEvent('onRestore', windowEl);
2865 }.bind(this)
2866 });
2867 restoreMorph.start({
2868 '0': { 'height': contentWrapperEl.oldHeight,
2869 'width': contentWrapperEl.oldWidth
2870 },
2871 '1': { 'top': currentInstance.oldTop,
2872 'left': currentInstance.oldLeft
2873 }
2874 });
2875 }
2876 currentInstance.maximizeButtonEl.setProperty('title', 'Maximize');
2877
2878 },
2879 sidebarInitialize: function(){
2880 this.sidebarResizable = this.sidebar.makeResizable({
2881 handle: this.sidebarHandle ? this.sidebarHandle : false,
2882 modifiers: {
2883 x: 'width',
2884 y: false
2885 },
2886 limit: {
2887 x: this.options.sidebarLimitX
2888 },
2889 onBeforeStart: function(){
2890 // Using postion fixed fixes a minor display glitch while resizing the sidebar in Firefox PC
2891 // Mac Firefox needs position fixed all the time though it does not render as well as absolute
2892 if (!Browser.Platform.mac && Browser.Engine.gecko){
2893 $$('div.mocha').setStyle('position', 'fixed');
2894 }
2895 },
2896 onComplete: function(){
2897 if (!Browser.Platform.mac && Browser.Engine.gecko){
2898 $$('div.mocha').setStyle('position', 'absolute');
2899 }
2900 }
2901 });
2902
2903 // Part of IE6 3px jox bug fix
2904 if (Browser.Engine.trident4){
2905 this.page.set('margin-left', -3);
2906 }
2907
2908 this.sidebarWrapper.setStyle('display', 'block');
2909
2910 this.sidebarIsMinimized = false;
2911 this.sidebarMinimize.addEvent('click', function(event){
2912 this.sidebarMinimizeToggle();
2913 }.bind(this));
2914
2915 // Add check mark to menu if link exists in menu
2916 if ($('sidebarLinkCheck')){
2917 this.sidebarCheck = new Element('div', {
2918 'class': 'check',
2919 'id': 'sidebar_check'
2920 }).injectInside($('sidebarLinkCheck'));
2921 }
2922 },
2923 /*
2924
2925 Function: sidebarToggle
2926 Toggles the display of the sidebar.
2927
2928 Syntax:
2929 (start code)
2930 MochaUI.Desktop.sidebarToggle();
2931 (end)
2932
2933 */
2934 sidebarToggle: function(){
2935 // Hide sidebar.
2936 if (this.sidebarWrapper.getStyle('display') == 'block'){
2937 this.sidebarWrapper.setStyle('display', 'none');
2938 this.sidebarCheck.setStyle('display', 'none');
2939 // Part of IE6 3px jox bug fix
2940 if (Browser.Engine.trident4){
2941 this.page.set('margin-left', 0);
2942 }
2943 }
2944 // Show sidebar.
2945 else {
2946 // If the sidebar is minimized when toggling it's visibility on the sidebar will be restored.
2947 if (this.sidebarIsMinimized){
2948 this.sidebarMinimizeToggle();
2949 }
2950 this.sidebarWrapper.setStyle('display', 'block');
2951 this.sidebarCheck.setStyle('display', 'block');
2952 // Part of IE6 3px jox bug fix
2953 if (Browser.Engine.trident4){
2954 this.page.set('margin-left', -3);
2955 }
2956 }
2957 },
2958 /*
2959
2960 Function: sidebarMinimizeToggle
2961 Minimize and restore the sidebar.
2962
2963 Syntax:
2964 (start code)
2965 MochaUI.Desktop.sidebarMinimizeToggle();
2966 (end)
2967
2968 */
2969 sidebarMinimizeToggle: function(){
2970 // Expand sidebar.
2971 var windows = $$('div.mocha');
2972 if (!this.sidebarIsMinimized){
2973 this.sidebarResizable.detach();
2974 this.sidebarHandle.setStyle('cursor', 'default');
2975 this.sidebar.setStyle('display', 'none');
2976 // Part of IE6 3px jox bug fix
2977 if (Browser.Engine.trident4){
2978 this.sidebarMinimize.setStyle('margin-right', 0);
2979 }
2980 if (!Browser.Platform.mac && Browser.Engine.gecko){
2981 windows.setStyle('position', 'absolute');
2982 }
2983 this.sidebarIsMinimized = true;
2984 }
2985 // Collapse sidebar
2986 else {
2987 this.sidebarResizable.attach();
2988 this.sidebarHandle.setStyles({
2989 'cursor': Browser.Engine.presto ? 'e-resize' : 'col-resize'
2990 });
2991 this.sidebar.setStyle('display', 'block');
2992 if (Browser.Engine.trident4){
2993 this.sidebarMinimize.setStyle('margin-right', 1);
2994 }
2995 if (!Browser.Platform.mac && Browser.Engine.gecko){
2996 windows.setStyle('position', 'absolute');
2997 }
2998 this.sidebarIsMinimized = false;
2999 }
3000 }
3001});
3002MochaUI.Desktop.implement(new Options, new Events);
3003/*
3004
3005Script: Dock.js
3006 Implements the dock/taskbar. Enables window minimize.
3007
3008Copyright:
3009 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
3010
3011License:
3012 MIT-style license.
3013
3014Requires:
3015 Core.js, Window.js, Desktop.js
3016
3017Todo:
3018 - Make it so the dock requires no initial html markup.
3019
3020*/
3021
3022MochaUI.options.extend({
3023 // Naming options:
3024 // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.
3025 dockWrapper: 'dockWrapper',
3026 dock: 'dock'
3027});
3028
3029MochaUI.dockVisible = true;
3030
3031MochaUI.extend({
3032 /*
3033
3034 Function: minimizeAll
3035 Minimize all windows.
3036
3037 */
3038 minimizeAll: function() {
3039 $$('div.mocha').each(function(windowEl){
3040 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
3041 if (!currentInstance.isMinimized){
3042 MochaUI.Dock.minimizeWindow(windowEl);
3043 }
3044 }.bind(this));
3045 }
3046});
3047
3048MochaUI.Dock = new Class({
3049 Extends: MochaUI.Window,
3050
3051 Implements: [Events, Options],
3052
3053 options: {
3054 useControls: true, // Toggles autohide and dock placement controls.
3055 useCanvasTabs: false, // Toggle use of canvas tab graphics. NOT YET IMPLEMENTED
3056 dockPosition: 'top', // Position the dock starts in, top or bottom.
3057 // Style options
3058 dockTabColor: [255, 255, 255],
3059 trueButtonColor: [70, 245, 70], // Color for autohide on
3060 enabledButtonColor: [255, 70, 70],
3061 disabledButtonColor: [150, 150, 150]
3062 },
3063 initialize: function(options){
3064 // Stops if MochaUI.Desktop is not implemented
3065 if (!MochaUI.Desktop) return;
3066 this.setOptions(options);
3067
3068 this.dockWrapper = $(MochaUI.options.dockWrapper);
3069 this.dock = $(MochaUI.options.dock);
3070 this.autoHideEvent = null;
3071 this.dockAutoHide = false; // True when dock autohide is set to on, false if set to off
3072
3073 if (!this.options.useControls){
3074 if($('dockPlacement')){
3075 $('dockPlacement').setStyle('cursor', 'default');
3076 }
3077 if($('dockAutoHide')){
3078 $('dockAutoHide').setStyle('cursor', 'default');
3079 }
3080 }
3081
3082 this.dockWrapper.setStyles({
3083 'display': 'block',
3084 'position': 'absolute',
3085 'top': null,
3086 'bottom': 0,
3087 'left': 0
3088 });
3089
3090 if (this.options.useControls){
3091 this.initializeDockControls();
3092 }
3093
3094 // Add check mark to menu if link exists in menu
3095 if ($('dockLinkCheck')){
3096 this.sidebarCheck = new Element('div', {
3097 'class': 'check',
3098 'id': 'dock_check'
3099 }).inject($('dockLinkCheck'));
3100 }
3101
3102 this.dockSortables = new Sortables('#dockSort', {
3103 opacity: Browser.Engine.trident ? 1 : .5,
3104 constrain: true,
3105 clone: false,
3106 revert: false
3107 });
3108
3109 MochaUI.Desktop.setDesktopSize();
3110 },
3111 initializeDockControls: function(){
3112
3113 if (this.options.useControls){
3114 // Insert canvas
3115 var canvas = new Element('canvas', {
3116 'id': 'dockCanvas',
3117 'width': '15',
3118 'height': '18'
3119 }).inject(this.dock);
3120
3121 // Dynamically initialize canvas using excanvas. This is only required by IE
3122 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){
3123 G_vmlCanvasManager.initElement(canvas);
3124 }
3125 }
3126
3127 var dockPlacement = $('dockPlacement');
3128 var dockAutoHide = $('dockAutoHide');
3129
3130 // Position top or bottom selector
3131 dockPlacement.setProperty('title','Position Dock Top');
3132
3133 // Attach event
3134 dockPlacement.addEvent('click', function(){
3135 this.moveDock();
3136 }.bind(this));
3137
3138 // Auto Hide toggle switch
3139 dockAutoHide.setProperty('title','Turn Auto Hide On');
3140
3141 // Attach event Auto Hide
3142 dockAutoHide.addEvent('click', function(event){
3143 if ( this.dockWrapper.getProperty('dockPosition') == 'top' )
3144 return false;
3145
3146 var ctx = $('dockCanvas').getContext('2d');
3147 this.dockAutoHide = !this.dockAutoHide; // Toggle
3148 if (this.dockAutoHide){
3149 $('dockAutoHide').setProperty('title', 'Turn Auto Hide Off');
3150 //ctx.clearRect(0, 11, 100, 100);
3151 MochaUI.circle(ctx, 5 , 14, 3, this.options.trueButtonColor, 1.0); // green
3152
3153 // Define event
3154 this.autoHideEvent = function(event) {
3155 if (!this.dockAutoHide)
3156 return;
3157 if (event.client.y > (document.getCoordinates().height - 25)){
3158 if (!MochaUI.dockVisible){
3159 this.dockWrapper.setStyle('display', 'block');
3160 MochaUI.dockVisible = true;
3161 MochaUI.Desktop.setDesktopSize();
3162 }
3163 } else {
3164 if (MochaUI.dockVisible){
3165 this.dockWrapper.setStyle('display', 'none');
3166 MochaUI.dockVisible = false;
3167 MochaUI.Desktop.setDesktopSize();
3168 }
3169 }
3170 }.bind(this);
3171
3172 // Add event
3173 document.addEvent('mousemove', this.autoHideEvent);
3174
3175 } else {
3176 $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');
3177 //ctx.clearRect(0, 11, 100, 100);
3178 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red
3179 // Remove event
3180 document.removeEvent('mousemove', this.autoHideEvent);
3181 }
3182
3183 }.bind(this));
3184
3185 // Draw dock controls
3186 var ctx = $('dockCanvas').getContext('2d');
3187 ctx.clearRect(0, 0, 100, 100);
3188 MochaUI.circle(ctx, 5 , 4, 3, this.options.enabledButtonColor, 1.0); // red
3189 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red
3190
3191 if (this.options.dockPosition == 'top'){
3192 this.moveDock();
3193 }
3194
3195 },
3196 moveDock: function(){
3197 var ctx = $('dockCanvas').getContext('2d');
3198 // Move dock to top position
3199 if (this.dockWrapper.getStyle('position') != 'relative'){
3200 this.dockWrapper.setStyles({
3201 'position': 'relative',
3202 'bottom': null
3203 });
3204 this.dockWrapper.addClass('top');
3205 MochaUI.Desktop.setDesktopSize();
3206 this.dockWrapper.setProperty('dockPosition','top');
3207 ctx.clearRect(0, 0, 100, 100);
3208 MochaUI.circle(ctx, 5, 4, 3, this.options.trueButtonColor, 1.0); // green
3209 MochaUI.circle(ctx, 5, 14, 3, this.options.disabledButtonColor, 1.0); // gray
3210 $('dockPlacement').setProperty('title', 'Position Dock Bottom');
3211 $('dockAutoHide').setProperty('title', 'Auto Hide Disabled in Top Dock Position');
3212 this.dockAutoHide = false;
3213 }
3214 // Move dock to bottom position
3215 else {
3216 this.dockWrapper.setStyles({
3217 'position': 'absolute',
3218 'bottom': 0
3219 });
3220 this.dockWrapper.removeClass('top');
3221 MochaUI.Desktop.setDesktopSize();
3222 this.dockWrapper.setProperty('dockPosition', 'bottom');
3223 ctx.clearRect(0, 0, 100, 100);
3224 MochaUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0); // red
3225 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red
3226 $('dockPlacement').setProperty('title', 'Position Dock Top');
3227 $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');
3228 }
3229 },
3230 createDockTab: function(windowEl){
3231
3232 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
3233
3234 var dockTab = new Element('div', {
3235 'id': currentInstance.options.id + '_dockTab',
3236 'class': 'dockTab',
3237 'title': titleText
3238 }).inject($('dockClear'), 'before');
3239
3240 dockTab.addEvent('mousedown', function(e){
3241 this.timeDown = $time();
3242 });
3243
3244 dockTab.addEvent('mouseup', function(e){
3245 this.timeUp = $time();
3246 if ((this.timeUp - this.timeDown) < 275){
3247 // If window is minimized, restore window.
3248 if (currentInstance.isMinimized == true) {
3249 MochaUI.Dock.restoreMinimized.delay(25, MochaUI.Dock, windowEl);
3250 }
3251 else{
3252 // If window is maximized and focused, minimize window.
3253 if (currentInstance.windowEl.hasClass('isFocused')) {
3254 MochaUI.Dock.minimizeWindow(windowEl)
3255 }
3256 // If window is maximized and not focused, focus window.
3257 else{
3258 MochaUI.focusWindow(windowEl);
3259 }
3260 }
3261 }
3262 });
3263
3264 this.dockSortables.addItems(dockTab);
3265
3266 //Insert canvas
3267 if (this.options.useControls){
3268 if (this.options.useCanvasTabs){
3269 var dockTabCanvas = new Element('canvas', {
3270 'id': currentInstance.options.id + '_dockTabCanvas',
3271 'class': 'dockCanvas',
3272 'width': 120,
3273 'height': 20
3274 }).inject(dockTab);
3275
3276 // Dynamically initialize canvas using excanvas. This is only required by IE
3277 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
3278 G_vmlCanvasManager.initElement(dockTabCanvas);
3279 }
3280
3281 var ctx = $(currentInstance.options.id + '_dockTabCanvas').getContext('2d');
3282 MochaUI.roundedRect(ctx, 0, 0, 120, 20, 5, this.options.dockTabColor, 1);
3283 }
3284 }
3285
3286 var titleText = currentInstance.titleEl.innerHTML;
3287
3288 var dockTabText = new Element('div', {
3289 'id': currentInstance.options.id + '_dockTabText',
3290 'class': 'dockText'
3291 }).set('html', titleText.substring(0,18) + (titleText.length > 18 ? '...' : '')).inject($(dockTab));
3292
3293 // Need to resize everything in case the dock wraps when a new tab is added
3294 MochaUI.Desktop.setDesktopSize();
3295
3296 },
3297 makeActiveTab: function(){
3298
3299
3300 // getWindowWith HighestZindex is used in case the currently focused window
3301 // is closed.
3302 var windowEl = MochaUI.getWindowWithHighestZindex();
3303 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
3304
3305 $$('div.dockTab').removeClass('activeDockTab');
3306 if (currentInstance.isMinimized != true) {
3307
3308 currentInstance.windowEl.addClass('isFocused');
3309
3310 currentButton = $(currentInstance.options.id + '_dockTab');
3311 currentButton.addClass('activeDockTab');
3312 }
3313 else {
3314 currentInstance.windowEl.removeClass('isFocused');
3315 }
3316 },
3317 minimizeWindow: function(windowEl){
3318 if (windowEl != $(windowEl)) return;
3319
3320 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
3321 currentInstance.isMinimized = true;
3322
3323 // Hide iframe
3324 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
3325 if ( currentInstance.iframe ) {
3326 currentInstance.iframeEl.setStyle('visibility', 'hidden');
3327 }
3328
3329 // Hide window and add to dock
3330 currentInstance.contentBorderEl.setStyle('visibility', 'hidden');
3331 if(currentInstance.toolbarWrapperEl){
3332 currentInstance.toolbarWrapperEl.setStyle('visibility', 'hidden');
3333 }
3334 windowEl.setStyle('visibility', 'hidden');
3335
3336 // Fixes a scrollbar issue in Mac FF2
3337 if (Browser.Platform.mac && Browser.Engine.gecko){
3338 currentInstance.contentWrapperEl.setStyle('overflow', 'hidden');
3339 }
3340
3341 MochaUI.Desktop.setDesktopSize();
3342
3343 // Fixes a scrollbar issue in Mac FF2.
3344 // Have to use timeout because window gets focused when you click on the minimize button
3345 setTimeout(function(){
3346 windowEl.setStyle('zIndex', 1);
3347 windowEl.removeClass('isFocused');
3348 this.makeActiveTab();
3349 }.bind(this),100);
3350
3351 currentInstance.fireEvent('onMinimize', windowEl);
3352 },
3353 restoreMinimized: function(windowEl) {
3354
3355 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
3356
3357 if (currentInstance.isMinimized == false) return;
3358
3359 if (MochaUI.Windows.windowsVisible == false){
3360 MochaUI.toggleWindowVisibility();
3361 }
3362
3363 MochaUI.Desktop.setDesktopSize();
3364
3365 // Part of Mac FF2 scrollbar fix
3366 if (currentInstance.options.scrollbars == true && currentInstance.iframe == false){
3367 currentInstance.contentWrapperEl.setStyle('overflow', 'auto');
3368 }
3369
3370 if (currentInstance.isCollapsed) {
3371 MochaUI.collapseToggle(windowEl);
3372 }
3373
3374 windowEl.setStyle('visibility', 'visible');
3375 currentInstance.contentBorderEl.setStyle('visibility', 'visible');
3376 if(currentInstance.toolbarWrapperEl){
3377 currentInstance.toolbarWrapperEl.setStyle('visibility', 'visible');
3378 }
3379
3380 // Show iframe
3381 if ( currentInstance.iframe ) {
3382 currentInstance.iframeEl.setStyle('visibility', 'visible');
3383 }
3384
3385 currentInstance.isMinimized = false;
3386 MochaUI.focusWindow(windowEl);
3387 currentInstance.fireEvent('onRestore', windowEl);
3388
3389 }
3390});
3391MochaUI.Dock.implement(new Options, new Events);
3392/*
3393
3394Script: Workspaces.js
3395 Save and load workspaces. The Workspaces emulate Adobe Illustrator functionality remembering what windows are open and where they are positioned. There will be two versions, a limited version that saves state to a cookie, and a fully functional version that saves state to a database.
3396
3397Copyright:
3398 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
3399
3400License:
3401 MIT-style license.
3402
3403Requires:
3404 Core.js, Window.js
3405
3406To do:
3407 - Move to Window
3408
3409*/
3410
3411MochaUI.extend({
3412 /*
3413
3414 Function: saveWorkspace
3415 Save the current workspace.
3416
3417 Syntax:
3418 (start code)
3419 MochaUI.saveWorkspace();
3420 (end)
3421
3422 Notes:
3423 This is experimental. This version saves the ID of each open window to a cookie, and reloads those windows using the functions in mocha-init.js. This requires that each window have a function in mocha-init.js used to open them. Functions must be named the windowID + "Window". So if your window is called mywindow, it needs a function called mywindowWindow in mocha-init.js.
3424
3425 */
3426 saveWorkspace: function(){
3427 this.cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});
3428 this.cookie.empty();
3429 MochaUI.Windows.instances.each(function(instance) {
3430 instance.saveValues();
3431 this.cookie.set(instance.options.id, {
3432 'id': instance.options.id,
3433 'top': instance.options.y,
3434 'left': instance.options.x
3435 });
3436 }.bind(this));
3437 this.cookie.save();
3438
3439 new MochaUI.Window({
3440 loadMethod: 'html',
3441 type: 'notification',
3442 addClass: 'notification',
3443 content: 'Workspace saved.',
3444 closeAfter: '1400',
3445 width: 200,
3446 height: 40,
3447 y: 15,
3448 padding: { top: 10, right: 12, bottom: 10, left: 12 },
3449 shadowBlur: 5,
3450 bodyBgColor: [255, 255, 255]
3451 });
3452
3453 },
3454 windowUnload: function(){
3455 if ($$('div.mocha').length == 0 && this.myChain){
3456 this.myChain.callChain();
3457 }
3458 },
3459 loadWorkspace2: function(workspaceWindows){
3460 workspaceWindows.each(function(instance) {
3461 eval('MochaUI.' + instance.id + 'Window();');
3462 $(instance.id).setStyles({
3463 top: instance.top,
3464 left: instance.left
3465 });
3466 }.bind(this));
3467 this.loadingWorkspace = false;
3468 },
3469 /*
3470
3471 Function: loadWorkspace
3472 Load the saved workspace.
3473
3474 Syntax:
3475 (start code)
3476 MochaUI.loadWorkspace();
3477 (end)
3478
3479 */
3480 loadWorkspace: function(){
3481 cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});
3482 workspaceWindows = cookie.load();
3483
3484 if(!cookie.getKeys().length){
3485 new MochaUI.Window({
3486 loadMethod: 'html',
3487 type: 'notification',
3488 addClass: 'notification',
3489 content: 'You have no saved workspace.',
3490 width: 220,
3491 height: 40,
3492 y: 25,
3493 padding: { top: 10, right: 12, bottom: 10, left: 12 },
3494 shadowBlur: 5,
3495 bodyBgColor: [255, 255, 255]
3496 });
3497 return;
3498 }
3499
3500 if ($$('div.mocha').length != 0){
3501 this.loadingWorkspace = true;
3502 this.myChain = new Chain();
3503 this.myChain.chain(
3504 function(){
3505 $$('div.mocha').each(function(el) {
3506 this.closeWindow(el);
3507 }.bind(this));
3508 }.bind(this),
3509 function(){
3510 this.loadWorkspace2(workspaceWindows);
3511 }.bind(this)
3512 );
3513 this.myChain.callChain();
3514 }
3515 else {
3516 this.loadWorkspace2(workspaceWindows);
3517 }
3518
3519 }
3520});