]> jfr.im git - irc/quakenet/qwebirc.git/blame - static/js/mochaui/mocha.js
Add title changing.
[irc/quakenet/qwebirc.git] / static / js / mochaui / mocha.js
CommitLineData
08137ae6
CP
1/* \r
2\r
3Script: Core.js\r
4 MochaUI - A Web Applications User Interface Framework.\r
5\r
6Copyright:\r
7 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.\r
8\r
9License:\r
10 MIT-style license.\r
11\r
12Contributors:\r
13 - Scott F. Frederick\r
14 - Joel Lindau\r
15\r
16Note:\r
17 This documentation is taken directly from the javascript source files. It is built using Natural Docs.\r
18\r
19Todo:\r
20 Consider making title tooltips optional and using them more often.\r
21\r
22*/\r
23\r
24var MochaUI = new Hash({\r
25 options: new Hash({\r
26 useEffects: true // Toggles the majority of window fade and move effects.\r
27 }),\r
28 Columns: {\r
29 instances: new Hash()\r
30 },\r
31 Panels: {\r
32 instances: new Hash()\r
33 }, \r
34 Windows: { \r
35 instances: new Hash(),\r
36 indexLevel: 100, // Used for z-Index\r
37 windowIDCount: 0, // Used for windows without an ID defined by the user\r
38 windowsVisible: true // Ctrl-Alt-Q to toggle window visibility\r
39 }, \r
40 ieSupport: 'excanvas', // Makes it easier to switch between Excanvas and Moocanvas for testing\r
41 focusingWindow: 'false',\r
42 /*\r
43 \r
44 Function: updateContent\r
45 Replace the content of a window or panel.\r
46 \r
47 Arguments:\r
48 element - The parent window or panel.\r
49 childElement - The child element of the window or panel recieving the content.\r
50 title - (string) Change this if you want to change the title of the window or panel.\r
51 content - (string or element) An html loadMethod option.\r
52 loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html'.\r
53 url - Used if loadMethod is set to 'xhr' or 'iframe'.\r
54 padding - (object)\r
55\r
56 */ \r
57 updateContent: function(updateOptions){\r
58\r
59 var options = {\r
60 'element': null,\r
61 'childElement': null,\r
62 'title': null,\r
63 'content': null,\r
64 'loadMethod': null,\r
65 'url': null,\r
66 'padding': null\r
67 };\r
68 $extend(options, updateOptions);\r
69\r
70 if (!options.element) return;\r
71 var element = options.element;\r
72\r
73 if (MochaUI.Windows.instances.get(element.id)) {\r
74 var recipient = 'window';\r
75 var currentInstance = MochaUI.Windows.instances.get(element.id);\r
76 var spinnerEl = currentInstance.spinnerEl;\r
77 if (options.title) {\r
78 currentInstance.titleEl.set('html', options.title);\r
79 }\r
80 }\r
81 else {\r
82 var recipient = 'panel';\r
83 var currentInstance = MochaUI.Panels.instances.get(element.id);\r
84 if (options.title) {\r
85 currentInstance.titleEl.set('html', options.title);\r
86 }\r
87 }\r
88\r
89 var contentEl = currentInstance.contentEl;\r
90 if (options.childElement != null) {\r
91 var contentContainer = options.childElement;\r
92 }\r
93 else {\r
94 var contentContainer = currentInstance.contentEl;\r
95 }\r
96 \r
97 var loadMethod = options.loadMethod != null ? options.loadMethod : currentInstance.options.loadMethod;\r
98 \r
99 // Set scrollbars if loading content in main content container.\r
100 // Always use 'hidden' for iframe windows\r
101 if (contentContainer == currentInstance.contentEl) {\r
102 currentInstance.contentWrapperEl.setStyles({\r
103 'overflow': currentInstance.options.scrollbars == true && loadMethod != 'iframe' ? 'auto' : 'hidden'\r
104 });\r
105 }\r
106\r
107 var contentWrapperEl = currentInstance.contentWrapperEl;\r
108 \r
109 if (options.padding != null) {\r
110 contentEl.setStyles({\r
111 'padding-top': options.padding.top,\r
112 'padding-bottom': options.padding.bottom,\r
113 'padding-left': options.padding.left,\r
114 'padding-right': options.padding.right\r
115 });\r
116 }\r
117\r
118 // Remove old content.\r
119 if (contentContainer == contentEl){\r
120 contentEl.empty();\r
121 }\r
122\r
123 // Load new content.\r
124 switch(loadMethod){\r
125 case 'xhr':\r
126 new Request.HTML({\r
127 url: options.url,\r
128 update: contentContainer,\r
129 evalScripts: currentInstance.options.evalScripts,\r
130 evalResponse: currentInstance.options.evalResponse,\r
131 onRequest: function(){\r
132 if (recipient == 'window' && contentContainer == contentEl){\r
133 currentInstance.showSpinner(spinnerEl);\r
134 }\r
135 else if (recipient == 'panel' && contentContainer == contentEl && $('spinner')){\r
136 $('spinner').setStyle('visibility','visible'); \r
137 }\r
138 }.bind(this),\r
139 onFailure: function(){\r
140 if (contentContainer == contentEl){\r
141 contentContainer.set('html','<p><strong>Error Loading XMLHttpRequest</strong></p>');\r
142 if (recipient == 'window') {\r
143 currentInstance.hideSpinner(spinnerEl);\r
144 }\r
145 else if (recipient == 'panel' && $('spinner')) {\r
146 $('spinner').setStyle('visibility', 'hidden');\r
147 }\r
148 }\r
149 }.bind(this),\r
150 onException: function(){}.bind(this),\r
151 onSuccess: function(){\r
152 if (contentContainer == contentEl){\r
153 if (recipient == 'window'){\r
154 currentInstance.hideSpinner(spinnerEl);\r
155 }\r
156 else if (recipient == 'panel' && $('spinner')){\r
157 $('spinner').setStyle('visibility', 'hidden');\r
158 }\r
159 currentInstance.fireEvent('onContentLoaded', element);\r
160 }\r
161 }.bind(this),\r
162 onComplete: function(){}.bind(this)\r
163 }).get();\r
164 break;\r
165 case 'iframe': // May be able to streamline this if the iframe already exists.\r
166 if ( currentInstance.options.contentURL == '' || contentContainer != contentEl) {\r
167 break;\r
168 }\r
169 currentInstance.iframeEl = new Element('iframe', {\r
170 'id': currentInstance.options.id + '_iframe',\r
171 'name': currentInstance.options.id + '_iframe',\r
172 'class': 'mochaIframe',\r
173 'src': options.url,\r
174 'marginwidth': 0,\r
175 'marginheight': 0,\r
176 'frameBorder': 0,\r
177 'scrolling': 'auto',\r
178 'styles': {\r
179 'height': contentWrapperEl.offsetHeight - contentWrapperEl.getStyle('border-top').toInt() - contentWrapperEl.getStyle('border-bottom').toInt(),\r
180 'width': currentInstance.panelEl ? contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('border-left').toInt() - contentWrapperEl.getStyle('border-right').toInt() : '100%' \r
181 }\r
182 }).injectInside(contentEl);\r
183\r
184 // Add onload event to iframe so we can hide the spinner and run onContentLoaded()\r
185 currentInstance.iframeEl.addEvent('load', function(e) {\r
186 if (recipient == 'window') {\r
187 currentInstance.hideSpinner(spinnerEl);\r
188 }\r
189 else if (recipient == 'panel' && contentContainer == contentEl && $('spinner')) {\r
190 $('spinner').setStyle('visibility', 'hidden');\r
191 }\r
192 currentInstance.fireEvent('onContentLoaded', element);\r
193 }.bind(this));\r
194 if (recipient == 'window') {\r
195 currentInstance.showSpinner(spinnerEl);\r
196 }\r
197 else if (recipient == 'panel' && contentContainer == contentEl && $('spinner')){\r
198 $('spinner').setStyle('visibility', 'visible'); \r
199 }\r
200 break;\r
201 case 'html':\r
202 default:\r
203 // Need to test injecting elements as content.\r
204 var elementTypes = new Array('element', 'textnode', 'whitespace', 'collection');\r
205 if (elementTypes.contains($type(options.content))){\r
206 options.content.inject(contentContainer);\r
207 } else {\r
208 contentContainer.set('html', options.content);\r
209 }\r
210 currentInstance.fireEvent('onContentLoaded', element);\r
211 break;\r
212 }\r
213\r
214 },\r
215 /*\r
216 \r
217 Function: reloadIframe\r
218 Reload an iframe. Fixes an issue in Firefox when trying to use location.reload on an iframe that has been destroyed and recreated.\r
219\r
220 Arguments:\r
221 iframe - This should be both the name and the id of the iframe.\r
222\r
223 Syntax:\r
224 (start code)\r
225 MochaUI.reloadIframe(element);\r
226 (end)\r
227\r
228 Example:\r
229 To reload an iframe from within another iframe:\r
230 (start code)\r
231 parent.MochaUI.reloadIframe('myIframeName');\r
232 (end)\r
233\r
234 */\r
235 reloadIframe: function(iframe){\r
236 if (Browser.Engine.gecko) {\r
237 $(iframe).src = $(iframe).src;\r
238 }\r
239 else {\r
240 top.frames[iframe].location.reload(true);\r
241 }\r
242 },\r
243 collapseToggle: function(windowEl){\r
244 var instances = MochaUI.Windows.instances;\r
245 var currentInstance = instances.get(windowEl.id);\r
246 var handles = currentInstance.windowEl.getElements('.handle');\r
247 if (currentInstance.isMaximized == true) return; \r
248 if (currentInstance.isCollapsed == false) {\r
249 currentInstance.isCollapsed = true;\r
250 handles.setStyle('display', 'none');\r
251 if ( currentInstance.iframeEl ) {\r
252 currentInstance.iframeEl.setStyle('visibility', 'hidden');\r
253 }\r
254 currentInstance.contentBorderEl.setStyles({\r
255 visibility: 'hidden',\r
256 position: 'absolute',\r
257 top: -10000,\r
258 left: -10000\r
259 });\r
260 if(currentInstance.toolbarWrapperEl){\r
261 currentInstance.toolbarWrapperEl.setStyles({\r
262 visibility: 'hidden',\r
263 position: 'absolute',\r
264 top: -10000,\r
265 left: -10000\r
266 });\r
267 }\r
268 currentInstance.drawWindowCollapsed(windowEl);\r
269 }\r
270 else {\r
271 currentInstance.isCollapsed = false;\r
272 currentInstance.drawWindow(windowEl);\r
273 currentInstance.contentBorderEl.setStyles({\r
274 visibility: 'visible',\r
275 position: null,\r
276 top: null,\r
277 left: null\r
278 });\r
279 if(currentInstance.toolbarWrapperEl){\r
280 currentInstance.toolbarWrapperEl.setStyles({\r
281 visibility: 'visible',\r
282 position: null,\r
283 top: null,\r
284 left: null\r
285 });\r
286 }\r
287 if ( currentInstance.iframeEl ) {\r
288 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
289 }\r
290 handles.setStyle('display', 'block');\r
291 }\r
292 },\r
293 /*\r
294\r
295 Function: closeWindow\r
296 Closes a window.\r
297\r
298 Syntax:\r
299 (start code)\r
300 MochaUI.closeWindow();\r
301 (end)\r
302\r
303 Arguments: \r
304 windowEl - the ID of the window to be closed\r
305\r
306 Returns:\r
307 true - the window was closed\r
308 false - the window was not closed\r
309\r
310 */\r
311 closeWindow: function(windowEl){\r
312 // Does window exist and is not already in process of closing ?\r
313\r
314 var instances = MochaUI.Windows.instances;\r
315 var currentInstance = instances.get(windowEl.id);\r
316 if (windowEl != $(windowEl) || currentInstance.isClosing) return;\r
317 \r
318 currentInstance.isClosing = true;\r
319 currentInstance.fireEvent('onClose', windowEl);\r
320 if (currentInstance.check) currentInstance.check.destroy();\r
321\r
322 if ((currentInstance.options.type == 'modal' || currentInstance.options.type == 'modal2') && Browser.Engine.trident4){\r
323 $('modalFix').setStyle('display', 'none');\r
324 }\r
325\r
326 if (MochaUI.options.useEffects == false){\r
327 if (currentInstance.options.type == 'modal' || currentInstance.options.type == 'modal2'){\r
328 $('modalOverlay').setStyle('opacity', 0);\r
329 }\r
330 MochaUI.closingJobs(windowEl);\r
331 return true; \r
332 }\r
333 else {\r
334 // Redraws IE windows without shadows since IE messes up canvas alpha when you change element opacity\r
335 if (Browser.Engine.trident) currentInstance.drawWindow(windowEl, false);\r
336 if (currentInstance.options.type == 'modal' || currentInstance.options.type == 'modal2'){\r
337 MochaUI.Modal.modalOverlayCloseMorph.start({\r
338 'opacity': 0\r
339 });\r
340 }\r
341 var closeMorph = new Fx.Morph(windowEl, {\r
342 duration: 120,\r
343 onComplete: function(){\r
344 MochaUI.closingJobs(windowEl);\r
345 return true;\r
346 }.bind(this)\r
347 });\r
348 closeMorph.start({\r
349 'opacity': .4\r
350 });\r
351 }\r
352\r
353 },\r
354 closingJobs: function(windowEl){\r
355\r
356 var instances = MochaUI.Windows.instances;\r
357 var currentInstance = instances.get(windowEl.id);\r
358 windowEl.setStyle('visibility', 'hidden');\r
359 windowEl.destroy();\r
360 currentInstance.fireEvent('onCloseComplete');\r
361 \r
362 if (currentInstance.options.type != 'notification'){\r
363 var newFocus = this.getWindowWithHighestZindex();\r
364 this.focusWindow(newFocus);\r
365 }\r
366\r
367 instances.erase(currentInstance.options.id);\r
368 if (this.loadingWorkspace == true) {\r
369 this.windowUnload();\r
370 }\r
371\r
372 if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {\r
373 var currentButton = $(currentInstance.options.id + '_dockTab');\r
374 if (currentButton != null) {\r
375 MochaUI.Dock.dockSortables.removeItems(currentButton).destroy();\r
376 }\r
377 // Need to resize everything in case the dock becomes smaller when a tab is removed\r
378 MochaUI.Desktop.setDesktopSize();\r
379 }\r
380 },\r
381 /*\r
382 \r
383 Function: closeAll \r
384 Close all open windows.\r
385\r
386 */\r
387 closeAll: function() { \r
388 $$('div.mocha').each(function(windowEl){\r
389 this.closeWindow(windowEl);\r
390 }.bind(this));\r
391 },\r
392 /*\r
393\r
394 Function: toggleWindowVisibility\r
395 Toggle window visibility with Ctrl-Alt-Q.\r
396\r
397 */ \r
398 toggleWindowVisibility: function(){\r
399 MochaUI.Windows.instances.each(function(instance){\r
400 if (instance.options.type == 'modal' || instance.options.type == 'modal2' || instance.isMinimized == true) return; \r
401 var id = $(instance.options.id);\r
402 if (id.getStyle('visibility') == 'visible'){\r
403 if (instance.iframe){\r
404 instance.iframeEl.setStyle('visibility', 'hidden');\r
405 }\r
406 if (instance.toolbarEl){\r
407 instance.toolbarWrapperEl.setStyle('visibility', 'hidden');\r
408 }\r
409 instance.contentBorderEl.setStyle('visibility', 'hidden');\r
410\r
411 id.setStyle('visibility', 'hidden');\r
412 MochaUI.Windows.windowsVisible = false;\r
413 }\r
414 else {\r
415 id.setStyle('visibility', 'visible');\r
416 instance.contentBorderEl.setStyle('visibility', 'visible');\r
417 if (instance.iframe){\r
418 instance.iframeEl.setStyle('visibility', 'visible');\r
419 }\r
420 if (instance.toolbarEl){\r
421 instance.toolbarWrapperEl.setStyle('visibility', 'visible');\r
422 }\r
423 MochaUI.Windows.windowsVisible = true;\r
424 }\r
425 }.bind(this));\r
426\r
427 },\r
428 focusWindow: function(windowEl, fireEvent){\r
429\r
430 // This is used with blurAll\r
431 MochaUI.focusingWindow = 'true';\r
432 var windowClicked = function(){\r
433 MochaUI.focusingWindow = 'false';\r
434 }; \r
435 windowClicked.delay(170, this);\r
436\r
437 // Only focus when needed\r
438 if ($$('.mocha').length == 0) return;\r
439 if (windowEl != $(windowEl) || windowEl.hasClass('isFocused')) return;\r
440\r
441 var instances = MochaUI.Windows.instances;\r
442 var currentInstance = instances.get(windowEl.id);\r
443 \r
444 if (currentInstance.options.type == 'notification') return;\r
445\r
446 MochaUI.Windows.indexLevel += 2;\r
447 windowEl.setStyle('zIndex', MochaUI.Windows.indexLevel);\r
448\r
449 // Used when dragging and resizing windows\r
450 $('windowUnderlay').setStyle('zIndex', MochaUI.Windows.indexLevel - 1).inject($(windowEl),'after');\r
451\r
452 // Fire onBlur for the window that lost focus.\r
453 instances.each(function(instance){\r
454 if (instance.windowEl.hasClass('isFocused')){\r
455 instance.fireEvent('onBlur', instance.windowEl);\r
456 }\r
457 instance.windowEl.removeClass('isFocused');\r
458 });\r
459\r
460 if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {\r
461 MochaUI.Dock.makeActiveTab();\r
462 }\r
463 currentInstance.windowEl.addClass('isFocused');\r
464\r
465 if (fireEvent != false){\r
466 currentInstance.fireEvent('onFocus', windowEl);\r
467 }\r
468\r
469 },\r
470 getWindowWithHighestZindex: function(){\r
471 this.highestZindex = 0;\r
472 $$('div.mocha').each(function(element){\r
473 this.zIndex = element.getStyle('zIndex');\r
474 if (this.zIndex >= this.highestZindex) {\r
475 this.highestZindex = this.zIndex;\r
476 } \r
477 }.bind(this));\r
478 $$('div.mocha').each(function(element){\r
479 if (element.getStyle('zIndex') == this.highestZindex) {\r
480 this.windowWithHighestZindex = element;\r
481 }\r
482 }.bind(this));\r
483 return this.windowWithHighestZindex;\r
484 },\r
485 blurAll: function(){\r
486 if (MochaUI.focusingWindow == 'false') {\r
487 $$('.mocha').each(function(windowEl){\r
488 var instances = MochaUI.Windows.instances;\r
489 var currentInstance = instances.get(windowEl.id);\r
490 if (currentInstance.options.type != 'modal' && currentInstance.options.type != 'modal2'){\r
491 windowEl.removeClass('isFocused');\r
492 }\r
493 });\r
494 $$('div.dockTab').removeClass('activeDockTab');\r
495 }\r
496 },\r
497 roundedRect: function(ctx, x, y, width, height, radius, rgb, a){\r
498 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
499 ctx.beginPath();\r
500 ctx.moveTo(x, y + radius);\r
501 ctx.lineTo(x, y + height - radius);\r
502 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);\r
503 ctx.lineTo(x + width - radius, y + height);\r
504 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);\r
505 ctx.lineTo(x + width, y + radius);\r
506 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);\r
507 ctx.lineTo(x + radius, y);\r
508 ctx.quadraticCurveTo(x, y, x, y + radius);\r
509 ctx.fill(); \r
510 },\r
511 triangle: function(ctx, x, y, width, height, rgb, a){\r
512 ctx.beginPath();\r
513 ctx.moveTo(x + width, y);\r
514 ctx.lineTo(x, y + height);\r
515 ctx.lineTo(x + width, y + height);\r
516 ctx.closePath();\r
517 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
518 ctx.fill();\r
519 },\r
520 circle: function(ctx, x, y, diameter, rgb, a){\r
521 ctx.beginPath();\r
522 ctx.moveTo(x, y);\r
523 ctx.arc(x, y, diameter, 0, Math.PI*2, true);\r
524 ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
525 ctx.fill();\r
526 },\r
527 /*\r
528\r
529 Function: centerWindow\r
530 Center a window in it's container. If windowEl is undefined it will center the window that has focus.\r
531\r
532 */\r
533 centerWindow: function(windowEl){\r
534 \r
535 if(!windowEl){\r
536 MochaUI.Windows.instances.each(function(instance){\r
537 if (instance.windowEl.hasClass('isFocused')){\r
538 windowEl = instance.windowEl;\r
539 }\r
540 });\r
541 }\r
542\r
543 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
544 var options = currentInstance.options;\r
545 var dimensions = options.container.getCoordinates();\r
546 var windowPosTop = (dimensions.height * .5) - ((options.height + currentInstance.headerFooterShadow) * .5);\r
547 if (windowPosTop < 0) {\r
548 windowPosTop = 0;\r
549 }\r
550 var windowPosLeft = (dimensions.width * .5) - (options.width * .5);\r
551 if (windowPosLeft < 0) {\r
552 windowPosLeft = 0;\r
553 }\r
554 if (MochaUI.options.useEffects == true){\r
555 currentInstance.morph.start({\r
556 'top': windowPosTop,\r
557 'left': windowPosLeft\r
558 });\r
559 }\r
560 else {\r
561 windowEl.setStyles({\r
562 'top': windowPosTop,\r
563 'left': windowPosLeft\r
564 });\r
565 }\r
566 },\r
567 notification: function(message){\r
568 new MochaUI.Window({\r
569 loadMethod: 'html',\r
570 closeAfter: 1500,\r
571 type: 'notification',\r
572 addClass: 'notification',\r
573 content: message,\r
574 width: 220,\r
575 height: 40,\r
576 y: 53,\r
577 padding: { top: 10, right: 12, bottom: 10, left: 12 },\r
578 shadowBlur: 5,\r
579 bodyBgColor: [255, 255, 255] \r
580 });\r
581 },\r
582 /*\r
583\r
584 Function: dynamicResize\r
585 Use with a timer to resize a window as the window's content size changes, such as with an accordian.\r
586\r
587 */\r
588 dynamicResize: function(windowEl){\r
589 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
590 var contentWrapperEl = currentInstance.contentWrapperEl;\r
591 var contentEl = currentInstance.contentEl;\r
592 \r
593 contentWrapperEl.setStyle('height', contentEl.offsetHeight);\r
594 contentWrapperEl.setStyle('width', contentEl.offsetWidth); \r
595 currentInstance.drawWindow(windowEl);\r
596 }, \r
597 /*\r
598\r
599 Function: garbageCleanUp\r
600 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.\r
601\r
602 Syntax:\r
603 (start code)\r
604 MochaUI.garbageCleanUp();\r
605 (end)\r
606 \r
607 */\r
608 garbageCleanUp: function(){\r
609 $$('div.mocha').each(function(el){\r
610 el.destroy();\r
611 }.bind(this));\r
612 },\r
613 /*\r
614 \r
615 The underlay is inserted directly under windows when they are being dragged or resized\r
616 so that the cursor is not captured by iframes or other plugins (such as Flash)\r
617 underneath the window.\r
618 \r
619 */\r
620 underlayInitialize: function(){\r
621 var windowUnderlay = new Element('div', {\r
622 'id': 'windowUnderlay',\r
623 'styles': {\r
624 'height': parent.getCoordinates().height,\r
625 'opacity': .01,\r
626 'display': 'none'\r
627 }\r
628 }).inject(document.body);\r
629 },\r
630 setUnderlaySize: function(){\r
631 $('windowUnderlay').setStyle('height', parent.getCoordinates().height);\r
632 }\r
633});\r
634\r
635/* \r
636\r
637function: fixPNG\r
638 Bob Osola's PngFix for IE6.\r
639\r
640example:\r
641 (begin code)\r
642 <img src="xyz.png" alt="foo" width="10" height="20" onload="fixPNG(this)">\r
643 (end)\r
644\r
645note:\r
646 You must have the image height and width attributes specified in the markup.\r
647\r
648*/\r
649\r
650function fixPNG(myImage){\r
651 if (Browser.Engine.trident4 && document.body.filters){\r
652 var imgID = (myImage.id) ? "id='" + myImage.id + "' " : "";\r
653 var imgClass = (myImage.className) ? "class='" + myImage.className + "' " : "";\r
654 var imgTitle = (myImage.title) ? "title='" + myImage.title + "' " : "title='" + myImage.alt + "' ";\r
655 var imgStyle = "display:inline-block;" + myImage.style.cssText;\r
656 var strNewHTML = "<span " + imgID + imgClass + imgTitle\r
657 + " style=\"" + "width:" + myImage.width\r
658 + "px; height:" + myImage.height\r
659 + "px;" + imgStyle + ";"\r
660 + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"\r
661 + "(src=\'" + myImage.src + "\', sizingMethod='scale');\"></span>";\r
662 myImage.outerHTML = strNewHTML; \r
663 }\r
664}\r
665\r
666// Toggle window visibility with Ctrl-Alt-Q\r
667document.addEvent('keydown', function(event){\r
668 if (event.key == 'q' && event.control && event.alt) {\r
669 MochaUI.toggleWindowVisibility();\r
670 }\r
671});\r
672\r
673// Blur all windows if user clicks anywhere else on the page\r
674document.addEvent('mousedown', function(event){\r
675 MochaUI.blurAll.delay(50);\r
676});\r
677\r
678document.addEvent('domready', function(){\r
679 MochaUI.underlayInitialize();\r
680});\r
681\r
682window.addEvent('resize', function(){\r
683 MochaUI.setUnderlaySize();\r
684});\r
685/*\r
686\r
687Script: Window.js\r
688 Build windows.\r
689\r
690Copyright:\r
691 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.\r
692\r
693License:\r
694 MIT-style license. \r
695\r
696Requires:\r
697 Core.js\r
698\r
699*/\r
700\r
701/*\r
702Class: Window\r
703 Creates a single MochaUI window.\r
704 \r
705Syntax:\r
706 (start code)\r
707 new MochaUI.Window(options);\r
708 (end) \r
709\r
710Arguments:\r
711 options\r
712\r
713Options:\r
714 id - The ID of the window. If not defined, it will be set to 'win' + windowIDCount.\r
715 title - The title of the window.\r
716 icon - Place an icon in the window's titlebar. This is either set to false or to the url of the icon. It is set up for icons that are 16 x 16px.\r
717 type - ('window', 'modal', 'modal2', or 'notification') Defaults to 'window'.\r
718 loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html'.\r
719 contentURL - Used if loadMethod is set to 'xhr' or 'iframe'.\r
720 closeAfter - Either false or time in milliseconds. Closes the window after a certain period of time in milliseconds. This is particularly useful for notifications.\r
721 evalScripts - (boolean) An xhr loadMethod option. Defaults to true.\r
722 evalResponse - (boolean) An xhr loadMethod option. Defaults to false.\r
723 content - (string or element) An html loadMethod option.\r
724 toolbar - (boolean) Create window toolbar. Defaults to false. This can be used for tabs, media controls, and so forth.\r
725 toolbarPosition - ('top' or 'bottom') Defaults to top.\r
726 toolbarHeight - (number)\r
727 toolbarURL - (url) Defaults to 'pages/lipsum.html'.\r
728 toolbarContent - (string)\r
729 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.\r
730 restrict - (boolean) Restrict window to container when dragging.\r
731 shape - ('box' or 'gauge') Shape of window. Defaults to 'box'.\r
732 collapsible - (boolean) Defaults to true.\r
733 minimizable - (boolean) Requires MochaUI.Desktop and MochaUI.Dock. Defaults to true if dependenices are met. \r
734 maximizable - (boolean) Requires MochaUI.Desktop. Defaults to true if dependenices are met.\r
735 closable - (boolean) Defaults to true. \r
736 draggable - (boolean) Defaults to false for modals; otherwise true.\r
737 draggableGrid - (false or number) Distance in pixels for snap-to-grid dragging. Defaults to false. \r
738 draggableLimit - (false or number) An object with x and y properties used to limit the movement of the Window. Defaults to false.\r
739 draggableSnap - (boolean) The distance to drag before the Window starts to respond to the drag. Defaults to false.\r
740 resizable - (boolean) Defaults to false for modals, notifications and gauges; otherwise true.\r
741 resizeLimit - (object) Minimum and maximum width and height of window when resized.\r
742 addClass - (string) Add a class to the window for more control over styling. \r
743 width - (number) Width of content area. \r
744 height - (number) Height of content area.\r
745 x - (number) If x and y are left undefined the window is centered on the page.\r
746 y - (number)\r
747 scrollbars - (boolean)\r
748 padding - (object)\r
749 shadowBlur - (number) Width of shadows.\r
750 shadowOffset - Should be positive and not be greater than the ShadowBlur.\r
751 controlsOffset - Change this if you want to reposition the window controls.\r
752 useCanvas - (boolean) Set this to false if you don't want a canvas body.\r
753 useCanvasControls - (boolean) Set this to false if you wish to use images for the buttons.\r
754 headerHeight - (number) Height of window titlebar.\r
755 footerHeight - (number) Height of window footer.\r
756 cornerRadius - (number)\r
757 contentBgColor - (hex) Body background color\r
758 headerStartColor - ([r,g,b,]) Titlebar gradient's top color\r
759 headerStopColor - ([r,g,b,]) Titlebar gradient's bottom color\r
760 bodyBgColor - ([r,g,b,]) Background color of the main canvas shape\r
761 minimizeBgColor - ([r,g,b,]) Minimize button background color\r
762 minimizeColor - ([r,g,b,]) Minimize button color\r
763 maximizeBgColor - ([r,g,b,]) Maximize button background color\r
764 maximizeColor - ([r,g,b,]) Maximize button color\r
765 closeBgColor - ([r,g,b,]) Close button background color\r
766 closeColor - ([r,g,b,]) Close button color\r
767 resizableColor - ([r,g,b,]) Resizable icon color\r
768 onBeforeBuild - (function) Fired just before the window is built.\r
769 onContentLoaded - (function) Fired when content is successfully loaded via XHR or Iframe.\r
770 onFocus - (function) Fired when the window is focused.\r
771 onBlur - (function) Fired when window loses focus.\r
772 onResize - (function) Fired when the window is resized.\r
773 onMinimize - (function) Fired when the window is minimized.\r
774 onMaximize - (function) Fired when the window is maximized.\r
775 onRestore - (function) Fired when a window is restored from minimized or maximized.\r
776 onClose - (function) Fired just before the window is closed.\r
777 onCloseComplete - (function) Fired after the window is closed.\r
778\r
779Returns:\r
780 Window object.\r
781\r
782Example:\r
783 Define a window. It is suggested you name the function the same as your window ID + "Window".\r
784 (start code)\r
785 var mywindowWindow = function(){\r
786 new MochaUI.Window({\r
787 id: 'mywindow',\r
788 title: 'My Window',\r
789 loadMethod: 'xhr',\r
790 contentURL: 'pages/lipsum.html',\r
791 width: 340,\r
792 height: 150\r
793 });\r
794 }\r
795 (end)\r
796\r
797Example:\r
798 Create window onDomReady.\r
799 (start code) \r
800 window.addEvent('domready', function(){\r
801 mywindow();\r
802 });\r
803 (end)\r
804\r
805Example:\r
806 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.\r
807\r
808 If you wish to add links in windows that open other windows remember to add events to those links when the windows are created.\r
809\r
810 (start code)\r
811 // Javascript:\r
812 if ($('mywindowLink')){\r
813 $('mywindowLink').addEvent('click', function(e) {\r
814 new Event(e).stop();\r
815 mywindow();\r
816 });\r
817 }\r
818\r
819 // HTML:\r
820 <a id="mywindowLink" href="pages/lipsum.html">My Window</a> \r
821 (end)\r
822\r
823\r
824 Loading Content with an XMLHttpRequest(xhr):\r
825 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.\r
826 \r
827 Iframes:\r
828 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.\r
829\r
830*/\r
831\r
832// Having these options outside of the Class allows us to add, change, and remove\r
833// individual options without rewriting all of them.\r
834\r
835MochaUI.Windows.windowOptions = {\r
836 id: null,\r
837 title: 'New Window',\r
838 icon: false,\r
839 type: 'window',\r
840\r
841 loadMethod: 'html',\r
842 contentURL: 'pages/lipsum.html',\r
843\r
844 closeAfter: false,\r
845\r
846 // xhr options\r
847 evalScripts: true,\r
848 evalResponse: false,\r
849\r
850 // html options\r
851 content: 'Window content',\r
852\r
853 // Toolbar\r
854 toolbar: false,\r
855 toolbarPosition: 'top',\r
856 toolbarHeight: 29,\r
857 toolbarURL: 'pages/lipsum.html',\r
858 toolbarContent: '',\r
a59dc700
CP
859 toolbarLoadMethod: 'xhr',\r
860 \r
08137ae6
CP
861 // Toolbar\r
862 toolbar2: false,\r
863 toolbar2Position: 'bottom',\r
864 toolbar2Height: 29,\r
865 toolbar2URL: 'pages/lipsum.html',\r
866 toolbar2Content: '', \r
a59dc700
CP
867 toolbar2LoadMethod: 'xhr',\r
868 \r
08137ae6
CP
869 // Container options\r
870 container: null,\r
871 restrict: true,\r
872 shape: 'box',\r
873\r
874 // Window Controls\r
875 collapsible: true,\r
876 minimizable: true,\r
877 maximizable: true,\r
878 closable: true,\r
879\r
880 // Draggable\r
881 draggable: null,\r
882 draggableGrid: false,\r
883 draggableLimit: false,\r
884 draggableSnap: false,\r
885\r
886 // Resizable\r
887 resizable: null,\r
888 resizeLimit: {'x': [250, 2500], 'y': [125, 2000]},\r
889 \r
890 // Style options:\r
891 addClass: '',\r
892 width: 300,\r
893 height: 125,\r
894 x: null,\r
895 y: null,\r
896 scrollbars: true,\r
897 padding: { top: 10, right: 12, bottom: 10, left: 12 },\r
898 shadowBlur: 5,\r
899 shadowOffset: {'x': 0, 'y': 1},\r
900 controlsOffset: {'right': 6, 'top': 6},\r
901 useCanvas: true,\r
902 useCanvasControls: true,\r
903 useSpinner: true, // Toggles whether or not the ajax spinners are displayed in window footers.\r
904\r
905 // Color options: \r
906 headerHeight: 25,\r
907 footerHeight: 25,\r
908 cornerRadius: 8,\r
909 contentBgColor: '#fff',\r
910 headerStartColor: [250, 250, 250],\r
911 headerStopColor: [229, 229, 229],\r
912 bodyBgColor: [229, 229, 229],\r
913 minimizeBgColor: [255, 255, 255],\r
914 minimizeColor: [0, 0, 0],\r
915 maximizeBgColor: [255, 255, 255],\r
916 maximizeColor: [0, 0, 0],\r
917 closeBgColor: [255, 255, 255],\r
918 closeColor: [0, 0, 0],\r
919 resizableColor: [254, 254, 254],\r
920\r
921 // Events\r
922 onBeforeBuild: $empty,\r
923 onContentLoaded: $empty,\r
924 onFocus: $empty,\r
925 onBlur: $empty,\r
926 onResize: $empty,\r
927 onMinimize: $empty,\r
928 onMaximize: $empty,\r
929 onRestore: $empty,\r
930 onClose: $empty,\r
931 onCloseComplete: $empty\r
932};\r
933\r
934MochaUI.Window = new Class({\r
935 options: MochaUI.Windows.windowOptions,\r
936 initialize: function(options){\r
937 this.setOptions(options);\r
938\r
939 // Shorten object chain\r
940 var options = this.options;\r
941\r
942 $extend(this, {\r
943 mochaControlsWidth: 0,\r
944 minimizebuttonX: 0, // Minimize button horizontal position\r
945 maximizebuttonX: 0, // Maximize button horizontal position\r
946 closebuttonX: 0, // Close button horizontal position\r
947 headerFooterShadow: options.headerHeight + options.footerHeight + (options.shadowBlur * 2),\r
948 oldTop: 0,\r
949 oldLeft: 0,\r
950 isMaximized: false,\r
951 isMinimized: false,\r
952 isCollapsed: false,\r
953 timestamp: $time()\r
954 });\r
955 \r
956 // May be better to use if type != window\r
957 if (options.type != 'window'){\r
958 options.container = document.body;\r
959 options.minimizable = false;\r
960 }\r
961 if (!options.container){\r
962 options.container = MochaUI.Desktop.desktop ? MochaUI.Desktop.desktop : document.body;\r
963 }\r
964\r
965 // Set this.options.resizable to default if it was not defined\r
966 if (options.resizable == null){\r
967 if (options.type != 'window' || options.shape == 'gauge'){\r
968 options.resizable = false;\r
969 }\r
970 else {\r
971 options.resizable = true; \r
972 }\r
973 }\r
974\r
975 // Set this.options.draggable if it was not defined\r
976 if (options.draggable == null){\r
977 if (options.type != 'window'){\r
978 options.draggable = false;\r
979 }\r
980 else {\r
981 options.draggable = true;\r
982 }\r
983 }\r
984\r
985 // Gauges are not maximizable or resizable\r
986 if (options.shape == 'gauge' || options.type == 'notification'){\r
987 options.collapsible = false;\r
988 options.maximizable = false;\r
989 options.contentBgColor = 'transparent';\r
990 options.scrollbars = false;\r
991 options.footerHeight = 0;\r
992 }\r
993 if (options.type == 'notification'){\r
994 options.closable = false;\r
995 options.headerHeight = 0;\r
996 }\r
997 \r
998 // Minimizable, dock is required and window cannot be modal\r
999 if (MochaUI.Dock && $(MochaUI.options.dock)){\r
1000 if (MochaUI.Dock.dock && options.type != 'modal' && options.type != 'modal2'){\r
1001 options.minimizable = options.minimizable;\r
1002 }\r
1003 }\r
1004 else {\r
1005 options.minimizable = false;\r
1006 }\r
1007\r
1008 // Maximizable, desktop is required\r
1009 options.maximizable = MochaUI.Desktop.desktop && options.maximizable && options.type != 'modal' && options.type != 'modal2';\r
1010\r
1011 if (this.options.type == 'modal2') {\r
1012 this.options.shadowBlur = 0;\r
1013 this.options.shadowOffset = {'x': 0, 'y': 0};\r
1014 this.options.useSpinner = false;\r
1015 this.options.useCanvas = false;\r
1016 this.options.footerHeight = 0;\r
1017 this.options.headerHeight = 0;\r
1018 }\r
1019\r
1020 // If window has no ID, give it one.\r
1021 if (options.id == null){\r
1022 options.id = 'win' + (++MochaUI.Windows.windowIDCount);\r
1023 }\r
1024 this.windowEl = $(options.id);\r
1025 \r
1026 this.newWindow();\r
1027 \r
1028 // Return window object\r
1029 return this;\r
1030 },\r
1031 saveValues: function(){ \r
1032 var coordinates = this.windowEl.getCoordinates();\r
1033 this.options.x = coordinates.left.toInt();\r
1034 this.options.y = coordinates.top.toInt();\r
1035 },\r
1036 /*\r
1037\r
1038 Internal Function: newWindow\r
1039 \r
1040 Arguments: \r
1041 properties\r
1042\r
1043 */\r
1044 newWindow: function(properties){ // options is not doing anything\r
1045\r
1046 // Shorten object chain\r
1047 var instances = MochaUI.Windows.instances;\r
1048 var instanceID = instances.get(this.options.id);\r
1049 \r
1050 // Here we check to see if there is already a class instance for this window\r
1051 if (instanceID){\r
1052 var currentInstance = instanceID;\r
1053 }\r
1054\r
1055 // Check if window already exists and is not in progress of closing\r
1056 if ( this.windowEl && !this.isClosing ){\r
1057 // Restore if minimized\r
1058 if (currentInstance.isMinimized){\r
1059 MochaUI.Dock.restoreMinimized(this.windowEl);\r
1060 }\r
1061 // Expand and focus if collapsed\r
1062 if (currentInstance.isCollapsed){\r
1063 MochaUI.collapseToggle(this.windowEl);\r
1064 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);\r
1065 }\r
1066 // Else focus\r
1067 else {\r
1068 var coordinates = document.getCoordinates();\r
1069 if (this.windowEl.getStyle('left').toInt() > coordinates.width || this.windowEl.getStyle('top').toInt() > coordinates.height){\r
1070 MochaUI.centerWindow(this.windowEl); \r
1071 }\r
1072 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);\r
1073 }\r
1074 return;\r
1075 }\r
1076 else {\r
1077 instances.set(this.options.id, this);\r
1078 }\r
1079\r
1080 this.isClosing = false;\r
1081 this.fireEvent('onBeforeBuild');\r
1082\r
1083 // Create window div\r
1084 MochaUI.Windows.indexLevel++;\r
1085 this.windowEl = new Element('div', {\r
1086 'class': 'mocha',\r
1087 'id': this.options.id,\r
1088 'styles': {\r
1089 'width': this.options.width,\r
1090 'height': this.options.height,\r
1091 'display': 'block',\r
1092 'opacity': 0,\r
1093 'zIndex': MochaUI.Windows.indexLevel += 2\r
1094 }\r
1095 });\r
1096\r
1097 this.windowEl.addClass(this.options.addClass);\r
1098 \r
1099 if (this.options.type == 'modal2') {\r
1100 this.windowEl.addClass('modal2');\r
1101 }\r
1102\r
1103 // Fix a mouseover issue with gauges in IE7\r
1104 if ( Browser.Engine.trident && this.options.shape == 'gauge') {\r
1105 this.windowEl.setStyle('background', 'url(../images/spacer.gif)');\r
1106 }\r
1107\r
1108 if ((this.options.type == 'modal' || this.options.type == 'modal2' ) && Browser.Platform.mac && Browser.Engine.gecko){\r
1109 if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {\r
1110 var ffversion = new Number(RegExp.$1);\r
1111 if (ffversion < 3) {\r
1112 this.windowEl.setStyle('position', 'fixed');\r
1113 }\r
1114 }\r
1115 }\r
1116\r
1117 if (this.options.loadMethod == 'iframe') {\r
1118 this.options.padding = { top: 0, right: 0, bottom: 0, left: 0 };\r
1119 }\r
1120\r
1121 // Insert sub elements inside windowEl\r
1122 this.insertWindowElements();\r
1123\r
1124 // Set title\r
1125 this.titleEl.set('html',this.options.title);\r
1126\r
1127 // Set scrollbars, always use 'hidden' for iframe windows\r
1128 this.contentWrapperEl.setStyles({\r
1129 'overflow': 'hidden',\r
1130 'background': this.options.contentBgColor\r
1131 });\r
1132\r
1133 this.contentEl.setStyles({\r
1134 'padding-top': this.options.padding.top,\r
1135 'padding-bottom': this.options.padding.bottom,\r
1136 'padding-left': this.options.padding.left,\r
1137 'padding-right': this.options.padding.right\r
1138 });\r
1139\r
1140\r
1141 if (this.options.shape == 'gauge'){\r
1142 if (this.options.useCanvasControls){\r
1143 this.canvasControlsEl.setStyle('display', 'none');\r
1144 }\r
1145 else {\r
1146 this.controlsEl.setStyle('display', 'none');\r
1147 }\r
1148 this.windowEl.addEvent('mouseover', function(){\r
1149 this.mouseover = true;\r
1150 var showControls = function(){\r
1151 if (this.mouseover != false){\r
1152 if (this.options.useCanvasControls){\r
1153 this.canvasControlsEl.setStyle('display', 'block');\r
1154 }\r
1155 else {\r
1156 this.controlsEl.setStyle('display', 'block');\r
1157 }\r
1158 this.canvasHeaderEl.setStyle('display', 'block');\r
1159 this.titleEl.setStyle('display', 'block');\r
1160 }\r
1161 };\r
1162 showControls.delay(150, this);\r
1163\r
1164 }.bind(this));\r
1165 this.windowEl.addEvent('mouseleave', function(){\r
1166 this.mouseover = false;\r
1167 if (this.options.useCanvasControls){\r
1168 this.canvasControlsEl.setStyle('display', 'none');\r
1169 }\r
1170 else {\r
1171 this.controlsEl.setStyle('display', 'none');\r
1172 }\r
1173 this.canvasHeaderEl.setStyle('display', 'none');\r
1174 this.titleEl.setStyle('display', 'none');\r
1175 }.bind(this));\r
1176 }\r
1177\r
1178 // Inject window into DOM\r
1179 this.windowEl.injectInside(this.options.container);\r
1180\r
1181 if (this.options.type != 'notification'){\r
1182 this.setMochaControlsWidth();\r
1183 } \r
1184\r
1185 // Add content to window.\r
1186 MochaUI.updateContent({\r
1187 'element': this.windowEl,\r
1188 'content': this.options.content,\r
1189 'url': this.options.contentURL\r
1190 }); \r
1191 \r
1192 // Add content to window toolbar.\r
1193 if (this.options.toolbar == true){\r
1194 MochaUI.updateContent({\r
1195 'element': this.windowEl,\r
1196 'childElement': this.toolbarEl,\r
1197 'content': this.options.toolbarContent,\r
a59dc700 1198 'loadMethod': this.options.toolbarLoadMethod,\r
08137ae6
CP
1199 'url': this.options.toolbarURL\r
1200 });\r
1201 }\r
1202\r
1203 // Add content to window toolbar.\r
1204 if (this.options.toolbar2 == true){\r
1205 MochaUI.updateContent({\r
1206 'element': this.windowEl,\r
1207 'childElement': this.toolbar2El,\r
1208 'content': this.options.toolbar2Content,\r
a59dc700 1209 'loadMethod': this.options.toolbar2LoadMethod,\r
08137ae6
CP
1210 'url': this.options.toolbar2URL\r
1211 });\r
1212 }\r
1213 \r
1214 this.drawWindow(this.windowEl);\r
1215 \r
1216 // Attach events to the window\r
1217 this.attachDraggable(this.windowEl);\r
1218 this.attachResizable(this.windowEl);\r
1219 this.setupEvents(this.windowEl);\r
1220 \r
1221 if (this.options.resizable){\r
1222 this.adjustHandles();\r
1223 }\r
1224\r
1225 // Move window into position. If position not specified by user then center the window on the page.\r
1226 if (this.options.container == document.body || this.options.container == MochaUI.Desktop.desktop){\r
1227 var dimensions = window.getSize();\r
1228 }\r
1229 else {\r
1230 var dimensions = $(this.options.container).getSize();\r
1231 }\r
1232\r
1233 if (!this.options.y) {\r
1234 var y = (dimensions.y * .5) - ((this.options.height + this.headerFooterShadow + this.windowEl.getStyle('border-top').toInt() + this.windowEl.getStyle('border-bottom').toInt()) * .5);\r
1235 }\r
1236 else {\r
1237 var y = this.options.y - this.options.shadowBlur;\r
1238 }\r
1239\r
1240 if (!this.options.x) {\r
1241 var x = (dimensions.x * .5) - (this.options.width * .5);\r
1242 }\r
1243 else {\r
1244 var x = this.options.x - this.options.shadowBlur;\r
1245 }\r
1246\r
1247 this.windowEl.setStyles({\r
1248 'top': y,\r
1249 'left': x\r
1250 });\r
1251\r
1252 // Create opacityMorph\r
1253 if (MochaUI.options.useEffects == true){\r
1254 // IE cannot handle both element opacity and VML alpha at the same time.\r
1255 if (Browser.Engine.trident){\r
1256 this.drawWindow(this.windowEl, false);\r
1257 }\r
1258 this.opacityMorph = new Fx.Morph(this.windowEl, {\r
1259 'duration': 350,\r
1260 onComplete: function(){\r
1261 if (Browser.Engine.trident){\r
1262 this.drawWindow(this.windowEl);\r
1263 }\r
1264 }.bind(this)\r
1265 });\r
1266 }\r
1267\r
1268 if (this.options.type == 'modal' || this.options.type == 'modal2') {\r
1269 MochaUI.currentModal = this.windowEl;\r
1270 if (Browser.Engine.trident4){\r
1271 $('modalFix').setStyle('display', 'block');\r
1272 }\r
1273 $('modalOverlay').setStyle('display', 'block');\r
1274 if (MochaUI.options.useEffects == false){\r
1275 $('modalOverlay').setStyle('opacity', .6);\r
1276 this.windowEl.setStyles({\r
1277 'zIndex': 11000,\r
1278 'opacity': 1\r
1279 });\r
1280 }\r
1281 else {\r
1282 MochaUI.Modal.modalOverlayCloseMorph.cancel();\r
1283 MochaUI.Modal.modalOverlayOpenMorph.start({\r
1284 'opacity': .6\r
1285 });\r
1286 this.windowEl.setStyles({\r
1287 'zIndex': 11000\r
1288 });\r
1289 this.opacityMorph.start({\r
1290 'opacity': 1\r
1291 });\r
1292 }\r
1293\r
1294 $$('.dockTab').removeClass('activeDockTab');\r
1295 $$('.mocha').removeClass('isFocused');\r
1296 this.windowEl.addClass('isFocused');\r
1297 \r
1298 }\r
1299 else if (MochaUI.options.useEffects == false){\r
1300 this.windowEl.setStyle('opacity', 1);\r
1301 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);\r
1302 }\r
1303 else {\r
1304 this.opacityMorph.start({\r
1305 'opacity': 1\r
1306 });\r
1307 setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);\r
1308 }\r
1309\r
1310 // This is a generic morph that can be reused later by functions like centerWindow()\r
1311 this.morph = new Fx.Morph(this.windowEl, {\r
1312 'duration': 200\r
1313 });\r
1314\r
1315 // Add check mark to menu if link exists in menu\r
1316 // Need to make sure the check mark is not added to links not in menu\r
1317 \r
1318 if ($(this.windowEl.id + 'LinkCheck')){\r
1319 this.check = new Element('div', {\r
1320 'class': 'check',\r
1321 'id': this.options.id + '_check'\r
1322 }).inject(this.windowEl.id + 'LinkCheck');\r
1323 }\r
1324 \r
1325 if (this.options.closeAfter != false){\r
1326 MochaUI.closeWindow.delay(this.options.closeAfter, this, this.windowEl);\r
1327 }\r
1328\r
1329 if (MochaUI.Dock && $(MochaUI.options.dock) && this.options.type == 'window' ){\r
1330 MochaUI.Dock.createDockTab(this.windowEl);\r
1331 }\r
1332\r
1333 },\r
1334 setupEvents: function(windowEl) {\r
1335\r
1336 // Set events\r
1337 // Note: if a button does not exist, its due to properties passed to newWindow() stating otherwice\r
1338 if (this.closeButtonEl){\r
1339 this.closeButtonEl.addEvent('click', function(e) {\r
1340 new Event(e).stop();\r
1341 MochaUI.closeWindow(windowEl);\r
1342 }.bind(this));\r
1343 }\r
1344\r
1345 if (this.options.type == 'window'){\r
1346 windowEl.addEvent('mousedown', function() {\r
1347 MochaUI.focusWindow(windowEl);\r
1348 }.bind(this));\r
1349 }\r
1350\r
1351 if (this.minimizeButtonEl) {\r
1352 this.minimizeButtonEl.addEvent('click', function(e) {\r
1353 new Event(e).stop();\r
1354 MochaUI.Dock.minimizeWindow(windowEl);\r
1355 }.bind(this));\r
1356 }\r
1357\r
1358 if (this.maximizeButtonEl) {\r
1359 this.maximizeButtonEl.addEvent('click', function(e) {\r
1360 new Event(e).stop(); \r
1361 if (this.isMaximized) {\r
1362 MochaUI.Desktop.restoreWindow(windowEl);\r
1363 } else {\r
1364 MochaUI.Desktop.maximizeWindow(windowEl);\r
1365 }\r
1366 }.bind(this));\r
1367 }\r
1368\r
1369 if (this.options.collapsible == true){\r
1370 // Keep titlebar text from being selected on double click in Safari.\r
1371 this.titleEl.addEvent('selectstart', function(e) {\r
1372 e = new Event(e).stop();\r
1373 }.bind(this));\r
1374 // Keep titlebar text from being selected on double click in Opera.\r
1375 this.titleBarEl.addEvent('mousedown', function(e) {\r
1376 if (Browser.Engine.trident) {\r
1377 this.titleEl.setCapture();\r
1378 }\r
1379 }.bind(this));\r
1380 this.titleBarEl.addEvent('mouseup', function(e) {\r
1381 if (Browser.Engine.trident) {\r
1382 this.titleEl.releaseCapture();\r
1383 }\r
1384 }.bind(this));\r
1385 this.titleBarEl.addEvent('dblclick', function(e) {\r
1386 e = new Event(e).stop();\r
1387 MochaUI.collapseToggle(this.windowEl);\r
1388 }.bind(this));\r
1389 }\r
1390\r
1391 },\r
1392 /*\r
1393\r
1394 Internal Function: attachDraggable()\r
1395 Make window draggable.\r
1396\r
1397 Arguments:\r
1398 windowEl\r
1399 \r
1400 */\r
1401 attachDraggable: function(windowEl){\r
1402 if (!this.options.draggable) return;\r
1403 this.windowDrag = new Drag.Move(windowEl, {\r
1404 handle: this.titleBarEl,\r
1405 container: this.options.restrict == true ? $(this.options.container) : false,\r
1406 grid: this.options.draggableGrid,\r
1407 limit: this.options.draggableLimit,\r
1408 snap: this.options.draggableSnap,\r
1409 onStart: function() {\r
1410 if (this.options.type != 'modal' && this.options.type != 'modal2'){ \r
1411 MochaUI.focusWindow(windowEl);\r
1412 $('windowUnderlay').setStyle('display','block');\r
1413 }\r
1414 if ( this.iframeEl )\r
1415 this.iframeEl.setStyle('visibility', 'hidden');\r
1416 }.bind(this),\r
1417 onComplete: function() {\r
1418 if (this.options.type != 'modal' && this.options.type != 'modal2') {\r
1419 $('windowUnderlay').setStyle('display', 'none');\r
1420 }\r
1421 if ( this.iframeEl ){\r
1422 this.iframeEl.setStyle('visibility', 'visible');\r
1423 }\r
1424 // Store new position in options.\r
1425 this.saveValues();\r
1426 }.bind(this)\r
1427 });\r
1428 },\r
1429 /*\r
1430\r
1431 Internal Function: attachResizable\r
1432 Make window resizable.\r
1433\r
1434 Arguments:\r
1435 windowEl\r
1436\r
1437 */\r
1438 attachResizable: function(windowEl){\r
1439 if (!this.options.resizable) return;\r
1440 this.resizable1 = this.windowEl.makeResizable({\r
1441 handle: [this.n, this.ne, this.nw],\r
1442 limit: {\r
1443 y: [\r
1444 function(){\r
1445 return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[1];\r
1446 }.bind(this),\r
1447 function(){\r
1448 return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[0];\r
1449 }.bind(this)\r
1450 ]\r
1451 },\r
1452 modifiers: {x: false, y: 'top'},\r
1453 onStart: function(){\r
1454 this.resizeOnStart();\r
1455 this.coords = this.contentWrapperEl.getCoordinates();\r
1456 this.y2 = this.coords.top.toInt() + this.contentWrapperEl.offsetHeight;\r
1457 }.bind(this),\r
1458 onDrag: function(){\r
1459 this.coords = this.contentWrapperEl.getCoordinates();\r
1460 this.contentWrapperEl.setStyle('height', this.y2 - this.coords.top.toInt());\r
1461 this.drawWindow(windowEl);\r
1462 this.adjustHandles();\r
1463 }.bind(this),\r
1464 onComplete: function(){\r
1465 this.resizeOnComplete();\r
1466 }.bind(this)\r
1467 });\r
1468\r
1469 this.resizable2 = this.contentWrapperEl.makeResizable({\r
1470 handle: [this.e, this.ne],\r
1471 limit: {\r
1472 x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ]\r
1473 }, \r
1474 modifiers: {x: 'width', y: false},\r
1475 onStart: function(){\r
1476 this.resizeOnStart();\r
1477 }.bind(this),\r
1478 onDrag: function(){\r
1479 this.drawWindow(windowEl);\r
1480 this.adjustHandles();\r
1481 }.bind(this),\r
1482 onComplete: function(){\r
1483 this.resizeOnComplete();\r
1484 }.bind(this)\r
1485 });\r
1486\r
1487 this.resizable3 = this.contentWrapperEl.makeResizable({\r
1488 container: this.options.restrict == true ? $(this.options.container) : false,\r
1489 handle: this.se,\r
1490 limit: {\r
1491 x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ],\r
1492 y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]\r
1493 },\r
1494 modifiers: {x: 'width', y: 'height'},\r
1495 onStart: function(){\r
1496 this.resizeOnStart();\r
1497 }.bind(this),\r
1498 onDrag: function(){\r
1499 this.drawWindow(windowEl); \r
1500 this.adjustHandles();\r
1501 }.bind(this),\r
1502 onComplete: function(){\r
1503 this.resizeOnComplete();\r
1504 }.bind(this) \r
1505 });\r
1506\r
1507 this.resizable4 = this.contentWrapperEl.makeResizable({\r
1508 handle: [this.s, this.sw],\r
1509 limit: {\r
1510 y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]\r
1511 },\r
1512 modifiers: {x: false, y: 'height'},\r
1513 onStart: function(){\r
1514 this.resizeOnStart();\r
1515 }.bind(this),\r
1516 onDrag: function(){\r
1517 this.drawWindow(windowEl);\r
1518 this.adjustHandles();\r
1519 }.bind(this),\r
1520 onComplete: function(){\r
1521 this.resizeOnComplete();\r
1522 }.bind(this)\r
1523 });\r
1524\r
1525 this.resizable5 = this.windowEl.makeResizable({\r
1526 handle: [this.w, this.sw, this.nw],\r
1527 limit: {\r
1528 x: [\r
1529 function(){\r
1530 return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[1];\r
1531 }.bind(this),\r
1532 function(){\r
1533 return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[0];\r
1534 }.bind(this)\r
1535 ]\r
1536 },\r
1537 modifiers: {x: 'left', y: false},\r
1538 onStart: function(){\r
1539 this.resizeOnStart();\r
1540 this.coords = this.contentWrapperEl.getCoordinates();\r
1541 this.x2 = this.coords.left.toInt() + this.contentWrapperEl.offsetWidth;\r
1542 }.bind(this),\r
1543 onDrag: function(){\r
1544 this.coords = this.contentWrapperEl.getCoordinates();\r
1545 this.contentWrapperEl.setStyle('width', this.x2 - this.coords.left.toInt());\r
1546 this.drawWindow(windowEl);\r
1547 this.adjustHandles();\r
1548 }.bind(this),\r
1549 onComplete: function(){\r
1550 this.resizeOnComplete();\r
1551 }.bind(this)\r
1552 });\r
1553\r
1554 },\r
1555 resizeOnStart: function(){\r
1556 $('windowUnderlay').setStyle('display','block');\r
1557 if (this.iframeEl){\r
1558 this.iframeEl.setStyle('visibility', 'hidden');\r
1559 } \r
1560 }, \r
1561 resizeOnComplete: function(){\r
1562 $('windowUnderlay').setStyle('display','none');\r
1563 if (this.iframeEl){\r
1564 this.iframeEl.setStyle('visibility', 'visible');\r
1565 }\r
1566 this.fireEvent('onResize', this.windowEl);\r
1567 },\r
1568 adjustHandles: function(){\r
1569\r
1570 var shadowBlur = this.options.shadowBlur;\r
1571 var shadowBlur2x = shadowBlur * 2;\r
1572 var shadowOffset = this.options.shadowOffset;\r
1573 var top = shadowBlur - shadowOffset.y - 1;\r
1574 var right = shadowBlur + shadowOffset.x - 1;\r
1575 var bottom = shadowBlur + shadowOffset.y - 1;\r
1576 var left = shadowBlur - shadowOffset.x - 1;\r
1577 \r
1578 var coordinates = this.windowEl.getCoordinates();\r
1579 var width = coordinates.width - shadowBlur2x + 2;\r
1580 var height = coordinates.height - shadowBlur2x + 2;\r
1581\r
1582 this.n.setStyles({\r
1583 'top': top,\r
1584 'left': left + 10,\r
1585 'width': width - 20\r
1586 });\r
1587 this.e.setStyles({\r
1588 'top': top + 10,\r
1589 'right': right,\r
1590 'height': height - 30\r
1591 });\r
1592 this.s.setStyles({\r
1593 'bottom': bottom,\r
1594 'left': left + 10,\r
1595 'width': width - 30\r
1596 });\r
1597 this.w.setStyles({\r
1598 'top': top + 10,\r
1599 'left': left,\r
1600 'height': height - 20\r
1601 });\r
1602 this.ne.setStyles({\r
1603 'top': top,\r
1604 'right': right \r
1605 });\r
1606 this.se.setStyles({\r
1607 'bottom': bottom,\r
1608 'right': right\r
1609 });\r
1610 this.sw.setStyles({\r
1611 'bottom': bottom,\r
1612 'left': left\r
1613 });\r
1614 this.nw.setStyles({\r
1615 'top': top,\r
1616 'left': left\r
1617 });\r
1618 },\r
1619 detachResizable: function(){\r
1620 this.resizable1.detach();\r
1621 this.resizable2.detach();\r
1622 this.resizable3.detach();\r
1623 this.resizable4.detach();\r
1624 this.resizable5.detach();\r
1625 this.windowEl.getElements('.handle').setStyle('display', 'none');\r
1626 },\r
1627 reattachResizable: function(){\r
1628 this.resizable1.attach();\r
1629 this.resizable2.attach();\r
1630 this.resizable3.attach();\r
1631 this.resizable4.attach();\r
1632 this.resizable5.attach();\r
1633 this.windowEl.getElements('.handle').setStyle('display', 'block');\r
1634 },\r
1635 /*\r
1636\r
1637 Internal Function: insertWindowElements\r
1638\r
1639 Arguments:\r
1640 windowEl\r
1641\r
1642 */\r
1643 insertWindowElements: function(){\r
1644 \r
1645 var options = this.options;\r
1646 var height = options.height;\r
1647 var width = options.width;\r
1648 var id = options.id;\r
1649\r
1650 var cache = {};\r
1651\r
1652 if (Browser.Engine.trident4){\r
1653 cache.zIndexFixEl = new Element('iframe', {\r
1654 'id': id + '_zIndexFix',\r
1655 'class': 'zIndexFix',\r
1656 'scrolling': 'no',\r
1657 'marginWidth': 0,\r
1658 'marginHeight': 0,\r
1659 'src': ''\r
1660 }).inject(this.windowEl);\r
1661 }\r
1662\r
1663 cache.overlayEl = new Element('div', {\r
1664 'id': id + '_overlay',\r
1665 'class': 'mochaOverlay'\r
1666 }).inject(this.windowEl);\r
1667\r
1668 cache.titleBarEl = new Element('div', {\r
1669 'id': id + '_titleBar',\r
1670 'class': 'mochaTitlebar',\r
1671 'styles': {\r
1672 'cursor': options.draggable ? 'move' : 'default'\r
1673 }\r
1674 }).inject(cache.overlayEl, 'top');\r
1675\r
1676 cache.titleEl = new Element('h3', {\r
1677 'id': id + '_title',\r
1678 'class': 'mochaTitle'\r
1679 }).inject(cache.titleBarEl);\r
1680\r
1681 if (options.icon != false){\r
1682 cache.titleBarEl.setStyles({\r
1683 'padding-left': 15,\r
1684 'background': 'url(' + options.icon + ') 5px 5px no-repeat'\r
1685 });\r
1686 }\r
1687 \r
1688 cache.contentBorderEl = new Element('div', {\r
1689 'id': id + '_contentBorder',\r
1690 'class': 'mochaContentBorder'\r
1691 }).inject(cache.overlayEl);\r
1692\r
1693 if (options.toolbar){\r
1694 cache.toolbarWrapperEl = new Element('div', {\r
1695 'id': id + '_toolbarWrapper',\r
1696 'class': 'mochaToolbarWrapper'\r
1697 }).inject(cache.contentBorderEl, options.toolbarPosition == 'bottom' ? 'after' : 'before');\r
1698\r
1699 if (options.toolbarPosition == 'bottom') {\r
1700 cache.toolbarWrapperEl.addClass('bottom');\r
1701 }\r
1702 cache.toolbarEl = new Element('div', {\r
1703 'id': id + '_toolbar',\r
1704 'class': 'mochaToolbar'\r
1705 }).inject(cache.toolbarWrapperEl);\r
1706 }\r
1707\r
1708 if (options.toolbar2){\r
1709 cache.toolbar2WrapperEl = new Element('div', {\r
1710 'id': id + '_toolbar2Wrapper',\r
1711 'class': 'mochaToolbarWrapper'\r
1712 }).inject(cache.contentBorderEl, options.toolbar2Position == 'bottom' ? 'after' : 'before');\r
1713\r
1714 if (options.toolbar2Position == 'bottom') {\r
1715 cache.toolbar2WrapperEl.addClass('bottom');\r
1716 }\r
1717 cache.toolbar2El = new Element('div', {\r
1718 'id': id + '_toolbar2',\r
1719 'class': 'mochaToolbar'\r
1720 }).inject(cache.toolbar2WrapperEl);\r
1721 }\r
1722\r
1723 cache.contentWrapperEl = new Element('div', {\r
1724 'id': id + '_contentWrapper',\r
1725 'class': 'mochaContentWrapper',\r
1726 'styles': {\r
1727 'width': width + 'px',\r
1728 'height': height + 'px'\r
1729 }\r
1730 }).inject(cache.contentBorderEl);\r
1731 \r
1732 if (this.options.shape == 'gauge'){\r
1733 cache.contentBorderEl.setStyle('borderWidth', 0);\r
1734 }\r
1735\r
1736 cache.contentEl = new Element('div', {\r
1737 'id': id + '_content',\r
1738 'class': 'mochaContent'\r
1739 }).inject(cache.contentWrapperEl);\r
1740\r
1741 if (this.options.useCanvas == true) {\r
1742 cache.canvasEl = new Element('canvas', {\r
1743 'id': id + '_canvas',\r
1744 'class': 'mochaCanvas',\r
1745 'width': 1,\r
1746 'height': 1\r
1747 }).inject(this.windowEl);\r
1748\r
1749 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){\r
1750 G_vmlCanvasManager.initElement(cache.canvasEl);\r
1751 cache.canvasEl = this.windowEl.getElement('.mochaCanvas');\r
1752 }\r
1753 }\r
1754\r
1755 cache.controlsEl = new Element('div', {\r
1756 'id': id + '_controls',\r
1757 'class': 'mochaControls'\r
1758 }).inject(cache.overlayEl, 'after');\r
1759\r
1760 if (options.useCanvasControls == true){\r
1761 cache.canvasControlsEl = new Element('canvas', {\r
1762 'id': id + '_canvasControls',\r
1763 'class': 'mochaCanvasControls',\r
1764 'width': 14,\r
1765 'height': 14\r
1766 }).inject(this.windowEl);\r
1767\r
1768 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){\r
1769 G_vmlCanvasManager.initElement(cache.canvasControlsEl);\r
1770 cache.canvasControlsEl = this.windowEl.getElement('.mochaCanvasControls');\r
1771 }\r
1772 }\r
1773\r
1774 if (options.closable){\r
1775 cache.closeButtonEl = new Element('div', {\r
1776 'id': id + '_closeButton',\r
1777 'class': 'mochaCloseButton',\r
1778 'title': 'Close'\r
1779 }).inject(cache.controlsEl);\r
1780 if (options.useCanvasControls == true){\r
1781 cache.closeButtonEl.setStyle('background', 'none');\r
1782 }\r
1783 }\r
1784\r
1785 if (options.maximizable){\r
1786 cache.maximizeButtonEl = new Element('div', {\r
1787 'id': id + '_maximizeButton',\r
1788 'class': 'mochaMaximizeButton',\r
1789 'title': 'Maximize'\r
1790 }).inject(cache.controlsEl);\r
1791 if (options.useCanvasControls == true){\r
1792 cache.maximizeButtonEl.setStyle('background', 'none');\r
1793 }\r
1794 }\r
1795\r
1796 if (options.minimizable){\r
1797 cache.minimizeButtonEl = new Element('div', {\r
1798 'id': id + '_minimizeButton',\r
1799 'class': 'mochaMinimizeButton',\r
1800 'title': 'Minimize'\r
1801 }).inject(cache.controlsEl);\r
1802 if (options.useCanvasControls == true){\r
1803 cache.minimizeButtonEl.setStyle('background', 'none');\r
1804 }\r
1805 }\r
1806\r
1807 if (options.useSpinner == true && options.shape != 'gauge' && options.type != 'notification'){\r
1808 cache.spinnerEl = new Element('div', {\r
1809 'id': id + '_spinner',\r
1810 'class': 'mochaSpinner',\r
1811 'width': 16,\r
1812 'height': 16\r
1813 }).inject(this.windowEl, 'bottom');\r
1814 }\r
1815\r
1816 if (this.options.shape == 'gauge'){\r
1817 cache.canvasHeaderEl = new Element('canvas', {\r
1818 'id': id + '_canvasHeader',\r
1819 'class': 'mochaCanvasHeader',\r
1820 'width': this.options.width,\r
1821 'height': 26\r
1822 }).inject(this.windowEl, 'bottom');\r
1823 \r
1824 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){\r
1825 G_vmlCanvasManager.initElement(cache.canvasHeaderEl);\r
1826 cache.canvasHeaderEl = this.windowEl.getElement('.mochaCanvasHeader');\r
1827 }\r
1828 }\r
1829\r
1830 if ( Browser.Engine.trident ){\r
1831 cache.overlayEl.setStyle('zIndex', 2);\r
1832 }\r
1833\r
1834 // For Mac Firefox 2 to help reduce scrollbar bugs in that browser\r
1835 if (Browser.Platform.mac && Browser.Engine.gecko){\r
1836 if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){\r
1837 var ffversion = new Number(RegExp.$1);\r
1838 if (ffversion < 3){\r
1839 cache.overlayEl.setStyle('overflow', 'auto');\r
1840 }\r
1841 }\r
1842 }\r
1843\r
1844 if (options.resizable){\r
1845 cache.n = new Element('div', {\r
1846 'id': id + '_resizeHandle_n',\r
1847 'class': 'handle',\r
1848 'styles': {\r
1849 'top': 0,\r
1850 'left': 10,\r
1851 'cursor': 'n-resize'\r
1852 }\r
1853 }).inject(cache.overlayEl, 'after');\r
1854\r
1855 cache.ne = new Element('div', {\r
1856 'id': id + '_resizeHandle_ne',\r
1857 'class': 'handle corner',\r
1858 'styles': {\r
1859 'top': 0,\r
1860 'right': 0,\r
1861 'cursor': 'ne-resize'\r
1862 }\r
1863 }).inject(cache.overlayEl, 'after');\r
1864 \r
1865 cache.e = new Element('div', {\r
1866 'id': id + '_resizeHandle_e',\r
1867 'class': 'handle', \r
1868 'styles': {\r
1869 'top': 10,\r
1870 'right': 0,\r
1871 'cursor': 'e-resize'\r
1872 }\r
1873 }).inject(cache.overlayEl, 'after');\r
1874 \r
1875 cache.se = new Element('div', {\r
1876 'id': id + '_resizeHandle_se',\r
1877 'class': 'handle cornerSE',\r
1878 'styles': {\r
1879 'bottom': 0,\r
1880 'right': 0,\r
1881 'cursor': 'se-resize'\r
1882 }\r
1883 }).inject(cache.overlayEl, 'after');\r
1884\r
1885 cache.s = new Element('div', {\r
1886 'id': id + '_resizeHandle_s',\r
1887 'class': 'handle',\r
1888 'styles': {\r
1889 'bottom': 0,\r
1890 'left': 10,\r
1891 'cursor': 's-resize'\r
1892 }\r
1893 }).inject(cache.overlayEl, 'after');\r
1894 \r
1895 cache.sw = new Element('div', {\r
1896 'id': id + '_resizeHandle_sw',\r
1897 'class': 'handle corner',\r
1898 'styles': {\r
1899 'bottom': 0,\r
1900 'left': 0,\r
1901 'cursor': 'sw-resize'\r
1902 }\r
1903 }).inject(cache.overlayEl, 'after');\r
1904 \r
1905 cache.w = new Element('div', {\r
1906 'id': id + '_resizeHandle_w',\r
1907 'class': 'handle', \r
1908 'styles': {\r
1909 'top': 10,\r
1910 'left': 0,\r
1911 'cursor': 'w-resize'\r
1912 }\r
1913 }).inject(cache.overlayEl, 'after');\r
1914 \r
1915 cache.nw = new Element('div', {\r
1916 'id': id + '_resizeHandle_nw',\r
1917 'class': 'handle corner', \r
1918 'styles': {\r
1919 'top': 0,\r
1920 'left': 0,\r
1921 'cursor': 'nw-resize'\r
1922 }\r
1923 }).inject(cache.overlayEl, 'after');\r
1924 }\r
1925 $extend(this, cache);\r
1926 \r
1927 },\r
1928 /*\r
1929\r
1930 Internal function: drawWindow\r
1931 This is where we create the canvas GUI \r
1932\r
1933 Arguments: \r
1934 windowEl: the $(window)\r
1935 shadows: (boolean) false will draw a window without shadows\r
1936\r
1937 */ \r
1938 drawWindow: function(windowEl, shadows) {\r
1939 \r
1940 if (this.isCollapsed){\r
1941 this.drawWindowCollapsed(windowEl, shadows);\r
1942 return;\r
1943 }\r
1944\r
1945 var options = this.options;\r
1946 var shadowBlur = options.shadowBlur;\r
1947 var shadowBlur2x = shadowBlur * 2;\r
1948 var shadowOffset = this.options.shadowOffset;\r
1949\r
1950 this.overlayEl.setStyles({\r
1951 'width': this.contentWrapperEl.offsetWidth\r
1952 });\r
1953\r
1954 // Resize iframe when window is resized\r
1955 if (this.iframeEl) {\r
1956 this.iframeEl.setStyles({\r
1957 'height': this.contentWrapperEl.offsetHeight\r
1958 });\r
1959 }\r
1960\r
1961 var borderHeight = this.contentBorderEl.getStyle('border-top').toInt() + this.contentBorderEl.getStyle('border-bottom').toInt();\r
1962 var toolbarHeight = this.toolbarWrapperEl ? this.toolbarWrapperEl.getStyle('height').toInt() + this.toolbarWrapperEl.getStyle('border-top').toInt() : 0;\r
1963 var toolbar2Height = this.toolbar2WrapperEl ? this.toolbar2WrapperEl.getStyle('height').toInt() + this.toolbar2WrapperEl.getStyle('border-top').toInt() : 0;\r
1964\r
1965 this.headerFooterShadow = options.headerHeight + options.footerHeight + shadowBlur2x;\r
1966 var height = this.contentWrapperEl.getStyle('height').toInt() + this.headerFooterShadow + toolbarHeight + toolbar2Height + borderHeight;\r
1967 var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;\r
1968 this.windowEl.setStyles({\r
1969 'height': height,\r
1970 'width': width\r
1971 });\r
1972\r
1973 this.overlayEl.setStyles({\r
1974 'height': height,\r
1975 'top': shadowBlur - shadowOffset.y,\r
1976 'left': shadowBlur - shadowOffset.x\r
1977 }); \r
1978\r
1979 // Opera requires the canvas height and width be set this way when resizing:\r
1980 if (this.options.useCanvas == true) {\r
1981 this.canvasEl.height = height;\r
1982 this.canvasEl.width = width;\r
1983 }\r
1984\r
1985 // Part of the fix for IE6 select z-index bug\r
1986 if (Browser.Engine.trident4){\r
1987 this.zIndexFixEl.setStyles({\r
1988 'width': width,\r
1989 'height': height\r
1990 })\r
1991 }\r
1992\r
1993 this.titleBarEl.setStyles({\r
1994 'width': width - shadowBlur2x,\r
1995 'height': options.headerHeight\r
1996 });\r
1997\r
1998 // Make sure loading icon is placed correctly.\r
1999 if (options.useSpinner == true && options.shape != 'gauge' && options.type != 'notification'){\r
2000 this.spinnerEl.setStyles({\r
2001 'left': shadowBlur - shadowOffset.x + 3,\r
2002 'bottom': shadowBlur + shadowOffset.y + 4\r
2003 });\r
2004 }\r
2005 \r
2006 if (this.options.useCanvas != false) {\r
2007 \r
2008 // Draw Window\r
2009 var ctx = this.canvasEl.getContext('2d');\r
2010 ctx.clearRect(0, 0, width, height);\r
2011 \r
2012 switch (options.shape) {\r
2013 case 'box':\r
2014 this.drawBox(ctx, width, height, shadowBlur, shadowOffset, shadows);\r
2015 break;\r
2016 case 'gauge':\r
2017 this.drawGauge(ctx, width, height, shadowBlur, shadowOffset, shadows);\r
2018 break;\r
2019 }\r
2020\r
2021\r
2022 if (options.resizable){ \r
2023 MochaUI.triangle(\r
2024 ctx,\r
2025 width - (shadowBlur + shadowOffset.x + 17),\r
2026 height - (shadowBlur + shadowOffset.y + 18),\r
2027 11,\r
2028 11,\r
2029 options.resizableColor,\r
2030 1.0\r
2031 );\r
2032 }\r
2033\r
2034 // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7\r
2035 if (Browser.Engine.trident){\r
2036 MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);\r
2037 }\r
2038 }\r
2039 \r
2040 if (options.type != 'notification' && options.useCanvasControls == true){\r
2041 this.drawControls(width, height, shadows);\r
2042 }\r
2043\r
2044 },\r
2045 drawWindowCollapsed: function(windowEl, shadows) {\r
2046 \r
2047 var options = this.options;\r
2048 var shadowBlur = options.shadowBlur;\r
2049 var shadowBlur2x = shadowBlur * 2;\r
2050 var shadowOffset = options.shadowOffset;\r
2051 \r
2052 var headerShadow = options.headerHeight + shadowBlur2x + 2;\r
2053 var height = headerShadow;\r
2054 var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;\r
2055 this.windowEl.setStyle('height', height);\r
2056 \r
2057 this.overlayEl.setStyles({\r
2058 'height': height,\r
2059 'top': shadowBlur - shadowOffset.y,\r
2060 'left': shadowBlur - shadowOffset.x\r
2061 }); \r
2062\r
2063 // Opera height and width must be set like this, when resizing:\r
2064 this.canvasEl.height = height;\r
2065 this.canvasEl.width = width;\r
2066\r
2067 // Part of the fix for IE6 select z-index bug\r
2068 if (Browser.Engine.trident4){\r
2069 this.zIndexFixEl.setStyles({\r
2070 'width': width,\r
2071 'height': height\r
2072 });\r
2073 }\r
2074\r
2075 // Set width\r
2076 this.windowEl.setStyle('width', width);\r
2077 this.overlayEl.setStyle('width', width);\r
2078 this.titleBarEl.setStyles({\r
2079 'width': width - shadowBlur2x,\r
2080 'height': options.headerHeight\r
2081 });\r
2082 \r
2083 // Draw Window\r
2084 if (this.options.useCanvas != false) {\r
2085 var ctx = this.canvasEl.getContext('2d');\r
2086 ctx.clearRect(0, 0, width, height);\r
2087 \r
2088 this.drawBoxCollapsed(ctx, width, height, shadowBlur, shadowOffset, shadows);\r
2089 if (options.useCanvasControls == true) {\r
2090 this.drawControls(width, height, shadows);\r
2091 }\r
2092 \r
2093 // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7\r
2094 if (Browser.Engine.trident){\r
2095 MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);\r
2096 }\r
2097 }\r
2098\r
2099 }, \r
2100 drawControls : function(width, height, shadows){\r
2101 var options = this.options;\r
2102 var shadowBlur = options.shadowBlur;\r
2103 var shadowOffset = options.shadowOffset;\r
2104 var controlsOffset = options.controlsOffset;\r
2105 \r
2106 // Make sure controls are placed correctly.\r
2107 this.controlsEl.setStyles({\r
2108 'right': shadowBlur + shadowOffset.x + controlsOffset.right,\r
2109 'top': shadowBlur - shadowOffset.y + controlsOffset.top\r
2110 });\r
2111\r
2112 this.canvasControlsEl.setStyles({\r
2113 'right': shadowBlur + shadowOffset.x + controlsOffset.right,\r
2114 'top': shadowBlur - shadowOffset.y + controlsOffset.top\r
2115 });\r
2116\r
2117 // Calculate X position for controlbuttons\r
2118 //var mochaControlsWidth = 52;\r
2119 this.closebuttonX = options.closable ? this.mochaControlsWidth - 7 : this.mochaControlsWidth + 12;\r
2120 this.maximizebuttonX = this.closebuttonX - (options.maximizable ? 19 : 0);\r
2121 this.minimizebuttonX = this.maximizebuttonX - (options.minimizable ? 19 : 0);\r
2122 \r
2123 var ctx2 = this.canvasControlsEl.getContext('2d');\r
2124 ctx2.clearRect(0, 0, 100, 100);\r
2125\r
2126 if (this.options.closable){\r
2127 this.closebutton(\r
2128 ctx2,\r
2129 this.closebuttonX,\r
2130 7,\r
2131 options.closeBgColor,\r
2132 1.0,\r
2133 options.closeColor,\r
2134 1.0\r
2135 );\r
2136 }\r
2137 if (this.options.maximizable){\r
2138 this.maximizebutton(\r
2139 ctx2,\r
2140 this.maximizebuttonX,\r
2141 7,\r
2142 options.maximizeBgColor,\r
2143 1.0,\r
2144 options.maximizeColor,\r
2145 1.0\r
2146 );\r
2147 }\r
2148 if (this.options.minimizable){\r
2149 this.minimizebutton(\r
2150 ctx2,\r
2151 this.minimizebuttonX,\r
2152 7,\r
2153 options.minimizeBgColor,\r
2154 1.0,\r
2155 options.minimizeColor,\r
2156 1.0\r
2157 );\r
2158 }\r
2159 \r
2160 },\r
2161 drawBox: function(ctx, width, height, shadowBlur, shadowOffset, shadows){\r
2162\r
2163 var shadowBlur2x = shadowBlur * 2;\r
2164 var cornerRadius = this.options.cornerRadius;\r
2165\r
2166 // This is the drop shadow. It is created onion style.\r
2167 if ( shadows != false ) { \r
2168 for (var x = 0; x <= shadowBlur; x++){\r
2169 MochaUI.roundedRect(\r
2170 ctx,\r
2171 shadowOffset.x + x,\r
2172 shadowOffset.y + x,\r
2173 width - (x * 2) - shadowOffset.x,\r
2174 height - (x * 2) - shadowOffset.y,\r
2175 cornerRadius + (shadowBlur - x),\r
2176 [0, 0, 0],\r
2177 x == shadowBlur ? .29 : .065 + (x * .01)\r
2178 );\r
2179 }\r
2180 }\r
2181 // Window body.\r
2182 this.bodyRoundedRect(\r
2183 ctx, // context\r
2184 shadowBlur - shadowOffset.x, // x\r
2185 shadowBlur - shadowOffset.y, // y\r
2186 width - shadowBlur2x, // width\r
2187 height - shadowBlur2x, // height\r
2188 cornerRadius, // corner radius\r
2189 this.options.bodyBgColor // Footer color\r
2190 );\r
2191\r
2192 if (this.options.type != 'notification'){\r
2193 // Window header.\r
2194 this.topRoundedRect(\r
2195 ctx, // context\r
2196 shadowBlur - shadowOffset.x, // x\r
2197 shadowBlur - shadowOffset.y, // y\r
2198 width - shadowBlur2x, // width\r
2199 this.options.headerHeight, // height\r
2200 cornerRadius, // corner radius\r
2201 this.options.headerStartColor, // Header gradient's top color\r
2202 this.options.headerStopColor // Header gradient's bottom color\r
2203 );\r
2204 } \r
2205 },\r
2206 drawBoxCollapsed: function(ctx, width, height, shadowBlur, shadowOffset, shadows){\r
2207\r
2208 var options = this.options;\r
2209 var shadowBlur2x = shadowBlur * 2;\r
2210 var cornerRadius = options.cornerRadius;\r
2211 \r
2212 // This is the drop shadow. It is created onion style.\r
2213 if ( shadows != false ){\r
2214 for (var x = 0; x <= shadowBlur; x++){\r
2215 MochaUI.roundedRect(\r
2216 ctx,\r
2217 shadowOffset.x + x,\r
2218 shadowOffset.y + x,\r
2219 width - (x * 2) - shadowOffset.x,\r
2220 height - (x * 2) - shadowOffset.y,\r
2221 cornerRadius + (shadowBlur - x),\r
2222 [0, 0, 0],\r
2223 x == shadowBlur ? .3 : .06 + (x * .01)\r
2224 );\r
2225 }\r
2226 }\r
2227\r
2228 // Window header\r
2229 this.topRoundedRect2(\r
2230 ctx, // context\r
2231 shadowBlur - shadowOffset.x, // x\r
2232 shadowBlur - shadowOffset.y, // y\r
2233 width - shadowBlur2x, // width\r
2234 options.headerHeight + 2, // height\r
2235 cornerRadius, // corner radius\r
2236 options.headerStartColor, // Header gradient's top color\r
2237 options.headerStopColor // Header gradient's bottom color\r
2238 );\r
2239\r
2240 }, \r
2241 drawGauge: function(ctx, width, height, shadowBlur, shadowOffset, shadows){\r
2242 var options = this.options;\r
2243 var radius = (width * .5) - (shadowBlur) + 16;\r
2244 if (shadows != false) { \r
2245 for (var x = 0; x <= shadowBlur; x++){\r
2246 MochaUI.circle(\r
2247 ctx,\r
2248 width * .5 + shadowOffset.x,\r
2249 (height + options.headerHeight) * .5 + shadowOffset.x,\r
2250 (width *.5) - (x * 2) - shadowOffset.x,\r
2251 [0, 0, 0],\r
2252 x == shadowBlur ? .75 : .075 + (x * .04)\r
2253 );\r
2254 }\r
2255 }\r
2256 MochaUI.circle(\r
2257 ctx,\r
2258 width * .5 - shadowOffset.x,\r
2259 (height + options.headerHeight) * .5 - shadowOffset.y,\r
2260 (width *.5) - shadowBlur,\r
2261 options.bodyBgColor,\r
2262 1\r
2263 );\r
2264\r
2265 // Draw gauge header\r
2266 this.canvasHeaderEl.setStyles({\r
2267 'top': shadowBlur - shadowOffset.y,\r
2268 'left': shadowBlur - shadowOffset.x\r
2269 }); \r
2270 var ctx = this.canvasHeaderEl.getContext('2d');\r
2271 ctx.clearRect(0, 0, width, 100);\r
2272 ctx.beginPath();\r
2273 ctx.lineWidth = 24;\r
2274 ctx.lineCap = 'round';\r
2275 ctx.moveTo(13, 13);\r
2276 ctx.lineTo(width - (shadowBlur*2) - 13, 13);\r
2277 ctx.strokeStyle = 'rgba(0, 0, 0, .65)';\r
2278 ctx.stroke();\r
2279 },\r
2280 bodyRoundedRect: function(ctx, x, y, width, height, radius, rgb){\r
2281 ctx.fillStyle = 'rgba(' + rgb.join(',') + ', 100)';\r
2282 ctx.beginPath();\r
2283 ctx.moveTo(x, y + radius);\r
2284 ctx.lineTo(x, y + height - radius);\r
2285 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);\r
2286 ctx.lineTo(x + width - radius, y + height);\r
2287 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);\r
2288 ctx.lineTo(x + width, y + radius);\r
2289 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);\r
2290 ctx.lineTo(x + radius, y);\r
2291 ctx.quadraticCurveTo(x, y, x, y + radius);\r
2292 ctx.fill();\r
2293\r
2294 },\r
2295 topRoundedRect: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){\r
2296 var lingrad = ctx.createLinearGradient(0, 0, 0, height);\r
2297 lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');\r
2298 lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)'); \r
2299 ctx.fillStyle = lingrad;\r
2300 ctx.beginPath();\r
2301 ctx.moveTo(x, y);\r
2302 ctx.lineTo(x, y + height);\r
2303 ctx.lineTo(x + width, y + height);\r
2304 ctx.lineTo(x + width, y + radius);\r
2305 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);\r
2306 ctx.lineTo(x + radius, y);\r
2307 ctx.quadraticCurveTo(x, y, x, y + radius);\r
2308 ctx.fill();\r
2309 /*\r
2310 ctx.beginPath();\r
2311 ctx.strokeStyle = '#000';\r
2312 ctx.lineWidth = 1;\r
2313 ctx.moveTo(x, y + height + .5);\r
2314 ctx.lineTo(x + width, y + height + .5);\r
2315 ctx.stroke();\r
2316 */\r
2317\r
2318 },\r
2319 topRoundedRect2: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){\r
2320 var lingrad = ctx.createLinearGradient(0, this.options.shadowBlur - 1, 0, height + this.options.shadowBlur + 3);\r
2321 lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');\r
2322 lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)');\r
2323 ctx.fillStyle = lingrad;\r
2324 ctx.beginPath();\r
2325 ctx.moveTo(x, y + radius);\r
2326 ctx.lineTo(x, y + height - radius);\r
2327 ctx.quadraticCurveTo(x, y + height, x + radius, y + height);\r
2328 ctx.lineTo(x + width - radius, y + height);\r
2329 ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);\r
2330 ctx.lineTo(x + width, y + radius);\r
2331 ctx.quadraticCurveTo(x + width, y, x + width - radius, y);\r
2332 ctx.lineTo(x + radius, y);\r
2333 ctx.quadraticCurveTo(x, y, x, y + radius);\r
2334 ctx.fill(); \r
2335 },\r
2336 maximizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){\r
2337 // Circle\r
2338 ctx.beginPath();\r
2339 ctx.moveTo(x, y);\r
2340 ctx.arc(x, y, 7, 0, Math.PI*2, true);\r
2341 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';\r
2342 ctx.fill();\r
2343 // X sign\r
2344 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
2345 ctx.beginPath();\r
2346 ctx.moveTo(x, y - 4);\r
2347 ctx.lineTo(x, y + 4);\r
2348 ctx.stroke();\r
2349 ctx.beginPath();\r
2350 ctx.moveTo(x - 4, y);\r
2351 ctx.lineTo(x + 4, y);\r
2352 ctx.stroke();\r
2353 },\r
2354 closebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){\r
2355 // Circle\r
2356 ctx.beginPath();\r
2357 ctx.moveTo(x, y);\r
2358 ctx.arc(x, y, 7, 0, Math.PI*2, true);\r
2359 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';\r
2360 ctx.fill();\r
2361 // Plus sign\r
2362 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
2363 ctx.beginPath();\r
2364 ctx.moveTo(x - 3, y - 3);\r
2365 ctx.lineTo(x + 3, y + 3);\r
2366 ctx.stroke();\r
2367 ctx.beginPath();\r
2368 ctx.moveTo(x + 3, y - 3);\r
2369 ctx.lineTo(x - 3, y + 3);\r
2370 ctx.stroke();\r
2371 },\r
2372 minimizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){\r
2373 // Circle\r
2374 ctx.beginPath();\r
2375 ctx.moveTo(x,y);\r
2376 ctx.arc(x,y,7,0,Math.PI*2,true);\r
2377 ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';\r
2378 ctx.fill();\r
2379 // Minus sign\r
2380 ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';\r
2381 ctx.beginPath();\r
2382 ctx.moveTo(x - 4, y);\r
2383 ctx.lineTo(x + 4, y);\r
2384 ctx.stroke();\r
2385 },\r
2386 /*\r
2387\r
2388 Function: hideSpinner\r
2389 Hides the spinner.\r
2390 \r
2391 */ \r
2392 hideSpinner: function(spinner) {\r
2393 if ($(spinner)) $(spinner).setStyle('visibility', 'hidden');\r
2394 },\r
2395 /*\r
2396\r
2397 Function: showSpinner\r
2398 Shows the spinner.\r
2399 \r
2400 */ \r
2401 showSpinner: function(spinner){\r
2402 if (!this.options.useSpinner || this.options.shape == 'gauge' || this.options.type == 'notification') return;\r
2403 $(spinner).setStyles({\r
2404 'visibility': 'visible'\r
2405 });\r
2406 },\r
2407 setMochaControlsWidth: function(){\r
2408 this.mochaControlsWidth = 0;\r
2409 var options = this.options;\r
2410 if (options.minimizable){\r
2411 this.mochaControlsWidth += (this.minimizeButtonEl.getStyle('margin-left').toInt() + this.minimizeButtonEl.getStyle('width').toInt());\r
2412 }\r
2413 if (options.maximizable){\r
2414 this.mochaControlsWidth += (this.maximizeButtonEl.getStyle('margin-left').toInt() + this.maximizeButtonEl.getStyle('width').toInt());\r
2415 }\r
2416 if (options.closable){\r
2417 this.mochaControlsWidth += (this.closeButtonEl.getStyle('margin-left').toInt() + this.closeButtonEl.getStyle('width').toInt());\r
2418 }\r
2419 this.controlsEl.setStyle('width', this.mochaControlsWidth);\r
2420 if (options.useCanvasControls == true){\r
2421 this.canvasControlsEl.setProperty('width', this.mochaControlsWidth);\r
2422 }\r
2423 }\r
2424});\r
2425MochaUI.Window.implement(new Options, new Events);\r
2426/*\r
2427\r
2428Script: Modal.js\r
2429 Create modal dialog windows.\r
2430\r
2431Copyright:\r
2432 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
2433\r
2434License:\r
2435 MIT-style license. \r
2436\r
2437Requires:\r
2438 Core.js, Window.js\r
2439\r
2440See Also:\r
2441 <Window> \r
2442 \r
2443*/\r
2444\r
2445MochaUI.Modal = new Class({\r
2446\r
2447 Extends: MochaUI.Window,\r
2448\r
2449 Implements: [Events, Options],\r
2450\r
2451 initialize: function(options){\r
2452\r
2453 this.modalInitialize();\r
2454 \r
2455 window.addEvent('resize', function(){\r
2456 this.setModalSize();\r
2457 }.bind(this));\r
2458\r
2459 },\r
2460 modalInitialize: function(){\r
2461 var modalOverlay = new Element('div', {\r
2462 'id': 'modalOverlay',\r
2463 'styles': {\r
2464 'height': document.getCoordinates().height,\r
2465 'opacity': .6\r
2466 }\r
2467 }).inject(document.body);\r
2468 \r
2469 modalOverlay.addEvent('click', function(e){\r
2470 MochaUI.closeWindow(MochaUI.currentModal);\r
2471 });\r
2472 \r
2473 if (Browser.Engine.trident4){\r
2474 var modalFix = new Element('iframe', {\r
2475 'id': 'modalFix',\r
2476 'scrolling': 'no',\r
2477 'marginWidth': 0,\r
2478 'marginHeight': 0,\r
2479 'src': '',\r
2480 'styles': {\r
2481 'height': document.getCoordinates().height\r
2482 }\r
2483 }).inject(document.body);\r
2484 }\r
2485\r
2486 this.modalOverlayOpenMorph = new Fx.Morph($('modalOverlay'), {\r
2487 'duration': 150\r
2488 });\r
2489 this.modalOverlayCloseMorph = new Fx.Morph($('modalOverlay'), {\r
2490 'duration': 150,\r
2491 onComplete: function(){\r
2492 $('modalOverlay').setStyle('display', 'none');\r
2493 if (Browser.Engine.trident4){\r
2494 $('modalFix').setStyle('display', 'none');\r
2495 }\r
2496 }.bind(this)\r
2497 });\r
2498 },\r
2499 setModalSize: function(){\r
2500 $('modalOverlay').setStyle('height', document.getCoordinates().height);\r
2501 if (Browser.Engine.trident4){\r
2502 $('modalFix').setStyle('height', document.getCoordinates().height);\r
2503 }\r
2504 }\r
2505});\r
2506MochaUI.Modal.implement(new Options, new Events);\r
2507/*\r
2508\r
2509Script: Windows-from-html.js\r
2510 Create windows from html markup in page.\r
2511\r
2512Copyright:\r
2513 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
2514\r
2515License:\r
2516 MIT-style license. \r
2517\r
2518Requires:\r
2519 Core.js, Window.js\r
2520\r
2521Example:\r
2522 HTML markup.\r
2523 (start code)\r
2524<div class="mocha" id="mywindow" style="width:300px;height:255px;top:50px;left:350px">\r
2525 <h3 class="mochaTitle">My Window</h3>\r
2526 <p>My Window Content</p>\r
2527</div> \r
2528 (end)\r
2529\r
2530See Also:\r
2531 <Window>\r
2532\r
2533*/\r
2534\r
2535MochaUI.extend({\r
2536 NewWindowsFromHTML: function(){\r
2537 $$('div.mocha').each(function(el) {\r
2538 // Get the window title and destroy that element, so it does not end up in window content\r
2539 if ( Browser.Engine.presto || Browser.Engine.trident5 ){\r
2540 el.setStyle('display','block'); // Required by Opera, and probably IE7\r
2541 }\r
2542 var title = el.getElement('h3.mochaTitle');\r
2543 var elDimensions = el.getStyles('height', 'width');\r
2544 var properties = {\r
2545 id: el.getProperty('id'),\r
2546 height: elDimensions.height.toInt(),\r
2547 width: elDimensions.width.toInt(),\r
2548 x: el.getStyle('left').toInt(),\r
2549 y: el.getStyle('top').toInt()\r
2550 };\r
2551 // If there is a title element, set title and destroy the element so it does not end up in window content\r
2552 if ( title ) {\r
2553 properties.title = title.innerHTML;\r
2554 title.destroy();\r
2555 }\r
2556 \r
2557 // Get content and destroy the element\r
2558 properties.content = el.innerHTML;\r
2559 el.destroy();\r
2560 \r
2561 // Create window\r
2562 new MochaUI.Window(properties, true);\r
2563 }.bind(this));\r
2564 }\r
2565});\r
2566/*\r
2567\r
2568Script: Windows-from-json.js\r
2569 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.\r
2570\r
2571Copyright:\r
2572 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
2573\r
2574License:\r
2575 MIT-style license. \r
2576\r
2577Syntax:\r
2578 (start code)\r
2579 MochaUI.newWindowsFromJSON(properties);\r
2580 (end)\r
2581\r
2582Example:\r
2583 (start code)\r
2584 MochaUI.jsonWindows = function(){\r
2585 var url = 'data/json-windows-data.js';\r
2586 var request = new Request.JSON({\r
2587 url: url,\r
2588 method: 'get',\r
2589 onComplete: function(properties) {\r
2590 MochaUI.newWindowsFromJSON(properties.windows);\r
2591 }\r
2592 }).send();\r
2593 }\r
2594 (end)\r
2595\r
2596Note: \r
2597 Windows created from JSON are not compatible with the current cookie based version\r
2598 of Save and Load Workspace. \r
2599\r
2600See Also:\r
2601 <Window>\r
2602\r
2603*/\r
2604\r
2605MochaUI.extend({ \r
2606 newWindowsFromJSON: function(properties){\r
2607 properties.each(function(properties) {\r
2608 new MochaUI.Window(properties);\r
2609 }.bind(this));\r
2610 }\r
2611});\r
2612/*\r
2613\r
2614Script: Arrange-cascade.js\r
2615 Cascade windows.\r
2616\r
2617Copyright:\r
2618 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
2619\r
2620License:\r
2621 MIT-style license. \r
2622\r
2623Requires:\r
2624 Core.js, Window.js\r
2625\r
2626Syntax:\r
2627 (start code)\r
2628 MochaUI.arrangeCascade();\r
2629 (end)\r
2630\r
2631*/\r
2632\r
2633MochaUI.options.extend({\r
2634 viewportTopOffset: 30, // Use a negative number if neccessary to place first window where you want it\r
2635 viewportLeftOffset: 20,\r
2636 windowTopOffset: 50, // Initial vertical spacing of each window\r
2637 windowLeftOffset: 40 // Initial horizontal spacing of each window \r
2638});\r
2639\r
2640MochaUI.extend({ \r
2641 arrangeCascade: function(){\r
2642 // See how much space we have to work with\r
2643 var coordinates = document.getCoordinates();\r
2644 \r
2645 var openWindows = 0;\r
2646 MochaUI.Windows.instances.each(function(instance){\r
2647 if (!instance.isMinimized) openWindows ++; \r
2648 });\r
2649 \r
2650 if ((this.options.windowTopOffset * (openWindows + 1)) >= (coordinates.height - this.options.viewportTopOffset)) {\r
2651 var topOffset = (coordinates.height - this.options.viewportTopOffset) / (openWindows + 1);\r
2652 }\r
2653 else {\r
2654 var topOffset = this.options.windowTopOffset;\r
2655 }\r
2656 \r
2657 if ((this.options.windowLeftOffset * (openWindows + 1)) >= (coordinates.width - this.options.viewportLeftOffset - 20)) {\r
2658 var leftOffset = (coordinates.width - this.options.viewportLeftOffset - 20) / (openWindows + 1);\r
2659 }\r
2660 else {\r
2661 var leftOffset = this.options.windowLeftOffset;\r
2662 }\r
2663\r
2664 var x = this.options.viewportLeftOffset;\r
2665 var y = this.options.viewportTopOffset;\r
2666 $$('div.mocha').each(function(windowEl){\r
2667 var currentWindowClass = MochaUI.Windows.instances.get(windowEl.id);\r
2668 if (!currentWindowClass.isMinimized && !currentWindowClass.isMaximized){\r
2669 id = windowEl.id;\r
2670 MochaUI.focusWindow(windowEl);\r
2671 x += leftOffset;\r
2672 y += topOffset;\r
2673\r
2674 if (MochaUI.options.useEffects == false){\r
2675 windowEl.setStyles({\r
2676 'top': y,\r
2677 'left': x\r
2678 });\r
2679 }\r
2680 else {\r
2681 var cascadeMorph = new Fx.Morph(windowEl, {\r
2682 'duration': 550\r
2683 });\r
2684 cascadeMorph.start({\r
2685 'top': y,\r
2686 'left': x\r
2687 });\r
2688 }\r
2689 }\r
2690 }.bind(this));\r
2691 }\r
2692});\r
2693/*\r
2694\r
2695Script: Arrange-tile.js\r
2696 Cascade windows.\r
2697\r
2698Authors:\r
2699 Harry Roberts and Greg Houston\r
2700\r
2701License:\r
2702 MIT-style license. \r
2703\r
2704Requires:\r
2705 Core.js, Window.js\r
2706\r
2707Syntax:\r
2708 (start code)\r
2709 MochaUI.arrangeTile();\r
2710 (end)\r
2711\r
2712*/\r
2713 \r
2714MochaUI.extend({\r
2715 arrangeTile: function(){\r
2716 var x = 10;\r
2717 var y = 10;\r
2718 \r
2719 var instances = MochaUI.Windows.instances;\r
2720\r
2721 var windowsNum = 0;\r
2722\r
2723 instances.each(function(instance){\r
2724 if (!instance.isMinimized && !instance.isMaximized){\r
2725 windowsNum++;\r
2726 }\r
2727 });\r
2728\r
2729 var cols = 3;\r
2730 var rows = Math.ceil(windowsNum / cols);\r
2731 \r
2732 var coordinates = document.getCoordinates();\r
2733 \r
2734 var col_width = ((coordinates.width - this.options.viewportLeftOffset) / cols);\r
2735 var col_height = ((coordinates.height - this.options.viewportTopOffset) / rows);\r
2736 \r
2737 var row = 0;\r
2738 var col = 0;\r
2739 \r
2740 instances.each(function(instance){\r
2741 if (!instance.isMinimized && !instance.isMaximized){\r
2742 \r
2743 var content = instance.contentWrapperEl;\r
2744 var content_coords = content.getCoordinates();\r
2745 var window_coords = instance.windowEl.getCoordinates();\r
2746 \r
2747 // Calculate the amount of padding around the content window\r
2748 var padding_top = content_coords.top - window_coords.top;\r
2749 var padding_bottom = window_coords.height - content_coords.height - padding_top;\r
2750 var padding_left = content_coords.left - window_coords.left;\r
2751 var padding_right = window_coords.width - content_coords.width - padding_left;\r
2752\r
2753 /*\r
2754\r
2755 // This resizes the windows\r
2756 if (instance.options.shape != 'gauge' && instance.options.resizable == true){\r
2757 var width = (col_width - 3 - padding_left - padding_right);\r
2758 var height = (col_height - 3 - padding_top - padding_bottom);\r
2759\r
2760 if (width > instance.options.resizeLimit.x[0] && width < instance.options.resizeLimit.x[1]){\r
2761 content.setStyle('width', width);\r
2762 }\r
2763 if (height > instance.options.resizeLimit.y[0] && height < instance.options.resizeLimit.y[1]){\r
2764 content.setStyle('height', height);\r
2765 }\r
2766\r
2767 }*/\r
2768\r
2769 var left = (x + (col * col_width));\r
2770 var top = (y + (row * col_height));\r
2771\r
2772 instance.windowEl.setStyles({\r
2773 'left': left,\r
2774 'top': top\r
2775 });\r
2776\r
2777 instance.drawWindow(instance.windowEl);\r
2778\r
2779 MochaUI.focusWindow(instance.windowEl);\r
2780\r
2781 if (++col === cols) {\r
2782 row++;\r
2783 col = 0;\r
2784 }\r
2785 }\r
2786 }.bind(this));\r
2787 }\r
2788});/*\r
2789\r
2790Script: Tabs.js\r
2791 Functionality for window tabs.\r
2792\r
2793Copyright:\r
2794 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
2795\r
2796License:\r
2797 MIT-style license.\r
2798\r
2799Requires:\r
2800 Core.js, Window.js (for tabbed windows) or Layout.js (for tabbed panels)\r
2801\r
2802*/\r
2803\r
2804MochaUI.extend({\r
2805 /*\r
2806\r
2807 Function: initializeTabs\r
2808 Add click event to each list item that fires the selected function.\r
2809\r
2810 */\r
2811 initializeTabs: function(el){\r
2812 $(el).getElements('li').each(function(listitem){\r
2813 listitem.addEvent('click', function(e){\r
2814 MochaUI.selected(this, el);\r
2815 });\r
2816 });\r
2817 },\r
2818 /*\r
2819\r
2820 Function: selected\r
2821 Add "selected" class to current list item and remove it from sibling list items.\r
2822\r
2823 Syntax:\r
2824 (start code)\r
2825 selected(el, parent);\r
2826 (end)\r
2827\r
2828Arguments:\r
2829 el - the list item\r
2830 parent - the ul\r
2831\r
2832 */\r
2833 selected: function(el, parent){\r
2834 $(parent).getChildren().each(function(listitem){\r
2835 listitem.removeClass('selected');\r
2836 });\r
2837 el.addClass('selected');\r
2838 }\r
2839});\r
2840\r
2841/*\r
2842\r
2843Script: Layout.js\r
2844 Create web application layouts. Enables window maximize.\r
2845 \r
2846Copyright:\r
2847 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.\r
2848\r
2849License:\r
2850 MIT-style license. \r
2851\r
2852Requires:\r
2853 Core.js, Window.js\r
2854 \r
2855*/\r
2856\r
2857MochaUI.Desktop = new Class({\r
2858\r
2859 Extends: MochaUI.Window,\r
2860\r
2861 Implements: [Events, Options],\r
2862 \r
2863 options: {\r
2864 // Naming options:\r
2865 // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.\r
2866 desktop: 'desktop',\r
2867 desktopHeader: 'desktopHeader',\r
2868 desktopFooter: 'desktopFooter',\r
2869 desktopNavBar: 'desktopNavbar',\r
2870 pageWrapper: 'pageWrapper',\r
2871 page: 'page',\r
2872 desktopFooter: 'desktopFooterWrapper'\r
2873 }, \r
2874 initialize: function(options){\r
2875 this.setOptions(options);\r
2876 this.desktop = $(this.options.desktop);\r
2877 this.desktopHeader = $(this.options.desktopHeader);\r
2878 this.desktopNavBar = $(this.options.desktopNavBar);\r
2879 this.pageWrapper = $(this.options.pageWrapper);\r
2880 this.page = $(this.options.page);\r
2881 this.desktopFooter = $(this.options.desktopFooter); \r
2882 \r
2883 // This is run on dock initialize so no need to do it twice.\r
2884 if (!MochaUI.Dock.dockWrapper){\r
2885 this.setDesktopSize();\r
2886 }\r
2887 this.menuInitialize(); \r
2888\r
2889 // Resize desktop, page wrapper, modal overlay, and maximized windows when browser window is resized\r
2890 window.addEvent('resize', function(e){\r
2891 this.onBrowserResize();\r
2892 }.bind(this));\r
2893 },\r
2894 menuInitialize: function(){\r
2895 // Fix for dropdown menus in IE6\r
2896 if (Browser.Engine.trident4 && this.desktopNavBar){\r
2897 this.desktopNavBar.getElements('li').each(function(element) {\r
2898 element.addEvent('mouseenter', function(){\r
2899 this.addClass('ieHover');\r
2900 });\r
2901 element.addEvent('mouseleave', function(){\r
2902 this.removeClass('ieHover');\r
2903 });\r
2904 });\r
2905 };\r
2906 },\r
2907 onBrowserResize: function(){\r
2908 this.setDesktopSize();\r
2909 // Resize maximized windows to fit new browser window size\r
2910 setTimeout( function(){\r
2911 MochaUI.Windows.instances.each(function(instance){\r
2912 if (instance.isMaximized){\r
2913\r
2914 // Hide iframe while resize for better performance\r
2915 if ( instance.iframeEl ){\r
2916 instance.iframeEl.setStyle('visibility', 'hidden');\r
2917 }\r
2918\r
2919 var coordinates = document.getCoordinates();\r
2920 var borderHeight = instance.contentBorderEl.getStyle('border-top').toInt() + instance.contentBorderEl.getStyle('border-bottom').toInt();\r
2921 var toolbarHeight = instance.toolbarWrapperEl ? instance.toolbarWrapperEl.getStyle('height').toInt() + instance.toolbarWrapperEl.getStyle('border-top').toInt() : 0;\r
2922 instance.contentWrapperEl.setStyles({\r
2923 'height': coordinates.height - instance.options.headerHeight - instance.options.footerHeight - borderHeight - toolbarHeight,\r
2924 'width': coordinates.width\r
2925 });\r
2926\r
2927 instance.drawWindow($(instance.options.id));\r
2928 if ( instance.iframeEl ){\r
2929 instance.iframeEl.setStyles({\r
2930 'height': instance.contentWrapperEl.getStyle('height')\r
2931 });\r
2932 instance.iframeEl.setStyle('visibility', 'visible');\r
2933 }\r
2934\r
2935 }\r
2936 }.bind(this));\r
2937 }.bind(this), 100);\r
2938 },\r
2939 setDesktopSize: function(){\r
2940 var windowDimensions = window.getCoordinates();\r
2941\r
2942 // var dock = $(MochaUI.options.dock);\r
2943 var dockWrapper = $(MochaUI.options.dockWrapper);\r
2944 \r
2945 // Setting the desktop height may only be needed by IE7\r
2946 if (this.desktop){\r
2947 this.desktop.setStyle('height', windowDimensions.height);\r
2948 }\r
2949\r
2950 // Set pageWrapper height so the dock doesn't cover the pageWrapper scrollbars.\r
2951 if (this.pageWrapper) {\r
2952\r
2953 var dockOffset = MochaUI.dockVisible ? dockWrapper.offsetHeight : 0;\r
2954 var pageWrapperHeight = windowDimensions.height;\r
2955 pageWrapperHeight -= this.pageWrapper.getStyle('border-top').toInt();\r
2956 pageWrapperHeight -= this.pageWrapper.getStyle('border-bottom').toInt();\r
2957 if (this.desktopHeader){ pageWrapperHeight -= this.desktopHeader.offsetHeight; }\r
2958 if (this.desktopFooter){ pageWrapperHeight -= this.desktopFooter.offsetHeight; }\r
2959 pageWrapperHeight -= dockOffset;\r
2960\r
2961 if (pageWrapperHeight < 0){\r
2962 pageWrapperHeight = 0;\r
2963 }\r
2964 this.pageWrapper.setStyle('height', pageWrapperHeight);\r
2965 }\r
2966\r
2967 if (MochaUI.Columns.instances.getKeys().length > 0){ // Conditional is a fix for a bug in IE6 in the no toolbars demo.\r
2968 MochaUI.Desktop.resizePanels();\r
2969 } \r
2970 },\r
2971 resizePanels: function(){\r
2972 if (Browser.Engine.trident4){\r
2973 $$('.pad').setStyle('display', 'none');\r
2974 $$('.rHeight').setStyle('height', 1);\r
2975 }\r
2976 MochaUI.panelHeight();\r
2977 MochaUI.rWidth();\r
2978 if (Browser.Engine.trident4) $$('.pad').setStyle('display', 'block');\r
2979 },\r
2980 /*\r
2981 \r
2982 Function: maximizeWindow\r
2983 Maximize a window.\r
2984 \r
2985 Syntax:\r
2986 (start code)\r
2987 MochaUI.Desktop.maximizeWindow(windowEl);\r
2988 (end) \r
2989\r
2990 */ \r
2991 maximizeWindow: function(windowEl){\r
2992\r
2993 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
2994 var options = currentInstance.options;\r
2995 var windowDrag = currentInstance.windowDrag;\r
2996\r
2997 // If window no longer exists or is maximized, stop\r
2998 if (windowEl != $(windowEl) || currentInstance.isMaximized ) return;\r
2999 \r
3000 if (currentInstance.isCollapsed){\r
3001 MochaUI.collapseToggle(windowEl); \r
3002 }\r
3003\r
3004 currentInstance.isMaximized = true;\r
3005 \r
3006 // If window is restricted to a container, it should not be draggable when maximized.\r
3007 if (currentInstance.options.restrict){\r
3008 windowDrag.detach();\r
3009 if (options.resizable) {\r
3010 currentInstance.detachResizable();\r
3011 }\r
3012 currentInstance.titleBarEl.setStyle('cursor', 'default');\r
3013 } \r
3014\r
3015 // If the window has a container that is not the desktop\r
3016 // temporarily move the window to the desktop while it is minimized.\r
3017 if (options.container != this.desktop){\r
3018 this.desktop.grab(windowEl);\r
3019 if (this.options.restrict){\r
3020 windowDrag.container = this.desktop;\r
3021 }\r
3022 } \r
3023\r
3024 // Save original position\r
3025 currentInstance.oldTop = windowEl.getStyle('top');\r
3026 currentInstance.oldLeft = windowEl.getStyle('left');\r
3027\r
3028 var contentWrapperEl = currentInstance.contentWrapperEl;\r
3029\r
3030 // Save original dimensions\r
3031 contentWrapperEl.oldWidth = contentWrapperEl.getStyle('width');\r
3032 contentWrapperEl.oldHeight = contentWrapperEl.getStyle('height');\r
3033\r
3034 // Hide iframe\r
3035 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues\r
3036 if ( currentInstance.iframeEl ) {\r
3037 currentInstance.iframeEl.setStyle('visibility', 'hidden');\r
3038 }\r
3039\r
3040 var windowDimensions = document.getCoordinates();\r
3041 var options = currentInstance.options;\r
3042 var shadowBlur = options.shadowBlur;\r
3043 var shadowOffset = options.shadowOffset;\r
3044 var newHeight = windowDimensions.height - options.headerHeight - options.footerHeight;\r
3045 newHeight -= currentInstance.contentBorderEl.getStyle('border-top').toInt();\r
3046 newHeight -= currentInstance.contentBorderEl.getStyle('border-bottom').toInt();\r
3047 newHeight -= ( currentInstance.toolbarWrapperEl ? currentInstance.toolbarWrapperEl.getStyle('height').toInt() + currentInstance.toolbarWrapperEl.getStyle('border-top').toInt() : 0);\r
3048\r
3049 if (MochaUI.options.useEffects == false){\r
3050 windowEl.setStyles({\r
3051 'top': shadowOffset.y - shadowBlur,\r
3052 'left': shadowOffset.x - shadowBlur\r
3053 });\r
3054 currentInstance.contentWrapperEl.setStyles({\r
3055 'height': newHeight,\r
3056 'width': windowDimensions.width\r
3057 });\r
3058 currentInstance.drawWindow(windowEl);\r
3059 // Show iframe\r
3060 if ( currentInstance.iframeEl ) {\r
3061 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
3062 }\r
3063 currentInstance.fireEvent('onMaximize', windowEl);\r
3064 }\r
3065 else {\r
3066\r
3067 // Todo: Initialize the variables for these morphs once in an initialize function and reuse them\r
3068\r
3069 var maximizeMorph = new Fx.Elements([contentWrapperEl, windowEl], { \r
3070 duration: 70,\r
3071 onStart: function(windowEl){\r
3072 currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);\r
3073 }.bind(this),\r
3074 onComplete: function(windowEl){\r
3075 $clear(currentInstance.maximizeAnimation);\r
3076 currentInstance.drawWindow(windowEl);\r
3077 // Show iframe\r
3078 if ( currentInstance.iframeEl ) {\r
3079 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
3080 }\r
3081 currentInstance.fireEvent('onMaximize', windowEl); \r
3082 }.bind(this)\r
3083 });\r
3084 maximizeMorph.start({\r
3085 '0': { 'height': newHeight,\r
3086 'width': windowDimensions.width\r
3087 },\r
3088 '1': { 'top': shadowOffset.y - shadowBlur,\r
3089 'left': shadowOffset.x - shadowBlur \r
3090 }\r
3091 }); \r
3092 }\r
3093 currentInstance.maximizeButtonEl.setProperty('title', 'Restore');\r
3094 MochaUI.focusWindow(windowEl);\r
3095\r
3096 },\r
3097 /*\r
3098\r
3099 Function: restoreWindow\r
3100 Restore a maximized window.\r
3101\r
3102 Syntax:\r
3103 (start code)\r
3104 MochaUI.Desktop.restoreWindow(windowEl);\r
3105 (end) \r
3106\r
3107 */ \r
3108 restoreWindow: function(windowEl){ \r
3109 \r
3110 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
3111 \r
3112 // Window exists and is maximized ?\r
3113 if (windowEl != $(windowEl) || !currentInstance.isMaximized) return;\r
3114 \r
3115 var options = currentInstance.options;\r
3116 currentInstance.isMaximized = false;\r
3117 \r
3118 if (options.restrict){\r
3119 currentInstance.windowDrag.attach();\r
3120 if (options.resizable){\r
3121 currentInstance.reattachResizable();\r
3122 } \r
3123 currentInstance.titleBarEl.setStyle('cursor', 'move');\r
3124 } \r
3125 \r
3126 // Hide iframe\r
3127 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues\r
3128 if ( currentInstance.iframeEl ) {\r
3129 currentInstance.iframeEl.setStyle('visibility', 'hidden');\r
3130 }\r
3131 \r
3132 var contentWrapperEl = currentInstance.contentWrapperEl;\r
3133 \r
3134 if (MochaUI.options.useEffects == false){\r
3135 contentWrapperEl.setStyles({\r
3136 'width': contentWrapperEl.oldWidth,\r
3137 'height': contentWrapperEl.oldHeight\r
3138 });\r
3139 currentInstance.drawWindow(windowEl);\r
3140 windowEl.setStyles({\r
3141 'top': currentInstance.oldTop,\r
3142 'left': currentInstance.oldLeft\r
3143 });\r
3144 if ( currentInstance.iframeEl ) {\r
3145 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
3146 } \r
3147 if (options.container != this.desktop){\r
3148 $(options.container).grab(windowEl);\r
3149 if (options.restrict){\r
3150 currentInstance.windowDrag.container = $(options.container);\r
3151 }\r
3152 }\r
3153 currentInstance.fireEvent('onRestore', windowEl);\r
3154 }\r
3155 else {\r
3156 var restoreMorph = new Fx.Elements([contentWrapperEl, windowEl], { \r
3157 'duration': 150,\r
3158 'onStart': function(windowEl){\r
3159 currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);\r
3160 }.bind(this),\r
3161 'onComplete': function(el){\r
3162 $clear(currentInstance.maximizeAnimation);\r
3163 currentInstance.drawWindow(windowEl);\r
3164 if (currentInstance.iframeEl){\r
3165 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
3166 }\r
3167 if (options.container != this.desktop){\r
3168 $(options.container).grab(windowEl);\r
3169 if (options.restrict){ \r
3170 currentInstance.windowDrag.container = $(options.container);\r
3171 }\r
3172 }\r
3173 currentInstance.fireEvent('onRestore', windowEl);\r
3174 }.bind(this)\r
3175 });\r
3176 restoreMorph.start({ \r
3177 '0': { 'height': contentWrapperEl.oldHeight,\r
3178 'width': contentWrapperEl.oldWidth\r
3179 },\r
3180 '1': { 'top': currentInstance.oldTop,\r
3181 'left': currentInstance.oldLeft\r
3182 }\r
3183 });\r
3184 }\r
3185 currentInstance.maximizeButtonEl.setProperty('title', 'Maximize');\r
3186 }\r
3187});\r
3188MochaUI.Desktop.implement(new Options, new Events);\r
3189\r
3190/*\r
3191\r
3192Class: Column\r
3193 Create a column. Columns should be created from left to right.\r
3194\r
3195Syntax:\r
3196(start code)\r
3197 MochaUI.Panel();\r
3198(end)\r
3199\r
3200Arguments:\r
3201 options\r
3202\r
3203Options:\r
3204 id - The ID of the column. This must be set when creating the column. \r
3205 placement - Can be 'right', 'main', or 'left'. There must be at least one column with the 'main' option.\r
3206 width - 'main' column is fluid and should not be given a width.\r
3207 resizeLimit - resizelimit of a 'right' or 'left' column.\r
3208 onResize - (function) Fired when the column is resized.\r
3209 onCollapse - (function) Fired when the column is collapsed.\r
3210 onExpand - (function) Fired when the column is expanded.\r
3211 \r
3212*/\r
3213MochaUI.Column = new Class({\r
3214\r
3215 Extends: MochaUI.Desktop,\r
3216\r
3217 Implements: [Events, Options],\r
3218\r
3219 options: {\r
3220 id: null, \r
3221 placement: null, \r
3222 width: null,\r
3223 resizeLimit: [],\r
3224\r
3225 // Events\r
3226 onResize: $empty, \r
3227 onCollapse: $empty,\r
3228 onExpand: $empty\r
3229\r
3230 },\r
3231 initialize: function(options){\r
3232 this.setOptions(options);\r
3233 \r
3234 $extend(this, {\r
3235 timestamp: $time(),\r
3236 isCollapsed: false,\r
3237 oldWidth: 0\r
3238 });\r
3239\r
3240 // Shorten object chain\r
3241 var options = this.options;\r
3242 var instances = MochaUI.Columns.instances;\r
3243 var instanceID = instances.get(options.id);\r
3244\r
3245 // Check to see if there is already a class instance for this Column\r
3246 if (instanceID){\r
3247 var currentInstance = instanceID;\r
3248 }\r
3249\r
3250 // Check if column already exists\r
3251 if ( this.columnEl ){\r
3252 return;\r
3253 }\r
3254 else { \r
3255 instances.set(options.id, this);\r
3256 } \r
3257 \r
3258 this.columnEl = new Element('div', {\r
3259 'id': this.options.id,\r
3260 'class': 'column expanded',\r
3261 'styles': {\r
3262 'width': options.placement == 'main' ? null : options.width\r
3263 }\r
3264 }).inject($(MochaUI.Desktop.pageWrapper));\r
3265\r
3266 var parent = this.columnEl.getParent();\r
3267 var columnHeight = parent.getStyle('height').toInt();\r
3268 this.columnEl.setStyle('height', columnHeight);\r
3269\r
3270 if (options.placement == 'main'){\r
3271 this.columnEl.addClass('rWidth');\r
3272 }\r
3273\r
3274 this.spacerEl = new Element('div', {\r
3275 'id': this.options.id + '_spacer',\r
3276 'class': 'horizontalHandle'\r
3277 }).inject(this.columnEl);\r
3278\r
3279 switch (this.options.placement) {\r
3280 case 'left':\r
3281 this.handleEl = new Element('div', {\r
3282 'id': this.options.id + '_handle',\r
3283 'class': 'columnHandle'\r
3284 }).inject(this.columnEl, 'after');\r
3285\r
3286 this.handleIconEl = new Element('div', {\r
3287 'id': options.id + '_handle_icon',\r
3288 'class': 'handleIcon'\r
3289 }).inject(this.handleEl);\r
3290\r
3291 addResizeRight(this.columnEl, options.resizeLimit[0], options.resizeLimit[1]);\r
3292 break;\r
3293 case 'right':\r
3294 this.handleEl = new Element('div', {\r
3295 'id': this.options.id + '_handle',\r
3296 'class': 'columnHandle'\r
3297 }).inject(this.columnEl, 'before');\r
3298\r
3299 this.handleIconEl = new Element('div', {\r
3300 'id': options.id + '_handle_icon',\r
3301 'class': 'handleIcon'\r
3302 }).inject(this.handleEl);\r
3303 addResizeLeft(this.columnEl, options.resizeLimit[0], options.resizeLimit[1]);\r
3304 break;\r
3305 }\r
3306\r
3307 if (this.handleEl != null){\r
3308 this.handleEl.addEvent('dblclick', function(){\r
3309 this.columnToggle();\r
3310 }.bind(this));\r
3311 }\r
3312\r
3313 MochaUI.rWidth();\r
3314\r
3315 },\r
3316 columnToggle: function(){\r
3317 var column= this.columnEl;\r
3318 \r
3319 // Collapse\r
3320 if (this.isCollapsed == false){\r
3321 this.oldWidth = column.getStyle('width').toInt();\r
3322\r
3323 this.resize.detach();\r
3324 this.handleEl.removeEvents('dblclick');\r
3325 this.handleEl.addEvent('click', function(){\r
3326 this.columnToggle();\r
3327 }.bind(this));\r
3328 this.handleEl.setStyle('cursor', 'pointer').addClass('detached');\r
3329 \r
3330 column.setStyle('width', 0);\r
3331 this.isCollapsed = true;\r
3332 column.addClass('collapsed');\r
3333 column.removeClass('expanded');\r
3334\r
3335 MochaUI.rWidth();\r
3336 this.fireEvent('onCollapse');\r
3337 }\r
3338 // Expand\r
3339 else {\r
3340 column.setStyle('width', this.oldWidth);\r
3341 this.isCollapsed = false;\r
3342 column.addClass('expanded');\r
3343 column.removeClass('collapsed');\r
3344\r
3345 this.handleEl.removeEvents('click');\r
3346 this.handleEl.addEvent('dblclick', function(){\r
3347 this.columnToggle();\r
3348 }.bind(this));\r
3349 this.resize.attach();\r
3350 this.handleEl.setStyle('cursor', 'e-resize').addClass('attached');\r
3351\r
3352 MochaUI.rWidth();\r
3353 this.fireEvent('onExpand');\r
3354 }\r
3355 }\r
3356});\r
3357MochaUI.Column.implement(new Options, new Events);\r
3358\r
3359/*\r
3360\r
3361Class: Panel\r
3362 Create a panel. Panels go one on top of another in columns. Create your columns first and then add your panels. Panels should be created from top to bottom, left to right.\r
3363\r
3364Syntax:\r
3365(start code)\r
3366 MochaUI.Panel();\r
3367(end)\r
3368\r
3369Arguments:\r
3370 options\r
3371\r
3372Options:\r
3373 id - The ID of the panel. This must be set when creating the panel.\r
3374 column - Where to inject the panel. This must be set when creating the panel.\r
3375 loadMethod - ('html', 'xhr', or 'iframe')\r
3376 contentURL - Used if loadMethod is set to 'xhr' or 'iframe'.\r
3377 evalScripts - (boolean) An xhr loadMethod option. Defaults to true.\r
3378 evalResponse - (boolean) An xhr loadMethod option. Defaults to false.\r
3379 content - (string or element) An html loadMethod option.\r
3380 tabsURL - (url) \r
3381 footer - (boolean)\r
3382 footerURL - (url)\r
3383 height - (number) Height of content area.\r
3384 addClass - (string) Add a class to the panel.\r
3385 scrollbars - (boolean)\r
3386 padding - (object)\r
3387 panelBackground - CSS background property for the panel.\r
3388 onBeforeBuild - (function) Fired before the panel is created.\r
3389 onContentLoaded - (function) Fired after the panel's conten is loaded.\r
3390 onResize - (function) Fired when the panel is resized.\r
3391 onCollapse - (function) Fired when the panel is collapsed.\r
3392 onExpand - (function) Fired when the panel is expanded.\r
3393 \r
3394*/\r
3395MochaUI.Panel = new Class({\r
3396 \r
3397 Extends: MochaUI.Desktop,\r
3398 \r
3399 Implements: [Events, Options],\r
3400 \r
3401 options: {\r
3402 id: null,\r
3403 title: 'New Panel',\r
3404 column: null,\r
3405 loadMethod: 'html',\r
3406 contentURL: 'pages/lipsum.html',\r
3407 \r
3408 // xhr options\r
3409 evalScripts: true,\r
3410 evalResponse: false,\r
3411 \r
3412 // html options\r
3413 content: 'Panel content',\r
3414 \r
3415 // Tabs\r
3416 tabsURL: null,\r
3417\r
3418 footer: false,\r
3419 footerURL: 'pages/lipsum.html',\r
3420 \r
3421 // Style options:\r
3422 height: 125,\r
3423 addClass: '',\r
3424 scrollbars: true,\r
3425 padding: { top: 8, right: 8, bottom: 8, left: 8 },\r
3426\r
3427 // Color options: \r
3428 panelBackground: '#f8f8f8',\r
3429\r
3430 // Events\r
3431 onBeforeBuild: $empty,\r
3432 onContentLoaded: $empty,\r
3433 onResize: $empty,\r
3434 onCollapse: $empty,\r
3435 onExpand: $empty\r
3436\r
3437 }, \r
3438 initialize: function(options){\r
3439 this.setOptions(options);\r
3440\r
3441 $extend(this, {\r
3442 timestamp: $time(),\r
3443 isCollapsed: false,\r
3444 oldHeight: 0,\r
3445 partner: null\r
3446 });\r
3447\r
3448 // Shorten object chain\r
3449 var instances = MochaUI.Panels.instances;\r
3450 var instanceID = instances.get(this.options.id);\r
3451 \r
3452 // Check to see if there is already a class instance for this panel\r
3453 if (instanceID){\r
3454 var currentInstance = instanceID;\r
3455 }\r
3456\r
3457 // Check if panel already exists\r
3458 if ( this.panelEl ){\r
3459 return;\r
3460 }\r
3461 else { \r
3462 instances.set(this.options.id, this);\r
3463 }\r
3464\r
3465 this.fireEvent('onBeforeBuild');\r
3466 \r
3467 if (this.options.loadMethod == 'iframe') {\r
3468 // Iframes have their own scrollbars and padding.\r
3469 this.options.scrollbars = false;\r
3470 this.options.padding = { top: 0, right: 0, bottom: 0, left: 0 };\r
3471 }\r
3472\r
3473 this.showHandle = true;\r
3474 if ($(this.options.column).getChildren().length == 0){\r
3475 this.showHandle = false;\r
3476 }\r
3477\r
3478 this.panelEl = new Element('div', {\r
3479 'id': this.options.id,\r
3480 'class': 'panel expanded',\r
3481 'styles': {\r
3482 'height': this.options.height,\r
3483 'background': this.options.panelBackground\r
3484 }\r
3485 }).inject($(this.options.column));\r
3486\r
3487 this.panelEl.addClass(this.options.addClass);\r
3488\r
3489 this.contentEl = new Element('div', {\r
3490 'id': this.options.id + '_pad',\r
3491 'class': 'pad'\r
3492 }).inject(this.panelEl);\r
3493\r
3494 if (this.options.footer){\r
3495 this.footerWrapperEl = new Element('div', {\r
3496 'id': this.options.id + '_panelFooterWrapper',\r
3497 'class': 'panel-footerWrapper'\r
3498 }).inject(this.panelEl);\r
3499 \r
3500 this.footerEl = new Element('div', {\r
3501 'id': this.options.id + '_panelFooter',\r
3502 'class': 'panel-footer'\r
3503 }).inject(this.footerWrapperEl);\r
3504\r
3505\r
3506 MochaUI.updateContent({\r
3507 'element': this.panelEl,\r
3508 'childElement': this.footerEl,\r
3509 'loadMethod': 'xhr',\r
3510 'url': this.options.footerURL\r
3511 });\r
3512 \r
3513 }\r
3514\r
3515 // This is in order to use the same variable as the windows do in updateContent.\r
3516 // May rethink this.\r
3517 this.contentWrapperEl = this.panelEl;\r
3518 \r
3519 // Set scrollbars, always use 'hidden' for iframe windows\r
3520 this.contentWrapperEl.setStyles({\r
3521 'overflow': this.options.scrollbars && !this.iframeEl ? 'auto' : 'hidden'\r
3522 });\r
3523\r
3524 this.contentEl.setStyles({\r
3525 'padding-top': this.options.padding.top,\r
3526 'padding-bottom': this.options.padding.bottom,\r
3527 'padding-left': this.options.padding.left,\r
3528 'padding-right': this.options.padding.right\r
3529 }); \r
3530 \r
3531 this.panelHeaderEl = new Element('div', {\r
3532 'id': this.options.id + '_header',\r
3533 'class': 'panel-header'\r
3534 }).inject(this.panelEl, 'before');\r
3535 \r
3536 this.panelHeaderToolboxEl = new Element('div', {\r
3537 'id': this.options.id + '_headerToolbox',\r
3538 'class': 'panel-header-toolbox'\r
3539 }).inject(this.panelHeaderEl);\r
3540\r
3541 this.collapseToggleEl = new Element('div', {\r
3542 'id': this.options.id + '_minmize',\r
3543 'class': 'panel-collapse icon16',\r
3544 'styles': {\r
3545 'width': 16,\r
3546 'height': 16\r
3547 },\r
3548 'title': 'Collapse Panel'\r
3549 }).inject(this.panelHeaderToolboxEl);\r
3550\r
3551 this.collapseToggleEl.addEvent('click', function(event){\r
3552 var panel = this.panelEl;\r
3553 \r
3554 // Get siblings and make sure they are not all collapsed.\r
3555 var instances = MochaUI.Panels.instances;\r
3556 var expandedSiblings = [];\r
3557 panel.getAllPrevious('.panel').each(function(sibling){\r
3558 var currentInstance = instances.get(sibling.id);\r
3559 if (currentInstance.isCollapsed == false){\r
3560 expandedSiblings.push(sibling);\r
3561 }\r
3562 });\r
3563 panel.getAllNext('.panel').each(function(sibling){\r
3564 var currentInstance = instances.get(sibling.id);\r
3565 if (currentInstance.isCollapsed == false){\r
3566 expandedSiblings.push(sibling);\r
3567 }\r
3568 });\r
3569\r
3570 if (this.isCollapsed == false) {\r
3571 var currentColumn = MochaUI.Columns.instances.get($(this.options.column).id);\r
3572\r
3573 if (expandedSiblings.length == 0 && currentColumn.options.placement != 'main'){\r
3574 var currentColumn = MochaUI.Columns.instances.get($(this.options.column).id);\r
3575 currentColumn.columnToggle();\r
3576 return;\r
3577 }\r
3578 else if (expandedSiblings.length == 0 && currentColumn.options.placement == 'main'){\r
3579 return;\r
3580 }\r
3581 this.oldHeight = panel.getStyle('height').toInt();\r
3582 if (this.oldHeight < 10) this.oldHeight = 20;\r
3583 panel.setStyle('height', 0);\r
3584 this.isCollapsed = true;\r
3585 panel.addClass('collapsed');\r
3586 panel.removeClass('expanded');\r
3587 MochaUI.panelHeight(this.options.column, panel, 'collapsing');\r
3588 this.collapseToggleEl.removeClass('panel-collapsed');\r
3589 this.collapseToggleEl.addClass('panel-expand');\r
3590 this.collapseToggleEl.setProperty('title','Expand Panel');\r
3591 this.fireEvent('onCollapse');\r
3592 }\r
3593 else {\r
3594 panel.setStyle('height', this.oldHeight);\r
3595 this.isCollapsed = false;\r
3596 panel.addClass('expanded');\r
3597 panel.removeClass('collapsed');\r
3598 MochaUI.panelHeight(this.options.column, panel, 'expanding');\r
3599 this.collapseToggleEl.removeClass('panel-expand');\r
3600 this.collapseToggleEl.addClass('panel-collapsed');\r
3601 this.collapseToggleEl.setProperty('title','Collapse Panel');\r
3602 this.fireEvent('onExpand');\r
3603 }\r
3604 }\r
3605 .bind(this));\r
3606 \r
3607 this.panelHeaderContentEl = new Element('div', {\r
3608 'id': this.options.id + '_headerContent',\r
3609 'class': 'panel-headerContent'\r
3610 }).inject(this.panelHeaderEl);\r
3611\r
3612 this.titleEl = new Element('h2', {\r
3613 'id': this.options.id + '_title'\r
3614 }).inject(this.panelHeaderContentEl);\r
3615\r
3616 if (this.options.tabsURL == null){\r
3617 this.titleEl.set('html', this.options.title);\r
3618 } \r
3619 else {\r
3620 this.panelHeaderContentEl.addClass('tabs');\r
3621 MochaUI.updateContent({\r
3622 'element': this.panelEl,\r
3623 'childElement': this.panelHeaderContentEl,\r
3624 'loadMethod': 'xhr',\r
3625 'url': this.options.tabsURL\r
3626 });\r
3627 }\r
3628\r
3629 this.handleEl = new Element('div', {\r
3630 'id': this.options.id + '_handle',\r
3631 'class': 'horizontalHandle',\r
3632 'styles': {\r
3633 'display': this.showHandle == true ? 'block' : 'none'\r
3634 }\r
3635 }).inject(this.panelEl, 'after');\r
3636 \r
3637 this.handleIconEl = new Element('div', {\r
3638 'id': this.options.id + '_handle_icon',\r
3639 'class': 'handleIcon'\r
3640 }).inject(this.handleEl);\r
3641\r
3642 addResizeBottom(this.options.id);\r
3643\r
3644 // Add content to panel.\r
3645 MochaUI.updateContent({\r
3646 'element': this.panelEl,\r
3647 'content': this.options.content,\r
3648 'url': this.options.contentURL\r
3649 });\r
3650\r
3651 MochaUI.panelHeight(this.options.column, this.panelEl, 'new');\r
3652\r
3653 }\r
3654});\r
3655MochaUI.Panel.implement(new Options, new Events);\r
3656\r
3657\r
3658MochaUI.extend({\r
3659 // Panel Height \r
3660 panelHeight: function(column, changing, action){\r
3661 if (column != null) {\r
3662 MochaUI.panelHeight2($(column), changing, action);\r
3663 }\r
3664 else {\r
3665 $$('.column').each(function(column){\r
3666 MochaUI.panelHeight2(column);\r
3667 }.bind(this));\r
3668 }\r
3669 },\r
3670 /*\r
3671\r
3672 actions can be new, collapsing or expanding.\r
3673\r
3674 */\r
3675 panelHeight2: function(column, changing, action){\r
3676\r
3677 var instances = MochaUI.Panels.instances;\r
3678 \r
3679 var parent = column.getParent();\r
3680 var columnHeight = parent.getStyle('height').toInt();\r
3681 if (Browser.Engine.trident4){\r
3682 columnHeight -= 1;\r
3683 }\r
3684 column.setStyle('height', columnHeight);\r
3685\r
3686 var panels = column.getChildren('.panel'); // All the panels in the column.\r
3687 var panelsExpanded = column.getChildren('.expanded'); // All the expanded panels in the column.\r
3688 var panelsToResize = []; // All the panels in the column whose height will be effected.\r
3689 var tallestPanel; // The panel with the greatest height\r
3690 var tallestPanelHeight = 0;\r
3691\r
3692 this.panelsHeight = 0; // Height of all the panels in the column \r
3693 this.height = 0; // Height of all the elements in the column \r
3694\r
3695 // Set panel resize partners\r
3696 panels.each(function(panel){\r
3697 currentInstance = instances.get(panel.id);\r
3698 if (panel.hasClass('expanded') && panel.getNext('.expanded')){\r
3699 currentInstance.partner = panel.getNext('.expanded');\r
3700 currentInstance.resize.attach();\r
3701 currentInstance.handleEl.setStyles({\r
3702 'display': 'block',\r
3703 'cursor': 'n-resize'\r
3704 }).removeClass('detached');\r
3705 }\r
3706 else {\r
3707 currentInstance.resize.detach();\r
3708 currentInstance.handleEl.setStyle('cursor', null).addClass('detached');\r
3709 }\r
3710 if (panel.getNext('.panel') == null){\r
3711 currentInstance.handleEl.setStyle('display', 'none');\r
3712 }\r
3713 }.bind(this));\r
3714 \r
3715 // Get the total height of all the column's children\r
3716 column.getChildren().each(function(el){\r
3717\r
3718 if (el.hasClass('panel')){\r
3719 var currentInstance = instances.get(el.id);\r
3720\r
3721 // Are any next siblings Expanded?\r
3722 areAnyNextSiblingsExpanded = function(el){\r
3723 var test;\r
3724 el.getAllNext('.panel').each(function(sibling){\r
3725 var siblingInstance = instances.get(sibling.id);\r
3726 if (siblingInstance.isCollapsed == false){\r
3727 test = true;\r
3728 }\r
3729 }.bind(this));\r
3730 return test;\r
3731 }.bind(this);\r
3732\r
3733 // If a next sibling is expanding, are any of the nexts siblings of the expanding sibling Expanded?\r
3734 areAnyExpandingNextSiblingsExpanded = function(){\r
3735 var test;\r
3736 changing.getAllNext('.panel').each(function(sibling){\r
3737 var siblingInstance = instances.get(sibling.id);\r
3738 if (siblingInstance.isCollapsed == false){\r
3739 test = true;\r
3740 }\r
3741 }.bind(this));\r
3742 return test;\r
3743 }.bind(this);\r
3744 \r
3745 // Resize panels that are not collapsed or "new"\r
3746 if (action == 'new' ) {\r
3747 if (currentInstance.isCollapsed != true && el != changing) {\r
3748 panelsToResize.push(el);\r
3749 }\r
3750 \r
3751 // Height of panels that can be resized\r
3752 if (currentInstance.isCollapsed != true && el != changing) {\r
3753 this.panelsHeight += el.offsetHeight.toInt();\r
3754 }\r
3755 }\r
3756 // Resize panels that are not collapsed. If a panel is collapsing\r
3757 // resize any expanded panels below. If there are no expanded panels\r
3758 // below it, resize the expanded panels above it.\r
3759 else if (action == null || action == 'collapsing' ){\r
3760 if (currentInstance.isCollapsed != true && (el.getAllNext('.panel').contains(changing) != true || areAnyNextSiblingsExpanded(el) != true)){\r
3761 panelsToResize.push(el);\r
3762 }\r
3763 \r
3764 // Height of panels that can be resized\r
3765 if (currentInstance.isCollapsed != true && (el.getAllNext('.panel').contains(changing) != true || areAnyNextSiblingsExpanded(el) != true)){\r
3766 this.panelsHeight += el.offsetHeight.toInt();\r
3767 }\r
3768 }\r
3769 // Resize panels that are not collapsed and are not expanding.\r
3770 // Resize any expanded panels below the expanding panel. If there are no expanded panels\r
3771 // below it, resize the first expanded panel above it.\r
3772 else if (action == 'expanding'){\r
3773 \r
3774 if (currentInstance.isCollapsed != true && (el.getAllNext('.panel').contains(changing) != true || (areAnyExpandingNextSiblingsExpanded() != true && el.getNext('.expanded') == changing)) && el != changing){\r
3775 panelsToResize.push(el);\r
3776 }\r
3777 // Height of panels that can be resized\r
3778 if (currentInstance.isCollapsed != true && (el.getAllNext('.panel').contains(changing) != true || (areAnyExpandingNextSiblingsExpanded() != true && el.getNext('.expanded') == changing)) && el != changing){\r
3779 this.panelsHeight += el.offsetHeight.toInt();\r
3780 }\r
3781 }\r
3782\r
3783 if (el.style.height){\r
3784 this.height += el.getStyle('height').toInt();\r
3785 }\r
3786 }\r
3787 else {\r
3788 this.height += el.offsetHeight.toInt();\r
3789 }\r
3790 }.bind(this));\r
3791\r
3792 // Get the remaining height\r
3793 var remainingHeight = column.offsetHeight.toInt() - this.height;\r
3794 \r
3795 this.height = 0;\r
3796\r
3797 // Get height of all the column's children\r
3798 column.getChildren().each(function(el){\r
3799 this.height += el.offsetHeight.toInt();\r
3800 }.bind(this));\r
3801 \r
3802 var remainingHeight = column.offsetHeight.toInt() - this.height;\r
3803\r
3804 panelsToResize.each(function(panel){\r
3805 var ratio = this.panelsHeight / panel.offsetHeight.toInt();\r
3806 var newPanelHeight = panel.getStyle('height').toInt() + (remainingHeight / ratio);\r
3807 if (newPanelHeight < 1){\r
3808 newPanelHeight = 0;\r
3809 }\r
3810 panel.setStyle('height', newPanelHeight);\r
3811 }.bind(this)); \r
3812\r
3813 // Make sure the remaining height is 0. If not add/subtract the\r
3814 // remaining height to the tallest panel. This makes up for browser resizing,\r
3815 // off ratios, and users trying to give panels too much height.\r
3816 \r
3817 // Get height of all the column's children\r
3818 this.height = 0;\r
3819 column.getChildren().each(function(el){\r
3820 this.height += el.offsetHeight.toInt();\r
3821 if (el.hasClass('panel') && el.getStyle('height').toInt() > tallestPanelHeight){\r
3822 tallestPanel = el;\r
3823 tallestPanelHeight = el.getStyle('height').toInt();\r
3824 }\r
3825 }.bind(this));\r
3826\r
3827 var remainingHeight = column.offsetHeight.toInt() - this.height;\r
3828\r
3829 if ((remainingHeight > 0 || remainingHeight < 0) && tallestPanelHeight > 0){\r
3830 tallestPanel.setStyle('height', tallestPanel.getStyle('height').toInt() + remainingHeight );\r
3831 if (tallestPanel.getStyle('height') < 1){\r
3832 tallestPanel.setStyle('height', 0 );\r
3833 }\r
3834 }\r
3835\r
3836 $$('.columnHandle').each(function(handle){\r
3837 var handleHeight = parent.getStyle('height').toInt() - handle.getStyle('border-top').toInt() - handle.getStyle('border-bottom').toInt();\r
3838 if (Browser.Engine.trident4){\r
3839 handleHeight -= 1;\r
3840 }\r
3841 handle.setStyle('height', handleHeight);\r
3842 });\r
3843 \r
3844 panelsExpanded.each(function(panel){\r
3845 MochaUI.resizeChildren(panel);\r
3846 }.bind(this));\r
3847 },\r
3848 // May rename this resizeIframeEl()\r
3849 resizeChildren: function(panel){\r
3850 var instances = MochaUI.Panels.instances;\r
3851 var currentInstance = instances.get(panel.id);\r
3852 var contentWrapperEl = currentInstance.contentWrapperEl;\r
3853\r
3854 if (currentInstance.iframeEl){\r
3855 currentInstance.iframeEl.setStyles({\r
3856 'height': contentWrapperEl.getStyle('height'),\r
3857 'width': contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('border-left').toInt() - contentWrapperEl.getStyle('border-right').toInt()\r
3858 });\r
3859 }\r
3860 },\r
3861 // Remaining Width\r
3862 rWidth: function(){ \r
3863 $$('.rWidth').each(function(column){\r
3864 var currentWidth = column.offsetWidth.toInt();\r
3865 currentWidth -= column.getStyle('border-left').toInt();\r
3866 currentWidth -= column.getStyle('border-right').toInt();\r
3867\r
3868 var parent = column.getParent();\r
3869 this.width = 0;\r
3870 \r
3871 // Get the total width of all the parent element's children\r
3872 parent.getChildren().each(function(el){\r
3873 if (el.hasClass('mocha') != true){\r
3874 this.width += el.offsetWidth.toInt();\r
3875 }\r
3876 }.bind(this));\r
3877 \r
3878 // Add the remaining width to the current element\r
3879 var remainingWidth = parent.offsetWidth.toInt() - this.width;\r
3880 var newWidth = currentWidth + remainingWidth;\r
3881 if (newWidth < 1) newWidth = 0;\r
3882 column.setStyle('width', newWidth);\r
3883 column.getChildren('.panel').each(function(panel){\r
3884 panel.setStyle('width', newWidth - panel.getStyle('border-left').toInt() - panel.getStyle('border-right').toInt());\r
3885 MochaUI.resizeChildren(panel);\r
3886 }.bind(this));\r
3887 });\r
3888 }\r
3889\r
3890});\r
3891\r
3892function addResizeRight(element, min, max){\r
3893 if (!$(element)) return;\r
3894 element = $(element);\r
3895\r
3896 var instances = MochaUI.Columns.instances;\r
3897 var currentInstance = instances.get(element.id);\r
3898\r
3899 var handle = element.getNext('.columnHandle');\r
3900 handle.setStyle('cursor', 'e-resize'); \r
3901 if (!min) min = 50;\r
3902 if (!max) max = 250;\r
3903 if (Browser.Engine.trident){\r
3904 handle.addEvents({\r
3905 'mousedown': function(){\r
3906 handle.setCapture();\r
3907 },\r
3908 'mouseup': function(){\r
3909 handle.releaseCapture();\r
3910 }\r
3911 });\r
3912 }\r
3913 currentInstance.resize = element.makeResizable({\r
3914 handle: handle,\r
3915 modifiers: {x: 'width', y: false},\r
3916 limit: { x: [min, max] },\r
3917 onStart: function(){\r
3918 element.getElements('iframe').setStyle('visibility','hidden');\r
3919 element.getNext('.column').getElements('iframe').setStyle('visibility','hidden');\r
3920 }.bind(this),\r
3921 onDrag: function(){\r
3922 MochaUI.rWidth();\r
3923 if (Browser.Engine.trident4){\r
3924 element.getChildren().each(function(el){\r
3925 var width = $(element).getStyle('width').toInt();\r
3926 width -= el.getStyle('border-right').toInt();\r
3927 width -= el.getStyle('border-left').toInt();\r
3928 width -= el.getStyle('padding-right').toInt();\r
3929 width -= el.getStyle('padding-left').toInt();\r
3930 el.setStyle('width', width);\r
3931 }.bind(this));\r
3932 } \r
3933 }.bind(this),\r
3934 onComplete: function(){\r
3935 MochaUI.rWidth();\r
3936 element.getElements('iframe').setStyle('visibility','visible');\r
3937 element.getNext('.column').getElements('iframe').setStyle('visibility','visible');\r
3938 currentInstance.fireEvent('onResize');\r
3939 }.bind(this)\r
3940 }); \r
3941}\r
3942\r
3943function addResizeLeft(element, min, max){\r
3944 if (!$(element)) return;\r
3945 element = $(element);\r
3946\r
3947 var instances = MochaUI.Columns.instances;\r
3948 var currentInstance = instances.get(element.id);\r
3949\r
3950 var handle = element.getPrevious('.columnHandle');\r
3951 handle.setStyle('cursor', 'e-resize');\r
3952 var partner = element.getPrevious('.column');\r
3953 if (!min) min = 50;\r
3954 if (!max) max = 250;\r
3955 if (Browser.Engine.trident){ \r
3956 handle.addEvents({\r
3957 'mousedown': function(){\r
3958 handle.setCapture();\r
3959 }, \r
3960 'mouseup': function(){\r
3961 handle.releaseCapture();\r
3962 }\r
3963 });\r
3964 }\r
3965 currentInstance.resize = element.makeResizable({\r
3966 handle: handle,\r
3967 modifiers: {x: 'width' , y: false},\r
3968 invert: true,\r
3969 limit: { x: [min, max] },\r
3970 onStart: function(){\r
3971 $(element).getElements('iframe').setStyle('visibility','hidden');\r
3972 partner.getElements('iframe').setStyle('visibility','hidden');\r
3973 }.bind(this),\r
3974 onDrag: function(){\r
3975 MochaUI.rWidth();\r
3976 }.bind(this),\r
3977 onComplete: function(){\r
3978 MochaUI.rWidth();\r
3979 $(element).getElements('iframe').setStyle('visibility','visible');\r
3980 partner.getElements('iframe').setStyle('visibility','visible');\r
3981 currentInstance.fireEvent('onResize');\r
3982 }.bind(this)\r
3983 });\r
3984}\r
3985\r
3986function addResizeBottom(element){\r
3987 if (!$(element)) return;\r
3988 var element = $(element);\r
3989 \r
3990 var instances = MochaUI.Panels.instances;\r
3991 var currentInstance = instances.get(element.id);\r
3992 var handle = currentInstance.handleEl;\r
3993 handle.setStyle('cursor', 'n-resize');\r
3994 partner = currentInstance.partner;\r
3995 min = 0;\r
3996 max = function(){\r
3997 return element.getStyle('height').toInt() + partner.getStyle('height').toInt();\r
3998 }.bind(this);\r
3999 \r
4000 if (Browser.Engine.trident){ \r
4001 handle.addEvents({\r
4002 'mousedown': function(){\r
4003 handle.setCapture();\r
4004 }, \r
4005 'mouseup': function(){\r
4006 handle.releaseCapture();\r
4007 }\r
4008 });\r
4009 }\r
4010 currentInstance.resize = element.makeResizable({\r
4011 handle: handle,\r
4012 modifiers: {x: false, y: 'height'},\r
4013 limit: { y: [min, max] },\r
4014 invert: false,\r
4015 onBeforeStart: function(){\r
4016 partner = currentInstance.partner;\r
4017 this.originalHeight = element.getStyle('height').toInt();\r
4018 this.partnerOriginalHeight = partner.getStyle('height').toInt();\r
4019 }.bind(this),\r
4020 onStart: function(){\r
4021 if (currentInstance.iframeEl) {\r
4022 currentInstance.iframeEl.setStyle('visibility', 'hidden');\r
4023 }\r
4024 partner.getElements('iframe').setStyle('visibility','hidden');\r
4025 }.bind(this),\r
4026 onDrag: function(){\r
4027 partnerHeight = partnerOriginalHeight + (this.originalHeight - element.getStyle('height').toInt());\r
4028 partner.setStyle('height', partnerHeight);\r
4029 MochaUI.resizeChildren(element, element.getStyle('height').toInt());\r
4030 MochaUI.resizeChildren(partner, partnerHeight);\r
4031 }.bind(this),\r
4032 onComplete: function(){\r
4033 partnerHeight = partnerOriginalHeight + (this.originalHeight - element.getStyle('height').toInt());\r
4034 partner.setStyle('height', partnerHeight);\r
4035 MochaUI.resizeChildren(element, element.getStyle('height').toInt());\r
4036 MochaUI.resizeChildren(partner, partnerHeight);\r
4037 if (currentInstance.iframeEl) {\r
4038 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
4039 }\r
4040 partner.getElements('iframe').setStyle('visibility','visible');\r
4041 currentInstance.fireEvent('onResize');\r
4042 }.bind(this)\r
4043 });\r
4044}\r
4045/*\r
4046\r
4047Script: Dock.js\r
4048 Implements the dock/taskbar. Enables window minimize.\r
4049\r
4050Copyright:\r
4051 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>. \r
4052\r
4053License:\r
4054 MIT-style license.\r
4055\r
4056Requires:\r
4057 Core.js, Window.js, Layout.js \r
4058\r
4059Todo:\r
4060 - Make it so the dock requires no initial html markup.\r
4061\r
4062*/\r
4063\r
4064MochaUI.options.extend({\r
4065 // Naming options:\r
4066 // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.\r
4067 dockWrapper: 'dockWrapper',\r
4068 dock: 'dock'\r
4069});\r
4070\r
4071// Used by Desktop.js before MochaUI.Dock is initialized.\r
4072window.addEvent('domready', function(){ \r
4073 if ($('dockWrapper')) {\r
4074 MochaUI.dockVisible = true;\r
4075 }\r
4076});\r
4077\r
4078MochaUI.extend({\r
4079 /*\r
4080\r
4081 Function: minimizeAll\r
4082 Minimize all windows that are minimizable.\r
4083\r
4084 */ \r
4085 minimizeAll: function() {\r
4086 $$('div.mocha').each(function(windowEl){\r
4087 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
4088 if (!currentInstance.isMinimized && currentInstance.options.minimizable == true){\r
4089 MochaUI.Dock.minimizeWindow(windowEl);\r
4090 }\r
4091 }.bind(this));\r
4092 }\r
4093});\r
4094\r
4095MochaUI.Dock = new Class({\r
4096 Extends: MochaUI.Window,\r
4097\r
4098 Implements: [Events, Options],\r
4099\r
4100 options: {\r
4101 useControls: true, // Toggles autohide and dock placement controls.\r
4102 dockPosition: 'top', // Position the dock starts in, top or bottom.\r
4103 // Style options\r
4104 dockTabColor: [255, 255, 255],\r
4105 trueButtonColor: [70, 245, 70], // Color for autohide on\r
4106 enabledButtonColor: [125, 208, 250], \r
4107 disabledButtonColor: [170, 170, 170]\r
4108 },\r
4109 initialize: function(options){\r
4110 // Stops if MochaUI.Desktop is not implemented\r
4111 if (!MochaUI.Desktop) return;\r
4112 this.setOptions(options);\r
4113 \r
4114 this.dockWrapper = $(MochaUI.options.dockWrapper);\r
4115 this.dock = $(MochaUI.options.dock);\r
4116 this.autoHideEvent = null; \r
4117 this.dockAutoHide = false; // True when dock autohide is set to on, false if set to off\r
4118\r
4119 if (!this.dockWrapper) return;\r
4120\r
4121 if (!this.options.useControls){\r
4122 if($('dockPlacement')){\r
4123 $('dockPlacement').setStyle('cursor', 'default');\r
4124 }\r
4125 if($('dockAutoHide')){\r
4126 $('dockAutoHide').setStyle('cursor', 'default');\r
4127 }\r
4128 }\r
4129\r
4130 this.dockWrapper.setStyles({\r
4131 'display': 'block',\r
4132 'position': 'absolute',\r
4133 'top': null,\r
4134 'bottom': MochaUI.Desktop.desktopFooter ? MochaUI.Desktop.desktopFooter.offsetHeight : 0,\r
4135 'left': 0\r
4136 });\r
4137 \r
4138 if (this.options.useControls){\r
4139 this.initializeDockControls();\r
4140 }\r
4141\r
4142 // Add check mark to menu if link exists in menu\r
4143 if ($('dockLinkCheck')){\r
4144 this.sidebarCheck = new Element('div', {\r
4145 'class': 'check',\r
4146 'id': 'dock_check'\r
4147 }).inject($('dockLinkCheck'));\r
4148 }\r
4149\r
4150 this.dockSortables = new Sortables('#dockSort', {\r
4151 opacity: Browser.Engine.trident ? 1 : .5,\r
4152 constrain: true,\r
4153 clone: false,\r
4154 revert: false\r
4155 });\r
4156\r
4157 MochaUI.Desktop.setDesktopSize();\r
4158 },\r
4159 initializeDockControls: function(){\r
4160 \r
4161 if (this.options.useControls){\r
4162 // Insert canvas\r
4163 var canvas = new Element('canvas', {\r
4164 'id': 'dockCanvas',\r
4165 'width': '15',\r
4166 'height': '18'\r
4167 }).inject(this.dock);\r
4168\r
4169 // Dynamically initialize canvas using excanvas. This is only required by IE\r
4170 if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){\r
4171 G_vmlCanvasManager.initElement(canvas);\r
4172 }\r
4173 }\r
4174 \r
4175 var dockPlacement = $('dockPlacement');\r
4176 var dockAutoHide = $('dockAutoHide');\r
4177\r
4178 // Position top or bottom selector\r
4179 dockPlacement.setProperty('title','Position Dock Top');\r
4180\r
4181 // Attach event\r
4182 dockPlacement.addEvent('click', function(){\r
4183 this.moveDock();\r
4184 }.bind(this));\r
4185\r
4186 // Auto Hide toggle switch\r
4187 dockAutoHide.setProperty('title','Turn Auto Hide On');\r
4188 \r
4189 // Attach event Auto Hide \r
4190 dockAutoHide.addEvent('click', function(event){\r
4191 if ( this.dockWrapper.getProperty('dockPosition') == 'top' )\r
4192 return false;\r
4193\r
4194 var ctx = $('dockCanvas').getContext('2d');\r
4195 this.dockAutoHide = !this.dockAutoHide; // Toggle\r
4196 if (this.dockAutoHide){\r
4197 $('dockAutoHide').setProperty('title', 'Turn Auto Hide Off');\r
4198 //ctx.clearRect(0, 11, 100, 100);\r
4199 MochaUI.circle(ctx, 5 , 14, 3, this.options.trueButtonColor, 1.0);\r
4200\r
4201 // Define event\r
4202 this.autoHideEvent = function(event) {\r
4203 if (!this.dockAutoHide)\r
4204 return;\r
4205 if (!MochaUI.Desktop.desktopFooter) {\r
4206 var dockHotspotHeight = this.dockWrapper.offsetHeight;\r
4207 if (dockHotspotHeight < 25) dockHotspotHeight = 25;\r
4208 }\r
4209 else if (MochaUI.Desktop.desktopFooter) {\r
4210 var dockHotspotHeight = this.dockWrapper.offsetHeight + MochaUI.Desktop.desktopFooter.offsetHeight;\r
4211 if (dockHotspotHeight < 25) dockHotspotHeight = 25;\r
4212 } \r
4213 if (!MochaUI.Desktop.desktopFooter && event.client.y > (document.getCoordinates().height - dockHotspotHeight)){\r
4214 if (!MochaUI.dockVisible){\r
4215 this.dockWrapper.setStyle('display', 'block');\r
4216 MochaUI.dockVisible = true;\r
4217 MochaUI.Desktop.setDesktopSize();\r
4218 }\r
4219 }\r
4220 else if (MochaUI.Desktop.desktopFooter && event.client.y > (document.getCoordinates().height - dockHotspotHeight)){\r
4221 if (!MochaUI.dockVisible){\r
4222 this.dockWrapper.setStyle('display', 'block');\r
4223 MochaUI.dockVisible = true;\r
4224 MochaUI.Desktop.setDesktopSize();\r
4225 }\r
4226 }\r
4227 else if (MochaUI.dockVisible){\r
4228 this.dockWrapper.setStyle('display', 'none');\r
4229 MochaUI.dockVisible = false;\r
4230 MochaUI.Desktop.setDesktopSize();\r
4231 \r
4232 }\r
4233 }.bind(this);\r
4234\r
4235 // Add event\r
4236 document.addEvent('mousemove', this.autoHideEvent);\r
4237\r
4238 } else {\r
4239 $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');\r
4240 //ctx.clearRect(0, 11, 100, 100);\r
4241 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0);\r
4242 // Remove event\r
4243 document.removeEvent('mousemove', this.autoHideEvent);\r
4244 }\r
4245\r
4246 }.bind(this));\r
4247\r
4248 // Draw dock controls\r
4249 var ctx = $('dockCanvas').getContext('2d');\r
4250 ctx.clearRect(0, 0, 100, 100);\r
4251 MochaUI.circle(ctx, 5 , 4, 3, this.options.enabledButtonColor, 1.0);\r
4252 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0);\r
4253 \r
4254 if (this.options.dockPosition == 'top'){\r
4255 this.moveDock();\r
4256 }\r
4257\r
4258 },\r
4259 moveDock: function(){\r
4260 var ctx = $('dockCanvas').getContext('2d');\r
4261 // Move dock to top position\r
4262 if (this.dockWrapper.getStyle('position') != 'relative'){\r
4263 this.dockWrapper.setStyles({\r
4264 'position': 'relative',\r
4265 'bottom': null\r
4266 });\r
4267 this.dockWrapper.addClass('top');\r
4268 MochaUI.Desktop.setDesktopSize();\r
4269 this.dockWrapper.setProperty('dockPosition','top');\r
4270 ctx.clearRect(0, 0, 100, 100);\r
4271 MochaUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0);\r
4272 MochaUI.circle(ctx, 5, 14, 3, this.options.disabledButtonColor, 1.0);\r
4273 $('dockPlacement').setProperty('title', 'Position Dock Bottom');\r
4274 $('dockAutoHide').setProperty('title', 'Auto Hide Disabled in Top Dock Position');\r
4275 this.dockAutoHide = false;\r
4276 }\r
4277 // Move dock to bottom position\r
4278 else {\r
4279 this.dockWrapper.setStyles({\r
4280 'position': 'absolute',\r
4281 'bottom': MochaUI.Desktop.desktopFooter ? MochaUI.Desktop.desktopFooter.offsetHeight : 0\r
4282 });\r
4283 this.dockWrapper.removeClass('top');\r
4284 MochaUI.Desktop.setDesktopSize();\r
4285 this.dockWrapper.setProperty('dockPosition', 'bottom');\r
4286 ctx.clearRect(0, 0, 100, 100);\r
4287 MochaUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0);\r
4288 MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0);\r
4289 $('dockPlacement').setProperty('title', 'Position Dock Top');\r
4290 $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');\r
4291 }\r
4292 },\r
4293 createDockTab: function(windowEl){\r
4294\r
4295 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
4296\r
4297 var dockTab = new Element('div', {\r
4298 'id': currentInstance.options.id + '_dockTab',\r
4299 'class': 'dockTab',\r
4300 'title': titleText\r
4301 }).inject($('dockClear'), 'before');\r
4302 \r
4303 dockTab.addEvent('mousedown', function(e){\r
4304 new Event(e).stop();\r
4305 this.timeDown = $time();\r
4306 });\r
4307 \r
4308 dockTab.addEvent('mouseup', function(e){\r
4309 this.timeUp = $time();\r
4310 if ((this.timeUp - this.timeDown) < 275){\r
4311 // If the visibility of the windows on the page are toggled off, toggle visibility on.\r
4312 if (MochaUI.Windows.windowsVisible == false) {\r
4313 MochaUI.toggleWindowVisibility();\r
4314 if (currentInstance.isMinimized == true) {\r
4315 MochaUI.Dock.restoreMinimized.delay(25, MochaUI.Dock, windowEl);\r
4316 }\r
4317 else {\r
4318 MochaUI.focusWindow(windowEl);\r
4319 }\r
4320 return;\r
4321 }\r
4322 // If window is minimized, restore window.\r
4323 if (currentInstance.isMinimized == true) {\r
4324 MochaUI.Dock.restoreMinimized.delay(25, MochaUI.Dock, windowEl);\r
4325 }\r
4326 else{\r
4327 // If window is not minimized and is focused, minimize window.\r
4328 if (currentInstance.windowEl.hasClass('isFocused') && currentInstance.options.minimizable == true){\r
4329 MochaUI.Dock.minimizeWindow(windowEl)\r
4330 }\r
4331 // If window is not minimized and is not focused, focus window. \r
4332 else{\r
4333 MochaUI.focusWindow(windowEl);\r
4334 }\r
4335 // if the window is not minimized and is outside the viewport, center it in the viewport.\r
4336 var coordinates = document.getCoordinates();\r
4337 if (windowEl.getStyle('left').toInt() > coordinates.width || windowEl.getStyle('top').toInt() > coordinates.height){\r
4338 MochaUI.centerWindow(windowEl); \r
4339 }\r
4340 }\r
4341 }\r
4342 });\r
4343\r
4344 this.dockSortables.addItems(dockTab);\r
4345\r
4346 var titleText = currentInstance.titleEl.innerHTML;\r
4347\r
4348 var dockTabText = new Element('div', {\r
4349 'id': currentInstance.options.id + '_dockTabText',\r
4350 'class': 'dockText'\r
4351 }).set('html', titleText.substring(0,20) + (titleText.length > 20 ? '...' : '')).inject($(dockTab));\r
4352\r
4353 // If I implement this again, will need to also adjust the titleText truncate and the tab's\r
4354 // left padding.\r
4355 if (currentInstance.options.icon != false){\r
4356 // dockTabText.setStyle('background', 'url(' + currentInstance.options.icon + ') 4px 4px no-repeat');\r
4357 }\r
4358 \r
4359 // Need to resize everything in case the dock wraps when a new tab is added\r
4360 MochaUI.Desktop.setDesktopSize();\r
4361\r
4362 },\r
4363 makeActiveTab: function(){\r
4364\r
4365 // getWindowWith HighestZindex is used in case the currently focused window\r
4366 // is closed. \r
4367 var windowEl = MochaUI.getWindowWithHighestZindex();\r
4368 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
4369 \r
4370 $$('div.dockTab').removeClass('activeDockTab');\r
4371 if (currentInstance.isMinimized != true) {\r
4372 \r
4373 currentInstance.windowEl.addClass('isFocused');\r
4374\r
4375 var currentButton = $(currentInstance.options.id + '_dockTab');\r
4376 if (currentButton != null) {\r
4377 currentButton.addClass('activeDockTab');\r
4378 }\r
4379 }\r
4380 else {\r
4381 currentInstance.windowEl.removeClass('isFocused');\r
4382 } \r
4383 }, \r
4384 minimizeWindow: function(windowEl){\r
4385 if (windowEl != $(windowEl)) return;\r
4386 \r
4387 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
4388 currentInstance.isMinimized = true;\r
4389\r
4390 // Hide iframe\r
4391 // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues\r
4392 if ( currentInstance.iframeEl ) {\r
4393 currentInstance.iframeEl.setStyle('visibility', 'hidden');\r
4394 }\r
4395\r
4396 // Hide window and add to dock \r
4397 currentInstance.contentBorderEl.setStyle('visibility', 'hidden');\r
4398 if(currentInstance.toolbarWrapperEl){ \r
4399 currentInstance.toolbarWrapperEl.setStyle('visibility', 'hidden');\r
4400 }\r
4401 windowEl.setStyle('visibility', 'hidden');\r
4402\r
4403 // Fixes a scrollbar issue in Mac FF2\r
4404 if (Browser.Platform.mac && Browser.Engine.gecko){\r
4405 if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {\r
4406 var ffversion = new Number(RegExp.$1);\r
4407 if (ffversion < 3) {\r
4408 currentInstance.contentWrapperEl.setStyle('overflow', 'hidden');\r
4409 }\r
4410 }\r
4411 }\r
4412 \r
4413 MochaUI.Desktop.setDesktopSize();\r
4414\r
4415 // Have to use timeout because window gets focused when you click on the minimize button\r
4416 setTimeout(function(){\r
4417 windowEl.setStyle('zIndex', 1);\r
4418 windowEl.removeClass('isFocused');\r
4419 this.makeActiveTab(); \r
4420 }.bind(this),100); \r
4421\r
4422 currentInstance.fireEvent('onMinimize', windowEl);\r
4423 },\r
4424 restoreMinimized: function(windowEl) {\r
4425\r
4426 var currentInstance = MochaUI.Windows.instances.get(windowEl.id);\r
4427\r
4428 if (currentInstance.isMinimized == false) return;\r
4429\r
4430 if (MochaUI.Windows.windowsVisible == false){\r
4431 MochaUI.toggleWindowVisibility();\r
4432 }\r
4433\r
4434 MochaUI.Desktop.setDesktopSize();\r
4435\r
4436 // Part of Mac FF2 scrollbar fix\r
4437 if (currentInstance.options.scrollbars == true && !currentInstance.iframeEl){ \r
4438 currentInstance.contentWrapperEl.setStyle('overflow', 'auto');\r
4439 }\r
4440\r
4441 if (currentInstance.isCollapsed) {\r
4442 MochaUI.collapseToggle(windowEl);\r
4443 }\r
4444\r
4445 windowEl.setStyle('visibility', 'visible');\r
4446 currentInstance.contentBorderEl.setStyle('visibility', 'visible');\r
4447 if(currentInstance.toolbarWrapperEl){\r
4448 currentInstance.toolbarWrapperEl.setStyle('visibility', 'visible');\r
4449 }\r
4450\r
4451 // Show iframe\r
4452 if ( currentInstance.iframeEl ) {\r
4453 currentInstance.iframeEl.setStyle('visibility', 'visible');\r
4454 }\r
4455\r
4456 currentInstance.isMinimized = false;\r
4457 MochaUI.focusWindow(windowEl);\r
4458 currentInstance.fireEvent('onRestore', windowEl);\r
4459\r
4460 }\r
4461});\r
4462MochaUI.Dock.implement(new Options, new Events);\r
4463/*\r
4464\r
4465Script: Workspaces.js\r
4466 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.\r
4467\r
4468Copyright:\r
4469 Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.\r
4470\r
4471License:\r
4472 MIT-style license.\r
4473\r
4474Requires:\r
4475 Core.js, Window.js\r
4476\r
4477To do:\r
4478 - Move to Window\r
4479\r
4480*/\r
4481\r
4482MochaUI.extend({ \r
4483 /*\r
4484 \r
4485 Function: saveWorkspace\r
4486 Save the current workspace.\r
4487 \r
4488 Syntax:\r
4489 (start code)\r
4490 MochaUI.saveWorkspace();\r
4491 (end)\r
4492 \r
4493 Notes:\r
4494 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.\r
4495 \r
4496 */\r
4497 saveWorkspace: function(){\r
4498 this.cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});\r
4499 this.cookie.empty();\r
4500 MochaUI.Windows.instances.each(function(instance) {\r
4501 instance.saveValues();\r
4502 this.cookie.set(instance.options.id, {\r
4503 'id': instance.options.id,\r
4504 'top': instance.options.y,\r
4505 'left': instance.options.x\r
4506 });\r
4507 }.bind(this));\r
4508 this.cookie.save();\r
4509\r
4510 new MochaUI.Window({\r
4511 loadMethod: 'html',\r
4512 type: 'notification',\r
4513 addClass: 'notification',\r
4514 content: 'Workspace saved.',\r
4515 closeAfter: '1400',\r
4516 width: 200,\r
4517 height: 40,\r
4518 y: 53,\r
4519 padding: { top: 10, right: 12, bottom: 10, left: 12 },\r
4520 shadowBlur: 5,\r
4521 bodyBgColor: [255, 255, 255]\r
4522 });\r
4523 \r
4524 },\r
4525 windowUnload: function(){\r
4526 if ($$('div.mocha').length == 0 && this.myChain){\r
4527 this.myChain.callChain();\r
4528 } \r
4529 },\r
4530 loadWorkspace2: function(workspaceWindows){ \r
4531 workspaceWindows.each(function(instance){\r
4532 windowFunction = eval('MochaUI.' + instance.id + 'Window');\r
4533 if (windowFunction){\r
4534 eval('MochaUI.' + instance.id + 'Window();');\r
4535 $(instance.id).setStyles({\r
4536 top: instance.top,\r
4537 left: instance.left\r
4538 });\r
4539 }\r
4540 }.bind(this));\r
4541 this.loadingWorkspace = false;\r
4542 },\r
4543 /*\r
4544\r
4545 Function: loadWorkspace\r
4546 Load the saved workspace.\r
4547\r
4548 Syntax:\r
4549 (start code)\r
4550 MochaUI.loadWorkspace();\r
4551 (end)\r
4552\r
4553 */\r
4554 loadWorkspace: function(){\r
4555 cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});\r
4556 workspaceWindows = cookie.load();\r
4557\r
4558 if(!cookie.getKeys().length){\r
4559 new MochaUI.Window({\r
4560 loadMethod: 'html',\r
4561 type: 'notification',\r
4562 addClass: 'notification',\r
4563 content: 'You have no saved workspace.',\r
4564 closeAfter: '1400',\r
4565 width: 220,\r
4566 height: 40,\r
4567 y: 25,\r
4568 padding: { top: 10, right: 12, bottom: 10, left: 12 },\r
4569 shadowBlur: 5,\r
4570 bodyBgColor: [255, 255, 255]\r
4571 });\r
4572 return;\r
4573 }\r
4574\r
4575 if ($$('div.mocha').length != 0){\r
4576 this.loadingWorkspace = true;\r
4577 this.myChain = new Chain();\r
4578 this.myChain.chain(\r
4579 function(){\r
4580 $$('div.mocha').each(function(el) {\r
4581 this.closeWindow(el);\r
4582 }.bind(this));\r
4583 }.bind(this),\r
4584 function(){\r
4585 this.loadWorkspace2(workspaceWindows);\r
4586 }.bind(this)\r
4587 );\r
4588 this.myChain.callChain();\r
4589 }\r
4590 else {\r
4591 this.loadWorkspace2(workspaceWindows);\r
4592 }\r
4593\r
4594 }\r
4595});\r