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