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