source: ether_megapoli/trunk/web/resources/js/windows_js_1.3/javascripts/window.js @ 131

Last change on this file since 131 was 131, checked in by vmipsl, 13 years ago

[Visualization] javascript librairies

  • Property svn:executable set to *
File size: 73.1 KB
Line 
1// Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
2//
3// Permission is hereby granted, free of charge, to any person obtaining
4// a copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to
8// permit persons to whom the Software is furnished to do so, subject to
9// the following conditions:
10//
11// The above copyright notice and this permission notice shall be
12// included in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21//
22// VERSION 1.3
23
24var Window = Class.create();
25
26Window.keepMultiModalWindow = false;
27Window.hasEffectLib = (typeof Effect != 'undefined');
28Window.resizeEffectDuration = 0.4;
29
30Window.prototype = {
31    // Constructor
32    // Available parameters : className, blurClassName, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, recenterAuto, wiredDrag
33    //                        hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload
34    //                        add all callbacks (if you do not use an observer)
35    //                        onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
36
37    initialize: function()
38    {
39        var id;
40        var optionIndex = 0;
41        // For backward compatibility like win= new Window("id", {...}) instead of win = new Window({id: "id", ...})
42        if( arguments.length > 0 )
43        {
44            if( typeof arguments[0] == "string" )
45            {
46                id = arguments[0];
47                optionIndex = 1;
48            }
49            else
50                id = arguments[0] ? arguments[0].id : null;
51        }
52
53        // Generate unique ID if not specified
54        if( !id )
55            id = "window_" + new Date().getTime();
56
57        if( $( id ) )
58            alert( "Window " + id + " is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor" );
59
60        this.options = Object.extend( {
61            className:         "dialog",
62            blurClassName:     null,
63            minWidth:          100,
64            minHeight:         20,
65            resizable:         true,
66            closable:          true,
67            minimizable:       true,
68            maximizable:       true,
69            draggable:         true,
70            userData:          null,
71            showEffect:        (Window.hasEffectLib ? Effect.Appear : Element.show),
72            hideEffect:        (Window.hasEffectLib ? Effect.Fade : Element.hide),
73            showEffectOptions: {},
74            hideEffectOptions: {},
75            effectOptions:     null,
76            parent:            document.body,
77            title:             " ",
78            url:               null,
79            onload:            Prototype.emptyFunction,
80            width:             200,
81            height:            300,
82            opacity:           1,
83            recenterAuto:      true,
84            wiredDrag:         false,
85            closeCallback:     null,
86            destroyOnClose:    false,
87            gridX:             1,
88            gridY:             1
89        }, arguments[optionIndex] || {} );
90        if( this.options.blurClassName )
91            this.options.focusClassName = this.options.className;
92
93        if( typeof this.options.top == "undefined" && typeof this.options.bottom == "undefined" )
94            this.options.top = this._round( Math.random() * 500, this.options.gridY );
95        if( typeof this.options.left == "undefined" && typeof this.options.right == "undefined" )
96            this.options.left = this._round( Math.random() * 500, this.options.gridX );
97
98        if( this.options.effectOptions )
99        {
100            Object.extend( this.options.hideEffectOptions, this.options.effectOptions );
101            Object.extend( this.options.showEffectOptions, this.options.effectOptions );
102            if( this.options.showEffect == Element.Appear )
103                this.options.showEffectOptions.to = this.options.opacity;
104        }
105        if( Window.hasEffectLib )
106        {
107            if( this.options.showEffect == Effect.Appear )
108                this.options.showEffectOptions.to = this.options.opacity;
109
110            if( this.options.hideEffect == Effect.Fade )
111                this.options.hideEffectOptions.from = this.options.opacity;
112        }
113        if( this.options.hideEffect == Element.hide )
114            this.options.hideEffect = function()
115            {
116                Element.hide( this.element );
117                if( this.options.destroyOnClose ) this.destroy();
118            }.bind( this )
119
120        if( this.options.parent != document.body )
121            this.options.parent = $( this.options.parent );
122
123        this.element = this._createWindow( id );
124        this.element.win = this;
125
126        // Bind event listener
127        this.eventMouseDown = this._initDrag.bindAsEventListener( this );
128        this.eventMouseUp = this._endDrag.bindAsEventListener( this );
129        this.eventMouseMove = this._updateDrag.bindAsEventListener( this );
130        this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener( this );
131        this.eventMouseDownContent = this.toFront.bindAsEventListener( this );
132        this.eventResize = this._recenter.bindAsEventListener( this );
133
134        this.topbar = $( this.element.id + "_top" );
135        this.bottombar = $( this.element.id + "_bottom" );
136        this.content = $( this.element.id + "_content" );
137
138        Event.observe( this.topbar, "mousedown", this.eventMouseDown );
139        Event.observe( this.bottombar, "mousedown", this.eventMouseDown );
140        Event.observe( this.content, "mousedown", this.eventMouseDownContent );
141        Event.observe( window, "load", this.eventOnLoad );
142        Event.observe( window, "resize", this.eventResize );
143        Event.observe( window, "scroll", this.eventResize );
144        Event.observe( this.options.parent, "scroll", this.eventResize );
145
146        if( this.options.draggable )
147        {
148            var that = this;
149            [this.topbar, this.topbar.up().previous(), this.topbar.up().next()].each( function( element )
150            {
151                element.observe( "mousedown", that.eventMouseDown );
152                element.addClassName( "top_draggable" );
153            } );
154            [this.bottombar.up(), this.bottombar.up().previous(), this.bottombar.up().next()].each( function( element )
155            {
156                element.observe( "mousedown", that.eventMouseDown );
157                element.addClassName( "bottom_draggable" );
158            } );
159
160        }
161
162        if( this.options.resizable )
163        {
164            this.sizer = $( this.element.id + "_sizer" );
165            Event.observe( this.sizer, "mousedown", this.eventMouseDown );
166        }
167
168        this.useLeft = null;
169        this.useTop = null;
170        if( typeof this.options.left != "undefined" )
171        {
172            this.element.setStyle( {left: parseFloat( this.options.left ) + 'px'} );
173            this.useLeft = true;
174        }
175        else
176        {
177            this.element.setStyle( {right: parseFloat( this.options.right ) + 'px'} );
178            this.useLeft = false;
179        }
180
181        if( typeof this.options.top != "undefined" )
182        {
183            this.element.setStyle( {top: parseFloat( this.options.top ) + 'px'} );
184            this.useTop = true;
185        }
186        else
187        {
188            this.element.setStyle( {bottom: parseFloat( this.options.bottom ) + 'px'} );
189            this.useTop = false;
190        }
191
192        this.storedLocation = null;
193
194        this.setOpacity( this.options.opacity );
195        if( this.options.zIndex )
196            this.setZIndex( this.options.zIndex )
197
198        if( this.options.destroyOnClose )
199            this.setDestroyOnClose( true );
200
201        this._getWindowBorderSize();
202        this.width = this.options.width;
203        this.height = this.options.height;
204        this.visible = false;
205
206        this.constraint = false;
207        this.constraintPad = {top: 0, left:0, bottom:0, right:0};
208
209        if( this.width && this.height )
210            this.setSize( this.options.width, this.options.height );
211        this.setTitle( this.options.title )
212        Windows.register( this );
213    },
214
215    // Destructor
216    destroy: function()
217    {
218        this._notify( "onDestroy" );
219        Event.stopObserving( this.topbar, "mousedown", this.eventMouseDown );
220        Event.stopObserving( this.bottombar, "mousedown", this.eventMouseDown );
221        Event.stopObserving( this.content, "mousedown", this.eventMouseDownContent );
222
223        Event.stopObserving( window, "load", this.eventOnLoad );
224        Event.stopObserving( window, "resize", this.eventResize );
225        Event.stopObserving( window, "scroll", this.eventResize );
226
227        Event.stopObserving( this.content, "load", this.options.onload );
228
229        if( this._oldParent )
230        {
231            var content = this.getContent();
232            var originalContent = null;
233            for( var i = 0; i < content.childNodes.length; i++ )
234            {
235                originalContent = content.childNodes[i];
236                if( originalContent.nodeType == 1 )
237                    break;
238                originalContent = null;
239            }
240            if( originalContent )
241                this._oldParent.appendChild( originalContent );
242            this._oldParent = null;
243        }
244
245        if( this.sizer )
246            Event.stopObserving( this.sizer, "mousedown", this.eventMouseDown );
247
248        if( this.options.url )
249            this.content.src = null
250
251        if( this.iefix )
252            Element.remove( this.iefix );
253
254        Element.remove( this.element );
255        Windows.unregister( this );
256    },
257
258    // Sets close callback, if it sets, it should return true to be able to close the window.
259    setCloseCallback: function( callback )
260    {
261        this.options.closeCallback = callback;
262    },
263
264    // Gets window content
265    getContent: function ()
266    {
267        return this.content;
268    },
269
270    // Sets the content with an element id
271    setContent: function( id, autoresize, autoposition )
272    {
273        var element = $( id );
274        if( null == element ) throw "Unable to find element '" + id + "' in DOM";
275        this._oldParent = element.parentNode;
276
277        var d = null;
278        var p = null;
279
280        if( autoresize )
281            d = Element.getDimensions( element );
282        if( autoposition )
283            p = Position.cumulativeOffset( element );
284
285        var content = this.getContent();
286        // Clear HTML (and even iframe)
287        this.setHTMLContent( "" );
288        content = this.getContent();
289
290        content.appendChild( element );
291        element.show();
292        if( autoresize )
293            this.setSize( d.width, d.height );
294        if( autoposition )
295            this.setLocation( p[1] - this.heightN, p[0] - this.widthW );
296    },
297
298    setHTMLContent: function( html )
299    {
300        // It was an url (iframe), recreate a div content instead of iframe content
301        if( this.options.url )
302        {
303            this.content.src = null;
304            this.options.url = null;
305
306            var content = "<div id=\"" + this.getId() + "_content\" class=\"" + this.options.className + "_content\"> </div>";
307            $( this.getId() + "_table_content" ).innerHTML = content;
308
309            this.content = $( this.element.id + "_content" );
310        }
311
312        this.getContent().innerHTML = html;
313    },
314
315    setAjaxContent: function( url, options, showCentered, showModal )
316    {
317        this.showFunction = showCentered ? "showCenter" : "show";
318        this.showModal = showModal || false;
319
320        options = options || {};
321
322        // Clear HTML (and even iframe)
323        this.setHTMLContent( "" );
324
325        this.onComplete = options.onComplete;
326        if( ! this._onCompleteHandler )
327            this._onCompleteHandler = this._setAjaxContent.bind( this );
328        options.onComplete = this._onCompleteHandler;
329
330        new Ajax.Request( url, options );
331        options.onComplete = this.onComplete;
332    },
333
334    _setAjaxContent: function( originalRequest )
335    {
336        Element.update( this.getContent(), originalRequest.responseText );
337        if( this.onComplete )
338            this.onComplete( originalRequest );
339        this.onComplete = null;
340        this[this.showFunction]( this.showModal )
341    },
342
343    setURL: function( url )
344    {
345        // Not an url content, change div to iframe
346        if( this.options.url )
347            this.content.src = null;
348        this.options.url = url;
349        var content = "<iframe frameborder='0' name='" + this.getId() + "_content'  id='" + this.getId() + "_content' src='" + url + "' width='" + this.width + "' height='" + this.height + "'> </iframe>";
350        $( this.getId() + "_table_content" ).innerHTML = content;
351
352        this.content = $( this.element.id + "_content" );
353    },
354
355    getURL: function()
356    {
357        return this.options.url ? this.options.url : null;
358    },
359
360    refresh: function()
361    {
362        if( this.options.url )
363            $( this.element.getAttribute( 'id' ) + '_content' ).src = this.options.url;
364    },
365
366    // Stores position/size in a cookie, by default named with window id
367    setCookie: function( name, expires, path, domain, secure )
368    {
369        name = name || this.element.id;
370        this.cookie = [name, expires, path, domain, secure];
371
372        // Get cookie
373        var value = WindowUtilities.getCookie( name )
374        // If exists
375        if( value )
376        {
377            var values = value.split( ',' );
378            var x = values[0].split( ':' );
379            var y = values[1].split( ':' );
380
381            var w = parseFloat( values[2] ), h = parseFloat( values[3] );
382            var mini = values[4];
383            var maxi = values[5];
384
385            this.setSize( w, h );
386            if( mini == "true" )
387                this.doMinimize = true; // Minimize will be done at onload window event
388            else if( maxi == "true" )
389                this.doMaximize = true; // Maximize will be done at onload window event
390
391            this.useLeft = x[0] == "l";
392            this.useTop = y[0] == "t";
393
394            this.element.setStyle( this.useLeft ? {left: x[1]} : {right: x[1]} );
395            this.element.setStyle( this.useTop ? {top: y[1]} : {bottom: y[1]} );
396        }
397    },
398
399    // Gets window ID
400    getId: function()
401    {
402        return this.element.id;
403    },
404
405    // Detroys itself when closing
406    setDestroyOnClose: function()
407    {
408        this.options.destroyOnClose = true;
409    },
410
411    setConstraint: function( bool, padding )
412    {
413        this.constraint = bool;
414        this.constraintPad = Object.extend( this.constraintPad, padding || {} );
415        // Reset location to apply constraint
416        if( this.useTop && this.useLeft )
417            this.setLocation( parseFloat( this.element.style.top ), parseFloat( this.element.style.left ) );
418    },
419
420    // initDrag event
421
422    _initDrag: function( event )
423    {
424        // No resize on minimized window
425        if( Event.element( event ) == this.sizer && this.isMinimized() )
426            return;
427
428        // No move on maximzed window
429        if( Event.element( event ) != this.sizer && this.isMaximized() )
430            return;
431
432        if( Prototype.Browser.IE && this.heightN == 0 )
433            this._getWindowBorderSize();
434
435        // Get pointer X,Y
436        this.pointer = [this._round( Event.pointerX( event ), this.options.gridX ), this._round( Event.pointerY( event ), this.options.gridY )];
437        if( this.options.wiredDrag )
438            this.currentDrag = this._createWiredElement();
439        else
440            this.currentDrag = this.element;
441
442        // Resize
443        if( Event.element( event ) == this.sizer )
444        {
445            this.doResize = true;
446            this.widthOrg = this.width;
447            this.heightOrg = this.height;
448            this.bottomOrg = parseFloat( this.element.getStyle( 'bottom' ) );
449            this.rightOrg = parseFloat( this.element.getStyle( 'right' ) );
450            this._notify( "onStartResize" );
451        }
452        else
453        {
454            this.doResize = false;
455
456            // Check if click on close button,
457            var closeButton = $( this.getId() + '_close' );
458            if( closeButton && Position.within( closeButton, this.pointer[0], this.pointer[1] ) )
459            {
460                this.currentDrag = null;
461                return;
462            }
463
464            this.toFront();
465
466            if( ! this.options.draggable )
467                return;
468            this._notify( "onStartMove" );
469        }
470        // Register global event to capture mouseUp and mouseMove
471        Event.observe( document, "mouseup", this.eventMouseUp, false );
472        Event.observe( document, "mousemove", this.eventMouseMove, false );
473
474        // Add an invisible div to keep catching mouse event over iframes
475        WindowUtilities.disableScreen( '__invisible__', '__invisible__', this.overlayOpacity );
476
477        // Stop selection while dragging
478        document.body.ondrag = function ()
479        {
480            return false;
481        };
482        document.body.onselectstart = function ()
483        {
484            return false;
485        };
486
487        this.currentDrag.show();
488        Event.stop( event );
489    },
490
491    _round: function( val, round )
492    {
493        return round == 1 ? val : val = Math.floor( val / round ) * round;
494    },
495
496    // updateDrag event
497    _updateDrag: function( event )
498    {
499        var pointer = [this._round( Event.pointerX( event ), this.options.gridX ), this._round( Event.pointerY( event ), this.options.gridY )];
500        var dx = pointer[0] - this.pointer[0];
501        var dy = pointer[1] - this.pointer[1];
502
503        // Resize case, update width/height
504        if( this.doResize )
505        {
506            var w = this.widthOrg + dx;
507            var h = this.heightOrg + dy;
508
509            dx = this.width - this.widthOrg
510            dy = this.height - this.heightOrg
511
512            // Check if it's a right position, update it to keep upper-left corner at the same position
513            if( this.useLeft )
514                w = this._updateWidthConstraint( w )
515            else
516                this.currentDrag.setStyle( {right: (this.rightOrg - dx) + 'px'} );
517            // Check if it's a bottom position, update it to keep upper-left corner at the same position
518            if( this.useTop )
519                h = this._updateHeightConstraint( h )
520            else
521                this.currentDrag.setStyle( {bottom: (this.bottomOrg - dy) + 'px'} );
522
523            this.setSize( w, h );
524            this._notify( "onResize" );
525        }
526        // Move case, update top/left
527        else
528        {
529            this.pointer = pointer;
530
531            if( this.useLeft )
532            {
533                var left = parseFloat( this.currentDrag.getStyle( 'left' ) ) + dx;
534                var newLeft = this._updateLeftConstraint( left );
535                // Keep mouse pointer correct
536                this.pointer[0] += newLeft - left;
537                this.currentDrag.setStyle( {left: newLeft + 'px'} );
538            }
539            else
540                this.currentDrag.setStyle( {right: parseFloat( this.currentDrag.getStyle( 'right' ) ) - dx + 'px'} );
541
542            if( this.useTop )
543            {
544                var top = parseFloat( this.currentDrag.getStyle( 'top' ) ) + dy;
545                var newTop = this._updateTopConstraint( top );
546                // Keep mouse pointer correct
547                this.pointer[1] += newTop - top;
548                this.currentDrag.setStyle( {top: newTop + 'px'} );
549            }
550            else
551                this.currentDrag.setStyle( {bottom: parseFloat( this.currentDrag.getStyle( 'bottom' ) ) - dy + 'px'} );
552
553            this._notify( "onMove" );
554        }
555        if( this.iefix )
556            this._fixIEOverlapping();
557
558        this._removeStoreLocation();
559        Event.stop( event );
560    },
561
562    // endDrag callback
563    _endDrag: function( event )
564    {
565        // Remove temporary div over iframes
566        WindowUtilities.enableScreen( '__invisible__' );
567
568        if( this.doResize )
569            this._notify( "onEndResize" );
570        else
571            this._notify( "onEndMove" );
572
573        // Release event observing
574        Event.stopObserving( document, "mouseup", this.eventMouseUp, false );
575        Event.stopObserving( document, "mousemove", this.eventMouseMove, false );
576
577        Event.stop( event );
578
579        this._hideWiredElement();
580
581        // Store new location/size if need be
582        this._saveCookie()
583
584        // Restore selection
585        document.body.ondrag = null;
586        document.body.onselectstart = null;
587    },
588
589    _updateLeftConstraint: function( left )
590    {
591        if( this.constraint && this.useLeft && this.useTop )
592        {
593            var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
594
595            if( left < this.constraintPad.left )
596                left = this.constraintPad.left;
597            if( left + this.width + this.widthE + this.widthW > width - this.constraintPad.right )
598                left = width - this.constraintPad.right - this.width - this.widthE - this.widthW;
599        }
600        return left;
601    },
602
603    _updateTopConstraint: function( top )
604    {
605        if( this.constraint && this.useLeft && this.useTop )
606        {
607            var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
608
609            var h = this.height + this.heightN + this.heightS;
610
611            if( top < this.constraintPad.top )
612                top = this.constraintPad.top;
613            if( top + h > height - this.constraintPad.bottom )
614                top = height - this.constraintPad.bottom - h;
615        }
616        return top;
617    },
618
619    _updateWidthConstraint: function( w )
620    {
621        if( this.constraint && this.useLeft && this.useTop )
622        {
623            var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
624            var left = parseFloat( this.element.getStyle( "left" ) );
625
626            if( left + w + this.widthE + this.widthW > width - this.constraintPad.right )
627                w = width - this.constraintPad.right - left - this.widthE - this.widthW;
628        }
629        return w;
630    },
631
632    _updateHeightConstraint: function( h )
633    {
634        if( this.constraint && this.useLeft && this.useTop )
635        {
636            var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
637            var top = parseFloat( this.element.getStyle( "top" ) );
638
639            if( top + h + this.heightN + this.heightS > height - this.constraintPad.bottom )
640                h = height - this.constraintPad.bottom - top - this.heightN - this.heightS;
641        }
642        return h;
643    },
644
645
646    // Creates HTML window code
647    _createWindow: function( id )
648    {
649        var className = this.options.className;
650        var win = document.createElement( "div" );
651        win.setAttribute( 'id', id );
652        win.className = "dialog";
653
654        var content;
655        if( this.options.url )
656            content = "<iframe frameborder=\"0\" name=\"" + id + "_content\"  id=\"" + id + "_content\" src=\"" + this.options.url + "\"> </iframe>";
657        else
658            content = "<div id=\"" + id + "_content\" class=\"" + className + "_content\"> </div>";
659
660        var closeDiv = this.options.closable ? "<div class='" + className + "_close' id='" + id + "_close' onclick='Windows.close(\"" + id + "\", event)'> </div>" : "";
661        var minDiv = this.options.minimizable ? "<div class='" + className + "_minimize' id='" + id + "_minimize' onclick='Windows.minimize(\"" + id + "\", event)'> </div>" : "";
662        var maxDiv = this.options.maximizable ? "<div class='" + className + "_maximize' id='" + id + "_maximize' onclick='Windows.maximize(\"" + id + "\", event)'> </div>" : "";
663        var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'";
664        var blank = "../themes/default/blank.gif";
665
666        win.innerHTML = closeDiv + minDiv + maxDiv + "\
667      <table id='" + id + "_row1' class=\"top table_window\">\
668        <tr>\
669          <td class='" + className + "_nw'></td>\
670          <td class='" + className + "_n'><div id='" + id + "_top' class='" + className + "_title title_window'>" + this.options.title + "</div></td>\
671          <td class='" + className + "_ne'></td>\
672        </tr>\
673      </table>\
674      <table id='" + id + "_row2' class=\"mid table_window\">\
675        <tr>\
676          <td class='" + className + "_w'></td>\
677            <td id='" + id + "_table_content' class='" + className + "_content' valign='top'>" + content + "</td>\
678          <td class='" + className + "_e'></td>\
679        </tr>\
680      </table>\
681        <table id='" + id + "_row3' class=\"bot table_window\">\
682        <tr>\
683          <td class='" + className + "_sw'></td>\
684            <td class='" + className + "_s'><div id='" + id + "_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td>\
685            <td " + seAttributes + "></td>\
686        </tr>\
687      </table>\
688    ";
689        Element.hide( win );
690        this.options.parent.insertBefore( win, this.options.parent.firstChild );
691        Event.observe( $( id + "_content" ), "load", this.options.onload );
692        return win;
693    },
694
695
696    changeClassName: function( newClassName )
697    {
698        var className = this.options.className;
699        var id = this.getId();
700        $A( ["_close", "_minimize", "_maximize", "_sizer", "_content"] ).each( function( value )
701        {
702            this._toggleClassName( $( id + value ), className + value, newClassName + value )
703        }.bind( this ) );
704        this._toggleClassName( $( id + "_top" ), className + "_title", newClassName + "_title" );
705        $$( "#" + id + " td" ).each( function( td )
706        {
707            td.className = td.className.sub( className, newClassName );
708        } );
709        this.options.className = newClassName;
710    },
711
712    _toggleClassName: function( element, oldClassName, newClassName )
713    {
714        if( element )
715        {
716            element.removeClassName( oldClassName );
717            element.addClassName( newClassName );
718        }
719    },
720
721    // Sets window location
722    setLocation: function( top, left )
723    {
724        top = this._updateTopConstraint( top );
725        left = this._updateLeftConstraint( left );
726
727        var e = this.currentDrag || this.element;
728        e.setStyle( {top: top + 'px'} );
729        e.setStyle( {left: left + 'px'} );
730
731        this.useLeft = true;
732        this.useTop = true;
733    },
734
735    getLocation: function()
736    {
737        var location = {};
738        if( this.useTop )
739            location = Object.extend( location, {top: this.element.getStyle( "top" )} );
740        else
741            location = Object.extend( location, {bottom: this.element.getStyle( "bottom" )} );
742        if( this.useLeft )
743            location = Object.extend( location, {left: this.element.getStyle( "left" )} );
744        else
745            location = Object.extend( location, {right: this.element.getStyle( "right" )} );
746
747        return location;
748    },
749
750    // Gets window size
751    getSize: function()
752    {
753        return {width: this.width, height: this.height};
754    },
755
756    // Sets window size
757    setSize: function( width, height, useEffect )
758    {
759        width = parseFloat( width );
760        height = parseFloat( height );
761
762        // Check min and max size
763        if( !this.minimized && width < this.options.minWidth )
764            width = this.options.minWidth;
765
766        if( !this.minimized && height < this.options.minHeight )
767            height = this.options.minHeight;
768
769        if( this.options.maxHeight && height > this.options.maxHeight )
770            height = this.options.maxHeight;
771
772        if( this.options.maxWidth && width > this.options.maxWidth )
773            width = this.options.maxWidth;
774
775
776        if( this.useTop && this.useLeft && Window.hasEffectLib && Effect.ResizeWindow && useEffect )
777        {
778            new Effect.ResizeWindow( this, null, null, width, height, {duration: Window.resizeEffectDuration} );
779        }
780        else
781        {
782            this.width = width;
783            this.height = height;
784            var e = this.currentDrag ? this.currentDrag : this.element;
785
786            e.setStyle( {width: width + this.widthW + this.widthE + "px"} )
787            e.setStyle( {height: height + this.heightN + this.heightS + "px"} )
788
789            // Update content size
790            if( !this.currentDrag || this.currentDrag == this.element )
791            {
792                var content = $( this.element.id + '_content' );
793                content.setStyle( {height: height + 'px'} );
794                content.setStyle( {width: width + 'px'} );
795            }
796        }
797    },
798
799    updateHeight: function()
800    {
801        this.setSize( this.width, this.content.scrollHeight, true );
802    },
803
804    updateWidth: function()
805    {
806        this.setSize( this.content.scrollWidth, this.height, true );
807    },
808
809    // Brings window to front
810    toFront: function()
811    {
812        if( this.element.style.zIndex < Windows.maxZIndex )
813            this.setZIndex( Windows.maxZIndex + 1 );
814        if( this.iefix )
815            this._fixIEOverlapping();
816    },
817
818    getBounds: function( insideOnly )
819    {
820        if( ! this.width || !this.height || !this.visible )
821            this.computeBounds();
822        var w = this.width;
823        var h = this.height;
824
825        if( !insideOnly )
826        {
827            w += this.widthW + this.widthE;
828            h += this.heightN + this.heightS;
829        }
830        var bounds = Object.extend( this.getLocation(), {width: w + "px", height: h + "px"} );
831        return bounds;
832    },
833
834    computeBounds: function()
835    {
836        if( ! this.width || !this.height )
837        {
838            var size = WindowUtilities._computeSize( this.content.innerHTML, this.content.id, this.width, this.height, 0, this.options.className )
839            if( this.height )
840                this.width = size + 5
841            else
842                this.height = size + 5
843        }
844
845        this.setSize( this.width, this.height );
846        if( this.centered )
847            this._center( this.centerTop, this.centerLeft );
848    },
849
850    // Displays window modal state or not
851    show: function( modal )
852    {
853        this.visible = true;
854        if( modal )
855        {
856            // Hack for Safari !!
857            if( typeof this.overlayOpacity == "undefined" )
858            {
859                var that = this;
860                setTimeout( function()
861                {
862                    that.show( modal )
863                }, 10 );
864                return;
865            }
866            Windows.addModalWindow( this );
867
868            this.modal = true;
869            this.setZIndex( Windows.maxZIndex + 1 );
870            Windows.unsetOverflow( this );
871        }
872        else
873        if( !this.element.style.zIndex )
874            this.setZIndex( Windows.maxZIndex + 1 );
875
876        // To restore overflow if need be
877        if( this.oldStyle )
878            this.getContent().setStyle( {overflow: this.oldStyle} );
879
880        this.computeBounds();
881
882        this._notify( "onBeforeShow" );
883        if( this.options.showEffect != Element.show && this.options.showEffectOptions )
884            this.options.showEffect( this.element, this.options.showEffectOptions );
885        else
886            this.options.showEffect( this.element );
887
888        this._checkIEOverlapping();
889        WindowUtilities.focusedWindow = this
890        this._notify( "onShow" );
891    },
892
893    // Displays window modal state or not at the center of the page
894    showCenter: function( modal, top, left )
895    {
896        this.centered = true;
897        this.centerTop = top;
898        this.centerLeft = left;
899
900        this.show( modal );
901    },
902
903    isVisible: function()
904    {
905        return this.visible;
906    },
907
908    _center: function( top, left )
909    {
910        var windowScroll = WindowUtilities.getWindowScroll( this.options.parent );
911        var pageSize = WindowUtilities.getPageSize( this.options.parent );
912        if( typeof top == "undefined" )
913            top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS)) / 2;
914        top += windowScroll.top
915
916        if( typeof left == "undefined" )
917            left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE)) / 2;
918        left += windowScroll.left
919        this.setLocation( top, left );
920        this.toFront();
921    },
922
923    _recenter: function( event )
924    {
925        if( this.centered )
926        {
927            var pageSize = WindowUtilities.getPageSize( this.options.parent );
928            var windowScroll = WindowUtilities.getWindowScroll( this.options.parent );
929
930            // Check for this stupid IE that sends dumb events
931            if( this.pageSize && this.pageSize.windowWidth == pageSize.windowWidth && this.pageSize.windowHeight == pageSize.windowHeight &&
932                    this.windowScroll.left == windowScroll.left && this.windowScroll.top == windowScroll.top )
933                return;
934            this.pageSize = pageSize;
935            this.windowScroll = windowScroll;
936            // set height of Overlay to take up whole page and show
937            if( $( 'overlay_modal' ) )
938                $( 'overlay_modal' ).setStyle( {height: (pageSize.pageHeight + 'px')} );
939
940            if( this.options.recenterAuto )
941                this._center( this.centerTop, this.centerLeft );
942        }
943    },
944
945    // Hides window
946    hide: function()
947    {
948        this.visible = false;
949        if( this.modal )
950        {
951            Windows.removeModalWindow( this );
952            Windows.resetOverflow();
953        }
954        // To avoid bug on scrolling bar
955        this.oldStyle = this.getContent().getStyle( 'overflow' ) || "auto"
956        this.getContent().setStyle( {overflow: "hidden"} );
957
958        this.options.hideEffect( this.element, this.options.hideEffectOptions );
959
960        if( this.iefix )
961            this.iefix.hide();
962
963        if( !this.doNotNotifyHide )
964            this._notify( "onHide" );
965    },
966
967    close: function()
968    {
969        // Asks closeCallback if exists
970        if( this.visible )
971        {
972            if( this.options.closeCallback && ! this.options.closeCallback( this ) )
973                return;
974
975            if( this.options.destroyOnClose )
976            {
977                var destroyFunc = this.destroy.bind( this );
978                if( this.options.hideEffectOptions.afterFinish )
979                {
980                    var func = this.options.hideEffectOptions.afterFinish;
981                    this.options.hideEffectOptions.afterFinish = function()
982                    {
983                        func();
984                        destroyFunc()
985                    }
986                }
987                else
988                    this.options.hideEffectOptions.afterFinish = function()
989                    {
990                        destroyFunc()
991                    }
992            }
993            Windows.updateFocusedWindow();
994
995            this.doNotNotifyHide = true;
996            this.hide();
997            this.doNotNotifyHide = false;
998            this._notify( "onClose" );
999        }
1000    },
1001
1002    minimize: function()
1003    {
1004        if( this.resizing )
1005            return;
1006
1007        var r2 = $( this.getId() + "_row2" );
1008
1009        if( !this.minimized )
1010        {
1011            this.minimized = true;
1012
1013            var dh = r2.getDimensions().height;
1014            this.r2Height = dh;
1015            var h = this.element.getHeight() - dh;
1016
1017            if( this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow )
1018            {
1019                new Effect.ResizeWindow( this, null, null, null, this.height - dh, {duration: Window.resizeEffectDuration} );
1020            }
1021            else
1022            {
1023                this.height -= dh;
1024                this.element.setStyle( {height: h + "px"} );
1025                r2.hide();
1026            }
1027
1028            if( ! this.useTop )
1029            {
1030                var bottom = parseFloat( this.element.getStyle( 'bottom' ) );
1031                this.element.setStyle( {bottom: (bottom + dh) + 'px'} );
1032            }
1033        }
1034        else
1035        {
1036            this.minimized = false;
1037
1038            var dh = this.r2Height;
1039            this.r2Height = null;
1040            if( this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow )
1041            {
1042                new Effect.ResizeWindow( this, null, null, null, this.height + dh, {duration: Window.resizeEffectDuration} );
1043            }
1044            else
1045            {
1046                var h = this.element.getHeight() + dh;
1047                this.height += dh;
1048                this.element.setStyle( {height: h + "px"} )
1049                r2.show();
1050            }
1051            if( ! this.useTop )
1052            {
1053                var bottom = parseFloat( this.element.getStyle( 'bottom' ) );
1054                this.element.setStyle( {bottom: (bottom - dh) + 'px'} );
1055            }
1056            this.toFront();
1057        }
1058        this._notify( "onMinimize" );
1059
1060        // Store new location/size if need be
1061        this._saveCookie()
1062    },
1063
1064    maximize: function()
1065    {
1066        if( this.isMinimized() || this.resizing )
1067            return;
1068
1069        if( Prototype.Browser.IE && this.heightN == 0 )
1070            this._getWindowBorderSize();
1071
1072        if( this.storedLocation != null )
1073        {
1074            this._restoreLocation();
1075            if( this.iefix )
1076                this.iefix.hide();
1077        }
1078        else
1079        {
1080            this._storeLocation();
1081            Windows.unsetOverflow( this );
1082
1083            var windowScroll = WindowUtilities.getWindowScroll( this.options.parent );
1084            var pageSize = WindowUtilities.getPageSize( this.options.parent );
1085            var left = windowScroll.left;
1086            var top = windowScroll.top;
1087
1088            if( this.options.parent != document.body )
1089            {
1090                windowScroll = {top:0, left:0, bottom:0, right:0};
1091                var dim = this.options.parent.getDimensions();
1092                pageSize.windowWidth = dim.width;
1093                pageSize.windowHeight = dim.height;
1094                top = 0;
1095                left = 0;
1096            }
1097
1098            if( this.constraint )
1099            {
1100                pageSize.windowWidth -= Math.max( 0, this.constraintPad.left ) + Math.max( 0, this.constraintPad.right );
1101                pageSize.windowHeight -= Math.max( 0, this.constraintPad.top ) + Math.max( 0, this.constraintPad.bottom );
1102                left += Math.max( 0, this.constraintPad.left );
1103                top += Math.max( 0, this.constraintPad.top );
1104            }
1105
1106            var width = pageSize.windowWidth - this.widthW - this.widthE;
1107            var height = pageSize.windowHeight - this.heightN - this.heightS;
1108
1109            if( this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow )
1110            {
1111                new Effect.ResizeWindow( this, top, left, width, height, {duration: Window.resizeEffectDuration} );
1112            }
1113            else
1114            {
1115                this.setSize( width, height );
1116                this.element.setStyle( this.useLeft ? {left: left} : {right: left} );
1117                this.element.setStyle( this.useTop ? {top: top} : {bottom: top} );
1118            }
1119
1120            this.toFront();
1121            if( this.iefix )
1122                this._fixIEOverlapping();
1123        }
1124        this._notify( "onMaximize" );
1125
1126        // Store new location/size if need be
1127        this._saveCookie()
1128    },
1129
1130    isMinimized: function()
1131    {
1132        return this.minimized;
1133    },
1134
1135    isMaximized: function()
1136    {
1137        return (this.storedLocation != null);
1138    },
1139
1140    setOpacity: function( opacity )
1141    {
1142        if( Element.setOpacity )
1143            Element.setOpacity( this.element, opacity );
1144    },
1145
1146    setZIndex: function( zindex )
1147    {
1148        this.element.setStyle( {zIndex: zindex} );
1149        Windows.updateZindex( zindex, this );
1150    },
1151
1152    setTitle: function( newTitle )
1153    {
1154        if( !newTitle || newTitle == "" )
1155            newTitle = "&nbsp;";
1156
1157        Element.update( this.element.id + '_top', newTitle );
1158    },
1159
1160    getTitle: function()
1161    {
1162        return $( this.element.id + '_top' ).innerHTML;
1163    },
1164
1165    setStatusBar: function( element )
1166    {
1167        var statusBar = $( this.getId() + "_bottom" );
1168
1169        if( typeof(element) == "object" )
1170        {
1171            if( this.bottombar.firstChild )
1172                this.bottombar.replaceChild( element, this.bottombar.firstChild );
1173            else
1174                this.bottombar.appendChild( element );
1175        }
1176        else
1177            this.bottombar.innerHTML = element;
1178    },
1179
1180    _checkIEOverlapping: function()
1181    {
1182        if( !this.iefix && (navigator.appVersion.indexOf( 'MSIE' ) > 0) && (navigator.userAgent.indexOf( 'Opera' ) < 0) && (this.element.getStyle( 'position' ) == 'absolute') )
1183        {
1184            new Insertion.After( this.element.id, '<iframe id="' + this.element.id + '_iefix" ' + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>' );
1185            this.iefix = $( this.element.id + '_iefix' );
1186        }
1187        if( this.iefix )
1188            setTimeout( this._fixIEOverlapping.bind( this ), 50 );
1189    },
1190
1191    _fixIEOverlapping: function()
1192    {
1193        Position.clone( this.element, this.iefix );
1194        this.iefix.style.zIndex = this.element.style.zIndex - 1;
1195        this.iefix.show();
1196    },
1197
1198    _getWindowBorderSize: function( event )
1199    {
1200        // Hack to get real window border size!!
1201        var div = this._createHiddenDiv( this.options.className + "_n" )
1202        this.heightN = Element.getDimensions( div ).height;
1203        div.parentNode.removeChild( div )
1204
1205        var div = this._createHiddenDiv( this.options.className + "_s" )
1206        this.heightS = Element.getDimensions( div ).height;
1207        div.parentNode.removeChild( div )
1208
1209        var div = this._createHiddenDiv( this.options.className + "_e" )
1210        this.widthE = Element.getDimensions( div ).width;
1211        div.parentNode.removeChild( div )
1212
1213        var div = this._createHiddenDiv( this.options.className + "_w" )
1214        this.widthW = Element.getDimensions( div ).width;
1215        div.parentNode.removeChild( div );
1216
1217        var div = document.createElement( "div" );
1218        div.className = "overlay_" + this.options.className;
1219        document.body.appendChild( div );
1220        //alert("no timeout:\nopacity: " + div.getStyle("opacity") + "\nwidth: " + document.defaultView.getComputedStyle(div, null).width);
1221        var that = this;
1222
1223        // Workaround for Safari!!
1224        setTimeout( function()
1225        {
1226            that.overlayOpacity = ($( div ).getStyle( "opacity" ));
1227            div.parentNode.removeChild( div );
1228        }, 10 );
1229
1230        // Workaround for IE!!
1231        if( Prototype.Browser.IE )
1232        {
1233            this.heightS = $( this.getId() + "_row3" ).getDimensions().height;
1234            this.heightN = $( this.getId() + "_row1" ).getDimensions().height;
1235        }
1236
1237        // Safari size fix
1238        if( Prototype.Browser.WebKit && Prototype.Browser.WebKitVersion < 420 )
1239            this.setSize( this.width, this.height );
1240        if( this.doMaximize )
1241            this.maximize();
1242        if( this.doMinimize )
1243            this.minimize();
1244    },
1245
1246    _createHiddenDiv: function( className )
1247    {
1248        var objBody = document.body;
1249        var win = document.createElement( "div" );
1250        win.setAttribute( 'id', this.element.id + "_tmp" );
1251        win.className = className;
1252        win.style.display = 'none';
1253        win.innerHTML = '';
1254        objBody.insertBefore( win, objBody.firstChild );
1255        return win;
1256    },
1257
1258    _storeLocation: function()
1259    {
1260        if( this.storedLocation == null )
1261        {
1262            this.storedLocation = {useTop: this.useTop, useLeft: this.useLeft,
1263                top: this.element.getStyle( 'top' ), bottom: this.element.getStyle( 'bottom' ),
1264                left: this.element.getStyle( 'left' ), right: this.element.getStyle( 'right' ),
1265                width: this.width, height: this.height };
1266        }
1267    },
1268
1269    _restoreLocation: function()
1270    {
1271        if( this.storedLocation != null )
1272        {
1273            this.useLeft = this.storedLocation.useLeft;
1274            this.useTop = this.storedLocation.useTop;
1275
1276            if( this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow )
1277                new Effect.ResizeWindow( this, this.storedLocation.top, this.storedLocation.left, this.storedLocation.width, this.storedLocation.height, {duration: Window.resizeEffectDuration} );
1278            else
1279            {
1280                this.element.setStyle( this.useLeft ? {left: this.storedLocation.left} : {right: this.storedLocation.right} );
1281                this.element.setStyle( this.useTop ? {top: this.storedLocation.top} : {bottom: this.storedLocation.bottom} );
1282                this.setSize( this.storedLocation.width, this.storedLocation.height );
1283            }
1284
1285            Windows.resetOverflow();
1286            this._removeStoreLocation();
1287        }
1288    },
1289
1290    _removeStoreLocation: function()
1291    {
1292        this.storedLocation = null;
1293    },
1294
1295    _saveCookie: function()
1296    {
1297        if( this.cookie )
1298        {
1299            var value = "";
1300            if( this.useLeft )
1301                value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle( 'left' ))
1302            else
1303                value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle( 'right' ))
1304            if( this.useTop )
1305                value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle( 'top' ))
1306            else
1307                value += ",b:" + (this.storedLocation ? this.storedLocation.bottom : this.element.getStyle( 'bottom' ))
1308
1309            value += "," + (this.storedLocation ? this.storedLocation.width : this.width);
1310            value += "," + (this.storedLocation ? this.storedLocation.height : this.height);
1311            value += "," + this.isMinimized();
1312            value += "," + this.isMaximized();
1313            WindowUtilities.setCookie( value, this.cookie )
1314        }
1315    },
1316
1317    _createWiredElement: function()
1318    {
1319        if( ! this.wiredElement )
1320        {
1321            if( Prototype.Browser.IE )
1322                this._getWindowBorderSize();
1323            var div = document.createElement( "div" );
1324            div.className = "wired_frame " + this.options.className + "_wired_frame";
1325
1326            div.style.position = 'absolute';
1327            this.options.parent.insertBefore( div, this.options.parent.firstChild );
1328            this.wiredElement = $( div );
1329        }
1330        if( this.useLeft )
1331            this.wiredElement.setStyle( {left: this.element.getStyle( 'left' )} );
1332        else
1333            this.wiredElement.setStyle( {right: this.element.getStyle( 'right' )} );
1334
1335        if( this.useTop )
1336            this.wiredElement.setStyle( {top: this.element.getStyle( 'top' )} );
1337        else
1338            this.wiredElement.setStyle( {bottom: this.element.getStyle( 'bottom' )} );
1339
1340        var dim = this.element.getDimensions();
1341        this.wiredElement.setStyle( {width: dim.width + "px", height: dim.height + "px"} );
1342
1343        this.wiredElement.setStyle( {zIndex: Windows.maxZIndex + 30} );
1344        return this.wiredElement;
1345    },
1346
1347    _hideWiredElement: function()
1348    {
1349        if( ! this.wiredElement || ! this.currentDrag )
1350            return;
1351        if( this.currentDrag == this.element )
1352            this.currentDrag = null;
1353        else
1354        {
1355            if( this.useLeft )
1356                this.element.setStyle( {left: this.currentDrag.getStyle( 'left' )} );
1357            else
1358                this.element.setStyle( {right: this.currentDrag.getStyle( 'right' )} );
1359
1360            if( this.useTop )
1361                this.element.setStyle( {top: this.currentDrag.getStyle( 'top' )} );
1362            else
1363                this.element.setStyle( {bottom: this.currentDrag.getStyle( 'bottom' )} );
1364
1365            this.currentDrag.hide();
1366            this.currentDrag = null;
1367            if( this.doResize )
1368                this.setSize( this.width, this.height );
1369        }
1370    },
1371
1372    _notify: function( eventName )
1373    {
1374        if( this.options[eventName] )
1375            this.options[eventName]( this );
1376        else
1377            Windows.notify( eventName, this );
1378    },
1379
1380/** ************* ADDING FROM PROTOTYPE-UI ***************** **/
1381    /*
1382     Function: adapt
1383     Adapts window size to fit its content
1384
1385     Returns:
1386     this
1387     */
1388    adapt: function()
1389    {
1390        var dimensions = this.content.getDimensions();
1391        if( this.options.superflousEffects )
1392            this.morph( dimensions, true );
1393        else
1394            this.setSize( dimensions.width, dimensions.height, true );
1395        return this;
1396    }
1397/** ************* ADDING FROM PROTOTYPE-UI ***************** **/
1398};
1399
1400// Windows containers, register all page windows
1401var Windows = {
1402    windows: [],
1403    modalWindows: [],
1404    observers: [],
1405    focusedWindow: null,
1406    maxZIndex: 0,
1407    overlayShowEffectOptions: {duration: 0.5},
1408    overlayHideEffectOptions: {duration: 0.5},
1409
1410/** ************* ADDING FROM PROTOTYPE-UI ***************** **/
1411    /*
1412     Function: adapt
1413     Adapts window size to fit its content
1414
1415     Returns:
1416     this
1417     */
1418    adapt: function()
1419    {
1420        var dimensions = this.content.getScrollDimensions();
1421        if( this.options.superflousEffects )
1422            this.morph( dimensions, true );
1423        else
1424            this.setSize( dimensions.width, dimensions.height, true );
1425        return this;
1426    },
1427    /** ************* ADDING FROM PROTOTYPE-UI ***************** **/
1428
1429    addObserver: function( observer )
1430    {
1431        this.removeObserver( observer );
1432        this.observers.push( observer );
1433    },
1434
1435    removeObserver: function( observer )
1436    {
1437        this.observers = this.observers.reject( function( o )
1438        {
1439            return o == observer
1440        } );
1441    },
1442
1443    // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
1444    notify: function( eventName, win )
1445    {
1446        this.observers.each( function( o )
1447        {
1448            if( o[eventName] ) o[eventName]( eventName, win );
1449        } );
1450    },
1451
1452    // Gets window from its id
1453    getWindow: function( id )
1454    {
1455        return this.windows.detect( function( d )
1456        {
1457            return d.getId() == id
1458        } );
1459    },
1460
1461    // Gets the last focused window
1462    getFocusedWindow: function()
1463    {
1464        return this.focusedWindow;
1465    },
1466
1467    updateFocusedWindow: function()
1468    {
1469        this.focusedWindow = this.windows.length >= 2 ? this.windows[this.windows.length - 2] : null;
1470    },
1471
1472    // Registers a new window (called by Windows constructor)
1473    register: function( win )
1474    {
1475        this.windows.push( win );
1476    },
1477
1478    // Add a modal window in the stack
1479    addModalWindow: function( win )
1480    {
1481        // Disable screen if first modal window
1482        if( this.modalWindows.length == 0 )
1483        {
1484            WindowUtilities.disableScreen( win.options.className, 'overlay_modal', win.overlayOpacity, win.getId(), win.options.parent );
1485        }
1486        else
1487        {
1488            // Move overlay over all windows
1489            if( Window.keepMultiModalWindow )
1490            {
1491                $( 'overlay_modal' ).style.zIndex = Windows.maxZIndex + 1;
1492                Windows.maxZIndex += 1;
1493                WindowUtilities._hideSelect( this.modalWindows.last().getId() );
1494            }
1495            // Hide current modal window
1496            else
1497                this.modalWindows.last().element.hide();
1498            // Fucking IE select issue
1499            WindowUtilities._showSelect( win.getId() );
1500        }
1501        this.modalWindows.push( win );
1502    },
1503
1504    removeModalWindow: function( win )
1505    {
1506        this.modalWindows.pop();
1507
1508        // No more modal windows
1509        if( this.modalWindows.length == 0 )
1510            WindowUtilities.enableScreen();
1511        else
1512        {
1513            if( Window.keepMultiModalWindow )
1514            {
1515                this.modalWindows.last().toFront();
1516                WindowUtilities._showSelect( this.modalWindows.last().getId() );
1517            }
1518            else
1519                this.modalWindows.last().element.show();
1520        }
1521    },
1522
1523    // Registers a new window (called by Windows constructor)
1524    register: function( win )
1525    {
1526        this.windows.push( win );
1527    },
1528
1529    // Unregisters a window (called by Windows destructor)
1530    unregister: function( win )
1531    {
1532        this.windows = this.windows.reject( function( d )
1533        {
1534            return d == win
1535        } );
1536    },
1537
1538    // Closes all windows
1539    closeAll: function()
1540    {
1541        this.windows.each( function( w )
1542        {
1543            Windows.close( w.getId() )
1544        } );
1545    },
1546
1547    closeAllModalWindows: function()
1548    {
1549        WindowUtilities.enableScreen();
1550        this.modalWindows.each( function( win )
1551        {
1552            if( win ) win.close()
1553        } );
1554    },
1555
1556    // Minimizes a window with its id
1557    minimize: function( id, event )
1558    {
1559        var win = this.getWindow( id )
1560        if( win && win.visible )
1561            win.minimize();
1562        Event.stop( event );
1563    },
1564
1565    // Maximizes a window with its id
1566    maximize: function( id, event )
1567    {
1568        var win = this.getWindow( id )
1569        if( win && win.visible )
1570            win.maximize();
1571        Event.stop( event );
1572    },
1573
1574    // Closes a window with its id
1575    close: function( id, event )
1576    {
1577        var win = this.getWindow( id );
1578        if( win )
1579            win.close();
1580        if( event )
1581            Event.stop( event );
1582    },
1583
1584    blur: function( id )
1585    {
1586        var win = this.getWindow( id );
1587        if( !win )
1588            return;
1589        if( win.options.blurClassName )
1590            win.changeClassName( win.options.blurClassName );
1591        if( this.focusedWindow == win )
1592            this.focusedWindow = null;
1593        win._notify( "onBlur" );
1594    },
1595
1596    focus: function( id )
1597    {
1598        var win = this.getWindow( id );
1599        if( !win )
1600            return;
1601        if( this.focusedWindow )
1602            this.blur( this.focusedWindow.getId() )
1603
1604        if( win.options.focusClassName )
1605            win.changeClassName( win.options.focusClassName );
1606        this.focusedWindow = win;
1607        win._notify( "onFocus" );
1608    },
1609
1610    unsetOverflow: function( except )
1611    {
1612        this.windows.each( function( d )
1613        {
1614            d.oldOverflow = d.getContent().getStyle( "overflow" ) || "auto";
1615            d.getContent().setStyle( {overflow: "hidden"} )
1616        } );
1617        if( except && except.oldOverflow )
1618            except.getContent().setStyle( {overflow: except.oldOverflow} );
1619    },
1620
1621    resetOverflow: function()
1622    {
1623        this.windows.each( function( d )
1624        {
1625            if( d.oldOverflow ) d.getContent().setStyle( {overflow: d.oldOverflow} )
1626        } );
1627    },
1628
1629    updateZindex: function( zindex, win )
1630    {
1631        if( zindex > this.maxZIndex )
1632        {
1633            this.maxZIndex = zindex;
1634            if( this.focusedWindow )
1635                this.blur( this.focusedWindow.getId() )
1636        }
1637        this.focusedWindow = win;
1638        if( this.focusedWindow )
1639            this.focus( this.focusedWindow.getId() )
1640    }
1641};
1642
1643var Dialog = {
1644    dialogId: null,
1645    onCompleteFunc: null,
1646    callFunc: null,
1647    parameters: null,
1648
1649    confirm: function( content, parameters )
1650    {
1651        // Get Ajax return before
1652        if( content && typeof content != "string" )
1653        {
1654            Dialog._runAjaxRequest( content, parameters, Dialog.confirm );
1655            return
1656        }
1657        content = content || "";
1658
1659        parameters = parameters || {};
1660        var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
1661        var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";
1662
1663        // Backward compatibility
1664        parameters = Object.extend( parameters, parameters.windowParameters || {} );
1665        parameters.windowParameters = parameters.windowParameters || {};
1666
1667        parameters.className = parameters.className || "alert";
1668
1669        var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
1670        var cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'"
1671        var content = "\
1672      <div class='" + parameters.className + "_message'>" + content + "</div>\
1673        <div class='" + parameters.className + "_buttons'>\
1674          <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
1675          <input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + "/>\
1676        </div>\
1677    ";
1678        return this._openDialog( content, parameters )
1679    },
1680
1681    alert: function( content, parameters )
1682    {
1683        // Get Ajax return before
1684        if( content && typeof content != "string" )
1685        {
1686            Dialog._runAjaxRequest( content, parameters, Dialog.alert );
1687            return
1688        }
1689        content = content || "";
1690
1691        parameters = parameters || {};
1692        var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
1693
1694        // Backward compatibility   
1695        parameters = Object.extend( parameters, parameters.windowParameters || {} );
1696        parameters.windowParameters = parameters.windowParameters || {};
1697
1698        parameters.className = parameters.className || "alert";
1699
1700        var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
1701        var content = "\
1702      <div class='" + parameters.className + "_message'>" + content + "</div>\
1703        <div class='" + parameters.className + "_buttons'>\
1704          <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
1705        </div>";
1706        return this._openDialog( content, parameters )
1707    },
1708
1709    info: function( content, parameters )
1710    {
1711        // Get Ajax return before
1712        if( content && typeof content != "string" )
1713        {
1714            Dialog._runAjaxRequest( content, parameters, Dialog.info );
1715            return
1716        }
1717        content = content || "";
1718
1719        // Backward compatibility
1720        parameters = parameters || {};
1721        parameters = Object.extend( parameters, parameters.windowParameters || {} );
1722        parameters.windowParameters = parameters.windowParameters || {};
1723
1724        parameters.className = parameters.className || "alert";
1725
1726        var content = "<div id='modal_dialog_message' class='" + parameters.className + "_message'>" + content + "</div>";
1727        if( parameters.showProgress )
1728            content += "<div id='modal_dialog_progress' class='" + parameters.className + "_progress'>  </div>";
1729
1730        parameters.ok = null;
1731        parameters.cancel = null;
1732
1733        return this._openDialog( content, parameters )
1734    },
1735
1736    setInfoMessage: function( message )
1737    {
1738        $( 'modal_dialog_message' ).update( message );
1739    },
1740
1741    closeInfo: function()
1742    {
1743        Windows.close( this.dialogId );
1744    },
1745
1746    _openDialog: function( content, parameters )
1747    {
1748        var className = parameters.className;
1749
1750        if( ! parameters.height && ! parameters.width )
1751        {
1752            parameters.width = WindowUtilities.getPageSize( parameters.options.parent || document.body ).pageWidth / 2;
1753        }
1754        if( parameters.id )
1755            this.dialogId = parameters.id;
1756        else
1757        {
1758            var t = new Date();
1759            this.dialogId = 'modal_dialog_' + t.getTime();
1760            parameters.id = this.dialogId;
1761        }
1762
1763        // compute height or width if need be
1764        if( ! parameters.height || ! parameters.width )
1765        {
1766            var size = WindowUtilities._computeSize( content, this.dialogId, parameters.width, parameters.height, 5, className )
1767            if( parameters.height )
1768                parameters.width = size + 5
1769            else
1770                parameters.height = size + 5
1771        }
1772        parameters.effectOptions = parameters.effectOptions;
1773        parameters.resizable = parameters.resizable || false;
1774        parameters.minimizable = parameters.minimizable || false;
1775        parameters.maximizable = parameters.maximizable || false;
1776        parameters.draggable = parameters.draggable || false;
1777        parameters.closable = parameters.closable || false;
1778
1779        var win = new Window( parameters );
1780        win.getContent().innerHTML = content;
1781
1782        win.showCenter( true, parameters.top, parameters.left );
1783        win.setDestroyOnClose();
1784
1785        win.cancelCallback = parameters.onCancel || parameters.cancel;
1786        win.okCallback = parameters.onOk || parameters.ok;
1787
1788        return win;
1789    },
1790
1791    _getAjaxContent: function( originalRequest )
1792    {
1793        Dialog.callFunc( originalRequest.responseText, Dialog.parameters )
1794    },
1795
1796    _runAjaxRequest: function( message, parameters, callFunc )
1797    {
1798        if( message.options == null )
1799            message.options = {}
1800        Dialog.onCompleteFunc = message.options.onComplete;
1801        Dialog.parameters = parameters;
1802        Dialog.callFunc = callFunc;
1803
1804        message.options.onComplete = Dialog._getAjaxContent;
1805        new Ajax.Request( message.url, message.options );
1806    },
1807
1808    okCallback: function()
1809    {
1810        var win = Windows.focusedWindow;
1811        if( !win.okCallback || win.okCallback( win ) )
1812        {
1813            // Remove onclick on button
1814            $$( "#" + win.getId() + " input" ).each( function( element )
1815            {
1816                element.onclick = null;
1817            } )
1818            win.close();
1819        }
1820    },
1821
1822    cancelCallback: function()
1823    {
1824        var win = Windows.focusedWindow;
1825        // Remove onclick on button
1826        $$( "#" + win.getId() + " input" ).each( function( element )
1827        {
1828            element.onclick = null
1829        } )
1830        win.close();
1831        if( win.cancelCallback )
1832            win.cancelCallback( win );
1833    }
1834}
1835/*
1836 Based on Lightbox JS: Fullsize Image Overlays
1837 by Lokesh Dhakar - http://www.huddletogether.com
1838
1839 For more information on this script, visit:
1840 http://huddletogether.com/projects/lightbox/
1841
1842 Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
1843 (basically, do anything you want, just leave my name and link)
1844 */
1845
1846if( Prototype.Browser.WebKit )
1847{
1848    var array = navigator.userAgent.match( new RegExp( /AppleWebKit\/([\d\.\+]*)/ ) );
1849    Prototype.Browser.WebKitVersion = parseFloat( array[1] );
1850}
1851
1852var WindowUtilities = {
1853    // From dragdrop.js
1854    getWindowScroll: function( parent )
1855    {
1856        var T, L, W, H;
1857        parent = parent || document.body;
1858        if( parent != document.body )
1859        {
1860            T = parent.scrollTop;
1861            L = parent.scrollLeft;
1862            W = parent.scrollWidth;
1863            H = parent.scrollHeight;
1864        }
1865        else
1866        {
1867            var w = window;
1868            with( w.document )
1869            {
1870                if( w.document.documentElement && documentElement.scrollTop )
1871                {
1872                    T = documentElement.scrollTop;
1873                    L = documentElement.scrollLeft;
1874                } else if( w.document.body )
1875                {
1876                    T = body.scrollTop;
1877                    L = body.scrollLeft;
1878                }
1879                if( w.innerWidth )
1880                {
1881                    W = w.innerWidth;
1882                    H = w.innerHeight;
1883                } else if( w.document.documentElement && documentElement.clientWidth )
1884                {
1885                    W = documentElement.clientWidth;
1886                    H = documentElement.clientHeight;
1887                }
1888                else
1889                {
1890                    W = body.offsetWidth;
1891                    H = body.offsetHeight
1892                }
1893            }
1894        }
1895        return { top: T, left: L, width: W, height: H };
1896    },
1897    //
1898    // getPageSize()
1899    // Returns array with page width, height and window width, height
1900    // Core code from - quirksmode.org
1901    // Edit for Firefox by pHaez
1902    //
1903    getPageSize: function( parent )
1904    {
1905        parent = parent || document.body;
1906        var windowWidth, windowHeight;
1907        var pageHeight, pageWidth;
1908        if( parent != document.body )
1909        {
1910            windowWidth = parent.getWidth();
1911            windowHeight = parent.getHeight();
1912            pageWidth = parent.scrollWidth;
1913            pageHeight = parent.scrollHeight;
1914        }
1915        else
1916        {
1917            var xScroll, yScroll;
1918
1919            if( window.innerHeight && window.scrollMaxY )
1920            {
1921                xScroll = document.body.scrollWidth;
1922                yScroll = window.innerHeight + window.scrollMaxY;
1923            } else if( document.body.scrollHeight > document.body.offsetHeight )
1924            { // all but Explorer Mac
1925                xScroll = document.body.scrollWidth;
1926                yScroll = document.body.scrollHeight;
1927            }
1928            else
1929            { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
1930                xScroll = document.body.offsetWidth;
1931                yScroll = document.body.offsetHeight;
1932            }
1933
1934
1935            if( self.innerHeight )
1936            {  // all except Explorer
1937                windowWidth = self.innerWidth;
1938                windowHeight = self.innerHeight;
1939            } else if( document.documentElement && document.documentElement.clientHeight )
1940            { // Explorer 6 Strict Mode
1941                windowWidth = document.documentElement.clientWidth;
1942                windowHeight = document.documentElement.clientHeight;
1943            } else if( document.body )
1944            { // other Explorers
1945                windowWidth = document.body.clientWidth;
1946                windowHeight = document.body.clientHeight;
1947            }
1948
1949            // for small pages with total height less then height of the viewport
1950            if( yScroll < windowHeight )
1951            {
1952                pageHeight = windowHeight;
1953            }
1954            else
1955            {
1956                pageHeight = yScroll;
1957            }
1958
1959            // for small pages with total width less then width of the viewport
1960            if( xScroll < windowWidth )
1961            {
1962                pageWidth = windowWidth;
1963            }
1964            else
1965            {
1966                pageWidth = xScroll;
1967            }
1968        }
1969        return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight};
1970    },
1971
1972    disableScreen: function( className, overlayId, overlayOpacity, contentId, parent )
1973    {
1974        WindowUtilities.initLightbox( overlayId, className, function()
1975        {
1976            this._disableScreen( className, overlayId, overlayOpacity, contentId )
1977        }.bind( this ), parent || document.body );
1978    },
1979
1980    _disableScreen: function( className, overlayId, overlayOpacity, contentId )
1981    {
1982        // prep objects
1983        var objOverlay = $( overlayId );
1984
1985        var pageSize = WindowUtilities.getPageSize( objOverlay.parentNode );
1986
1987        // Hide select boxes as they will 'peek' through the image in IE, store old value
1988        if( contentId && Prototype.Browser.IE )
1989        {
1990            WindowUtilities._hideSelect();
1991            WindowUtilities._showSelect( contentId );
1992        }
1993
1994        // set height of Overlay to take up whole page and show
1995        objOverlay.style.height = (pageSize.pageHeight + 'px');
1996        objOverlay.style.display = 'none';
1997        if( overlayId == "overlay_modal" && Window.hasEffectLib && Windows.overlayShowEffectOptions )
1998        {
1999            objOverlay.overlayOpacity = overlayOpacity;
2000            new Effect.Appear( objOverlay, Object.extend( {from: 0, to: overlayOpacity}, Windows.overlayShowEffectOptions ) );
2001        }
2002        else
2003            objOverlay.style.display = "block";
2004    },
2005
2006    enableScreen: function( id )
2007    {
2008        id = id || 'overlay_modal';
2009        var objOverlay = $( id );
2010        if( objOverlay )
2011        {
2012            // hide lightbox and overlay
2013            if( id == "overlay_modal" && Window.hasEffectLib && Windows.overlayHideEffectOptions )
2014                new Effect.Fade( objOverlay, Object.extend( {from: objOverlay.overlayOpacity, to:0}, Windows.overlayHideEffectOptions ) );
2015            else
2016            {
2017                objOverlay.style.display = 'none';
2018                objOverlay.parentNode.removeChild( objOverlay );
2019            }
2020
2021            // make select boxes visible using old value
2022            if( id != "__invisible__" )
2023                WindowUtilities._showSelect();
2024        }
2025    },
2026
2027    _hideSelect: function( id )
2028    {
2029        if( Prototype.Browser.IE )
2030        {
2031            id = id == null ? "" : "#" + id + " ";
2032            $$( id + 'select' ).each( function( element )
2033            {
2034                if( ! WindowUtilities.isDefined( element.oldVisibility ) )
2035                {
2036                    element.oldVisibility = element.style.visibility ? element.style.visibility : "visible";
2037                    element.style.visibility = "hidden";
2038                }
2039            } );
2040        }
2041    },
2042
2043    _showSelect: function( id )
2044    {
2045        if( Prototype.Browser.IE )
2046        {
2047            id = id == null ? "" : "#" + id + " ";
2048            $$( id + 'select' ).each( function( element )
2049            {
2050                if( WindowUtilities.isDefined( element.oldVisibility ) )
2051                {
2052                    // Why?? Ask IE
2053                    try
2054                    {
2055                        element.style.visibility = element.oldVisibility;
2056                    }
2057                    catch( e )
2058                    {
2059                        element.style.visibility = "visible";
2060                    }
2061                    element.oldVisibility = null;
2062                }
2063                else
2064                {
2065                    if( element.style.visibility )
2066                        element.style.visibility = "visible";
2067                }
2068            } );
2069        }
2070    },
2071
2072    isDefined: function( object )
2073    {
2074        return typeof(object) != "undefined" && object != null;
2075    },
2076
2077    // initLightbox()
2078    // Function runs on window load, going through link tags looking for rel="lightbox".
2079    // These links receive onclick events that enable the lightbox display for their targets.
2080    // The function also inserts html markup at the top of the page which will be used as a
2081    // container for the overlay pattern and the inline image.
2082    initLightbox: function( id, className, doneHandler, parent )
2083    {
2084        // Already done, just update zIndex
2085        if( $( id ) )
2086        {
2087            Element.setStyle( id, {zIndex: Windows.maxZIndex + 1} );
2088            Windows.maxZIndex++;
2089            doneHandler();
2090        }
2091        // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
2092        else
2093        {
2094            var objOverlay = document.createElement( "div" );
2095            objOverlay.setAttribute( 'id', id );
2096            objOverlay.className = "overlay_" + className
2097            objOverlay.style.display = 'none';
2098            objOverlay.style.position = 'absolute';
2099            objOverlay.style.top = '0';
2100            objOverlay.style.left = '0';
2101            objOverlay.style.zIndex = Windows.maxZIndex + 1;
2102            Windows.maxZIndex++;
2103            objOverlay.style.width = '100%';
2104            parent.insertBefore( objOverlay, parent.firstChild );
2105            if( Prototype.Browser.WebKit && id == "overlay_modal" )
2106            {
2107                setTimeout( function()
2108                {
2109                    doneHandler()
2110                }, 10 );
2111            }
2112            else
2113                doneHandler();
2114        }
2115    },
2116
2117    setCookie: function( value, parameters )
2118    {
2119        document.cookie = parameters[0] + "=" + escape( value ) +
2120                ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
2121                ((parameters[2]) ? "; path=" + parameters[2] : "") +
2122                ((parameters[3]) ? "; domain=" + parameters[3] : "") +
2123                ((parameters[4]) ? "; secure" : "");
2124    },
2125
2126    getCookie: function( name )
2127    {
2128        var dc = document.cookie;
2129        var prefix = name + "=";
2130        var begin = dc.indexOf( "; " + prefix );
2131        if( begin == -1 )
2132        {
2133            begin = dc.indexOf( prefix );
2134            if( begin != 0 ) return null;
2135        }
2136        else
2137        {
2138            begin += 2;
2139        }
2140        var end = document.cookie.indexOf( ";", begin );
2141        if( end == -1 )
2142        {
2143            end = dc.length;
2144        }
2145        return unescape( dc.substring( begin + prefix.length, end ) );
2146    },
2147
2148    _computeSize: function( content, id, width, height, margin, className )
2149    {
2150        var objBody = document.body;
2151        var tmpObj = document.createElement( "div" );
2152        tmpObj.setAttribute( 'id', id );
2153        tmpObj.className = className + "_content";
2154
2155        if( height )
2156            tmpObj.style.height = height + "px"
2157        else
2158            tmpObj.style.width = width + "px"
2159
2160        tmpObj.style.position = 'absolute';
2161        tmpObj.style.top = '0';
2162        tmpObj.style.left = '0';
2163        tmpObj.style.display = 'none';
2164
2165        tmpObj.innerHTML = content;
2166        objBody.insertBefore( tmpObj, objBody.firstChild );
2167
2168        var size;
2169        if( height )
2170            size = $( tmpObj ).getDimensions().width + margin;
2171        else
2172            size = $( tmpObj ).getDimensions().height + margin;
2173        objBody.removeChild( tmpObj );
2174        return size;
2175    }
2176}
2177
Note: See TracBrowser for help on using the repository browser.