Created
June 25, 2013 09:59
-
-
Save speedupmate/5857348 to your computer and use it in GitHub Desktop.
Livepipe.net js library issues with IE10
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Ryan Johnson <http://syntacticx.com/> | |
* @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/> | |
* @package LivePipe UI | |
* @license MIT | |
* @url http://livepipe.net/core | |
* @require prototype.js | |
*/ | |
if(typeof(Control) == 'undefined') | |
Control = {}; | |
var $proc = function(proc){ | |
return typeof(proc) == 'function' ? proc : function(){return proc}; | |
}; | |
var $value = function(value){ | |
return typeof(value) == 'function' ? value() : value; | |
}; | |
Object.Event = { | |
extend: function(object){ | |
object._objectEventSetup = function(event_name){ | |
this._observers = this._observers || {}; | |
this._observers[event_name] = this._observers[event_name] || []; | |
}; | |
object.observe = function(event_name,observer){ | |
if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){ | |
this._objectEventSetup(event_name); | |
if(!this._observers[event_name].include(observer)) | |
this._observers[event_name].push(observer); | |
}else | |
for(var e in event_name) | |
this.observe(e,event_name[e]); | |
}; | |
object.stopObserving = function(event_name,observer){ | |
this._objectEventSetup(event_name); | |
if(event_name && observer) | |
this._observers[event_name] = this._observers[event_name].without(observer); | |
else if(event_name) | |
this._observers[event_name] = []; | |
else | |
this._observers = {}; | |
}; | |
object.observeOnce = function(event_name,outer_observer){ | |
var inner_observer = function(){ | |
outer_observer.apply(this,arguments); | |
this.stopObserving(event_name,inner_observer); | |
}.bind(this); | |
this._objectEventSetup(event_name); | |
this._observers[event_name].push(inner_observer); | |
}; | |
object.notify = function(event_name){ | |
this._objectEventSetup(event_name); | |
var collected_return_values = []; | |
var args = $A(arguments).slice(1); | |
try{ | |
for(var i = 0; i < this._observers[event_name].length; ++i) | |
collected_return_values.push(this._observers[event_name][i].apply(this,args) || null); | |
}catch(e){ | |
if(e == $break) | |
return false; | |
else | |
throw e; | |
} | |
return collected_return_values; | |
}; | |
if(object.prototype){ | |
object.prototype._objectEventSetup = object._objectEventSetup; | |
object.prototype.observe = object.observe; | |
object.prototype.stopObserving = object.stopObserving; | |
object.prototype.observeOnce = object.observeOnce; | |
object.prototype.notify = function(event_name){ | |
if(object.notify){ | |
var args = $A(arguments).slice(1); | |
args.unshift(this); | |
args.unshift(event_name); | |
object.notify.apply(object,args); | |
} | |
this._objectEventSetup(event_name); | |
var args = $A(arguments).slice(1); | |
var collected_return_values = []; | |
try{ | |
if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function') | |
collected_return_values.push(this.options[event_name].apply(this,args) || null); | |
var callbacks_copy = this._observers[event_name]; // since original array will be modified after observeOnce calls | |
for(var i = 0; i < callbacks_copy.length; ++i) | |
collected_return_values.push(callbacks_copy[i].apply(this,args) || null); | |
}catch(e){ | |
if(e == $break) | |
return false; | |
else | |
throw e; | |
} | |
return collected_return_values; | |
}; | |
} | |
} | |
}; | |
/* Begin Core Extensions */ | |
//Element.observeOnce | |
Element.addMethods({ | |
observeOnce: function(element,event_name,outer_callback){ | |
var inner_callback = function(){ | |
outer_callback.apply(this,arguments); | |
Element.stopObserving(element,event_name,inner_callback); | |
}; | |
Element.observe(element,event_name,inner_callback); | |
} | |
}); | |
//mouse:wheel | |
(function(){ | |
function wheel(event){ | |
var delta, element, custom_event; | |
// normalize the delta | |
if (event.wheelDelta) { // IE & Opera | |
delta = event.wheelDelta / 120; | |
} else if (event.detail) { // W3C | |
delta =- event.detail / 3; | |
} | |
if (!delta) { return; } | |
element = Event.extend(event).target; | |
element = Element.extend(element.nodeType === Node.TEXT_NODE ? element.parentNode : element); | |
custom_event = element.fire('mouse:wheel',{ delta: delta }); | |
if (custom_event.stopped) { | |
Event.stop(event); | |
return false; | |
} | |
} | |
document.observe('mousewheel',wheel); | |
document.observe('DOMMouseScroll',wheel); | |
})(); | |
/* End Core Extensions */ | |
//from PrototypeUI | |
var IframeShim = Class.create({ | |
initialize: function() { | |
if(navigator.appVersion.match(/MSIE\s+(?:6|7|8)\./)){ | |
this.element = new Element('iframe',{ | |
style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0); display:none', | |
src: 'about:blank', | |
frameborder: 0, | |
}); | |
} else { | |
this.element = new Element('iframe',{ | |
//style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0); display:none', | |
src: 'about:blank', | |
frameborder: 0, | |
}); | |
} | |
$(document.body).insert(this.element); | |
}, | |
hide: function() { | |
this.element.hide(); | |
return this; | |
}, | |
show: function() { | |
this.element.show(); | |
return this; | |
}, | |
positionUnder: function(element) { | |
var element = $(element); | |
var offset = element.cumulativeOffset(); | |
var dimensions = element.getDimensions(); | |
this.element.setStyle({ | |
left: offset[0] + 'px', | |
top: offset[1] + 'px', | |
width: dimensions.width + 'px', | |
height: dimensions.height + 'px', | |
zIndex: element.getStyle('zIndex') - 1 | |
}); | |
if(navigator.appVersion.match(/MSIE\s+(?:6|7|8)\./)){ | |
this.element.setStyle({ | |
position: 'absolute' | |
}); | |
} | |
this.element.show(); | |
return this; | |
}, | |
setBounds: function(bounds) { | |
for(prop in bounds) | |
bounds[prop] += 'px'; | |
this.element.setStyle(bounds); | |
return this; | |
}, | |
destroy: function() { | |
if(this.element) | |
this.element.remove(); | |
return this; | |
} | |
}); | |
/** | |
* @author Ryan Johnson <http://syntacticx.com/> | |
* @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/> | |
* @package LivePipe UI | |
* @license MIT | |
* @url http://livepipe.net/control/window | |
* @require prototype.js, effects.js, draggable.js, resizable.js, livepipe.js | |
*/ | |
//adds onDraw and constrainToViewport option to draggable | |
if(typeof(Draggable) != 'undefined'){ | |
//allows the point to be modified with an onDraw callback | |
Draggable.prototype.draw = function(point) { | |
var pos = Position.cumulativeOffset(this.element); | |
if(this.options.ghosting) { | |
var r = Position.realOffset(this.element); | |
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; | |
} | |
var d = this.currentDelta(); | |
pos[0] -= d[0]; pos[1] -= d[1]; | |
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { | |
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; | |
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; | |
} | |
var p = [0,1].map(function(i){ | |
return (point[i]-pos[i]-this.offset[i]) | |
}.bind(this)); | |
if(this.options.snap) { | |
if(typeof this.options.snap == 'function') { | |
p = this.options.snap(p[0],p[1],this); | |
} else { | |
if(this.options.snap instanceof Array) { | |
p = p.map( function(v, i) {return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this)) | |
} else { | |
p = p.map( function(v) {return Math.round(v/this.options.snap)*this.options.snap }.bind(this)) | |
} | |
} | |
} | |
if(this.options.onDraw) | |
this.options.onDraw.bind(this)(p); | |
else{ | |
var style = this.element.style; | |
if(this.options.constrainToViewport){ | |
var viewport_dimensions = document.viewport.getDimensions(); | |
var container_dimensions = this.element.getDimensions(); | |
var margin_top = parseInt(this.element.getStyle('margin-top')); | |
var margin_left = parseInt(this.element.getStyle('margin-left')); | |
var boundary = [[ | |
0 - margin_left, | |
0 - margin_top | |
],[ | |
(viewport_dimensions.width - container_dimensions.width) - margin_left, | |
(viewport_dimensions.height - container_dimensions.height) - margin_top | |
]]; | |
if((!this.options.constraint) || (this.options.constraint=='horizontal')){ | |
if((p[0] >= boundary[0][0]) && (p[0] <= boundary[1][0])) | |
this.element.style.left = p[0] + "px"; | |
else | |
this.element.style.left = ((p[0] < boundary[0][0]) ? boundary[0][0] : boundary[1][0]) + "px"; | |
} | |
if((!this.options.constraint) || (this.options.constraint=='vertical')){ | |
if((p[1] >= boundary[0][1] ) && (p[1] <= boundary[1][1])) | |
this.element.style.top = p[1] + "px"; | |
else | |
this.element.style.top = ((p[1] <= boundary[0][1]) ? boundary[0][1] : boundary[1][1]) + "px"; | |
} | |
}else{ | |
if((!this.options.constraint) || (this.options.constraint=='horizontal')) | |
style.left = p[0] + "px"; | |
if((!this.options.constraint) || (this.options.constraint=='vertical')) | |
style.top = p[1] + "px"; | |
} | |
if(style.visibility=="hidden") | |
style.visibility = ""; // fix gecko rendering | |
} | |
}; | |
} | |
if(typeof(Prototype) == "undefined") | |
throw "Control.Window requires Prototype to be loaded."; | |
if(typeof(IframeShim) == "undefined") | |
throw "Control.Window requires IframeShim to be loaded."; | |
if(typeof(Object.Event) == "undefined") | |
throw "Control.Window requires Object.Event to be loaded."; | |
/* | |
known issues: | |
- when iframe is clicked is does not gain focus | |
- safari can't open multiple iframes properly | |
- constrainToViewport: body must have no margin or padding for this to work properly | |
- iframe will be mis positioned during fade in | |
- document.viewport does not account for scrollbars (this will eventually be fixed in the prototype core) | |
notes | |
- setting constrainToViewport only works when the page is not scrollable | |
- setting draggable: true will negate the effects of position: center | |
*/ | |
Control.Window = Class.create({ | |
initialize: function(container,options){ | |
Control.Window.windows.push(this); | |
//attribute initialization | |
this.container = false; | |
this.isOpen = false; | |
this.href = false; | |
this.sourceContainer = false; //this is optionally the container that will open the window | |
this.ajaxRequest = false; | |
this.remoteContentLoaded = false; //this is set when the code to load the remote content is run, onRemoteContentLoaded is fired when the connection is closed | |
this.numberInSequence = Control.Window.windows.length + 1; //only useful for the effect scoping | |
this.indicator = false; | |
this.effects = { | |
fade: false, | |
appear: false | |
}; | |
this.indicatorEffects = { | |
fade: false, | |
appear: false | |
}; | |
//options | |
this.options = Object.extend({ | |
//lifecycle | |
beforeOpen: Prototype.emptyFunction, | |
afterOpen: Prototype.emptyFunction, | |
beforeClose: Prototype.emptyFunction, | |
afterClose: Prototype.emptyFunction, | |
//dimensions and modes | |
height: null, | |
width: null, | |
className: false, | |
position: 'center', //'center', 'center_once', 'relative', [x,y], [function(){return x;},function(){return y;}] | |
offsetLeft: 0, //available only for anchors opening the window, or windows set to position: hover | |
offsetTop: 0, //"" | |
iframe: false, //if the window has an href, this will display the href as an iframe instead of requesting the url as an an Ajax.Request | |
hover: false, //element object to hover over, or if "true" only available for windows with sourceContainer (an anchor or any element already on the page with an href attribute) | |
indicator: false, //element to show or hide when ajax requests, images and iframes are loading | |
closeOnClick: false, //does not work with hover,can be: true (click anywhere), 'container' (will refer to this.container), or element (a specific element) | |
iframeshim: true, //whether or not to position an iFrameShim underneath the window | |
//effects | |
fade: false, | |
fadeDuration: 0.75, | |
//draggable | |
draggable: false, | |
onDrag: Prototype.emptyFunction, | |
//resizable | |
resizable: false, | |
minHeight: false, | |
minWidth: false, | |
maxHeight: false, | |
maxWidth: false, | |
onResize: Prototype.emptyFunction, | |
//draggable and resizable | |
constrainToViewport: false, | |
//ajax | |
method: 'post', | |
parameters: {}, | |
onComplete: Prototype.emptyFunction, | |
onSuccess: Prototype.emptyFunction, | |
onFailure: Prototype.emptyFunction, | |
onException: Prototype.emptyFunction, | |
//any element with an href (image,iframe,ajax) will call this after it is done loading | |
onRemoteContentLoaded: Prototype.emptyFunction, | |
insertRemoteContentAt: false //false will set this to this.container, can be string selector (first returned will be selected), or an Element that must be a child of this.container | |
},options || {}); | |
//container setup | |
this.indicator = this.options.indicator ? $(this.options.indicator) : false; | |
if(container){ | |
if(typeof(container) == "string" && container.match(Control.Window.uriRegex)) | |
this.href = container; | |
else{ | |
this.container = $(container); | |
//need to create the container now for tooltips (or hover: element with no container already on the page) | |
//second call made below will not create the container since the check is done inside createDefaultContainer() | |
this.createDefaultContainer(container); | |
//if an element with an href was passed in we use it to activate the window | |
if(this.container && ((this.container.readAttribute('href') && this.container.readAttribute('href') != '') || (this.options.hover && this.options.hover !== true))){ | |
if(this.options.hover && this.options.hover !== true) | |
this.sourceContainer = $(this.options.hover); | |
else{ | |
this.sourceContainer = this.container; | |
this.href = this.container.readAttribute('href'); | |
var rel = this.href.match(/^#(.+)$/); | |
if(rel && rel[1]){ | |
this.container = $(rel[1]); | |
this.href = false; | |
}else | |
this.container = false; | |
} | |
//hover or click handling | |
this.sourceContainerOpenHandler = function(event){ | |
this.open(event); | |
event.stop(); | |
return false; | |
}.bindAsEventListener(this); | |
this.sourceContainerCloseHandler = function(event){ | |
this.close(event); | |
}.bindAsEventListener(this); | |
this.sourceContainerMouseMoveHandler = function(event){ | |
this.position(event); | |
}.bindAsEventListener(this); | |
if(this.options.hover){ | |
this.sourceContainer.observe('mouseenter',this.sourceContainerOpenHandler); | |
this.sourceContainer.observe('mouseleave',this.sourceContainerCloseHandler); | |
if(this.options.position == 'mouse') | |
this.sourceContainer.observe('mousemove',this.sourceContainerMouseMoveHandler); | |
}else | |
this.sourceContainer.observe('click',this.sourceContainerOpenHandler); | |
} | |
} | |
} | |
this.createDefaultContainer(container); | |
if(this.options.insertRemoteContentAt === false) | |
this.options.insertRemoteContentAt = this.container; | |
var styles = { | |
margin: 0, | |
position: 'absolute', | |
zIndex: Control.Window.initialZIndexForWindow() | |
}; | |
if(this.options.width) | |
styles.width = $value(this.options.width) + 'px'; | |
if(this.options.height) | |
styles.height = $value(this.options.height) + 'px'; | |
this.container.setStyle(styles); | |
if(this.options.className) | |
this.container.addClassName(this.options.className); | |
this.positionHandler = this.position.bindAsEventListener(this); | |
this.outOfBoundsPositionHandler = this.ensureInBounds.bindAsEventListener(this); | |
this.bringToFrontHandler = this.bringToFront.bindAsEventListener(this); | |
this.container.observe('mousedown',this.bringToFrontHandler); | |
this.container.hide(); | |
this.closeHandler = this.close.bindAsEventListener(this); | |
//iframeshim setup | |
if(this.options.iframeshim){ | |
this.iFrameShim = new IframeShim(); | |
this.iFrameShim.hide(); | |
} | |
//resizable support | |
this.applyResizable(); | |
//draggable support | |
this.applyDraggable(); | |
//makes sure the window can't go out of bounds | |
Event.observe(window,'resize',this.outOfBoundsPositionHandler); | |
this.notify('afterInitialize'); | |
}, | |
open: function(event){ | |
if(this.isOpen){ | |
this.bringToFront(); | |
return false; | |
} | |
if(this.notify('beforeOpen') === false) | |
return false; | |
//closeOnClick | |
if(this.options.closeOnClick){ | |
if(this.options.closeOnClick === true) | |
this.closeOnClickContainer = $(document.body); | |
else if(this.options.closeOnClick == 'container') | |
this.closeOnClickContainer = this.container; | |
else if (this.options.closeOnClick == 'overlay'){ | |
Control.Overlay.load(); | |
this.closeOnClickContainer = Control.Overlay.container; | |
}else | |
this.closeOnClickContainer = $(this.options.closeOnClick); | |
this.closeOnClickContainer.observe('click',this.closeHandler); | |
} | |
if(this.href && !this.options.iframe && !this.remoteContentLoaded){ | |
//link to image | |
this.remoteContentLoaded = true; | |
if(this.href.match(/\.(jpe?g|gif|png|tiff?)$/i)){ | |
var img = new Element('img'); | |
img.observe('load',function(img){ | |
this.getRemoteContentInsertionTarget().insert(img); | |
this.position(); | |
if(this.notify('onRemoteContentLoaded') !== false){ | |
if(this.options.indicator) | |
this.hideIndicator(); | |
this.finishOpen(); | |
} | |
}.bind(this,img)); | |
img.writeAttribute('src',this.href); | |
}else{ | |
//if this is an ajax window it will only open if the request is successful | |
if(!this.ajaxRequest){ | |
if(this.options.indicator) | |
this.showIndicator(); | |
this.ajaxRequest = new Ajax.Request(this.href,{ | |
method: this.options.method, | |
parameters: this.options.parameters, | |
onComplete: function(request){ | |
this.notify('onComplete',request); | |
this.ajaxRequest = false; | |
}.bind(this), | |
onSuccess: function(request){ | |
this.getRemoteContentInsertionTarget().insert(request.responseText); | |
this.notify('onSuccess',request); | |
if(this.notify('onRemoteContentLoaded') !== false){ | |
if(this.options.indicator) | |
this.hideIndicator(); | |
this.finishOpen(); | |
} | |
}.bind(this), | |
onFailure: function(request){ | |
this.notify('onFailure',request); | |
if(this.options.indicator) | |
this.hideIndicator(); | |
}.bind(this), | |
onException: function(request,e){ | |
this.notify('onException',request,e); | |
if(this.options.indicator) | |
this.hideIndicator(); | |
}.bind(this) | |
}); | |
} | |
} | |
return true; | |
}else if(this.options.iframe && !this.remoteContentLoaded){ | |
//iframe | |
this.remoteContentLoaded = true; | |
if(this.options.indicator) | |
this.showIndicator(); | |
this.getRemoteContentInsertionTarget().insert(Control.Window.iframeTemplate.evaluate({ | |
href: this.href | |
})); | |
var iframe = this.container.down('iframe'); | |
iframe.onload = function(){ | |
this.notify('onRemoteContentLoaded'); | |
if(this.options.indicator) | |
this.hideIndicator(); | |
iframe.onload = null; | |
}.bind(this); | |
} | |
this.finishOpen(event); | |
return true | |
}, | |
close: function(event){ //event may or may not be present | |
if(!this.isOpen || this.notify('beforeClose',event) === false) | |
return false; | |
if(this.options.closeOnClick) | |
this.closeOnClickContainer.stopObserving('click',this.closeHandler); | |
if(this.options.fade){ | |
this.effects.fade = new Effect.Fade(this.container,{ | |
queue: { | |
position: 'front', | |
scope: 'Control.Window' + this.numberInSequence | |
}, | |
from: 1, | |
to: 0, | |
duration: this.options.fadeDuration / 2, | |
afterFinish: function(){ | |
if(this.iFrameShim) | |
this.iFrameShim.hide(); | |
this.isOpen = false; | |
this.notify('afterClose'); | |
}.bind(this) | |
}); | |
}else{ | |
this.container.hide(); | |
if(this.iFrameShim) | |
this.iFrameShim.hide(); | |
} | |
if(this.ajaxRequest) | |
this.ajaxRequest.transport.abort(); | |
if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center') | |
Event.stopObserving(window,'resize',this.positionHandler); | |
if(!this.options.draggable && this.options.position == 'center') | |
Event.stopObserving(window,'scroll',this.positionHandler); | |
if(this.options.indicator) | |
this.hideIndicator(); | |
if(!this.options.fade){ | |
this.isOpen = false; | |
this.notify('afterClose'); | |
} | |
return true; | |
}, | |
position: function(event){ | |
//this is up top for performance reasons | |
if(this.options.position == 'mouse'){ | |
var xy = [Event.pointerX(event),Event.pointerY(event)]; | |
this.container.setStyle({ | |
top: xy[1] + $value(this.options.offsetTop) + 'px', | |
left: xy[0] + $value(this.options.offsetLeft) + 'px' | |
}); | |
return; | |
} | |
var container_dimensions = this.container.getDimensions(); | |
var viewport_dimensions = document.viewport.getDimensions(); | |
Position.prepare(); | |
var offset_left = (Position.deltaX + Math.floor((viewport_dimensions.width - container_dimensions.width) / 2)); | |
var offset_top = (Position.deltaY + ((viewport_dimensions.height > container_dimensions.height) ? Math.floor((viewport_dimensions.height - container_dimensions.height) / 2) : 0)); | |
if(this.options.position == 'center' || this.options.position == 'center_once'){ | |
this.container.setStyle({ | |
top: (container_dimensions.height <= viewport_dimensions.height) ? ((offset_top != null && offset_top > 0) ? offset_top : 0) + 'px' : 0, | |
left: (container_dimensions.width <= viewport_dimensions.width) ? ((offset_left != null && offset_left > 0) ? offset_left : 0) + 'px' : 0 | |
}); | |
}else if(this.options.position == 'relative'){ | |
var xy = this.sourceContainer.cumulativeOffset(); | |
var top = xy[1] + $value(this.options.offsetTop); | |
var left = xy[0] + $value(this.options.offsetLeft); | |
this.container.setStyle({ | |
top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0, | |
left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0 | |
}); | |
}else if(this.options.position.length){ | |
var top = $value(this.options.position[1]) + $value(this.options.offsetTop); | |
var left = $value(this.options.position[0]) + $value(this.options.offsetLeft); | |
this.container.setStyle({ | |
top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0, | |
left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0 | |
}); | |
} | |
if(this.iFrameShim) | |
this.updateIFrameShimZIndex(); | |
}, | |
ensureInBounds: function(){ | |
if(!this.isOpen) | |
return; | |
var viewport_dimensions = document.viewport.getDimensions(); | |
var container_offset = this.container.cumulativeOffset(); | |
var container_dimensions = this.container.getDimensions(); | |
if(container_offset.left + container_dimensions.width > viewport_dimensions.width){ | |
this.container.setStyle({ | |
left: (Math.max(0,viewport_dimensions.width - container_dimensions.width)) + 'px' | |
}); | |
} | |
if(container_offset.top + container_dimensions.height > viewport_dimensions.height){ | |
this.container.setStyle({ | |
top: (Math.max(0,viewport_dimensions.height - container_dimensions.height)) + 'px' | |
}); | |
} | |
}, | |
bringToFront: function(){ | |
Control.Window.bringToFront(this); | |
this.notify('bringToFront'); | |
}, | |
destroy: function(){ | |
this.container.stopObserving('mousedown',this.bringToFrontHandler); | |
if(this.draggable){ | |
Draggables.removeObserver(this.container); | |
this.draggable.handle.stopObserving('mousedown',this.bringToFrontHandler); | |
this.draggable.destroy(); | |
} | |
if(this.resizable){ | |
Resizables.removeObserver(this.container); | |
this.resizable.handle.stopObserving('mousedown',this.bringToFrontHandler); | |
this.resizable.destroy(); | |
} | |
if(this.container && !this.sourceContainer) | |
this.container.remove(); | |
if(this.sourceContainer){ | |
if(this.options.hover){ | |
this.sourceContainer.stopObserving('mouseenter',this.sourceContainerOpenHandler); | |
this.sourceContainer.stopObserving('mouseleave',this.sourceContainerCloseHandler); | |
if(this.options.position == 'mouse') | |
this.sourceContainer.stopObserving('mousemove',this.sourceContainerMouseMoveHandler); | |
}else | |
this.sourceContainer.stopObserving('click',this.sourceContainerOpenHandler); | |
} | |
if(this.iFrameShim) | |
this.iFrameShim.destroy(); | |
Event.stopObserving(window,'resize',this.outOfBoundsPositionHandler); | |
Control.Window.windows = Control.Window.windows.without(this); | |
this.notify('afterDestroy'); | |
}, | |
//private | |
applyResizable: function(){ | |
if(this.options.resizable){ | |
if(typeof(Resizable) == "undefined") | |
throw "Control.Window requires resizable.js to be loaded."; | |
var resizable_handle = null; | |
if(this.options.resizable === true){ | |
resizable_handle = new Element('div',{ | |
className: 'resizable_handle' | |
}); | |
this.container.insert(resizable_handle); | |
}else | |
resizable_handle = $(this.options.resziable); | |
this.resizable = new Resizable(this.container,{ | |
handle: resizable_handle, | |
minHeight: this.options.minHeight, | |
minWidth: this.options.minWidth, | |
maxHeight: this.options.constrainToViewport ? function(element){ | |
//viewport height - top - total border height | |
return (document.viewport.getDimensions().height - parseInt(element.style.top || 0)) - (element.getHeight() - parseInt(element.style.height || 0)); | |
} : this.options.maxHeight, | |
maxWidth: this.options.constrainToViewport ? function(element){ | |
//viewport width - left - total border width | |
return (document.viewport.getDimensions().width - parseInt(element.style.left || 0)) - (element.getWidth() - parseInt(element.style.width || 0)); | |
} : this.options.maxWidth | |
}); | |
this.resizable.handle.observe('mousedown',this.bringToFrontHandler); | |
Resizables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){ | |
if(this.iFrameShim) | |
this.updateIFrameShimZIndex(); | |
this.notify('onResize'); | |
}.bind(this))); | |
} | |
}, | |
applyDraggable: function(){ | |
if(this.options.draggable){ | |
if(typeof(Draggables) == "undefined") | |
throw "Control.Window requires dragdrop.js to be loaded."; | |
var draggable_handle = null; | |
if(this.options.draggable === true){ | |
draggable_handle = new Element('div',{ | |
className: 'draggable_handle' | |
}); | |
this.container.insert(draggable_handle); | |
}else | |
draggable_handle = $(this.options.draggable); | |
this.draggable = new Draggable(this.container,{ | |
handle: draggable_handle, | |
constrainToViewport: this.options.constrainToViewport, | |
zindex: this.container.getStyle('z-index'), | |
starteffect: function(){ | |
if(Prototype.Browser.IE){ | |
this.old_onselectstart = document.onselectstart; | |
document.onselectstart = function(){ | |
return false; | |
}; | |
} | |
}.bind(this), | |
endeffect: function(){ | |
document.onselectstart = this.old_onselectstart; | |
}.bind(this) | |
}); | |
this.draggable.handle.observe('mousedown',this.bringToFrontHandler); | |
Draggables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){ | |
if(this.iFrameShim) | |
this.updateIFrameShimZIndex(); | |
this.notify('onDrag'); | |
}.bind(this))); | |
} | |
}, | |
createDefaultContainer: function(container){ | |
if(!this.container){ | |
//no container passed or found, create it | |
this.container = new Element('div',{ | |
id: 'control_window_' + this.numberInSequence | |
}); | |
$(document.body).insert(this.container); | |
if(typeof(container) == "string" && $(container) == null && !container.match(/^#(.+)$/) && !container.match(Control.Window.uriRegex)) | |
this.container.update(container); | |
} | |
}, | |
finishOpen: function(event){ | |
this.bringToFront(); | |
if(this.options.fade){ | |
if(typeof(Effect) == "undefined") | |
throw "Control.Window requires effects.js to be loaded." | |
if(this.effects.fade) | |
this.effects.fade.cancel(); | |
this.effects.appear = new Effect.Appear(this.container,{ | |
queue: { | |
position: 'end', | |
scope: 'Control.Window.' + this.numberInSequence | |
}, | |
from: 0, | |
to: 1, | |
duration: this.options.fadeDuration / 2, | |
afterFinish: function(){ | |
if(this.iFrameShim) | |
this.updateIFrameShimZIndex(); | |
this.isOpen = true; | |
this.notify('afterOpen'); | |
}.bind(this) | |
}); | |
}else | |
this.container.show(); | |
this.position(event); | |
if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center') | |
Event.observe(window,'resize',this.positionHandler,false); | |
if(!this.options.draggable && this.options.position == 'center') | |
Event.observe(window,'scroll',this.positionHandler,false); | |
if(!this.options.fade){ | |
this.isOpen = true; | |
this.notify('afterOpen'); | |
} | |
return true; | |
}, | |
showIndicator: function(){ | |
this.showIndicatorTimeout = window.setTimeout(function(){ | |
if(this.options.fade){ | |
this.indicatorEffects.appear = new Effect.Appear(this.indicator,{ | |
queue: { | |
position: 'front', | |
scope: 'Control.Window.indicator.' + this.numberInSequence | |
}, | |
from: 0, | |
to: 1, | |
duration: this.options.fadeDuration / 2 | |
}); | |
}else | |
this.indicator.show(); | |
}.bind(this),Control.Window.indicatorTimeout); | |
}, | |
hideIndicator: function(){ | |
if(this.showIndicatorTimeout) | |
window.clearTimeout(this.showIndicatorTimeout); | |
this.indicator.hide(); | |
}, | |
getRemoteContentInsertionTarget: function(){ | |
return typeof(this.options.insertRemoteContentAt) == "string" ? this.container.down(this.options.insertRemoteContentAt) : $(this.options.insertRemoteContentAt); | |
}, | |
updateIFrameShimZIndex: function(){ | |
if(this.iFrameShim) | |
this.iFrameShim.positionUnder(this.container); | |
} | |
}); | |
//class methods | |
Object.extend(Control.Window,{ | |
windows: [], | |
baseZIndex: 9999, | |
indicatorTimeout: 250, | |
iframeTemplate: new Template('<iframe src="#{href}" width="100%" height="100%" frameborder="0" allowtransparency="true"></iframe>'), | |
uriRegex: /^(\/|\#|https?\:\/\/|[\w]+\/)/, | |
bringToFront: function(w){ | |
Control.Window.windows = Control.Window.windows.without(w); | |
Control.Window.windows.push(w); | |
Control.Window.windows.each(function(w,i){ | |
var z_index = Control.Window.baseZIndex + i; | |
w.container.setStyle({ | |
zIndex: z_index | |
}); | |
if(w.isOpen){ | |
if(w.iFrameShim) | |
w.updateIFrameShimZIndex(); | |
} | |
if(w.options.draggable) | |
w.draggable.options.zindex = z_index; | |
}); | |
}, | |
open: function(container,options){ | |
var w = new Control.Window(container,options); | |
w.open(); | |
return w; | |
}, | |
//protected | |
initialZIndexForWindow: function(w){ | |
return Control.Window.baseZIndex + (Control.Window.windows.length - 1); | |
} | |
}); | |
Object.Event.extend(Control.Window); | |
//this is the observer for both Resizables and Draggables | |
Control.Window.LayoutUpdateObserver = Class.create({ | |
initialize: function(w,observer){ | |
this.w = w; | |
this.element = $(w.container); | |
this.observer = observer; | |
}, | |
onStart: Prototype.emptyFunction, | |
onEnd: function(event_name,instance){ | |
if(instance.element == this.element && this.iFrameShim) | |
this.w.updateIFrameShimZIndex(); | |
}, | |
onResize: function(event_name,instance){ | |
if(instance.element == this.element) | |
this.observer(this.element); | |
}, | |
onDrag: function(event_name,instance){ | |
if(instance.element == this.element) | |
this.observer(this.element); | |
} | |
}); | |
//overlay for Control.Modal | |
Control.Overlay = { | |
id: 'control_overlay', | |
loaded: false, | |
container: false, | |
lastOpacity: 0, | |
getStyles: function() { | |
return { | |
position: 'fixed', | |
top: 0, | |
left: 0, | |
width: '100%', | |
height: '100%', | |
zIndex: Control.Window.baseZIndex - 1 | |
}; | |
}, | |
getIeStyles: function() { | |
return { | |
position: 'absolute', | |
top: 0, | |
left: 0, | |
zIndex: Control.Window.baseZIndex - 1 | |
}; | |
}, | |
effects: { | |
fade: false, | |
appear: false | |
}, | |
load: function(){ | |
if(Control.Overlay.loaded) | |
return false; | |
Control.Overlay.loaded = true; | |
Control.Overlay.container = new Element('div',{ | |
id: Control.Overlay.id | |
}); | |
$(document.body).insert(Control.Overlay.container); | |
if(Prototype.Browser.IE){ | |
Control.Overlay.container.setStyle(Control.Overlay.getIeStyles()); | |
Event.observe(window,'scroll',Control.Overlay.positionOverlay); | |
Event.observe(window,'resize',Control.Overlay.positionOverlay); | |
Control.Overlay.observe('beforeShow',Control.Overlay.positionOverlay); | |
}else | |
Control.Overlay.container.setStyle(Control.Overlay.getStyles()); | |
Control.Overlay.iFrameShim = new IframeShim(); | |
Control.Overlay.iFrameShim.hide(); | |
Event.observe(window,'resize',Control.Overlay.positionIFrameShim); | |
Control.Overlay.container.hide(); | |
return true; | |
}, | |
unload: function(){ | |
if(!Control.Overlay.loaded) | |
return false; | |
Event.stopObserving(window,'resize',Control.Overlay.positionOverlay); | |
Control.Overlay.stopObserving('beforeShow',Control.Overlay.positionOverlay); | |
Event.stopObserving(window,'resize',Control.Overlay.positionIFrameShim); | |
Control.Overlay.iFrameShim.destroy(); | |
Control.Overlay.container.remove(); | |
Control.Overlay.loaded = false; | |
return true; | |
}, | |
show: function(opacity,fade){ | |
if(Control.Overlay.notify('beforeShow') === false) | |
return false; | |
Control.Overlay.lastOpacity = opacity; | |
Control.Overlay.positionIFrameShim(); | |
Control.Overlay.iFrameShim.show(); | |
if(fade){ | |
if(typeof(Effect) == "undefined") | |
throw "Control.Window requires effects.js to be loaded." | |
if(Control.Overlay.effects.fade) | |
Control.Overlay.effects.fade.cancel(); | |
Control.Overlay.effects.appear = new Effect.Appear(Control.Overlay.container,{ | |
queue: { | |
position: 'end', | |
scope: 'Control.Overlay' | |
}, | |
afterFinish: function(){ | |
Control.Overlay.notify('afterShow'); | |
}, | |
from: 0, | |
to: Control.Overlay.lastOpacity, | |
duration: (fade === true ? 0.75 : fade) / 2 | |
}); | |
}else{ | |
Control.Overlay.container.setStyle({ | |
opacity: opacity || 1 | |
}); | |
Control.Overlay.container.show(); | |
Control.Overlay.notify('afterShow'); | |
} | |
return true; | |
}, | |
hide: function(fade){ | |
if(Control.Overlay.notify('beforeHide') === false) | |
return false; | |
if(Control.Overlay.effects.appear) | |
Control.Overlay.effects.appear.cancel(); | |
Control.Overlay.iFrameShim.hide(); | |
if(fade){ | |
Control.Overlay.effects.fade = new Effect.Fade(Control.Overlay.container,{ | |
queue: { | |
position: 'front', | |
scope: 'Control.Overlay' | |
}, | |
afterFinish: function(){ | |
Control.Overlay.notify('afterHide'); | |
}, | |
from: Control.Overlay.lastOpacity, | |
to: 0, | |
duration: (fade === true ? 0.75 : fade) / 2 | |
}); | |
}else{ | |
Control.Overlay.container.hide(); | |
Control.Overlay.notify('afterHide'); | |
} | |
return true; | |
}, | |
positionIFrameShim: function(){ | |
if(Control.Overlay.container.visible()) | |
Control.Overlay.iFrameShim.positionUnder(Control.Overlay.container); | |
}, | |
//IE only | |
positionOverlay: function(){ | |
Control.Overlay.container.setStyle({ | |
width: document.body.clientWidth + 'px', | |
height: document.body.clientHeight + 'px' | |
}); | |
} | |
}; | |
Object.Event.extend(Control.Overlay); | |
Control.ToolTip = Class.create(Control.Window,{ | |
initialize: function($super,container,tooltip,options){ | |
$super(tooltip,Object.extend(Object.extend(Object.clone(Control.ToolTip.defaultOptions),options || {}),{ | |
position: 'mouse', | |
hover: container | |
})); | |
} | |
}); | |
Object.extend(Control.ToolTip,{ | |
defaultOptions: { | |
offsetLeft: 10 | |
} | |
}); | |
Control.Modal = Class.create(Control.Window,{ | |
initialize: function($super,container,options){ | |
Control.Modal.InstanceMethods.beforeInitialize.bind(this)(); | |
$super(container,Object.extend(Object.clone(Control.Modal.defaultOptions),options || {})); | |
}, | |
closeWithoutOverlay: function(){ | |
this.keepOverlay = true; | |
this.close(); | |
} | |
}); | |
Object.extend(Control.Modal,{ | |
defaultOptions: { | |
overlayOpacity: 0.5, | |
closeOnClick: 'overlay' | |
}, | |
current: false, | |
open: function(container,options){ | |
var modal = new Control.Modal(container,options); | |
modal.open(); | |
return modal; | |
}, | |
close: function(){ | |
if(Control.Modal.current) | |
Control.Modal.current.close(); | |
}, | |
InstanceMethods: { | |
beforeInitialize: function(){ | |
Control.Overlay.load(); | |
this.observe('beforeOpen',Control.Modal.Observers.beforeOpen.bind(this)); | |
this.observe('afterOpen',Control.Modal.Observers.afterOpen.bind(this)); | |
this.observe('afterClose',Control.Modal.Observers.afterClose.bind(this)); | |
} | |
}, | |
Observers: { | |
beforeOpen: function(){ | |
Control.Window.windows.without(this).each(function(w){ | |
if(w.closeWithoutOverlay && w.isOpen){ | |
w.closeWithoutOverlay(); | |
}else{ | |
w.close(); | |
} | |
}); | |
if(!Control.Overlay.overlayFinishedOpening){ | |
Control.Overlay.observeOnce('afterShow',function(){ | |
Control.Overlay.overlayFinishedOpening = true; | |
this.open(); | |
}.bind(this)); | |
Control.Overlay.show(this.options.overlayOpacity,this.options.fade ? this.options.fadeDuration : false); | |
throw $break; | |
} | |
}, | |
afterOpen: function(){ | |
Control.Overlay.show(this.options.overlayOpacity); | |
Control.Overlay.overlayFinishedOpening = true; | |
Control.Modal.current = this; | |
}, | |
afterClose: function(){ | |
if(!this.keepOverlay){ | |
Control.Overlay.hide(this.options.fade ? this.options.fadeDuration : false); | |
Control.Overlay.overlayFinishedOpening = false; | |
} | |
this.keepOverlay = false; | |
Control.Modal.current = false; | |
} | |
} | |
}); | |
Control.LightBox = Class.create(Control.Window,{ | |
initialize: function($super,container,options){ | |
this.allImagesLoaded = false; | |
if(options.modal){ | |
var options = Object.extend(Object.clone(Control.LightBox.defaultOptions),options || {}); | |
options = Object.extend(Object.clone(Control.Modal.defaultOptions),options); | |
options = Control.Modal.InstanceMethods.beforeInitialize.bind(this)(options); | |
$super(container,options); | |
}else | |
$super(container,Object.extend(Object.clone(Control.LightBox.defaultOptions),options || {})); | |
this.hasRemoteContent = this.href && !this.options.iframe; | |
if(this.hasRemoteContent) | |
this.observe('onRemoteContentLoaded',Control.LightBox.Observers.onRemoteContentLoaded.bind(this)); | |
else | |
this.applyImageObservers(); | |
this.observe('beforeOpen',Control.LightBox.Observers.beforeOpen.bind(this)); | |
}, | |
applyImageObservers:function(){ | |
var images = this.getImages(); | |
this.numberImagesToLoad = images.length; | |
this.numberofImagesLoaded = 0; | |
images.each(function(image){ | |
image.observe('load',function(image){ | |
++this.numberofImagesLoaded; | |
if(this.numberImagesToLoad == this.numberofImagesLoaded){ | |
this.allImagesLoaded = true; | |
this.onAllImagesLoaded(); | |
} | |
}.bind(this,image)); | |
image.hide(); | |
}.bind(this)); | |
}, | |
onAllImagesLoaded: function(){ | |
this.getImages().each(function(image){ | |
this.showImage(image); | |
}.bind(this)); | |
if(this.hasRemoteContent){ | |
if(this.options.indicator) | |
this.hideIndicator(); | |
this.finishOpen(); | |
}else | |
this.open(); | |
}, | |
getImages: function(){ | |
return this.container.select(Control.LightBox.imageSelector); | |
}, | |
showImage: function(image){ | |
image.show(); | |
} | |
}); | |
Object.extend(Control.LightBox,{ | |
imageSelector: 'img', | |
defaultOptions: {}, | |
Observers: { | |
beforeOpen: function(){ | |
if(!this.hasRemoteContent && !this.allImagesLoaded) | |
throw $break; | |
}, | |
onRemoteContentLoaded: function(){ | |
this.applyImageObservers(); | |
if(!this.allImagesLoaded) | |
throw $break; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment