From 0ef487587dea1c0c69ddfeaa4c1485ed8f7319ce Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sun, 18 Feb 2007 06:18:50 +0000 Subject: [PATCH] Merged in newer versions of the Prototype and Prototype Window libraries git-svn-id: file:///home/svn/framework3/trunk@4427 4d416f70-5f16-0410-b530-b9f4589650da --- data/msfweb/public/javascripts/application.js | 2 +- data/msfweb/public/javascripts/debug.js | 137 ++ data/msfweb/public/javascripts/effects.js | 500 ++-- .../public/javascripts/extended_debug.js | 113 + data/msfweb/public/javascripts/prototype.js | 1321 ++++++---- data/msfweb/public/javascripts/tooltip.js | 239 ++ data/msfweb/public/javascripts/window.js | 2118 ++++++++++------- data/msfweb/public/javascripts/window_ext.js | 107 + 8 files changed, 3107 insertions(+), 1430 deletions(-) create mode 100644 data/msfweb/public/javascripts/debug.js create mode 100755 data/msfweb/public/javascripts/extended_debug.js create mode 100644 data/msfweb/public/javascripts/tooltip.js create mode 100755 data/msfweb/public/javascripts/window_ext.js diff --git a/data/msfweb/public/javascripts/application.js b/data/msfweb/public/javascripts/application.js index df528c4c68..553ff66add 100644 --- a/data/msfweb/public/javascripts/application.js +++ b/data/msfweb/public/javascripts/application.js @@ -168,7 +168,7 @@ function create_window_ajax(target_url, wid, wtitle, wwidth, wheight) { * Height and width are fixed, should be working values in all cases. */ function openModuleWindow(mtype, refname, wtitle) { - var mWin = create_window_ajax("/" + mtype + "/view?refname=" + refname, mtype + "-view-" + obtainWindowId(), wtitle, 500, 350); + var mWin = create_window_ajax("/" + mtype + "/view?refname=" + refname, mtype + "-view-" + obtainWindowId(), wtitle, 650, 350); mWin.setDestroyOnClose(); mWin.showCenter(); } diff --git a/data/msfweb/public/javascripts/debug.js b/data/msfweb/public/javascripts/debug.js new file mode 100644 index 0000000000..3d8f338836 --- /dev/null +++ b/data/msfweb/public/javascripts/debug.js @@ -0,0 +1,137 @@ +var debugWindow = null; +function debug(text, reverse) { + if (debugWindow == null) + return; + + time = "-"; //new Date(); + if (reverse) { + $('debug').innerHTML = time + " " + text + "
"+ $('debug').innerHTML; + debugWindow.getContent().scrollTop=0; + } + else { + $('debug').innerHTML += time + " " + text + "
"; + debugWindow.getContent().scrollTop=10000; // Far away + } +} + +function hideDebug() { + if (debugWindow) { + debugWindow.destroy(); + debugWindow = null; + } +} + +function showDebug(bShow) { + if (debugWindow == null) { + debugWindow = new Window('debug_window', {className: 'dialog',width:250, height:100, right:4, bottom:42, zIndex:1000, opacity:1, showEffect: Element.show, resizable: true, title: "Debug"}) + debugWindow.getContent().innerHTML = "
"; + date=new Date; + date.setMonth(date.getMonth()+3); + + //debugWindow.setCookie(null, date); + } + if( typeof bShow == 'undefined' || bShow)debugWindow.show() +} + + +function clearDebug() { + if (debugWindow == null) + return; + $('debug').innerHTML = ""; +} + +/** + * document.createElement convenience wrapper + * + * The data parameter is an object that must have the "tag" key, containing + * a string with the tagname of the element to create. It can optionally have + * a "children" key which can be: a string, "data" object, or an array of "data" + * objects to append to this element as children. Any other key is taken as an + * attribute to be applied to this tag. + * + * Available under an MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * @param {Object} data The data representing the element to create + * @return {Element} The element created. + */ +function $E(data) { + var el; + if ('string'==typeof data) { + el=document.createTextNode(data); + } else { + //create the element + el=document.createElement(data.tag); + delete(data.tag); + + //append the children + if ('undefined'!=typeof data.children) { + if ('string'==typeof data.children ||'undefined'==typeof data.children.length) { + //strings and single elements + el.appendChild($E(data.children)); + } else { + //arrays of elements + for (var i=0, child=null; 'undefined'!=typeof (child=data.children[i]); i++) { + el.appendChild($E(child)); + } + } + delete(data.children); + } + + //any other data is attributes + for (attr in data) { + el[attr]=data[attr]; + } + } + + return el; +} + +// FROM Nick Hemsley +var Debug = { + inspectOutput: function (container, within) { + within = within || debugWindow.getContent() + + if (debugWindow == null) + return; + + within.appendChild(container) + }, + + inspect: function(object) { + var cont = $E({tag: "div", className: "inspector"}) + Debug.inspectObj(object, cont) + debugWindow.getContent().appendChild(cont) + }, + + inspectObj: function (object, container) { + for (prop in object) { + Debug.inspectOutput(Debug.inspectable(object, prop), container) + } + }, + + inspectable: function(object, prop) { + cont = $E({tag: 'div', className: 'inspectable', children: [prop + " value: " + object[prop] ]}) + cont.toInspect = object[prop] + Event.observe(cont, 'click', Debug.inspectClicked, false) + return cont + }, + + inspectClicked: function(e) { + Debug.inspectContained(Event.element(e)) + Event.stop(e) + }, + + inspectContained: function(container) { + if (container.opened) { + container.parentNode.removeChild(container.opened) + delete(container.opened) + } else { + sibling = container.parentNode.insertBefore($E({tag: "div", className: "child"}), container.nextSibling) + if (container.toInspect) + Debug.inspectObj(container.toInspect, sibling) + container.opened = sibling + } + } +} +var inspect = Debug.inspect; diff --git a/data/msfweb/public/javascripts/effects.js b/data/msfweb/public/javascripts/effects.js index 927400502d..06f59b4769 100644 --- a/data/msfweb/public/javascripts/effects.js +++ b/data/msfweb/public/javascripts/effects.js @@ -1,15 +1,18 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 + +// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) // Martin Bialasinki // -// See scriptaculous.js for full license. +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ // converts rgb() and #xxx to #xxxxxx format, // returns self (or first argument) if not convertable String.prototype.parseColor = function() { - var color = '#'; + var color = '#'; if(this.slice(0,4) == 'rgb(') { var cols = this.slice(4,this.length-1).split(','); var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); @@ -41,48 +44,21 @@ Element.collectTextNodesIgnoreClass = function(element, className) { Element.setContentZoom = function(element, percent) { element = $(element); - Element.setStyle(element, {fontSize: (percent/100) + 'em'}); + element.setStyle({fontSize: (percent/100) + 'em'}); if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); + return element; } -Element.getOpacity = function(element){ - var opacity; - if (opacity = Element.getStyle(element, 'opacity')) - return parseFloat(opacity); - if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) - if(opacity[1]) return parseFloat(opacity[1]) / 100; - return 1.0; +Element.getOpacity = function(element){ + return $(element).getStyle('opacity'); } -Element.setOpacity = function(element, value){ - element= $(element); - if (value == 1){ - Element.setStyle(element, { opacity: - (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? - 0.999999 : null }); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); - } else { - if(value < 0.00001) value = 0; - Element.setStyle(element, {opacity: value}); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, - { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + - 'alpha(opacity='+value*100+')' }); - } -} - -Element.getInlineOpacity = function(element){ +Element.setOpacity = function(element, value){ + return $(element).setStyle({opacity:value}); +} + +Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; -} - -Element.childrenWithClassName = function(element, className, findFirst) { - var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); - var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { - return (c.className && c.className.match(classNameRegExp)); - }); - if(!results) results = []; - return results; } Element.forceRerendering = function(element) { @@ -104,9 +80,17 @@ Array.prototype.call = function() { /*--------------------------------------------------------------------------*/ var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, tagifyText: function(element) { + if(typeof Builder == 'undefined') + throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); + var tagifyStyle = 'position:relative'; - if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; + if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; + element = $(element); $A(element.childNodes).each( function(child) { if(child.nodeType==3) { @@ -159,33 +143,35 @@ var Effect2 = Effect; // deprecated /* ------------- transitions ------------- */ -Effect.Transitions = {} - -Effect.Transitions.linear = function(pos) { - return pos; -} -Effect.Transitions.sinoidal = function(pos) { - return (-Math.cos(pos*Math.PI)/2) + 0.5; -} -Effect.Transitions.reverse = function(pos) { - return 1-pos; -} -Effect.Transitions.flicker = function(pos) { - return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; -} -Effect.Transitions.wobble = function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; -} -Effect.Transitions.pulse = function(pos) { - return (Math.floor(pos*10) % 2 == 0 ? - (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); -} -Effect.Transitions.none = function(pos) { - return 0; -} -Effect.Transitions.full = function(pos) { - return 1; -} +Effect.Transitions = { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; + }, + pulse: function(pos, pulses) { + pulses = pulses || 5; + return ( + Math.round((pos % (1/pulses)) * pulses) == 0 ? + ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : + 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) + ); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } +}; /* ------------- core effects ------------- */ @@ -212,6 +198,9 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { e.finishOn += effect.finishOn; }); break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; case 'end': // start effect after last queued effect has finished timestamp = this.effects.pluck('finishOn').max() || timestamp; @@ -225,7 +214,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { this.effects.push(effect); if(!this.interval) - this.interval = setInterval(this.loop.bind(this), 40); + this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e==effect }); @@ -236,7 +225,8 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { }, loop: function() { var timePos = new Date().getTime(); - this.effects.invoke('loop', timePos); + for(var i=0, len=this.effects.length;i'; + var data = $H(); + for(property in this) + if(typeof this[property] != 'function') data[property] = this[property]; + return '#'; } } @@ -348,12 +341,24 @@ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { } }); +Effect.Event = Class.create(); +Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), { + initialize: function() { + var options = Object.extend({ + duration: 0 + }, arguments[0] || {}); + this.start(options); + }, + update: Prototype.emptyFunction +}); + Effect.Opacity = Class.create(); Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) + if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, @@ -370,6 +375,7 @@ Effect.Move = Class.create(); Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, @@ -393,8 +399,8 @@ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { }, update: function(position) { this.element.setStyle({ - left: this.options.x * position + this.originalLeft + 'px', - top: this.options.y * position + this.originalTop + 'px' + left: Math.round(this.options.x * position + this.originalLeft) + 'px', + top: Math.round(this.options.y * position + this.originalTop) + 'px' }); } }); @@ -408,7 +414,8 @@ Effect.MoveBy = function(element, toTop, toLeft) { Effect.Scale = Class.create(); Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { initialize: function(element, percent) { - this.element = $(element) + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, @@ -433,7 +440,7 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%'].each( function(fontSizeType) { + ['em','px','%','pt'].each( function(fontSizeType) { if(fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; @@ -458,12 +465,12 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); }, finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle); }, setDimensions: function(height, width) { var d = {}; - if(this.options.scaleX) d.width = width + 'px'; - if(this.options.scaleY) d.height = height + 'px'; + if(this.options.scaleX) d.width = Math.round(width) + 'px'; + if(this.options.scaleY) d.height = Math.round(height) + 'px'; if(this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; @@ -483,6 +490,7 @@ Effect.Highlight = Class.create(); Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); this.start(options); }, @@ -490,9 +498,11 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), // Prevent executing on elements not in the layout flow if(this.element.getStyle('display')=='none') { this.cancel(); return; } // Disable background image during the effect - this.oldStyle = { - backgroundImage: this.element.getStyle('background-image') }; - this.element.setStyle({backgroundImage: 'none'}); + this.oldStyle = {}; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } if(!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); if(!this.options.restorecolor) @@ -547,8 +557,7 @@ Effect.Fade = function(element) { to: 0.0, afterFinishInternal: function(effect) { if(effect.options.to!=0) return; - effect.element.hide(); - effect.element.setStyle({opacity: oldOpacity}); + effect.element.hide().setStyle({opacity: oldOpacity}); }}, arguments[1] || {}); return new Effect.Opacity(element,options); } @@ -563,25 +572,31 @@ Effect.Appear = function(element) { effect.element.forceRerendering(); }, beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from); - effect.element.show(); + effect.element.setOpacity(effect.options.from).show(); }}, arguments[1] || {}); return new Effect.Opacity(element,options); } Effect.Puff = function(element) { element = $(element); - var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; return new Effect.Parallel( [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { - effect.effects[0].element.setStyle({position: 'absolute'}); }, + Position.absolutize(effect.effects[0].element) + }, afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.setStyle(oldStyle); } + effect.effects[0].element.hide().setStyle(oldStyle); } }, arguments[1] || {}) ); } @@ -589,13 +604,12 @@ Effect.Puff = function(element) { Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); - return new Effect.Scale(element, 0, + return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); + effect.element.hide().undoClipping(); } }, arguments[1] || {}) ); @@ -604,28 +618,25 @@ Effect.BlindUp = function(element) { Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, - Object.extend({ scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {})); } Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, { + return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, @@ -634,18 +645,14 @@ Effect.SwitchOff = function(element) { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { - effect.element.makePositioned(); - effect.element.makeClipping(); + effect.element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.undoPositioned(); - effect.element.setStyle({opacity: oldOpacity}); + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); } }) } - }); + }, arguments[1] || {})); } Effect.DropOut = function(element) { @@ -663,9 +670,7 @@ Effect.DropOut = function(element) { effect.effects[0].element.makePositioned(); }, afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); } }, arguments[1] || {})); } @@ -687,54 +692,42 @@ Effect.Shake = function(element) { { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { - effect.element.undoPositioned(); - effect.element.setStyle(oldStyle); + effect.element.undoPositioned().setStyle(oldStyle); }}) }}) }}) }}) }}) }}); } Effect.SlideDown = function(element) { - element = $(element); - element.cleanWhitespace(); + element = $(element).cleanWhitespace(); // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, - scaleFrom: 0, + scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); + effect.element.down().makePositioned(); if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); }, + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: + effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { - effect.element.undoClipping(); - // IE will crash if child is undoPositioned first - if(/MSIE/.test(navigator.userAgent)){ - effect.element.undoPositioned(); - effect.element.firstChild.undoPositioned(); - }else{ - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - } - effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || {}) ); } - + Effect.SlideUp = function(element) { - element = $(element); - element.cleanWhitespace(); - var oldInnerBottom = $(element.firstChild).getStyle('bottom'); - return new Effect.Scale(element, 0, + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', @@ -742,32 +735,32 @@ Effect.SlideUp = function(element) { restoreAfterFinish: true, beforeStartInternal: function(effect) { effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); + effect.element.down().makePositioned(); if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.show(); }, + effect.element.makeClipping().show(); + }, afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - effect.element.setStyle({bottom: oldInnerBottom}); } + effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom}); + effect.element.down().undoPositioned(); + } }, arguments[1] || {}) ); } // Bug in opera makes the TD containing this element expand for a instance after finish Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, - { restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(effect.element); }, - afterFinishInternal: function(effect) { - effect.element.hide(effect.element); - effect.element.undoClipping(effect.element); } + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } }); } @@ -823,9 +816,7 @@ Effect.Grow = function(element) { y: initialMoveY, duration: 0.01, beforeSetup: function(effect) { - effect.element.hide(); - effect.element.makeClipping(); - effect.element.makePositioned(); + effect.element.hide().makeClipping().makePositioned(); }, afterFinishInternal: function(effect) { new Effect.Parallel( @@ -836,13 +827,10 @@ Effect.Grow = function(element) { sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) ], Object.extend({ beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}); - effect.effects[0].element.show(); + effect.effects[0].element.setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ) @@ -896,13 +884,10 @@ Effect.Shrink = function(element) { new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) ], Object.extend({ beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned(); - effect.effects[0].element.makeClipping(); }, + effect.effects[0].element.makePositioned().makeClipping(); + }, afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); } + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ); } @@ -912,10 +897,10 @@ Effect.Pulsate = function(element) { var options = arguments[1] || {}; var oldOpacity = element.getInlineOpacity(); var transition = options.transition || Effect.Transitions.sinoidal; - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; reverser.bind(transition); return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 3.0, from: 0, + Object.extend(Object.extend({ duration: 2.0, from: 0, afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } }, options), {transition: reverser})); } @@ -927,7 +912,7 @@ Effect.Fold = function(element) { left: element.style.left, width: element.style.width, height: element.style.height }; - Element.makeClipping(element); + element.makeClipping(); return new Effect.Scale(element, 5, Object.extend({ scaleContent: false, scaleX: false, @@ -936,15 +921,162 @@ Effect.Fold = function(element) { scaleContent: false, scaleY: false, afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.setStyle(oldStyle); + effect.element.hide().undoClipping().setStyle(oldStyle); } }); }}, arguments[1] || {})); }; +Effect.Morph = Class.create(); +Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: {} + }, arguments[1] || {}); + if (typeof options.style == 'string') { + if(options.style.indexOf(':') == -1) { + var cssText = '', selector = '.' + options.style; + $A(document.styleSheets).reverse().each(function(styleSheet) { + if (styleSheet.cssRules) cssRules = styleSheet.cssRules; + else if (styleSheet.rules) cssRules = styleSheet.rules; + $A(cssRules).reverse().each(function(rule) { + if (selector == rule.selectorText) { + cssText = rule.style.cssText; + throw $break; + } + }); + if (cssText) throw $break; + }); + this.style = cssText.parseStyle(); + options.afterFinishInternal = function(effect){ + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + if(transform.style != 'opacity') + effect.element.style[transform.style.camelize()] = ''; + }); + } + } else this.style = options.style.parseStyle(); + } else this.style = $H(options.style) + this.start(options); + }, + setup: function(){ + function parseColor(color){ + if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ) + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0].underscore().dasherize(), value = pair[1], unit = null; + + if(value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if(property == 'opacity') { + value = parseFloat(value); + if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if(Element.CSS_LENGTH.test(value)) + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), + value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; + + var originalValue = this.element.getStyle(property); + return $H({ + style: property, + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }); + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ) + }); + }, + update: function(position) { + var style = $H(), value = null; + this.transforms.each(function(transform){ + value = transform.unit=='color' ? + $R(0,2).inject('#',function(m,v,i){ + return m+(Math.round(transform.originalValue[i]+ + (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : + transform.originalValue + Math.round( + ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; + style[transform.style] = value; + }); + this.element.setStyle(style); + } +}); + +Effect.Transform = Class.create(); +Object.extend(Effect.Transform.prototype, { + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || {}; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + var data = $H(track).values().first(); + this.tracks.push($H({ + ids: $H(track).keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var elements = [$(track.ids) || $$(track.ids)].flatten(); + return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.prototype.parseStyle = function(){ + var element = Element.extend(document.createElement('div')); + element.innerHTML = '
'; + var style = element.down().style, styleRules = $H(); + + Element.CSS_PROPERTIES.each(function(property){ + if(style[property]) styleRules[property] = style[property]; + }); + if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) { + styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; + } + return styleRules; +}; + +Element.morph = function(element, style) { + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {})); + return element; +}; + ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', - 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( + 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( function(f) { Element.Methods[f] = Element[f]; } ); diff --git a/data/msfweb/public/javascripts/extended_debug.js b/data/msfweb/public/javascripts/extended_debug.js new file mode 100755 index 0000000000..2b935b1b7d --- /dev/null +++ b/data/msfweb/public/javascripts/extended_debug.js @@ -0,0 +1,113 @@ +var commandHistory; +var historyIndex; + +function showExtendedDebug() { + if (debugWindow != null) { + hideDebug(); + } + + if (debugWindow == null) { + commandHistory = new Array(); + historyIndex = 0; + + debugWindow = new Window('debug_window', {className: 'dialog',width:250, height:100, right:4, minWidth:250, bottom:42, zIndex:1000, opacity:1, showEffect: Element.show, resizable: true, title: "Debug"}) + debugWindow.getContent().innerHTML = "
"; + + //create hourglass icon and attach events to it. + var cont = "
"; + + new Insertion.After('debug_window_maximize', cont); + Event.observe('debug_window_inspect', 'click', enterInspectionMode, false); + + //create command text box + cont = "Eval:" + debugWindow.setStatusBar(cont); + + Event.observe('debug_window_command', 'mousedown', donothing); + Event.observe('debug_window_command', 'keypress', evalJS, false); + } + debugWindow.show(); +} + +function donothing(evt){ + Field.activate('debug_window_command'); + return false; +} + +function evalJS(evt){ + if(evt.keyCode == Event.KEY_RETURN){ + var js = $F('debug_window_command'); + try{ + var ret = eval(js); + if(ret != null) + debug(ret); + }catch(e){ + debug(e); + } + $('debug_window_command').value = ''; + + Field.activate('debug_window_command'); + commandHistory.push(js); + historyIndex = 0; + } + + if(evt.keyCode == Event.KEY_UP){ + if(commandHistory.length > historyIndex){ + historyIndex++; + var js = commandHistory[commandHistory.length-historyIndex]; + $('debug_window_command').value = js; + Event.stop(evt); + Field.activate('debug_window_command'); + } + } + + if(evt.keyCode == Event.KEY_DOWN){ + if(commandHistory.length >= historyIndex && historyIndex > 1){ + historyIndex--; + var js = commandHistory[commandHistory.length-historyIndex]; + $('debug_window_command').value = js; + Event.stop(evt); + Field.activate('debug_window_command'); + } + } +} + +function enterInspectionMode(evt){ + //stop observing magnifying glass + Event.stopObserving('debug_window_inspect', 'click', enterInspectionMode, false); + //change pointer + document.body.style.cursor='help'; + //start observing mouse clicks + Event.observe(window, 'click', inspectItem, false); +} + +function inspectItem(evt){ + // the element that triggered the event + var element = Event.element(evt); + if(element.id!="debug_window_inspect"){ + clearDebug() + //change pointer + document.body.style.cursor='default'; + debug(element.id); + inspect(element); + //stop observing mouse clicks + Event.stopObserving(window, 'click', inspectItem, false); + //alert('doing something'); + //start observing mag + Event.observe('debug_window_inspect', 'click', enterInspectionMode, false); + } +} + +function clearDebug() { + var win = $('debug'); + if (win == null) + return; + + win.innerHTML=" "; + //clear inspections too + var divs = document.getElementsByClassName('inspector'); + divs.each(function(div){ + Element.remove(div); + }); +} + diff --git a/data/msfweb/public/javascripts/prototype.js b/data/msfweb/public/javascripts/prototype.js index 0caf9cd7f0..0476b8fdcc 100644 --- a/data/msfweb/public/javascripts/prototype.js +++ b/data/msfweb/public/javascripts/prototype.js @@ -1,5 +1,5 @@ -/* Prototype JavaScript framework, version 1.5.0_rc0 - * (c) 2005 Sam Stephenson +/* Prototype JavaScript framework, version 1.5.0 + * (c) 2005-2007 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ @@ -7,11 +7,14 @@ /*--------------------------------------------------------------------------*/ var Prototype = { - Version: '1.5.0_rc0', - ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + Version: '1.5.0', + BrowserFeatures: { + XPath: !!document.evaluate + }, + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, - K: function(x) {return x} + K: function(x) { return x } } var Class = { @@ -31,16 +34,36 @@ Object.extend = function(destination, source) { return destination; } -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); } -} +}); Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); @@ -50,9 +73,9 @@ Function.prototype.bind = function() { } Function.prototype.bindAsEventListener = function(object) { - var __method = this; + var __method = this, args = $A(arguments), object = args.shift(); return function(event) { - return __method.call(object, event || window.event); + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); } } @@ -77,7 +100,7 @@ var Try = { these: function() { var returnValue; - for (var i = 0; i < arguments.length; i++) { + for (var i = 0, length = arguments.length; i < length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); @@ -102,20 +125,30 @@ PeriodicalExecuter.prototype = { }, registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; - this.callback(); + this.callback(this); } finally { this.currentlyExecuting = false; } } } } +String.interpret = function(value){ + return value == null ? '' : String(value); +} + Object.extend(String.prototype, { gsub: function(pattern, replacement) { var result = '', source = this, match; @@ -124,7 +157,7 @@ Object.extend(String.prototype, { while (source.length > 0) { if (match = source.match(pattern)) { result += source.slice(0, match.index); - result += (replacement(match) || '').toString(); + result += String.interpret(replacement(match)); source = source.slice(match.index + match[0].length); } else { result += source, source = ''; @@ -189,15 +222,28 @@ Object.extend(String.prototype, { unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; }, - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var name = decodeURIComponent(pair[0]); + var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; + + if (hash[name] !== undefined) { + if (hash[name].constructor != Array) + hash[name] = [hash[name]]; + if (value) hash[name].push(value); + } + else hash[name] = value; + } + return hash; }); }, @@ -205,24 +251,43 @@ Object.extend(String.prototype, { return this.split(''); }, - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); }, - inspect: function() { - return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function(){ + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.replace(/\\/g, '\\\\'); + if (useDoubleQuotes) + return '"' + escapedString.replace(/"/g, '\\"') + '"'; + else + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; } }); @@ -246,7 +311,7 @@ Template.prototype = { return this.template.gsub(this.pattern, function(match) { var before = match[1]; if (before == '\\') return match[2]; - return before + (object[match[3]] || '').toString(); + return before + String.interpret(object[match[3]]); }); } } @@ -268,6 +333,14 @@ var Enumerable = { } catch (e) { if (e != $break) throw e; } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); }, all: function(iterator) { @@ -280,7 +353,7 @@ var Enumerable = { }, any: function(iterator) { - var result = true; + var result = false; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; @@ -291,12 +364,12 @@ var Enumerable = { collect: function(iterator) { var results = []; this.each(function(value, index) { - results.push(iterator(value, index)); + results.push((iterator || Prototype.K)(value, index)); }); return results; }, - detect: function (iterator) { + detect: function(iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { @@ -337,6 +410,14 @@ var Enumerable = { return found; }, + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); @@ -346,7 +427,7 @@ var Enumerable = { invoke: function(method) { var args = $A(arguments).slice(1); - return this.collect(function(value) { + return this.map(function(value) { return value[method].apply(value, args); }); }, @@ -398,7 +479,7 @@ var Enumerable = { }, sortBy: function(iterator) { - return this.collect(function(value, index) { + return this.map(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; @@ -407,7 +488,7 @@ var Enumerable = { }, toArray: function() { - return this.collect(Prototype.K); + return this.map(); }, zip: function() { @@ -421,6 +502,10 @@ var Enumerable = { }); }, + size: function() { + return this.toArray().length; + }, + inspect: function() { return '#'; } @@ -439,7 +524,7 @@ var $A = Array.from = function(iterable) { return iterable.toArray(); } else { var results = []; - for (var i = 0; i < iterable.length; i++) + for (var i = 0, length = iterable.length; i < length; i++) results.push(iterable[i]); return results; } @@ -452,7 +537,7 @@ if (!Array.prototype._reverse) Object.extend(Array.prototype, { _each: function(iterator) { - for (var i = 0; i < this.length; i++) + for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); }, @@ -471,7 +556,7 @@ Object.extend(Array.prototype, { compact: function() { return this.select(function(value) { - return value != undefined || value != null; + return value != null; }); }, @@ -490,7 +575,7 @@ Object.extend(Array.prototype, { }, indexOf: function(object) { - for (var i = 0; i < this.length; i++) + for (var i = 0, length = this.length; i < length; i++) if (this[i] == object) return i; return -1; }, @@ -499,15 +584,88 @@ Object.extend(Array.prototype, { return (inline !== false ? this : this.toArray())._reverse(); }, + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function() { + return this.inject([], function(array, value) { + return array.include(value) ? array : array.concat([value]); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; } }); -var Hash = { + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string){ + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if(window.opera){ + Array.prototype.concat = function(){ + var array = []; + for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for(var i = 0, length = arguments.length; i < length; i++) { + if(arguments[i].constructor == Array) { + for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(obj) { + Object.extend(this, obj || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + + if (pair.value && pair.value.constructor == Array) { + var values = pair.value.compact(); + if (values.length < 2) pair.value = values.reduce(); + else { + key = encodeURIComponent(pair.key); + values.each(function(value) { + value = value != undefined ? encodeURIComponent(value) : ''; + parts.push(key + '=' + encodeURIComponent(value)); + }); + return; + } + } + if (pair.value == undefined) pair[1] = ''; + parts.push(pair.map(encodeURIComponent).join('=')); + }); + + return parts.join('&'); + } +}); + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { _each: function(iterator) { for (var key in this) { var value = this[key]; - if (typeof value == 'function') continue; + if (value && value == Hash.prototype[key]) continue; var pair = [key, value]; pair.key = key; @@ -525,16 +683,30 @@ var Hash = { }, merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { + return $H(hash).inject(this, function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); }, + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); + return Hash.toQueryString(this); }, inspect: function() { @@ -542,14 +714,12 @@ var Hash = { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; } -} +}); function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} + if (object && object.constructor == Hash) return object; + return new Hash(object); +}; ObjectRange = Class.create(); Object.extend(ObjectRange.prototype, Enumerable); Object.extend(ObjectRange.prototype, { @@ -561,10 +731,10 @@ Object.extend(ObjectRange.prototype, { _each: function(iterator) { var value = this.start; - do { + while (this.include(value)) { iterator(value); value = value.succ(); - } while (this.include(value)); + } }, include: function(value) { @@ -599,18 +769,18 @@ Ajax.Responders = { this.responders._each(iterator); }, - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); }, - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); + unregister: function(responder) { + this.responders = this.responders.without(responder); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { + if (typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} @@ -625,7 +795,6 @@ Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, - onComplete: function() { Ajax.activeRequestCount--; } @@ -638,19 +807,14 @@ Ajax.Base.prototype = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', parameters: '' } Object.extend(this.options, options || {}); - }, - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); } } @@ -659,6 +823,8 @@ Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); @@ -666,74 +832,138 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { }, request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; + this.url = url; + this.method = this.options.method; + var params = this.options.parameters; + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + params = Hash.toQueryString(params); + if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' + + // when GET, append parameters to URL + if (this.method == 'get' && params) + this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - Ajax.Responders.dispatch('onCreate', this, this.transport); - this.transport.open(this.options.method, this.url, + this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); + var body = this.method == 'post' ? (this.options.postBody || params) : null; - } catch (e) { + this.transport.send(body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { this.dispatchException(e); } }, - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version, - 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', this.options.contentType); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - onStateChange: function() { var readyState = this.transport.readyState; - if (readyState != 1) + if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState); }, - header: function(name) { + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.getHeader('Content-type') || 'text/javascript').strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { try { return this.transport.getResponseHeader(name); - } catch (e) {} + } catch (e) { return null } }, evalJSON: function() { try { - return eval('(' + this.header('X-JSON') + ')'); - } catch (e) {} + var json = this.getHeader('X-JSON'); + return json ? eval('(' + json + ')') : null; + } catch (e) { return null } }, evalResponse: function() { @@ -744,35 +974,6 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { } }, - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); @@ -783,41 +984,37 @@ Ajax.Updater = Class.create(); Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) } this.transport = Ajax.getTransport(); this.setOptions(options); var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { + this.options.onComplete = (function(transport, param) { this.updateContent(); - onComplete(transport, object); + onComplete(transport, param); }).bind(this); this.request(url); }, updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; + var receiver = this.container[this.success() ? 'success' : 'failure']; var response = this.transport.responseText; - if (!this.options.evalScripts) - response = response.stripScripts(); + if (!this.options.evalScripts) response = response.stripScripts(); - if (receiver) { - if (this.options.insertion) { + if (receiver = $(receiver)) { + if (this.options.insertion) new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } + else + receiver.update(response); } - if (this.responseIsSuccess()) { + if (this.success()) { if (this.onComplete) setTimeout(this.onComplete.bind(this), 10); } @@ -846,7 +1043,7 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { }, stop: function() { - this.updater.onComplete = undefined; + this.updater.options.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, @@ -866,25 +1063,43 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); -function $() { - var results = [], element; - for (var i = 0; i < arguments.length; i++) { - element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - results.push(Element.extend(element)); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; } - return results.length < 2 ? results[0] : results; + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; } document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(Element.extend(child)); + if (Prototype.BrowserFeatures.XPath) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } else { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } return elements; - }); -} + } +}; /*--------------------------------------------------------------------------*/ @@ -892,21 +1107,28 @@ if (!window.Element) var Element = new Object(); Element.extend = function(element) { - if (!element) return; - if (_nativeExtensions) return element; + if (!element || _nativeExtensions || element.nodeType == 3) return element; if (!element._extended && element.tagName && element != window) { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { + var methods = Object.clone(Element.Methods), cache = Element.extend.cache; + + if (element.tagName == 'FORM') + Object.extend(methods, Form.Methods); + if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) + Object.extend(methods, Form.Element.Methods); + + Object.extend(methods, Element.Methods.Simulated); + + for (var property in methods) { var value = methods[property]; - if (typeof value == 'function') + if (typeof value == 'function' && !(property in element)) element[property] = cache.findOrStore(value); } } element._extended = true; return element; -} +}; Element.extend.cache = { findOrStore: function(value) { @@ -914,46 +1136,45 @@ Element.extend.cache = { return value.apply(null, [this].concat($A(arguments))); } } -} +}; Element.Methods = { visible: function(element) { return $(element).style.display != 'none'; }, - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; }, - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } + hide: function(element) { + $(element).style.display = 'none'; + return element; }, - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } + show: function(element) { + $(element).style.display = ''; + return element; }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); + return element; }, update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); $(element).innerHTML = html.stripScripts(); setTimeout(function() {html.evalScripts()}, 10); + return element; }, replace: function(element, html) { element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); if (element.outerHTML) { element.outerHTML = html.stripScripts(); } else { @@ -963,11 +1184,106 @@ Element.Methods = { range.createContextualFragment(html.stripScripts()), element); } setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + return Selector.findElement($(element).ancestors(), expression, index); + }, + + down: function(element, expression, index) { + return Selector.findElement($(element).descendants(), expression, index); + }, + + previous: function(element, expression, index) { + return Selector.findElement($(element).previousSiblings(), expression, index); + }, + + next: function(element, expression, index) { + return Selector.findElement($(element).nextSiblings(), expression, index); + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (document.all && !window.opera) { + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + if(attribute) return attribute.nodeValue; + } + return element.getAttribute(name); }, getHeight: function(element) { - element = $(element); - return element.offsetHeight; + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; }, classNames: function(element) { @@ -976,34 +1292,60 @@ Element.Methods = { hasClassName: function(element, className) { if (!(element = $(element))) return; - return Element.classNames(element).include(className); + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; }, addClassName: function(element, className) { if (!(element = $(element))) return; - return Element.classNames(element).add(className); + Element.classNames(element).add(className); + return element; }, removeClassName: function(element, className) { if (!(element = $(element))) return; - return Element.classNames(element).remove(className); + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); }, // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); + element.removeChild(node); + node = nextNode; } + return element; }, empty: function(element) { return $(element).innerHTML.match(/^\s*$/); }, - childOf: function(element, ancestor) { + descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); while (element = element.parentNode) if (element == ancestor) return true; @@ -1012,38 +1354,69 @@ Element.Methods = { scrollTo: function(element) { element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; }, getStyle: function(element, style) { element = $(element); - var value = element.style[style.camelize()]; + if (['float','cssFloat'].include(style)) + style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); + style = style.camelize(); + var value = element.style[style]; if (!value) { if (document.defaultView && document.defaultView.getComputedStyle) { var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; + value = css ? css[style] : null; } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; + value = element.currentStyle[style]; } } + if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) + value = element['offset'+style.capitalize()] + 'px'; + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - + if(style == 'opacity') { + if(value) return parseFloat(value); + if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } return value == 'auto' ? null : value; }, setStyle: function(element, style) { element = $(element); - for (var name in style) - element.style[name.camelize()] = style[name]; + for (var name in style) { + var value = style[name]; + if(name == 'opacity') { + if (value == 1) { + value = (/Gecko/.test(navigator.userAgent) && + !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else if(value === '') { + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else { + if(value < 0.00001) value = 0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')'; + } + } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; + element.style[name.camelize()] = value; + } + return element; }, getDimensions: function(element) { element = $(element); - if (Element.getStyle(element, 'display') != 'none') + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, @@ -1051,12 +1424,13 @@ Element.Methods = { var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; + var originalDisplay = els.display; els.visibility = 'hidden'; els.position = 'absolute'; - els.display = ''; + els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; - els.display = 'none'; + els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; @@ -1075,6 +1449,7 @@ Element.Methods = { element.style.left = 0; } } + return element; }, undoPositioned: function(element) { @@ -1087,49 +1462,153 @@ Element.Methods = { element.style.bottom = element.style.right = ''; } + return element; }, makeClipping: function(element) { element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden'; + return element; }, undoClipping: function(element) { element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; } -} +}; + +Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); + +Element._attributeTranslations = {}; + +Element._attributeTranslations.names = { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" +}; + +Element._attributeTranslations.values = { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } +}; + +Object.extend(Element._attributeTranslations.values, { + href: Element._attributeTranslations.values._getAttr, + src: Element._attributeTranslations.values._getAttr, + disabled: Element._attributeTranslations.values._flag, + checked: Element._attributeTranslations.values._flag, + readonly: Element._attributeTranslations.values._flag, + multiple: Element._attributeTranslations.values._flag +}); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations; + attribute = t.names[attribute] || attribute; + return $(element).getAttributeNode(attribute).specified; + } +}; + +// IE is missing .innerHTML support for TABLE-related elements +if (document.all && !window.opera){ + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + depth = 4; + } + $A(element.childNodes).each(function(node){ + element.removeChild(node) + }); + depth.times(function(){ div = div.firstChild }); + + $A(div.childNodes).each( + function(node){ element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + } +}; Object.extend(Element, Element.Methods); var _nativeExtensions = false; -if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - var HTMLElement = {} - HTMLElement.prototype = document.createElement('div').__proto__; -} +if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { + var className = 'HTML' + tag + 'Element'; + if(window[className]) return; + var klass = window[className] = {}; + klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; + }); Element.addMethods = function(methods) { Object.extend(Element.Methods, methods || {}); - if(typeof HTMLElement != 'undefined') { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { var value = methods[property]; - if (typeof value == 'function') - HTMLElement.prototype[property] = cache.findOrStore(value); + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); } + } + + if (typeof HTMLElement != 'undefined') { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Form.Methods, HTMLFormElement.prototype); + [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { + copy(Form.Element.Methods, klass.prototype); + }); _nativeExtensions = true; } } -Element.addMethods(); - var Toggle = new Object(); Toggle.display = Element.toggle; @@ -1148,8 +1627,8 @@ Abstract.Insertion.prototype = { try { this.element.insertAdjacentHTML(this.adjacency, this.content); } catch (e) { - var tagName = this.element.tagName.toLowerCase(); - if (tagName == 'tbody' || tagName == 'tr') { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { this.insertContent(this.contentFromAnonymousTable()); } else { throw e; @@ -1248,20 +1727,18 @@ Element.ClassNames.prototype = { add: function(classNameToAdd) { if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); + this.set($A(this).concat(classNameToAdd).join(' ')); }, remove: function(classNameToRemove) { if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); + this.set($A(this).without(classNameToRemove).join(' ')); }, toString: function() { - return this.toArray().join(' '); + return $A(this).join(' '); } -} +}; Object.extend(Element.ClassNames.prototype, Enumerable); var Selector = Class.create(); @@ -1308,15 +1785,15 @@ Selector.prototype = { if (params.wildcard) conditions.push('true'); if (clause = params.id) - conditions.push('element.id == ' + clause.inspect()); + conditions.push('element.readAttribute("id") == ' + clause.inspect()); if (clause = params.tagName) conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); if ((clause = params.classNames).length > 0) - for (var i = 0; i < clause.length; i++) - conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); + for (var i = 0, length = clause.length; i < length; i++) + conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); if (clause = params.attributes) { clause.each(function(attribute) { - var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; + var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; var splitValueBy = function(delimiter) { return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; } @@ -1329,7 +1806,7 @@ Selector.prototype = { ); break; case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; case '': - case undefined: conditions.push(value + ' != null'); break; + case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; default: throw 'Unknown operator ' + attribute.operator + ' in selector'; } }); @@ -1340,6 +1817,7 @@ Selector.prototype = { compileMatcher: function() { this.match = new Function('element', 'if (!element.tagName) return false; \ + element = $(element); \ return ' + this.buildMatchExpression()); }, @@ -1354,7 +1832,7 @@ Selector.prototype = { scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); var results = []; - for (var i = 0; i < scope.length; i++) + for (var i = 0, length = scope.length; i < length; i++) if (this.match(element = scope[i])) results.push(Element.extend(element)); @@ -1366,206 +1844,241 @@ Selector.prototype = { } } -function $$() { - return $A(arguments).map(function(expression) { - return expression.strip().split(/\s+/).inject([null], function(results, expr) { - var selector = new Selector(expr); - return results.map(selector.findElements.bind(selector)).flatten(); - }); - }).flatten(); -} -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; +Object.extend(Selector, { + matchElements: function(elements, expression) { + var selector = new Selector(expression); + return elements.select(selector.match.bind(selector)).map(Element.extend); }, - focus: function(element) { - $(element).focus(); + findElement: function(elements, expression, index) { + if (typeof expression == 'number') index = expression, expression = false; + return Selector.matchElements(elements, expression || '*')[index || 0]; }, - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); + findChildElements: function(element, expressions) { + return expressions.map(function(expression) { + return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.inject([], function(elements, result) { + return elements.concat(selector.findElements(result || element)); + }); + }); + }).flatten(); } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); } - -/*--------------------------------------------------------------------------*/ - var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); + reset: function(form) { + $(form).reset(); + return form; + }, - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != undefined) { + if (result[key]) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); - return queryComponents.join('&'); + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); }, getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (var tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); - if (!typeName && !name) - return inputs; + if (!typeName && !name) return $A(inputs).map(Element.extend); - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) + if ((typeName && input.type != typeName) || (name && input.name != name)) continue; - matchingInputs.push(input); + matchingInputs.push(Element.extend(input)); } return matchingInputs; }, disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; + form = $(form); + form.getElements().each(function(element) { element.blur(); element.disabled = 'true'; - } + }); + return form; }, enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; + form = $(form); + form.getElements().each(function(element) { element.disabled = ''; - } + }); + return form; }, findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { + return $(form).getElements().find(function(element) { return element.type != 'hidden' && !element.disabled && ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); + form = $(form); + form.findFirstElement().activate(); + return form; } } +Object.extend(Form, Form.Methods); + +/*--------------------------------------------------------------------------*/ + Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { serialize: function(element) { element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } } + return ''; }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); + return Form.Element.Serializers[method](element); + }, - if (parameter) - return parameter[1]; + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select && ( element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type) ) ) + element.select(); + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.blur(); + element.disabled = false; + return element; } } +Object.extend(Form.Element, Form.Element.Methods); +var Field = Form.Element; +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + Form.Element.Serializers = { input: function(element) { switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); } - return false; }, inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; + return element.checked ? element.value : null; }, textarea: function(element) { - return [element.name, element.value]; + return element.value; }, select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? + return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); }, selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value || opt.text; - } - return [element.name, value]; + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; }, selectMany: function(element) { - var value = []; - for (var i = 0; i < element.length; i++) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { var opt = element.options[i]; - if (opt.selected) - value.push(opt.value || opt.text); + if (opt.selected) values.push(this.optionValue(opt)); } - return [element.name, value]; + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } } /*--------------------------------------------------------------------------*/ -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - Abstract.TimedObserver = function() {} Abstract.TimedObserver.prototype = { initialize: function(element, frequency, callback) { @@ -1583,7 +2096,9 @@ Abstract.TimedObserver.prototype = { onTimerEvent: function() { var value = this.getValue(); - if (this.lastValue != value) { + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { this.callback(this.element, value); this.lastValue = value; } @@ -1628,9 +2143,7 @@ Abstract.EventObserver.prototype = { }, registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); + Form.getElements(this.element).each(this.registerCallback.bind(this)); }, registerCallback: function(element) { @@ -1640,11 +2153,7 @@ Abstract.EventObserver.prototype = { case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': + default: Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } @@ -1679,6 +2188,10 @@ Object.extend(Event, { KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, element: function(event) { return event.target || event.srcElement; @@ -1734,7 +2247,7 @@ Object.extend(Event, { unloadCache: function() { if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { + for (var i = 0, length = Event.observers.length; i < length; i++) { Event.stopObserving.apply(this, Event.observers[i]); Event.observers[i][0] = null; } @@ -1742,7 +2255,7 @@ Object.extend(Event, { }, observe: function(element, name, observer, useCapture) { - var element = $(element); + element = $(element); useCapture = useCapture || false; if (name == 'keypress' && @@ -1750,11 +2263,11 @@ Object.extend(Event, { || element.attachEvent)) name = 'keydown'; - this._observeAndCache(element, name, observer, useCapture); + Event._observeAndCache(element, name, observer, useCapture); }, stopObserving: function(element, name, observer, useCapture) { - var element = $(element); + element = $(element); useCapture = useCapture || false; if (name == 'keypress' && @@ -1765,7 +2278,9 @@ Object.extend(Event, { if (element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); + try { + element.detachEvent('on' + name, observer); + } catch (e) {} } } }); @@ -1819,7 +2334,8 @@ var Position = { valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { - p = Element.getStyle(element, 'position'); + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') break; } } while (element); @@ -1875,17 +2391,6 @@ var Position = { element.offsetWidth; }, - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - page: function(forElement) { var valueT = 0, valueL = 0; @@ -1902,8 +2407,10 @@ var Position = { element = forElement; do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } } while (element = element.parentNode); return [valueL, valueT]; @@ -1964,10 +2471,10 @@ var Position = { element._originalHeight = element.style.height; element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; }, relativize: function(element) { @@ -2003,4 +2510,6 @@ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { return [valueL, valueT]; } -} \ No newline at end of file +} + +Element.addMethods(); \ No newline at end of file diff --git a/data/msfweb/public/javascripts/tooltip.js b/data/msfweb/public/javascripts/tooltip.js new file mode 100644 index 0000000000..4b9ac45a3f --- /dev/null +++ b/data/msfweb/public/javascripts/tooltip.js @@ -0,0 +1,239 @@ +// Singleton class TooltipWindow +// This class works with special className. The tooltip content could be in your HTML page as an hidden element or +// can be retreive by an AJAX call. +// +// To work, You just need to set two class name on elements that should show tooltips +// - One to say to TooltipManager that this element must have a tooltip ('tooltip' by default) +// - Another to indicate how to find the tooltip content +// It could be html_XXXX if tootltip content is somewhere hidden in your page, XXX must be DOM ID of this hidden element +// It could be ajax_XXXX if tootltip content must be find by an ajax request, XXX will be the string send as id parameter to your server. +// Check samples/tooltips/tooltip.html to see how it works +// +TooltipManager = { + options: {cssClassName: 'tooltip', delayOver: 200, delayOut: 1000, shiftX: 10, shiftY: 10, + className: 'alphacube', width: 200, height: null, + draggable: false, minimizable: false, maximizable: false, showEffect: Element.show, hideEffect: Element.hide}, + ajaxInfo: null, + elements: null, + showTimer: null, + hideTimer: null, + + // Init tooltip manager + // parameters: + // - cssClassName (string) : CSS class name where tooltip should be shown. + // - ajaxOptions (hash) : Ajax options for ajax tooltip. + // For examples {url: "/tooltip/get.php", options: {method: 'get'}} + // see Ajax.Request documentation for details + //- tooltipOptions (hash) : available keys + // - delayOver: int in ms (default 10) delay before showing tooltip + // - delayOut: int in ms (default 1000) delay before hidding tooltip + // - shiftX: int in pixels (default 10) left shift of the tooltip window + // - shiftY: int in pixels (default 10) top shift of the tooltip window + // and All window options like showEffect: Element.show, hideEffect: Element.hide to remove animation + // default: {className: 'alphacube', width: 200, height: null, draggable: false, minimizable: false, maximizable: false} + + init: function(cssClassName, ajaxInfo, tooltipOptions) { + TooltipManager.options = Object.extend(TooltipManager.options, tooltipOptions || {}); + + cssClassName = TooltipManager.options.cssClassName || "tooltip"; + TooltipManager.ajaxInfo = ajaxInfo; + TooltipManager.elements = $$("." + cssClassName); + TooltipManager.elements.each(function(element) { + element = $(element) + var info = TooltipManager._getInfo(element); + if (info.ajax) { + element.ajaxId = info.id; + element.ajaxInfo = ajaxInfo; + } + else { + element.tooltipElement = $(info.id); + } + element.observe("mouseover", TooltipManager._mouseOver); + element.observe("mouseout", TooltipManager._mouseOut); + }); + Windows.addObserver(this); + }, + + addHTML: function(element, tooltipElement) { + element = $(element); + tooltipElement = $(tooltipElement); + element.tooltipElement = tooltipElement; + + element.observe("mouseover", TooltipManager._mouseOver); + element.observe("mouseout", TooltipManager._mouseOut); + }, + + addAjax: function(element, ajaxInfo) { + element = $(element); + element.ajaxInfo = ajaxInfo; + element.observe("mouseover", TooltipManager._mouseOver); + element.observe("mouseout", TooltipManager._mouseOut); + }, + + addURL: function(element, url, width, height) { + element = $(element); + element.url = url; + element.frameWidth = width; + element.frameHeight = height; + element.observe("mouseover", TooltipManager._mouseOver); + element.observe("mouseout", TooltipManager._mouseOut); + }, + + close: function() { + if (TooltipManager.tooltipWindow) + TooltipManager.tooltipWindow.hide(); + }, + + preloadImages: function(path, images, extension) { + if (!extension) + extension = ".gif"; + + //preload images + $A(images).each(function(i) { + var image = new Image(); + image.src= path + "/" + i + extension; + }); + }, + + _showTooltip: function(element) { + if (this.element == element) + return; + // Get original element + while (element && (!element.tooltipElement && !element.ajaxInfo && !element.url)) + element = element.parentNode; + this.element = element; + + TooltipManager.showTimer = null; + if (TooltipManager.hideTimer) + clearTimeout(TooltipManager.hideTimer); + + var position = Position.cumulativeOffset(element); + var dimension = element.getDimensions(); + + if (! this.tooltipWindow) + this.tooltipWindow = new Window("__tooltip__", TooltipManager.options); + + this.tooltipWindow.hide(); + this.tooltipWindow.setLocation(position[1] + dimension.height + TooltipManager.options.shiftY, position[0] + TooltipManager.options.shiftX); + + Event.observe(this.tooltipWindow.element, "mouseover", function(event) {TooltipManager._tooltipOver(event, element)}); + Event.observe(this.tooltipWindow.element, "mouseout", function(event) {TooltipManager._tooltipOut(event, element)}); + + // Reset width/height for computation + this.tooltipWindow.height = TooltipManager.options.height; + this.tooltipWindow.width = TooltipManager.options.width; + + // Ajax content + if (element.ajaxInfo) { + var p = element.ajaxInfo.options.parameters; + var saveParam = p; + + // Set by CSS + if (element.ajaxId) { + if (p) + p += "&id=" + element.ajaxId; + else + p = "id=" + element.ajaxId; + } + element.ajaxInfo.options.parameters = p || ""; + this.tooltipWindow.setHTMLContent(""); + this.tooltipWindow.setAjaxContent(element.ajaxInfo.url, element.ajaxInfo.options); + element.ajaxInfo.options.parameters = saveParam; + } + // URL content + else if (element.url) { + this.tooltipWindow.setURL(element.url); + this.tooltipWindow.setSize(element.frameWidth, element.frameHeight); + + // Set tooltip size + this.tooltipWindow.height = element.frameHeight; + this.tooltipWindow.width = element.frameWidth; + } + // HTML content + else + this.tooltipWindow.setHTMLContent(element.tooltipElement.innerHTML); + + if (!element.ajaxInfo) + this.tooltipWindow.show(); + }, + + _hideTooltip: function(element) { + if (this.tooltipWindow) { + this.tooltipWindow.hide(); + this.element = null; + } + }, + + _mouseOver: function (event) { + var element = Event.element(event); + if (TooltipManager.showTimer) + clearTimeout(TooltipManager.showTimer); + + TooltipManager.showTimer = setTimeout(function() {TooltipManager._showTooltip(element)}, TooltipManager.options.delayOver) + }, + + _mouseOut: function(event) { + var element = Event.element(event); + if (TooltipManager.showTimer) { + clearTimeout(TooltipManager.showTimer); + TooltipManager.showTimer = null; + return; + } + if (TooltipManager.tooltipWindow) + TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut) + }, + + _tooltipOver: function(event, element) { + if (TooltipManager.hideTimer) { + clearTimeout(TooltipManager.hideTimer); + TooltipManager.hideTimer = null; + } + }, + + _tooltipOut: function(event, element) { + if (TooltipManager.hideTimer == null) + TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut) + }, + + _getInfo: function(element) { + // Find html_ for static content + var id = element.className.split(' ').detect(function(name) {return name.indexOf("html_") == 0}); + var ajax = true; + if (id) + ajax = false; + else + // Find ajax_ for ajax content + id = element.className.split(' ').detect(function(name) {return name.indexOf("ajax_") == 0}); + + id = id.substr(id.indexOf('_')+1, id.length) + return id ? {ajax: ajax, id: id} : null; + }, + + onBeforeShow: function(eventName, win) { + var top = parseFloat(win.getLocation().top); + var dim = win.element.getDimensions(); + + if (top + dim.height > TooltipManager._getScrollTop() + TooltipManager._getPageHeight()) { + var position = Position.cumulativeOffset(this.element); + + var top = position[1] - TooltipManager.options.shiftY - dim.height; + win.setLocation(top, position[0] + TooltipManager.options.shiftX) + } + }, + + _getPageWidth: function(){ + return window.innerWidth || document.documentElement.clientWidth || 0; + }, + + _getPageHeight: function(){ + return window.innerHeight || document.documentElement.clientHeight || 0; + }, + + _getScrollTop: function(){ + return document.documentElement.scrollTop || window.pageYOffset || 0; + }, + + _getScrollLeft: function(){ + return document.documentElement.scrollLeft || window.pageXOffset || 0; + } +}; diff --git a/data/msfweb/public/javascripts/window.js b/data/msfweb/public/javascripts/window.js index 4a8b6d62eb..20378171d4 100644 --- a/data/msfweb/public/javascripts/window.js +++ b/data/msfweb/public/javascripts/window.js @@ -19,21 +19,41 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -// VERSION 0.96.3 +// VERSION 1.1 var Window = Class.create(); +Window.keepMultiModalWindow = false; Window.prototype = { - // Constructor - // Available parameters : className, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, - // hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload - initialize: function(id) { - if ($(id)) - alert("Window " + id + " is already register is the DOM!!, be sure to use setDestroyOnClose()") - - this.hasEffectLib = String.prototype.parseColor != null; - this.options = Object.extend({ - className: "dialog", - minWidth: 100, + // Constructor + // Available parameters : className, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, recenterAuto, wiredDrag + // hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload + // add all callbacks (if you do not use an observer) + // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBeforeShow onShow onHide onMinimize onMaximize onClose + + initialize: function() { + var id; + var optionIndex = 0; + // For backward compatibility like win= new Window("id", {...}) instead of win = new Window({id: "id", ...}) + if (arguments.length > 0) { + if (typeof arguments[0] == "string" ) { + id = arguments[0]; + optionIndex = 1; + } + else + id = arguments[0] ? arguments[0].id : null; + } + + // Generate unique ID if not specified + if (!id) + id = "window_" + new Date().getTime(); + + if ($(id)) + alert("Window " + id + " is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor"); + + this.hasEffectLib = String.prototype.parseColor != null; + this.options = Object.extend({ + className: "dialog", + minWidth: 100, minHeight: 20, resizable: true, closable: true, @@ -46,513 +66,713 @@ Window.prototype = { showEffectOptions: {}, hideEffectOptions: {}, effectOptions: null, - parent: document.getElementsByTagName("body").item(0), + parent: document.body, title: " ", url: null, onload: Prototype.emptyFunction, width: 200, height: 300, - opacity: 1 - }, arguments[1] || {}); - - if (this.options.effectOptions) { - Object.extend(this.options.hideEffectOptions, this.options.effectOptions); - Object.extend(this.options.showEffectOptions, this.options.effectOptions); - } - if (this.options.hideEffect == Element.hide) - this.options.hideEffect = function(){ Element.hide(this.element); if (this.destroyOnClose) this.destroy(); }.bind(this) - - this.element = this._createWindow(id); - - // Bind event listener + opacity: 1, + recenterAuto: true, + wiredDrag: false, + closeCallback: null, + destroyOnClose: false + }, arguments[optionIndex] || {}); + + if (typeof this.options.top == "undefined" && typeof this.options.bottom == "undefined") + this.options.top = Math.random()*500; + if (typeof this.options.left == "undefined" && typeof this.options.right == "undefined") + this.options.left = Math.random()*500; + + if (this.options.effectOptions) { + Object.extend(this.options.hideEffectOptions, this.options.effectOptions); + Object.extend(this.options.showEffectOptions, this.options.effectOptions); + if (this.options.showEffect == Element.Appear) + this.options.showEffectOptions.to = this.options.opacity; + } + if (this.hasEffectLib) { + if (this.options.showEffect == Effect.Appear) + this.options.showEffectOptions.to = this.options.opacity; + + if (this.options.hideEffect == Effect.Fade) + this.options.hideEffectOptions.from = this.options.opacity; + } + if (this.options.hideEffect == Element.hide) + this.options.hideEffect = function(){ Element.hide(this.element); if (this.options.destroyOnClose) this.destroy(); }.bind(this) + + if (this.options.parent != document.body) + this.options.parent = $(this.options.parent); + + this.element = this._createWindow(id); + + // Bind event listener this.eventMouseDown = this._initDrag.bindAsEventListener(this); - this.eventMouseUp = this._endDrag.bindAsEventListener(this); - this.eventMouseMove = this._updateDrag.bindAsEventListener(this); - this.eventKeyPress = this._keyPress.bindAsEventListener(this); - this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener(this); + this.eventMouseUp = this._endDrag.bindAsEventListener(this); + this.eventMouseMove = this._updateDrag.bindAsEventListener(this); + this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener(this); this.eventMouseDownContent = this.toFront.bindAsEventListener(this); this.eventResize = this._recenter.bindAsEventListener(this); - this.topbar = $(this.element.id + "_top"); - this.bottombar = $(this.element.id + "_bottom"); + this.topbar = $(this.element.id + "_top"); + this.bottombar = $(this.element.id + "_bottom"); this.content = $(this.element.id + "_content"); - Event.observe(this.topbar, "mousedown", this.eventMouseDown); - Event.observe(this.bottombar, "mousedown", this.eventMouseDown); - Event.observe(this.content, "mousedown", this.eventMouseDownContent); - Event.observe(window, "load", this.eventOnLoad); - Event.observe(window, "resize", this.eventResize); - Event.observe(window, "scroll", this.eventResize); - - if (this.options.draggable) { - this.bottombar.addClassName("bottom_draggable"); - this.topbar.addClassName("top_draggable"); - } + Event.observe(this.topbar, "mousedown", this.eventMouseDown); + Event.observe(this.bottombar, "mousedown", this.eventMouseDown); + Event.observe(this.content, "mousedown", this.eventMouseDownContent); + Event.observe(window, "load", this.eventOnLoad); + Event.observe(window, "resize", this.eventResize); + Event.observe(window, "scroll", this.eventResize); - if (this.options.resizable) { - this.sizer = $(this.element.id + "_sizer"); - Event.observe(this.sizer, "mousedown", this.eventMouseDown); - } + if (this.options.draggable) { + var that = this; + [this.topbar, this.topbar.up().previous(), this.topbar.up().next()].each(function(element) { + element.observe("mousedown", that.eventMouseDown); + element.addClassName("top_draggable"); + }); + [this.bottombar.up(), this.bottombar.up().previous(), this.bottombar.up().next()].each(function(element) { + element.observe("mousedown", that.eventMouseDown); + element.addClassName("bottom_draggable"); + }); + + } + + if (this.options.resizable) { + this.sizer = $(this.element.id + "_sizer"); + Event.observe(this.sizer, "mousedown", this.eventMouseDown); + } this.useLeft = null; this.useTop = null; - if (arguments[1].left != null) { - this.element.setStyle({left: parseFloat(arguments[1].left) + 'px'}); - this.useLeft = true; - } - if (arguments[1].right != null) { - this.element.setStyle({right: parseFloat(arguments[1].right) + 'px'}); - this.useLeft = false; - } - if (this.useLeft == null) { - this.element.setStyle({left: "0px"}); - this.useLeft = true; + if (typeof this.options.left != "undefined") { + this.element.setStyle({left: parseFloat(this.options.left) + 'px'}); + this.useLeft = true; + } + else { + this.element.setStyle({right: parseFloat(this.options.right) + 'px'}); + this.useLeft = false; } - if (arguments[1].top != null) { - this.element.setStyle({top: parseFloat(arguments[1].top) + 'px'}); - this.useTop = true; - } - if (arguments[1].bottom != null) { - this.element.setStyle({bottom: parseFloat(arguments[1].bottom) + 'px'}); - this.useTop = false; - } - if (this.useTop == null) { - this.element.setStyle({top: "0px"}); - this.useTop = true; + if (typeof this.options.top != "undefined") { + this.element.setStyle({top: parseFloat(this.options.top) + 'px'}); + this.useTop = true; } - + else { + this.element.setStyle({bottom: parseFloat(this.options.bottom) + 'px'}); + this.useTop = false; + } + this.storedLocation = null; - this.setOpacity(this.options.opacity); - if (this.options.zIndex) - this.setZIndex(this.options.zIndex) + this.setOpacity(this.options.opacity); + if (this.options.zIndex) + this.setZIndex(this.options.zIndex) - this.destroyOnClose = false; + if (this.options.destroyOnClose) + this.setDestroyOnClose(true); this._getWindowBorderSize(); this.width = this.options.width; this.height = this.options.height; + this.visible = false; + + this.constraint = false; + this.constraintPad = {top: 0, left:0, bottom:0, right:0}; if (this.width && this.height) - this.setSize(this.options.width, this.options.height); - this.setTitle(this.options.title) - Windows.register(this); + this.setSize(this.options.width, this.options.height); + this.setTitle(this.options.title) + Windows.register(this); }, - // Destructor - destroy: function() { - Windows.notify("onDestroy", this); - Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown); - Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown); - Event.stopObserving(this.content, "mousedown", this.eventMouseDownContent); + // Destructor + destroy: function() { + this._notify("onDestroy"); + Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown); + Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown); + Event.stopObserving(this.content, "mousedown", this.eventMouseDownContent); - Event.stopObserving(window, "load", this.eventOnLoad); - Event.stopObserving(window, "resize", this.eventResize); - Event.stopObserving(window, "scroll", this.eventResize); - - Event.stopObserving(this.content, "load", this.options.onload); + Event.stopObserving(window, "load", this.eventOnLoad); + Event.stopObserving(window, "resize", this.eventResize); + Event.stopObserving(window, "scroll", this.eventResize); + + Event.stopObserving(this.content, "load", this.options.onload); - if (this.sizer) - Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown); + if (this._oldParent) { + var content = this.getContent(); + var originalContent = null; + for(var i = 0; i < content.childNodes.length; i++) { + originalContent = content.childNodes[i]; + if (originalContent.nodeType == 1) + break; + originalContent = null; + } + if (originalContent) + this._oldParent.appendChild(originalContent); + this._oldParent = null; + } - if (this.options.url) - this.content.src = null + if (this.sizer) + Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown); - if(this.iefix) - Element.remove(this.iefix); + if (this.options.url) + this.content.src = null + + if(this.iefix) + Element.remove(this.iefix); Element.remove(this.element); - Windows.unregister(this); - }, - - // Sets window deleagte, should have functions: "canClose(window)" - setDelegate: function(delegate) { - this.delegate = delegate - }, - - // Gets current window delegate - getDelegate: function() { - return this.delegate; - }, - - // Gets window content - getContent: function () { - return this.content; - }, - - // Sets the content with an element id - setContent: function(id, autoresize, autoposition) { - var d = null; - var p = null; + Windows.unregister(this); + }, + + // Sets close callback, if it sets, it should return true to be able to close the window. + setCloseCallback: function(callback) { + this.options.closeCallback = callback; + }, + + // Gets window content + getContent: function () { + return this.content; + }, + + // Sets the content with an element id + setContent: function(id, autoresize, autoposition) { + var element = $(id); + if (null == element) throw "Unable to find element '" + id + "' in DOM"; + this._oldParent = element.parentNode; - if (autoresize) - d = Element.getDimensions(id); - if (autoposition) - p = Position.cumulativeOffset($(id)); + var d = null; + var p = null; - var content = this.getContent() - content.appendChild($(id)); - $(id).show(); - if (autoresize) - this.setSize(d.width, d.height); - if (autoposition) - this.setLocation(p[1] - this.heightN, p[0] - this.widthW); - }, - - setAjaxContent: function(url, options, showCentered, showModal) { - this.showFunction = showCentered ? "showCenter" : "show"; - this.showModal = showModal || false; - - if (options == null) - options = {} - this.onComplete = options.onComplete; - options.onComplete = this._setAjaxContent.bind(this); - - new Ajax.Request(url, options); - }, - - _setAjaxContent: function(originalRequest) { - this.getContent().innerHTML = originalRequest.responseText; - if (this.onComplete) - this.onComplete(originalRequest); - this[this.showFunction](this.showModal) - }, - - // Stores position/size in a cookie, by default named with window id - setCookie: function(name, expires, path, domain, secure) { - name = name || this.element.id; - this.cookie = [name, expires, path, domain, secure]; - - // Get cookie - var value = WindowUtilities.getCookie(name) - // If exists - if (value) { - var values = value.split(','); - var x = values[0].split(':'); - var y = values[1].split(':'); + if (autoresize) + d = Element.getDimensions(element); + if (autoposition) + p = Position.cumulativeOffset(element); - var w = parseFloat(values[2]), h = parseFloat(values[3]); - var mini = values[4]; - var maxi = values[5]; - - this.setSize(w, h); - if (mini == "true") - this.doMinimize = true; // Minimize will be done at onload window event - else if (maxi == "true") - this.doMaximize = true; // Maximize will be done at onload window event - - this.useLeft = x[0] == "l"; - this.useTop = y[0] == "t"; - - this.element.setStyle(this.useLeft ? {left: x[1]} : {right: x[1]}); - this.element.setStyle(this.useTop ? {top: y[1]} : {bottom: y[1]}); - } - }, - - // Gets window ID - getId: function() { - return this.element.id; - }, - - // Detroys itself when closing - setDestroyOnClose: function() { - var destroyFunc = this.destroy.bind(this); - if (this.options.hideEffectOptions.afterFinish) { - var func = this.options.hideEffectOptions.afterFinish; - this.options.hideEffectOptions.afterFinish = function() {func();destroyFunc() } + var content = this.getContent(); + // Clear HTML (and even iframe) + this.setHTMLContent(""); + content = this.getContent(); + + content.appendChild(element); + element.show(); + if (autoresize) + this.setSize(d.width, d.height); + if (autoposition) + this.setLocation(p[1] - this.heightN, p[0] - this.widthW); + }, + + setHTMLContent: function(html) { + // It was an url (iframe), recreate a div content instead of iframe content + if (this.options.url) { + this.content.src = null; + this.options.url = null; + + var content ="
"; + $(this.getId() +"_table_content").innerHTML = content; + + this.content = $(this.element.id + "_content"); } - else - this.options.hideEffectOptions.afterFinish = function() {destroyFunc() } - this.destroyOnClose = true; - }, - - // initDrag event - _initDrag: function(event) { + + this.getContent().innerHTML = html; + }, + + setAjaxContent: function(url, options, showCentered, showModal) { + this.showFunction = showCentered ? "showCenter" : "show"; + this.showModal = showModal || false; + + options = options || {}; + + // Clear HTML (and even iframe) + this.setHTMLContent(""); + + this.onComplete = options.onComplete; + if (! this._onCompleteHandler) + this._onCompleteHandler = this._setAjaxContent.bind(this); + options.onComplete = this._onCompleteHandler; + + new Ajax.Request(url, options); + options.onComplete = this.onComplete; + }, + + _setAjaxContent: function(originalRequest) { + Element.update(this.getContent(), originalRequest.responseText); + if (this.onComplete) + this.onComplete(originalRequest); + this.onComplete = null; + this[this.showFunction](this.showModal) + }, + + setURL: function(url) { + // Not an url content, change div to iframe + if (!this.options.url) { + this.options.url = url; + var content= ""; + $(this.getId() +"_table_content").innerHTML = content; + + this.content = $(this.element.id + "_content"); + } else { + this.options.url = url; + $(this.element.getAttribute('id') + '_content').src = url; + } + }, + + getURL: function() { + return this.options.url ? this.options.url : null; + }, + + refresh: function() { + if (this.options.url) + $(this.element.getAttribute('id') + '_content').src = this.options.url; + }, + + // Stores position/size in a cookie, by default named with window id + setCookie: function(name, expires, path, domain, secure) { + name = name || this.element.id; + this.cookie = [name, expires, path, domain, secure]; + + // Get cookie + var value = WindowUtilities.getCookie(name) + // If exists + if (value) { + var values = value.split(','); + var x = values[0].split(':'); + var y = values[1].split(':'); + + var w = parseFloat(values[2]), h = parseFloat(values[3]); + var mini = values[4]; + var maxi = values[5]; + + this.setSize(w, h); + if (mini == "true") + this.doMinimize = true; // Minimize will be done at onload window event + else if (maxi == "true") + this.doMaximize = true; // Maximize will be done at onload window event + + this.useLeft = x[0] == "l"; + this.useTop = y[0] == "t"; + + this.element.setStyle(this.useLeft ? {left: x[1]} : {right: x[1]}); + this.element.setStyle(this.useTop ? {top: y[1]} : {bottom: y[1]}); + } + }, + + // Gets window ID + getId: function() { + return this.element.id; + }, + + // Detroys itself when closing + setDestroyOnClose: function() { + this.options.destroyOnClose = true; + }, + + setConstraint: function(bool, padding) { + this.constraint = bool; + this.constraintPad = Object.extend(this.constraintPad, padding || {}); + // Reset location to apply constraint + if (this.useTop && this.useLeft) + this.setLocation(parseFloat(this.element.style.top), parseFloat(this.element.style.left)); + }, + + // initDrag event + + _initDrag: function(event) { + // No resize on minimized window + if (Event.element(event) == this.sizer && this.isMinimized()) + return; + + // No move on maximzed window + if (Event.element(event) != this.sizer && this.isMaximized()) + return; + + if (isIE && this.heightN == 0) + this._getWindowBorderSize(); + // Get pointer X,Y - this.pointer = [Event.pointerX(event), Event.pointerY(event)]; - + this.pointer = [Event.pointerX(event), Event.pointerY(event)]; + + if (this.options.wiredDrag) + this.currentDrag = this._createWiredElement(); + else + this.currentDrag = this.element; + // Resize - if (Event.element(event) == this.sizer) { - this.doResize = true; - this.widthOrg = this.width; - this.heightOrg = this.height; - this.bottomOrg = parseFloat(this.element.getStyle('bottom')); - this.rightOrg = parseFloat(this.element.getStyle('right')); - Windows.notify("onStartResize", this); - } + if (Event.element(event) == this.sizer) { + this.doResize = true; + this.widthOrg = this.width; + this.heightOrg = this.height; + this.bottomOrg = parseFloat(this.element.getStyle('bottom')); + this.rightOrg = parseFloat(this.element.getStyle('right')); + this._notify("onStartResize"); + } else { - this.doResize = false; + this.doResize = false; - // Check if click on close button, - var closeButton = $(this.getId() + '_close'); - if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) - return; + // Check if click on close button, + var closeButton = $(this.getId() + '_close'); + if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) { + this.currentDrag = null; + return; + } - this.toFront(); + this.toFront(); - if (! this.options.draggable) - return; - Windows.notify("onStartMove", this); - } - // Register global event to capture mouseUp and mouseMove - Event.observe(document, "mouseup", this.eventMouseUp, false); + if (! this.options.draggable) + return; + this._notify("onStartMove"); + } + // Register global event to capture mouseUp and mouseMove + Event.observe(document, "mouseup", this.eventMouseUp, false); Event.observe(document, "mousemove", this.eventMouseMove, false); - - // Add an invisible div to keep catching mouse event over iframes - WindowUtilities.disableScreen('__invisible__', '__invisible__'); + + // Add an invisible div to keep catching mouse event over iframes + WindowUtilities.disableScreen('__invisible__', '__invisible__'); // Stop selection while dragging document.body.ondrag = function () { return false; }; document.body.onselectstart = function () { return false; }; + this.currentDrag.show(); Event.stop(event); }, // updateDrag event - _updateDrag: function(event) { - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var dx = pointer[0] - this.pointer[0]; - var dy = pointer[1] - this.pointer[1]; - - // Resize case, update width/height - if (this.doResize) { - this.setSize(this.widthOrg + dx , this.heightOrg + dy); - + _updateDrag: function(event) { + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + var dx = pointer[0] - this.pointer[0]; + var dy = pointer[1] - this.pointer[1]; + + // Resize case, update width/height + if (this.doResize) { + var w = this.widthOrg + dx; + var h = this.heightOrg + dy; + dx = this.width - this.widthOrg dy = this.height - this.heightOrg - - // Check if it's a right position, update it to keep upper-left corner at the same position - if (! this.useLeft) - this.element.setStyle({right: (this.rightOrg -dx) + 'px'}); - // Check if it's a bottom position, update it to keep upper-left corner at the same position - if (! this.useTop) - this.element.setStyle({bottom: (this.bottomOrg -dy) + 'px'}); - } - // Move case, update top/left - else { - this.pointer = pointer; - - if (this.useLeft) - this.element.setStyle({left: parseFloat(this.element.getStyle('left')) + dx + 'px'}); - else - this.element.setStyle({right: parseFloat(this.element.getStyle('right')) - dx + 'px'}); - - if (this.useTop) - this.element.setStyle({top: parseFloat(this.element.getStyle('top')) + dy + 'px'}); - else - this.element.setStyle({bottom: parseFloat(this.element.getStyle('bottom')) - dy + 'px'}); - } - if (this.iefix) - this._fixIEOverlapping(); - - this._removeStoreLocation(); + + // Check if it's a right position, update it to keep upper-left corner at the same position + if (this.useLeft) + w = this._updateWidthConstraint(w) + else + this.currentDrag.setStyle({right: (this.rightOrg -dx) + 'px'}); + // Check if it's a bottom position, update it to keep upper-left corner at the same position + if (this.useTop) + h = this._updateHeightConstraint(h) + else + this.currentDrag.setStyle({bottom: (this.bottomOrg -dy) + 'px'}); + + this.setSize(w , h); + this._notify("onResize"); + } + // Move case, update top/left + else { + this.pointer = pointer; + + if (this.useLeft) { + var left = parseFloat(this.currentDrag.getStyle('left')) + dx; + var newLeft = this._updateLeftConstraint(left); + // Keep mouse pointer correct + this.pointer[0] += newLeft-left; + this.currentDrag.setStyle({left: newLeft + 'px'}); + } + else + this.currentDrag.setStyle({right: parseFloat(this.currentDrag.getStyle('right')) - dx + 'px'}); + + if (this.useTop) { + var top = parseFloat(this.currentDrag.getStyle('top')) + dy; + var newTop = this._updateTopConstraint(top); + // Keep mouse pointer correct + this.pointer[1] += newTop - top; + this.currentDrag.setStyle({top: newTop + 'px'}); + } + else + this.currentDrag.setStyle({bottom: parseFloat(this.currentDrag.getStyle('bottom')) - dy + 'px'}); + + this._notify("onMove"); + } + if (this.iefix) + this._fixIEOverlapping(); + + this._removeStoreLocation(); Event.stop(event); - }, + }, - // endDrag callback - _endDrag: function(event) { - // Remove temporary div over iframes - WindowUtilities.enableScreen('__invisible__'); - - if (this.doResize) - Windows.notify("onEndResize", this); - else - Windows.notify("onEndMove", this); - - // Release event observing - Event.stopObserving(document, "mouseup", this.eventMouseUp,false); + // endDrag callback + _endDrag: function(event) { + // Remove temporary div over iframes + WindowUtilities.enableScreen('__invisible__'); + + if (this.doResize) + this._notify("onEndResize"); + else + this._notify("onEndMove"); + + // Release event observing + Event.stopObserving(document, "mouseup", this.eventMouseUp,false); Event.stopObserving(document, "mousemove", this.eventMouseMove, false); - // Store new location/size if need be - this._saveCookie() - Event.stop(event); + this._hideWiredElement(); + + // Store new location/size if need be + this._saveCookie() + // Restore selection document.body.ondrag = null; document.body.onselectstart = null; }, - _keyPress: function(event) { - //Dialog.cancelCallback(); - }, - - // Creates HTML window code - _createWindow: function(id) { - var className = this.options.className; - var win = document.createElement("div"); - win.setAttribute('id', id); - win.className = "dialog"; + _updateLeftConstraint: function(left) { + if (this.constraint && this.useLeft && this.useTop) { + var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width; - var content; - if (this.options.url) - content= ""; - else - content ="
"; - - var closeDiv = this.options.closable ? "
" : ""; - var minDiv = this.options.minimizable ? "
" : ""; - var maxDiv = this.options.maximizable ? "
" : ""; - var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'"; - + if (left < this.constraintPad.left) + left = this.constraintPad.left; + if (left + this.width + this.widthE + this.widthW > width - this.constraintPad.right) + left = width - this.constraintPad.right - this.width - this.widthE - this.widthW; + } + return left; + }, + + _updateTopConstraint: function(top) { + if (this.constraint && this.useLeft && this.useTop) { + var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height; + + var h = this.height + this.heightN + this.heightS; + + if (top < this.constraintPad.top) + top = this.constraintPad.top; + if (top + h > height - this.constraintPad.bottom) + top = height - this.constraintPad.bottom - h; + } + return top; + }, + + _updateWidthConstraint: function(w) { + if (this.constraint && this.useLeft && this.useTop) { + var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width; + var left = parseFloat(this.element.getStyle("left")); + + if (left + w + this.widthE + this.widthW > width - this.constraintPad.right) + w = width - this.constraintPad.right - left - this.widthE - this.widthW; + } + return w; + }, + + _updateHeightConstraint: function(h) { + if (this.constraint && this.useLeft && this.useTop) { + var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height; + var top = parseFloat(this.element.getStyle("top")); + + if (top + h + this.heightN + this.heightS > height - this.constraintPad.bottom) + h = height - this.constraintPad.bottom - top - this.heightN - this.heightS; + } + return h; + }, + + + // Creates HTML window code + _createWindow: function(id) { + var className = this.options.className; + var win = document.createElement("div"); + win.setAttribute('id', id); + win.className = "dialog"; + + var content; + if (this.options.url) + content= ""; + else + content ="
"; + + var closeDiv = this.options.closable ? "
" : ""; + var minDiv = this.options.minimizable ? "
" : ""; + var maxDiv = this.options.maximizable ? "
" : ""; + var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'"; + var blank = "../themes/default/blank.gif"; + win.innerHTML = closeDiv + minDiv + maxDiv + "\ \ \ - \ + \ \ - \ + \ \
 
"+ this.options.title +"
 
\ \ \ \ - \ + \ \ \
"+ content +"" + content + "
\ \ \ - \ - \ - \ + \ + \ + \ \
 
 
 
\ "; + Element.hide(win); + this.options.parent.insertBefore(win, this.options.parent.firstChild); + Event.observe($(id + "_content"), "load", this.options.onload); + return win; + }, + + + changeClassName: function(newClassName) { + var className = this.options.className; + var id = this.getId(); + var win = this; + $A(["_close","_minimize","_maximize","_sizer", "_content"]).each(function(value) { win._toggleClassName($(id + value), className + value, newClassName + value) }); + $$("#" + id + " td").each(function(td) {td.className = td.className.sub(className,newClassName) }); + this.options.className = newClassName; + }, + + _toggleClassName: function(element, oldClassName, newClassName) { + if (element) { + element.removeClassName(oldClassName); + element.addClassName(newClassName); + } + }, + + // Sets window location + setLocation: function(top, left) { + top = this._updateTopConstraint(top); + left = this._updateLeftConstraint(left); + + this.element.setStyle({top: top + 'px'}); + this.element.setStyle({left: left + 'px'}); + + this.useLeft = true; + this.useTop = true; + }, - Element.hide(win); - this.options.parent.insertBefore(win, this.options.parent.firstChild); - Event.observe($(id + "_content"), "load", this.options.onload); - return win; - }, - - // Sets window location - setLocation: function(top, left) { - if (top < 0) - top = 0; - if (left < 0) - left= 0 - this.element.setStyle({top: top + 'px'}); - this.element.setStyle({left: left + 'px'}); - this.useLeft = true; - this.useTop = true; - }, - - getLocation: function() { - var location = {}; - if (this.useTop) - location = Object.extend(location, {top: this.element.getStyle("top")}); + getLocation: function() { + var location = {}; + if (this.useTop) + location = Object.extend(location, {top: this.element.getStyle("top")}); else location = Object.extend(location, {bottom: this.element.getStyle("bottom")}); - if (this.useLeft) - location = Object.extend(location, {left: this.element.getStyle("left")}); + if (this.useLeft) + location = Object.extend(location, {left: this.element.getStyle("left")}); else location = Object.extend(location, {right: this.element.getStyle("right")}); - - return location; - }, - - // Gets window size - getSize: function() { - return {width: this.width, height: this.height}; - }, - - // Sets window size - setSize: function(width, height) { - width = parseFloat(width); - height = parseFloat(height); - - // Check min and max size - if (width < this.options.minWidth) - width = this.options.minWidth; + + return location; + }, + + // Gets window size + getSize: function() { + return {width: this.width, height: this.height}; + }, + + // Sets window size + setSize: function(width, height) { + width = parseFloat(width); + height = parseFloat(height); + + // Check min and max size + if (width < this.options.minWidth) + width = this.options.minWidth; - if (height < this.options.minHeight) - height = this.options.minHeight; - - if (this.options. maxHeight && height > this.options. maxHeight) - height = this.options. maxHeight; + if (height < this.options.minHeight) + height = this.options.minHeight; + + if (this.options. maxHeight && height > this.options. maxHeight) + height = this.options. maxHeight; - if (this.options. maxWidth && width > this.options. maxWidth) - width = this.options. maxWidth; + if (this.options. maxWidth && width > this.options. maxWidth) + width = this.options. maxWidth; - this.width = width; - this.height = height; - this.element.setStyle({width: width + this.widthW + this.widthE + "px"}) - this.element.setStyle({height: height + this.heightN + this.heightS + "px"}) + this.width = width; + this.height = height; + var e = this.currentDrag ? this.currentDrag : this.element; + e.setStyle({width: width + this.widthW + this.widthE + "px"}) + e.setStyle({height: height + this.heightN + this.heightS + "px"}) - // Update content height - var content = $(this.element.id + '_content') - content.setStyle({height: height + 'px'}); - content.setStyle({width: width + 'px'}); - }, - - updateHeight: function() { + // Update content height + if (!this.currentDrag || this.currentDrag == this.element) { + var content = $(this.element.id + '_content'); + content.setStyle({height: height + 'px'}); + content.setStyle({width: width + 'px'}); + } + }, + + updateHeight: function() { this.setSize(this.width, this.content.scrollHeight) - }, - - updateWidth: function() { + }, + + updateWidth: function() { this.setSize(this.content.scrollWidth, this.height) - }, - - // Brings window to front - toFront: function() { - if (Windows.focusedWindow == this) - return; + }, + + // Brings window to front + toFront: function() { + if (Windows.focusedWindow == this) + return; this.setZIndex(Windows.maxZIndex + 20); - Windows.notify("onFocus", this); - }, - - // Displays window modal state or not - show: function(modal) { - if (modal) { - WindowUtilities.disableScreen(this.options.className, 'overlay_modal', this.getId()); - this.modal = true; - this.setZIndex(Windows.maxZIndex + 20); - Windows.unsetOverflow(this); - Event.observe(document, "keypress", this.eventKeyPress); - } - - // To restore overflow if need be - if (this.oldStyle) - this.getContent().setStyle({overflow: this.oldStyle}); - - if (! this.width || !this.height) { - var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0) - if (this.height) - this.width = size + 5 - else - this.height = size + 5 - } + this._notify("onFocus"); + if (this.iefix) + this._fixIEOverlapping(); + }, + + // Displays window modal state or not + show: function(modal) { + if (modal) { + Windows.addModalWindow(this); + + this.modal = true; + this.setZIndex(Windows.maxZIndex + 20); + Windows.unsetOverflow(this); + } + + // To restore overflow if need be + if (this.oldStyle) + this.getContent().setStyle({overflow: this.oldStyle}); + + if (! this.width || !this.height) { + var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0, this.options.className) + if (this.height) + this.width = size + 5 + else + this.height = size + 5 + } - this.setSize(this.width, this.height); - if (this.centered) - this._center(this.centerTop, this.centerLeft); - - if (this.options.showEffect != Element.show && this.options.showEffectOptions ) - this.options.showEffect(this.element, this.options.showEffectOptions); - else - this.options.showEffect(this.element); - + this.setSize(this.width, this.height); + if (this.centered) + this._center(this.centerTop, this.centerLeft); + + this._notify("onBeforeShow"); + if (this.options.showEffect != Element.show && this.options.showEffectOptions ) + this.options.showEffect(this.element, this.options.showEffectOptions); + else + this.options.showEffect(this.element); + this._checkIEOverlapping(); - Windows.notify("onShow", this); - }, - - // Displays window modal state or not at the center of the page - showCenter: function(modal, top, left) { + this.visible = true; + WindowUtilities.focusedWindow = this + this._notify("onShow"); + }, + + // Displays window modal state or not at the center of the page + showCenter: function(modal, top, left) { this.centered = true; this.centerTop = top; this.centerLeft = left; - this.show(modal); - }, - - isVisible: function() { - return this.element.visible(); - }, - - _center: function(top, left) { - var windowScroll = WindowUtilities.getWindowScroll(); - var pageSize = WindowUtilities.getPageSize(); + this.show(modal); + }, + + isVisible: function() { + return this.visible; + }, + + _center: function(top, left) { + var windowScroll = WindowUtilities.getWindowScroll(); + var pageSize = WindowUtilities.getPageSize(); if (!top) top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2; @@ -564,94 +784,152 @@ Window.prototype = { this.setLocation(top, left); this.toFront(); - }, - - _recenter: function(event) { - if (this.modal) { - var pageSize = WindowUtilities.getPageSize(); - // set height of Overlay to take up whole page and show - if ($('overlay_modal')) { - $('overlay_modal').style.height = (pageSize.pageHeight + 'px'); - $('overlay_modal').style.width = (pageSize.pageWidth + 'px'); - } - if (this.centered) - this._center(this.centerTop, this.centerLeft); - } - }, - - // Hides window - hide: function() { - if (this.modal) { - WindowUtilities.enableScreen(); - Windows.resetOverflow(); - Event.stopObserving(document, "keypress", this.eventKeyPress); - } - // To avoid bug on scrolling bar - this.oldStyle = this.getContent().getStyle('overflow') || "auto" - this.getContent().setStyle({overflow: "hidden"}); + }, + + _recenter: function(event) { + if (this.modal && this.centered) { + var pageSize = WindowUtilities.getPageSize(); + // Check for this stupid IE that sends dumb events + if (this.pageSize && this.pageSize.pageWidth == pageSize.windowWidth && this.pageSize.pageHeight == pageSize.windowHeight) + return; + + this.pageSize = pageSize; + // set height of Overlay to take up whole page and show + if ($('overlay_modal')) { + $('overlay_modal').style.height = (pageSize.pageHeight + 'px'); + $('overlay_modal').style.width = (pageSize.pageWidth + 'px'); + } + if (this.options.recenterAuto) + this._center(this.centerTop, this.centerLeft); + } + }, + + // Hides window + hide: function() { + this.visible = false; + if (this.modal) { + Windows.removeModalWindow(this); + Windows.resetOverflow(); + } + // To avoid bug on scrolling bar + this.oldStyle = this.getContent().getStyle('overflow') || "auto" + this.getContent().setStyle({overflow: "hidden"}); - this.options.hideEffect(this.element, this.options.hideEffectOptions); + this.options.hideEffect(this.element, this.options.hideEffectOptions); - if(this.iefix) - this.iefix.hide(); - Windows.notify("onHide", this); - }, + if(this.iefix) + this.iefix.hide(); + if (!this.doNotNotifyHide) + this._notify("onHide"); + }, + + close: function() { + // Asks closeCallback if exists + if (this.visible) { + if (this.options.closeCallback && ! this.options.closeCallback(this)) + return; + + if (this.options.destroyOnClose) { + var destroyFunc = this.destroy.bind(this); + if (this.options.hideEffectOptions.afterFinish) { + var func = this.options.hideEffectOptions.afterFinish; + this.options.hideEffectOptions.afterFinish = function() {func();destroyFunc() } + } + else + this.options.hideEffectOptions.afterFinish = function() {destroyFunc() } + } + Windows.updateFocusedWindow(); + + this.doNotNotifyHide = true; + this.hide(); + this.doNotNotifyHide = false; + this._notify("onClose"); + } + }, + minimize: function() { var r2 = $(this.getId() + "_row2"); var dh = r2.getDimensions().height; if (r2.visible()) { - var h = this.element.getHeight() - dh + var h = this.element.getHeight() - dh; + this.height -= dh; + r2.hide() - this.element.setStyle({height: h + "px"}) - if (! this.useTop) { - var bottom = parseFloat(this.element.getStyle('bottom')); - this.element.setStyle({bottom: (bottom + dh) + 'px'}); - } - } - else { - var h = this.element.getHeight() + dh; this.element.setStyle({height: h + "px"}) - if (! this.useTop) { - var bottom = parseFloat(this.element.getStyle('bottom')); - this.element.setStyle({bottom: (bottom - dh) + 'px'}); - } + if (! this.useTop) { + var bottom = parseFloat(this.element.getStyle('bottom')); + this.element.setStyle({bottom: (bottom + dh) + 'px'}); + } + } + else { + var h = this.element.getHeight() + dh; + this.height += dh; + + this.element.setStyle({height: h + "px"}) + if (! this.useTop) { + var bottom = parseFloat(this.element.getStyle('bottom')); + this.element.setStyle({bottom: (bottom - dh) + 'px'}); + } r2.show(); - this.toFront(); } - Windows.notify("onMinimize", this); - + this._notify("onMinimize"); + // Store new location/size if need be - this._saveCookie() + this._saveCookie() }, maximize: function() { + if (this.isMinimized()) + return; + + if (isIE && this.heightN == 0) + this._getWindowBorderSize(); + if (this.storedLocation != null) { this._restoreLocation(); if(this.iefix) - this.iefix.hide(); + this.iefix.hide(); } else { this._storeLocation(); Windows.unsetOverflow(this); var windowScroll = WindowUtilities.getWindowScroll(); - var pageSize = WindowUtilities.getPageSize(); + var pageSize = WindowUtilities.getPageSize(); + var left = windowScroll.left; + var top = windowScroll.top; + + if (this.options.parent != document.body) { + windowScroll = {top:0, left:0, bottom:0, right:0}; + var dim = this.options.parent.getDimensions(); + pageSize.windowWidth = dim.width; + pageSize.windowHeight = dim.height; + top = 0; + left = 0; + } + + if (this.constraint) { + pageSize.windowWidth -= Math.max(0, this.constraintPad.left) + Math.max(0, this.constraintPad.right); + pageSize.windowHeight -= Math.max(0, this.constraintPad.top) + Math.max(0, this.constraintPad.bottom); + left += Math.max(0, this.constraintPad.left); + top += Math.max(0, this.constraintPad.top); + } + + this.element.setStyle(this.useLeft ? {left: left} : {right: left}); + this.element.setStyle(this.useTop ? {top: top} : {bottom: top}); - this.element.setStyle(this.useLeft ? {left: windowScroll.left} : {right: windowScroll.left}); - this.element.setStyle(this.useTop ? {top: windowScroll.top} : {bottom: windowScroll.top}); - - this.setSize(pageSize.windowWidth - this.widthW - this.widthE, pageSize.windowHeight - this.heightN - this.heightS) + this.setSize(pageSize.windowWidth - this.widthW - this.widthE , pageSize.windowHeight - this.heightN - this.heightS) this.toFront(); if (this.iefix) - this._fixIEOverlapping(); + this._fixIEOverlapping(); } - Windows.notify("onMaximize", this); + this._notify("onMaximize"); - // Store new location/size if need be - this._saveCookie() + // Store new location/size if need be + this._saveCookie() }, isMinimized: function() { @@ -663,25 +941,25 @@ Window.prototype = { return (this.storedLocation != null); }, - setOpacity: function(opacity) { - if (Element.setOpacity) - Element.setOpacity(this.element, opacity); - }, - - setZIndex: function(zindex) { - this.element.setStyle({zIndex: zindex}); - Windows.updateZindex(zindex, this); - }, - - setTitle: function(newTitle) { - if (!newTitle || newTitle == "") - newTitle = " "; - - Element.update(this.element.id + '_top', newTitle); + setOpacity: function(opacity) { + if (Element.setOpacity) + Element.setOpacity(this.element, opacity); + }, + + setZIndex: function(zindex) { + this.element.setStyle({zIndex: zindex}); + Windows.updateZindex(zindex, this); }, - setStatusBar: function(element) { - var statusBar = $(this.getId() + "_bottom"); + setTitle: function(newTitle) { + if (!newTitle || newTitle == "") + newTitle = " "; + + Element.update(this.element.id + '_top', newTitle); + }, + + setStatusBar: function(element) { + var statusBar = $(this.getId() + "_bottom"); if (typeof(element) == "object") { if (this.bottombar.firstChild) @@ -690,81 +968,88 @@ Window.prototype = { this.bottombar.appendChild(element); } else - this.bottombar.innerHTML = element; - }, + this.bottombar.innerHTML = element; + }, - _checkIEOverlapping: function() { + _checkIEOverlapping: function() { if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (navigator.userAgent.indexOf('Opera')<0) && (this.element.getStyle('position')=='absolute')) { new Insertion.After(this.element.id, ''); this.iefix = $(this.element.id+'_iefix'); } if(this.iefix) - setTimeout(this._fixIEOverlapping.bind(this), 50); - }, + setTimeout(this._fixIEOverlapping.bind(this), 50); + }, - _fixIEOverlapping: function() { - Position.clone(this.element, this.iefix); - this.iefix.style.zIndex = this.element.style.zIndex - 1; - this.iefix.show(); - }, - - _getWindowBorderSize: function(event) { + _fixIEOverlapping: function() { + Position.clone(this.element, this.iefix); + this.iefix.style.zIndex = this.element.style.zIndex - 1; + this.iefix.show(); + }, + + _getWindowBorderSize: function(event) { // Hack to get real window border size!! var div = this._createHiddenDiv(this.options.className + "_n") - this.heightN = Element.getDimensions(div).height; - div.parentNode.removeChild(div) + this.heightN = Element.getDimensions(div).height; + div.parentNode.removeChild(div) var div = this._createHiddenDiv(this.options.className + "_s") - this.heightS = Element.getDimensions(div).height; - div.parentNode.removeChild(div) + this.heightS = Element.getDimensions(div).height; + div.parentNode.removeChild(div) var div = this._createHiddenDiv(this.options.className + "_e") - this.widthE = Element.getDimensions(div).width; - div.parentNode.removeChild(div) + this.widthE = Element.getDimensions(div).width; + div.parentNode.removeChild(div) var div = this._createHiddenDiv(this.options.className + "_w") - this.widthW = Element.getDimensions(div).width; - div.parentNode.removeChild(div); - // Safari size fix - if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - this.setSize(this.width, this.height); - if (this.doMaximize) - this.maximize(); - if (this.doMinimize) - this.minimize(); + this.widthW = Element.getDimensions(div).width; + div.parentNode.removeChild(div); + + // Workaround for IE!! + if (isIE) { + this.heightS = $(this.getId() +"_row3").getDimensions().height; + this.heightN = $(this.getId() +"_row1").getDimensions().height; + } + + // Safari size fix + if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + this.setSize(this.width, this.height); + if (this.doMaximize) + this.maximize(); + if (this.doMinimize) + this.minimize(); }, _createHiddenDiv: function(className) { - var objBody = document.getElementsByTagName("body").item(0); + var objBody = document.body; var win = document.createElement("div"); - win.setAttribute('id', this.element.id+ "_tmp"); - win.className = className; - win.style.display = 'none'; - win.innerHTML = ''; - objBody.insertBefore(win, objBody.firstChild); - return win; + win.setAttribute('id', this.element.id+ "_tmp"); + win.className = className; + win.style.display = 'none'; + win.innerHTML = ''; + objBody.insertBefore(win, objBody.firstChild); + return win; + }, + + _storeLocation: function() { + if (this.storedLocation == null) { + this.storedLocation = {useTop: this.useTop, useLeft: this.useLeft, + top: this.element.getStyle('top'), bottom: this.element.getStyle('bottom'), + left: this.element.getStyle('left'), right: this.element.getStyle('right'), + width: this.width, height: this.height }; + } }, - _storeLocation: function() { - if (this.storedLocation == null) { - this.storedLocation = {useTop: this.useTop, useLeft: this.useLeft, - top: this.element.getStyle('top'), bottom: this.element.getStyle('bottom'), - left: this.element.getStyle('left'), right: this.element.getStyle('right'), - width: this.width, height: this.height }; - } - }, - _restoreLocation: function() { if (this.storedLocation != null) { this.useLeft = this.storedLocation.useLeft; this.useTop = this.storedLocation.useTop; this.element.setStyle(this.useLeft ? {left: this.storedLocation.left} : {right: this.storedLocation.right}); - this.element.setStyle(this.useTop ? {top: this.storedLocation.top} : {bottom: this.storedLocation.bottom}); - this.setSize(this.storedLocation.width, this.storedLocation.height); + this.element.setStyle(this.useTop ? {top: this.storedLocation.top} : {bottom: this.storedLocation.bottom}); + this.setSize(this.storedLocation.width, this.storedLocation.height); - Windows.resetOverflow(); - this._removeStoreLocation(); + Windows.resetOverflow(); + this._removeStoreLocation(); } }, @@ -774,28 +1059,87 @@ Window.prototype = { _saveCookie: function() { if (this.cookie) { - var value = ""; - if (this.useLeft) - value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left')) - else - value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right')) - if (this.useTop) - value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top')) - else - value += ",b:" + (this.storedLocation ? this.storedLocation.bottom :this.element.getStyle('bottom')) - - value += "," + (this.storedLocation ? this.storedLocation.width : this.width); - value += "," + (this.storedLocation ? this.storedLocation.height : this.height); - value += "," + this.isMinimized(); - value += "," + this.isMaximized(); - WindowUtilities.setCookie(value, this.cookie) + var value = ""; + if (this.useLeft) + value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left')) + else + value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right')) + if (this.useTop) + value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top')) + else + value += ",b:" + (this.storedLocation ? this.storedLocation.bottom :this.element.getStyle('bottom')) + + value += "," + (this.storedLocation ? this.storedLocation.width : this.width); + value += "," + (this.storedLocation ? this.storedLocation.height : this.height); + value += "," + this.isMinimized(); + value += "," + this.isMaximized(); + WindowUtilities.setCookie(value, this.cookie) } + }, + + _createWiredElement: function() { + if (! this.wiredElement) { + if (isIE) + this._getWindowBorderSize(); + var div = document.createElement("div"); + div.className = "wired_frame " + this.options.className + "_wired_frame"; + + div.style.position = 'absolute'; + this.options.parent.insertBefore(div, this.options.parent.firstChild); + this.wiredElement = $(div); + } + if (this.useLeft) + this.wiredElement.setStyle({left: this.element.getStyle('left')}); + else + this.wiredElement.setStyle({right: this.element.getStyle('right')}); + + if (this.useTop) + this.wiredElement.setStyle({top: this.element.getStyle('top')}); + else + this.wiredElement.setStyle({bottom: this.element.getStyle('bottom')}); + + var dim = this.element.getDimensions(); + this.wiredElement.setStyle({width: dim.width + "px", height: dim.height +"px"}); + + this.wiredElement.setStyle({zIndex: Windows.maxZIndex+30}); + return this.wiredElement; + }, + + _hideWiredElement: function() { + if (! this.wiredElement || ! this.currentDrag) + return; + if (this.currentDrag == this.element) + this.currentDrag = null; + else { + if (this.useLeft) + this.element.setStyle({left: this.currentDrag.getStyle('left')}); + else + this.element.setStyle({right: this.currentDrag.getStyle('right')}); + + if (this.useTop) + this.element.setStyle({top: this.currentDrag.getStyle('top')}); + else + this.element.setStyle({bottom: this.currentDrag.getStyle('bottom')}); + + this.currentDrag.hide(); + this.currentDrag = null; + if (this.doResize) + this.setSize(this.width, this.height); + } + }, + + _notify: function(eventName) { + if (this.options[eventName]) + this.options[eventName](this); + else + Windows.notify(eventName, this); } }; // Windows containers, register all page windows var Windows = { windows: [], + modalWindows: [], observers: [], focusedWindow: null, maxZIndex: 0, @@ -809,20 +1153,67 @@ var Windows = { this.observers = this.observers.reject( function(o) { return o==observer }); }, - notify: function(eventName, win) { // onStartResize(), onEndResize(), onStartMove(), onEndMove(), onClose(), onDestroy(), onMinimize(), onMaximize(), onHide(), onShow(), onFocus() + // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBeforeShow onShow onHide onMinimize onMaximize onClose + notify: function(eventName, win) { this.observers.each( function(o) {if(o[eventName]) o[eventName](eventName, win);}); }, // Gets window from its id getWindow: function(id) { - return this.windows.detect(function(d) { return d.getId() ==id }); + return this.windows.detect(function(d) { return d.getId() ==id }); }, // Gets the last focused window getFocusedWindow: function() { - return this.focusedWindow; + return this.focusedWindow; }, + updateFocusedWindow: function() { + this.focusedWindow = this.windows.length >=2 ? this.windows[this.windows.length-2] : null; + }, + + // Registers a new window (called by Windows constructor) + register: function(win) { + this.windows.push(win); + }, + + // Add a modal window in the stack + addModalWindow: function(win) { + // Disable screen if first modal window + if (this.modalWindows.length == 0) + WindowUtilities.disableScreen(win.options.className, 'overlay_modal', win.getId()); + else { + // Move overlay over all windows + if (Window.keepMultiModalWindow) { + $('overlay_modal').style.zIndex = Windows.maxZIndex + 20; + Windows.maxZIndex += 20; + WindowUtilities._hideSelect(this.modalWindows.last().getId()); + } + // Hide current modal window + else + this.modalWindows.last().element.hide(); + // Fucking IE select issue + WindowUtilities._showSelect(win.getId()); + } + this.modalWindows.push(win); + }, + + removeModalWindow: function(win) { + this.modalWindows.pop(); + + // No more modal windows + if (this.modalWindows.length == 0) + WindowUtilities.enableScreen(); + else { + if (Window.keepMultiModalWindow) { + this.modalWindows.last().toFront(); + WindowUtilities._showSelect(this.modalWindows.last().getId()); + } + else + this.modalWindows.last().element.show(); + } + }, + // Registers a new window (called by Windows constructor) register: function(win) { this.windows.push(win); @@ -832,220 +1223,237 @@ var Windows = { unregister: function(win) { this.windows = this.windows.reject(function(d) { return d==win }); }, - - // Closes a window with its id - close: function(event, id) { - var win = this.getWindow(id); - // Asks delegate if exists - if (win) { - if (win.getDelegate() && ! win.getDelegate().canClose(win)) - return; - if ($(id + "_close")) - $(id + "_close").onclick = null; - if ($(id + "_minimize")) - $(id + "_minimize").onclick = null; - if ($(id + "_maximize")) - $(id + "_maximize").onclick = null; - - this.notify("onClose", win); - win.hide(); - } - if (event) - Event.stop(event); - }, // Closes all windows closeAll: function() { this.windows.each( function(w) {Windows.close(w.getId())} ); }, + closeAllModalWindows: function() { + WindowUtilities.enableScreen(); + this.modalWindows.each( function(win) {win.hide()}); + }, + // Minimizes a window with its id - minimize: function(event, id) { - var win = this.getWindow(id) - if (win) - win.minimize(); - Event.stop(event); + minimize: function(id, event) { + var win = this.getWindow(id) + if (win && win.visible) + win.minimize(); + Event.stop(event); }, // Maximizes a window with its id - maximize: function(event, id) { - var win = this.getWindow(id) - if (win) - win.maximize(); - Event.stop(event); + maximize: function(id, event) { + var win = this.getWindow(id) + if (win && win.visible) + win.maximize(); + Event.stop(event); + }, + + // Closes a window with its id + close: function(id, event) { + var win = this.getWindow(id); + if (win) + win.close()//win.options.destroyOnClose ? win.close() : win.hide(); + if (event) + Event.stop(event); }, - unsetOverflow: function(except) { - this.windows.each(function(d) { d.oldOverflow = d.getContent().getStyle("overflow") || "auto" ; d.getContent().setStyle({overflow: "hidden"}) }); - if (except && except.oldOverflow) - except.getContent().setStyle({overflow: except.oldOverflow}); + unsetOverflow: function(except) { + this.windows.each(function(d) { d.oldOverflow = d.getContent().getStyle("overflow") || "auto" ; d.getContent().setStyle({overflow: "hidden"}) }); + if (except && except.oldOverflow) + except.getContent().setStyle({overflow: except.oldOverflow}); }, resetOverflow: function() { - this.windows.each(function(d) { if (d.oldOverflow) d.getContent().setStyle({overflow: d.oldOverflow}) }); + this.windows.each(function(d) { if (d.oldOverflow) d.getContent().setStyle({overflow: d.oldOverflow}) }); }, updateZindex: function(zindex, win) { - if (zindex > this.maxZIndex) - this.maxZIndex = zindex; + if (zindex > this.maxZIndex) + this.maxZIndex = zindex; this.focusedWindow = win; } }; var Dialog = { dialogId: null, - win: null, onCompleteFunc: null, callFunc: null, parameters: null, - confirm: function(content, parameters) { - // Get Ajax return before - if (typeof content != "string") { - Dialog._runAjaxRequest(content, parameters, Dialog.confirm); - return - } - - parameters = parameters || {}; - var okLabel = parameters.okLabel ? parameters.okLabel : "Ok"; - var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel"; - - var windowParam = parameters.windowParameters || {}; - windowParam.className = windowParam.className || "alert"; - - okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" - cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'" - var content = "\ -
" + content + "
\ -
\ - \ - \ -
\ - "; - this._openDialog(content, parameters) - return this.win - }, - - alert: function(content, parameters) { - // Get Ajax return before - if (typeof content != "string") { - Dialog._runAjaxRequest(content, parameters, Dialog.alert); - return - } - - parameters = parameters || {}; - var okLabel = parameters.okLabel ? parameters.okLabel : "Ok"; - - var windowParam = parameters.windowParameters || {}; - windowParam.className = windowParam.className || "alert"; - - okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" - var content = "\ -
" + content + "
\ -
\ - \ -
"; - return this._openDialog(content, parameters) - }, - - info: function(content, parameters) { - // Get Ajax return before - if (typeof content != "string") { - Dialog._runAjaxRequest(content, parameters, Dialog.info); - return - } - - parameters = parameters || {}; - parameters.windowParameters = parameters.windowParameters || {}; - - var className = parameters.windowParameters.className || "alert"; - - var content = ""; - if (parameters.showProgress) - content += ""; - - parameters.windowParameters.ok = null; - parameters.windowParameters.cancel = null; - parameters.windowParameters.className = className; - - return this._openDialog(content, parameters) - }, - - setInfoMessage: function(message) { - $('modal_dialog_message').update(message); - }, - - closeInfo: function() { - Windows.close(null, this.dialogId); - }, - - _openDialog: function(content, parameters) { - if (! parameters.windowParameters.height && ! parameters.windowParameters.width) { - parameters.windowParameters.width = WindowUtilities.getPageSize().pageWidth / 2; + confirm: function(content, parameters) { + // Get Ajax return before + if (content && typeof content != "string") { + Dialog._runAjaxRequest(content, parameters, Dialog.confirm); + return + } + content = content || ""; + + parameters = parameters || {}; + var okLabel = parameters.okLabel ? parameters.okLabel : "Ok"; + var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel"; + + // Backward compatibility + parameters = Object.extend(parameters, parameters.windowParameters || {}); + parameters.windowParameters = parameters.windowParameters || {}; + + parameters.className = parameters.className || "alert"; + + var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" + var cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'" + var content = "\ +
" + content + "
\ +
\ + \ + \ +
\ + "; + return this._openDialog(content, parameters) + }, + + alert: function(content, parameters) { + // Get Ajax return before + if (content && typeof content != "string") { + Dialog._runAjaxRequest(content, parameters, Dialog.alert); + return + } + content = content || ""; + + parameters = parameters || {}; + var okLabel = parameters.okLabel ? parameters.okLabel : "Ok"; + + // Backward compatibility + parameters = Object.extend(parameters, parameters.windowParameters || {}); + parameters.windowParameters = parameters.windowParameters || {}; + + parameters.className = parameters.className || "alert"; + + var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" + var content = "\ +
" + content + "
\ +
\ + \ +
"; + return this._openDialog(content, parameters) + }, + + info: function(content, parameters) { + // Get Ajax return before + if (content && typeof content != "string") { + Dialog._runAjaxRequest(content, parameters, Dialog.info); + return + } + content = content || ""; + + // Backward compatibility + parameters = parameters || {}; + parameters = Object.extend(parameters, parameters.windowParameters || {}); + parameters.windowParameters = parameters.windowParameters || {}; + + parameters.className = parameters.className || "alert"; + + var content = ""; + if (parameters.showProgress) + content += ""; + + parameters.ok = null; + parameters.cancel = null; + + return this._openDialog(content, parameters) + }, + + setInfoMessage: function(message) { + $('modal_dialog_message').update(message); + }, + + closeInfo: function() { + Windows.close(this.dialogId); + }, + + _openDialog: function(content, parameters) { + var className = parameters.className; + + if (! parameters.height && ! parameters.width) { + parameters.width = WindowUtilities.getPageSize().pageWidth / 2; + } + if (parameters.id) + this.dialogId = parameters.id; + else { + var t = new Date(); + this.dialogId = 'modal_dialog_' + t.getTime(); + parameters.id = this.dialogId; } - this.dialogId = parameters.id ? parameters.id : 'modal_dialog'; // compute height or width if need be - if (! parameters.windowParameters.height || ! parameters.windowParameters.width) { - var size = WindowUtilities._computeSize(content, this.dialogId, parameters.windowParameters.width, parameters.windowParameters.height) - if (parameters.windowParameters.height) - parameters.windowParameters.width = size + 5 - else - parameters.windowParameters.height = size + 5 + if (! parameters.height || ! parameters.width) { + var size = WindowUtilities._computeSize(content, this.dialogId, parameters.width, parameters.height, 5, className) + if (parameters.height) + parameters.width = size + 5 + else + parameters.height = size + 5 } - var windowParam = parameters && parameters.windowParameters ? parameters.windowParameters : {}; - windowParam.resizable = windowParam.resizable || false; - - windowParam.effectOptions = windowParam.effectOptions || {duration: 1}; - windowParam.minimizable = false; - windowParam.maximizable = false; - windowParam.closable = false; - this.win = new Window(this.dialogId, windowParam); - this.win.getContent().innerHTML = content; - this.win.showCenter(true, parameters.top, parameters.left); - this.win.setDestroyOnClose(); - - this.win.cancelCallback = parameters.cancel; - this.win.okCallback = parameters.ok; - - return this.win; - }, - - _getAjaxContent: function(originalRequest) { + //parameters.resizable = parameters.resizable || false; + + parameters.effectOptions = parameters.effectOptions || {duration: 1}; + parameters.minimizable = false; + parameters.maximizable = false; + //parameters.draggable = false; + parameters.closable = false; + + var win = new Window(parameters); + win.getContent().innerHTML = content; + win.showCenter(true, parameters.top, parameters.left); + win.setDestroyOnClose(); + + win.cancelCallback = parameters.onCancel || parameters.cancel; + win.okCallback = parameters.onOk || parameters.ok; + + return win; + }, + + _getAjaxContent: function(originalRequest) { Dialog.callFunc(originalRequest.responseText, Dialog.parameters) }, _runAjaxRequest: function(message, parameters, callFunc) { if (message.options == null) - message.options ={} - Dialog.onCompleteFunc = message.options.onComplete; + message.options = {} + Dialog.onCompleteFunc = message.options.onComplete; Dialog.parameters = parameters; Dialog.callFunc = callFunc; - message.options.onComplete = Dialog._getAjaxContent; + message.options.onComplete = Dialog._getAjaxContent; new Ajax.Request(message.url, message.options); }, - okCallback: function() { - if (!this.win.okCallback || this.win.okCallback(this.win)) - this.win.hide(); - }, + okCallback: function() { + var win = Windows.focusedWindow; + if (!win.okCallback || win.okCallback(win)) { + // Remove onclick on button + $$("#" + win.getId()+" input").each(function(element) {element.onclick=null;}) + win.close(); + } + }, - cancelCallback: function() { - this.win.hide(); - if (this.win.cancelCallback) - this.win.cancelCallback(this.win); - } + cancelCallback: function() { + var win = Windows.focusedWindow; + // Remove onclick on button + $$("#" + win.getId()+" input").each(function(element) {element.onclick=null}) + win.close(); + if (win.cancelCallback) + win.cancelCallback(win); + } } /* - Based on Lightbox JS: Fullsize Image Overlays - by Lokesh Dhakar - http://www.huddletogether.com + Based on Lightbox JS: Fullsize Image Overlays + by Lokesh Dhakar - http://www.huddletogether.com - For more information on this script, visit: - http://huddletogether.com/projects/lightbox/ + For more information on this script, visit: + http://huddletogether.com/projects/lightbox/ - Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ - (basically, do anything you want, just leave my name and link) + Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ + (basically, do anything you want, just leave my name and link) */ var isIE = navigator.appVersion.match(/MSIE/) == "MSIE"; @@ -1056,7 +1464,7 @@ var WindowUtilities = { var w = window; var T, L, W, H; with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { + if (w.document.documentElement && typeof documentElement.scrollTop != "undefined") { T = documentElement.scrollTop; L = documentElement.scrollLeft; } else if (w.document.body) { @@ -1066,7 +1474,7 @@ var WindowUtilities = { if (w.innerWidth) { W = w.innerWidth; H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { + } else if (w.document.documentElement && typeof documentElement.clientWidth != "undefined") { W = documentElement.clientWidth; H = documentElement.clientHeight; } else { @@ -1075,7 +1483,6 @@ var WindowUtilities = { } } return { top: T, left: L, width: W, height: H }; - }, // // getPageSize() @@ -1084,113 +1491,150 @@ var WindowUtilities = { // Edit for Firefox by pHaez // getPageSize: function(){ - var xScroll, yScroll; + var xScroll, yScroll; - if (window.innerHeight && window.scrollMaxY) { - xScroll = document.body.scrollWidth; - yScroll = window.innerHeight + window.scrollMaxY; - } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac - xScroll = document.body.scrollWidth; - yScroll = document.body.scrollHeight; - } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari - xScroll = document.body.offsetWidth; - yScroll = document.body.offsetHeight; - } + if (window.innerHeight && window.scrollMaxY) { + xScroll = document.body.scrollWidth; + yScroll = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac + xScroll = document.body.scrollWidth; + yScroll = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + xScroll = document.body.offsetWidth; + yScroll = document.body.offsetHeight; + } - var windowWidth, windowHeight; + var windowWidth, windowHeight; - if (self.innerHeight) { // all except Explorer - windowWidth = self.innerWidth; - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowWidth = document.documentElement.clientWidth; - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowWidth = document.body.clientWidth; - windowHeight = document.body.clientHeight; - } - var pageHeight, pageWidth; + if (self.innerHeight) { // all except Explorer + windowWidth = self.innerWidth; + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowWidth = document.documentElement.clientWidth; + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowWidth = document.body.clientWidth; + windowHeight = document.body.clientHeight; + } + var pageHeight, pageWidth; - // for small pages with total height less then height of the viewport - if(yScroll < windowHeight){ - pageHeight = windowHeight; - } else { - pageHeight = yScroll; - } + // for small pages with total height less then height of the viewport + if(yScroll < windowHeight){ + pageHeight = windowHeight; + } else { + pageHeight = yScroll; + } - // for small pages with total width less then width of the viewport - if(xScroll < windowWidth){ - pageWidth = windowWidth; - } else { - pageWidth = xScroll; - } + // for small pages with total width less then width of the viewport + if(xScroll < windowWidth){ + pageWidth = windowWidth; + } else { + pageWidth = xScroll; + } - return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight}; + return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight}; }, - disableScreen: function(className, overlayId, contentId) { - WindowUtilities.initLightbox(overlayId, className); - var objBody = document.getElementsByTagName("body").item(0); + disableScreen: function(className, overlayId, contentId) { + WindowUtilities.initLightbox(overlayId, className); + var objBody = document.body; - // prep objects - var objOverlay = $(overlayId); + // prep objects + var objOverlay = $(overlayId); - var pageSize = WindowUtilities.getPageSize(); + var pageSize = WindowUtilities.getPageSize(); - // Hide select boxes as they will 'peek' through the image in IE - if (contentId && isIE) { - $$('select').each(function(element) {element.style.visibility = "hidden"}); - $$('#'+contentId+' select').each(function(element) {element.style.visibility = "visible"}); - } - - // set height of Overlay to take up whole page and show - objOverlay.style.height = (pageSize.pageHeight + 'px'); - objOverlay.style.width = (pageSize.windowWidth + 'px'); - objOverlay.style.display = 'block'; - }, + // Hide select boxes as they will 'peek' through the image in IE, store old value + if (contentId && isIE) { + WindowUtilities._hideSelect(); + WindowUtilities._showSelect(contentId); + } + + // set height of Overlay to take up whole page and show + objOverlay.style.height = (pageSize.pageHeight + 'px'); + objOverlay.style.width = (pageSize.windowWidth + 'px'); + objOverlay.style.display = 'block'; + }, - enableScreen: function(id) { - id = id || 'overlay_modal'; - var objOverlay = $(id); - if (objOverlay) { - // hide lightbox and overlay - objOverlay.style.display = 'none'; + enableScreen: function(id) { + id = id || 'overlay_modal'; + var objOverlay = $(id); + if (objOverlay) { + // hide lightbox and overlay + objOverlay.style.display = 'none'; - // make select boxes visible - if (isIE) { - $$('select').each(function(element) {element.style.visibility = "visible"}); - } - objOverlay.parentNode.removeChild(objOverlay); - } - }, + // make select boxes visible using old value + if (id != "__invisible__") + WindowUtilities._showSelect(); + + objOverlay.parentNode.removeChild(objOverlay); + } + }, - // initLightbox() - // Function runs on window load, going through link tags looking for rel="lightbox". - // These links receive onclick events that enable the lightbox display for their targets. - // The function also inserts html markup at the top of the page which will be used as a - // container for the overlay pattern and the inline image. - initLightbox: function(id, className) { - // Already done, just update zIndex - if ($(id)) { - Element.setStyle(id, {zIndex: Windows.maxZIndex + 10}); - } - // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file) - else { - var objBody = document.getElementsByTagName("body").item(0); - var objOverlay = document.createElement("div"); - objOverlay.setAttribute('id', id); - objOverlay.className = "overlay_" + className - objOverlay.style.display = 'none'; - objOverlay.style.position = 'absolute'; - objOverlay.style.top = '0'; - objOverlay.style.left = '0'; - objOverlay.style.zIndex = Windows.maxZIndex + 10; - objOverlay.style.width = '100%'; - objBody.insertBefore(objOverlay, objBody.firstChild); - } - }, - - setCookie: function(value, parameters) { + _hideSelect: function(id) { + if (isIE) { + id = id == null ? "" : "#" + id + " "; + $$(id + 'select').each(function(element) { + if (! WindowUtilities.isDefined(element.oldVisibility)) { + element.oldVisibility = element.style.visibility ? element.style.visibility : "visible"; + element.style.visibility = "hidden"; + } + }); + } + }, + + _showSelect: function(id) { + if (isIE) { + id = id == null ? "" : "#" + id + " "; + $$(id + 'select').each(function(element) { + if (WindowUtilities.isDefined(element.oldVisibility)) { + // Why?? Ask IE + try { + element.style.visibility = element.oldVisibility; + } catch(e) { + element.style.visibility = "visible"; + } + element.oldVisibility = null; + } + else { + if (element.style.visibility) + element.style.visibility = "visible"; + } + }); + } + }, + + isDefined: function(object) { + return typeof(object) != "undefined" && object != null; + }, + + // initLightbox() + // Function runs on window load, going through link tags looking for rel="lightbox". + // These links receive onclick events that enable the lightbox display for their targets. + // The function also inserts html markup at the top of the page which will be used as a + // container for the overlay pattern and the inline image. + initLightbox: function(id, className) { + // Already done, just update zIndex + if ($(id)) { + Element.setStyle(id, {zIndex: Windows.maxZIndex + 10}); + } + // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file) + else { + var objBody = document.body; + var objOverlay = document.createElement("div"); + objOverlay.setAttribute('id', id); + objOverlay.className = "overlay_" + className + objOverlay.style.display = 'none'; + objOverlay.style.position = 'absolute'; + objOverlay.style.top = '0'; + objOverlay.style.left = '0'; + objOverlay.style.zIndex = Windows.maxZIndex + 10; + objOverlay.style.width = '100%'; + objBody.insertBefore(objOverlay, objBody.firstChild); + } + }, + + setCookie: function(value, parameters) { document.cookie= parameters[0] + "=" + escape(value) + ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") + ((parameters[2]) ? "; path=" + parameters[2] : "") + @@ -1214,37 +1658,33 @@ var WindowUtilities = { } return unescape(dc.substring(begin + prefix.length, end)); }, - - _computeSize: function(content, id, width, height, margin) { - if (margin == null) - margin = 5; + + _computeSize: function(content, id, width, height, margin, className) { + var objBody = document.body; + var tmpObj = document.createElement("div"); + tmpObj.setAttribute('id', id); + tmpObj.className = className + "_content"; - var objBody = document.getElementsByTagName("body").item(0); - var tmpObj = document.createElement("div"); - tmpObj.setAttribute('id', id); - - if (height) - tmpObj.style.height = height + "px" + if (height) + tmpObj.style.height = height + "px" else tmpObj.style.width = width + "px" - tmpObj.style.position = 'absolute'; - tmpObj.style.top = '0'; - tmpObj.style.left = '0'; + tmpObj.style.position = 'absolute'; + tmpObj.style.top = '0'; + tmpObj.style.left = '0'; tmpObj.style.display = 'none'; tmpObj.innerHTML = content; - objBody.insertBefore(tmpObj, objBody.firstChild); - - var size; - if (height) - size = $(id).getDimensions().width + margin; + objBody.insertBefore(tmpObj, objBody.firstChild); + + var size; + if (height) + size = $(id).getDimensions().width + margin; else size = $(id).getDimensions().height + margin; - objBody.removeChild(tmpObj); - - return size; - } + objBody.removeChild(tmpObj); + return size; + } } - diff --git a/data/msfweb/public/javascripts/window_ext.js b/data/msfweb/public/javascripts/window_ext.js new file mode 100755 index 0000000000..da8a9ff082 --- /dev/null +++ b/data/msfweb/public/javascripts/window_ext.js @@ -0,0 +1,107 @@ +// Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com) +// YOU MUST INCLUDE window.js BEFORE +// +// Object to store hide/show windows status in a cookie +// Just add at the end of your HTML file this javascript line: WindowStore.init() +WindowStore = { + doSetCookie: false, + cookieName: "__window_store__", + expired: null, + + // Init function with two optional parameters + // - cookieName (default = __window_store__) + // - expiration date (default 3 years from now) + init: function(cookieName, expired) { + WindowStore.cookieName = cookieName || WindowStore.cookieName + + if (! expired) { + var today = new Date(); + today.setYear(today.getYear()+1903); + WindowStore.expired = today; + } + else + WindowStore.expired = expired; + + Windows.windows.each(function(win) { + win.setCookie(win.getId(), WindowStore.expired); + }); + + // Create observer on show/hide events + var myObserver = { + onShow: function(eventName, win) { + WindowStore._saveCookie(); + }, + onHide: function(eventName, win) { + WindowStore._saveCookie(); + } + } + Windows.addObserver(myObserver); + + WindowStore._restoreWindows(); + WindowStore._saveCookie(); + }, + + show: function(win) { + eval("var cookie = " + WindowUtilities.getCookie(Windows.cookieName)); + if (cookie != null) { + if (cookie[win.getId()]) + win.show(); + } + else + win.show(); + }, + + // Function to store windows show/hide status in a cookie + _saveCookie: function() { + if (!doSetCookie) + return; + + var cookieValue = "{"; + Windows.windows.each(function(win) { + if (cookieValue != "{") + cookieValue += "," + cookieValue += win.getId() + ": " + win.isVisible(); + }); + cookieValue += "}" + + WindowUtilities.setCookie(cookieValue, [WindowStore.cookieName, WindowStore.expired]); + }, + + // Function to restore windows show/hide status from a cookie if exists + _restoreWindows: function() { + eval("var cookie = " + WindowUtilities.getCookie(Windows.cookieName)); + if (cookie != null) { + doSetCookie = false; + Windows.windows.each(function(win) { + if (cookie[win.getId()]) + win.show(); + }); + } + doSetCookie = true; + } +} + +// Object to set a close key an all windows +WindowCloseKey = { + keyCode: Event.KEY_ESC, + + init: function(keyCode) { + if (keyCode) + WindowCloseKey.keyCode = keyCode; + Event.observe(document, 'keydown', this._closeCurrentWindow.bindAsEventListener(this)); + }, + + _closeCurrentWindow: function(event) { + var e = event || window.event + var characterCode = e.which || e.keyCode; + var win = Windows.focusedWindow; + if (characterCode == WindowCloseKey.keyCode && win) { + if (win.cancelCallback) + Dialog.cancelCallback(); + else if (win.okCallback) + Dialog.okCallback(); + else + Windows.close(Windows.focusedWindow.getId()); + } + } +} \ No newline at end of file