This commit is contained in:
matt.zukowski 2008-11-14 16:54:38 -05:00
Родитель 7ac93405e3 c2bf6ee471
Коммит b4b08e42aa
6 изменённых файлов: 6017 добавлений и 0 удалений

375
lib/setup.rb Normal file
Просмотреть файл

@ -0,0 +1,375 @@
#!/usr/bin/env ruby
$:.unshift File.dirname(__FILE__) + "/../../lib"
require 'camping'
require 'camping/db'
require 'camping/session'
Camping.goes :Setup
module Setup
include Camping::Session
end
module Setup::Controllers
class Index < R '/'
def get
render :index
end
end
# Renders static pages from the ./static directory
#
class Static < R '/static/(.+)'
MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript',
'.jpg' => 'image/jpeg','.png' => 'image/png'}
PATH = File.expand_path(File.dirname(__FILE__))
def get(path)
@headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
unless path.include? ".." # prevent directory traversal attacks
@headers['X-Sendfile'] = "#{PATH}/static/#{path}"
else
@status = "403"
"403 - Invalid path"
end
end
end
class Style < R '/styles.css'
def get
@headers["Content-Type"] = "text/css; charset=utf-8"
@body = %{
body {
font-family: Utopia, Georga, serif;
}
h1.header {
background-color: #fef;
margin: 0; padding: 10px;
}
div.content {
padding: 10px;
}
.page{
position: absolute;
top: 70;
left: 100;
visibility: hidden;
text-align: right;
}
.tooltip {
border:1px solid #000;
background-color:#fff;
width:200px;
font-family:"Lucida Grande",Verdana;
font-size:10px;
color:#333;
}
}
end
end
class JavaScript < R '/javascript.js'
def get
@headers["Content-Type"] = "text/javascript; charset=utf-8"
@body = %{
var currentLayer = 'web_server_select';
function showLayer(lyr){
hideLayer(currentLayer);
document.getElementById(lyr).style.visibility = 'visible';
currentLayer = lyr;
};
function hideLayer(lyr){
document.getElementById(lyr).style.visibility = 'hidden';
};
/*
* Displays the results of the form. This is a debug only function.
* It will not be used in production
*/
function showValues(form){
var values = '';
var len = form.length - 1; //Leave off Submit Button
for(i=0; i<len; i++){
if(form[i].id.indexOf("C")!=-1||form[i].id.indexOf("B")!=-1)//Skip Continue and Back Buttons
continue;
if(form[i].id.indexOf("R")!=-1&&!form[i].checked)//Skip unchecked radio Back Buttons
continue;
if(form[i].id.indexOf("O")!=-1) //If other jump to the next box
i++;
values += form[i].name;
values += ': ';
values += form[i].value;
values += '\\n';
}
alert(values);
};
/*
* For a given radio name return the checked button value
*/
function getRadioValue(radio_name) {
var radio = document.forms['rubycas_form'].elements[radio_name]
for (var i=0; i < radio.length; i++)
if (radio[i].checked)
return radio[i].value;
};
// Wait for DOM to load
document.observe('dom:loaded',function(){
// Hide the other text box.
// TODO Maybe change this to use a css class name not the ID so we can
// hide many at once if needed
$('T_othersqltext').hide();
//Show the other box if other is selected.
//TODO change observed event click only works once...
Event.observe($('O_othersql'),'click',function(){$('T_othersqltext').toggle();});
});
}
end
end
end
module Setup::Views
def layout
html do
head do
title 'RubyCAS Server Configuration'
link :rel => 'stylesheet', :type => 'text/css', :href => '/styles.css'
script :type => 'text/javascript', :src => '/static/prototype.js'
script :type => 'text/javascript', :src => '/static/livepipe.js'
script :type => 'text/javascript', :src => '/static/window.js'
script :type => 'text/javascript', :src => '/javascript.js'
end
body do
self << yield
end
end
end
def index
form(:id => "rubycas_form", :method => "POST", :action => "javascript:void(0)", :onSubmit => "showValues(this)") {
h2 { "Welcome to RubyCAS-Server configuration." }
text "This is a step by step process for configuring you CAS server."
web_server_select
webrick_config
mongrel_config
database_select
mysql_config
sqlite_config
page3
}
end
# Web Server Selection Page
#
def web_server_select
div(:id => "web_server_select", :class => "page", :style => "visibility:visible;") {
h3 { "Step 1. Select the web server to use." }
text "Webrick"
input(:type => "radio", :id => 'R_webrick', :name => "webserver", :value => "webrick", :checked => true)
help("run as a stand-alone webrick server; this is the default method.")
br
text "Mongrel"
input(:type => "radio", :id => 'R_mongrel', :name => "webserver", :value => "mongrel")
help("run as a stand-alone mongrel server; fast, but you'll need to install mongrel and run it behind an https reverse proxy like Pound or Apache 2.2's mod_proxy). <p>IMPORTANT: If you use mongrel, you will need to run the server behind a reverse proxy (Pound, Apache 2.2 with mod_proxy, etc.) since mongrel does not support SSL/HTTPS. See the RubyCAS-Server install docs for more info.")
br
text "CGI"
input(:type => "radio", :id => 'R_cgi', :name => "webserver", :value => "cgi")
help("slow, but simple to set up if you're already familiar with deploying CGI scripts")
br
text "fastCGI"
input(:type => "radio", :id => 'R_fastcgi', :name => "webserver", :value => "fastcgi")
help("see http://www.fastcgi.com (e.g. under Apache you can use this with mod_fastcgi)")
p {
input(:type => "button",
:id => "C_web_server_select",
:value => "Continue",
:onClick => "showLayer(getRadioValue('webserver'));")
}
}
end
# Webrick Configuration page
#
def webrick_config
div(:id => "webrick", :class => "page") {
h3 { "Step 1a. Enter the web server's details" }
text "port"
input(:type => "text", :id => "T_wb_port", :name => 'wb_port', :size => "20", :value => '443')
br
text "SSL Cert"
input(:type => "text", :id => "T_wb_ssl_cert", :name => 'wb_ssl_cert', :size => "20")
help(" /path/to/your/ssl.pem")
br
text "SSL Key"
input(:type => "text", :id => "T_wb_ssl_key", :name => 'wb_ssl_key', :size => "20")
help("OPTIONAL: If private key is separate from cert")
br
text "URI Path"
input(:type => "text", :id => "T_wb_uri_path", :name => 'wb_uri_path', :size => "20")
help("OPTIONAL: By default the login page will be available at the root path (e.g. https://example.foo/). The uri_path option lets you serve it from a different path (e.g. https://example.foo/cas). uri_path: /cas")
br
text "Bind address"
input(:type => "text", :id => "T_wb_bind_addr", :name => 'wb_bind_addr', :size => "20")
help("OPTIONAL: Bind the server to a specific address. Use 0.0.0.0 to listen on all available interfaces.")
p {
input(:type => "button", :id => "B_webrick_config", :value => "Go Back", :onClick => "showLayer('web_server_select')")
input(:type => "button", :id => "C_webrick_config", :value => "Continue", :onClick => "showLayer('database_select')")
}
}
end
# Mongrel Configuration Page
#
def mongrel_config
div(:id => "mongrel", :class => "page") {
h3 { "Step 1b. Enter the web server's details" }
text "port"
input(:type => "text", :id => "T_mg_port", :name => 'mg_port', :size => "20", :value => '110011')
br
text "URI Path"
input(:type => "text", :id => "T_mg_uri_path", :name => 'mg_uri_path', :size => "20")
br
text "Bind address"
input(:type => "text", :id => "T_mg_bind_addr", :name => 'mg_bind_addr', :size => "20")
p {
input(:type => "button", :id => "B_mongrel_config", :value => "Go Back", :onClick => "showLayer('web_server_select')")
input(:type => "button", :id => "C_mongrel_config", :value => "Continue", :onClick => "showLayer('database_select')")
}
}
end
# Database Selection Page
#
def database_select
div(:id => "database_select", :class => "page") {
h3 { "Step 2. Select the Database to use." }
text "MySQL"
input(:type => "radio", :id => 'R_mysql', :name => "database", :value => "mysql", :checked => true)
help("By default, we use MySQL, since it is widely used and does not require any additional ruby libraries besides ActiveRecord.")
br
text "SQLite"
input(:type => "radio", :id => 'R_sqlite', :name => "database", :value => "sqlite")
br
text "PostgreSQL"
input(:type => "radio", :id => 'R_psql', :name => "database", :value => "psgsql")
br
text "MSSQL"
input(:type => "radio", :id => 'R_mssql', :name => "database", :value => "mssql")
br
text "Other"
input(:type => "radio", :id => 'O_othersql', :name => "database", :value => "othersql")
input(:type => "text", :id => 'T_othersqltext', :name => 'other_database', :size => "20")
p {
input(:type => "button", :id => "B_database_select", :value => "Go Back", :onClick => "showLayer(getRadioValue('webserver'))")
input(:type => "button",
:id => "C_database_select",
:value => "Continue",
:onClick => "showLayer(getRadioValue('database'));")
}
}
end
# MySQL Setup page
#
def mysql_config
div(:id => "mysql", :class => "page") {
h3 { "Step 2a. Configure the MySQL Database." }
text "Database Name"
input(:type => "text", :id => "T_mysql_db_name", :name => 'mysql_db_name', :size => "20")
br
text "Username"
input(:type => "text", :id => "T_mysql_username", :name => 'mysql_username', :size => "20")
br
text "Password"
input(:type => "text", :id => "T_mysql_password", :name => 'mysql_password', :size => "20")
br
text "Host"
input(:type => "text", :id => "T_mysql_host", :name => 'mysql_host', :size => "20", :value => 'localhost')
p {
input(:type => "button", :id => "B_mysql_config", :value => "Go Back", :onClick => "showLayer('database_select')")
input(:type => "button", :id => "C_mysql_config", :value => "Continue", :onClick => "showLayer('page3')")
}
}
end
# SQLite setup page
#
def sqlite_config
div(:id => "sqlite", :class => "page") {
h3 { "Step 2b. Configure the SQLite Database." }
text "Database Name"
input(:type => "text", :id => "T_sqlite_db_name", :name => 'sqlite_db_name', :size => "20")
p {
input(:type => "button", :id => "B_sqlite_config", :value => "Go Back", :onClick => "showLayer('database_select')")
input(:type => "button", :id => "C_sqlite_config", :value => "Continue", :onClick => "showLayer('page3')")
}
}
end
# Dummie last page for now
# TODO - change to post to server
#
def page3
div(:id => "page3", :class => "page") {
h3 { "Step 3. XXX." }
text "XXX"
input(:type => "text", :id => "T22", :name => 'xxx', :size => "20")
p {
input(:type => "button", :id => "B3", :value => "Go Back", :onClick => "showLayer(getRadioValue('database'))")
input(:type => "submit", :value => "Submit", :id => "submit")
}
}
end
# Creates a '?' image which will display the help_text
# upon mouse over
#
def help(help_text)
@help_count = (@help_count) ? @help_count + 1 : 0
id = "help_#{@help_count}"
img(:id => id, :height => 20, :src => "/static/q_mark.png")
script {
text "var #{id} = new Control.ToolTip($('#{id}'),\"#{help_text}\",{className: 'tooltip'});"
}
end
end

356
lib/static/livepipe.js Normal file
Просмотреть файл

@ -0,0 +1,356 @@
/**
* @author Ryan Johnson <http://saucytiger.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._observers[event_name][i],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);
for(var i = 0; i < this._observers[event_name].length; ++i)
collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],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);
}
});
//mouseenter, mouseleave
//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch
Object.extend(Event, (function() {
var cache = Event.cache;
function getEventID(element) {
if (element._prototypeEventID) return element._prototypeEventID[0];
arguments.callee.id = arguments.callee.id || 1;
return element._prototypeEventID = [++arguments.callee.id];
}
function getDOMEventName(eventName) {
if (eventName && eventName.include(':')) return "dataavailable";
//begin extension
if(!Prototype.Browser.IE){
eventName = {
mouseenter: 'mouseover',
mouseleave: 'mouseout'
}[eventName] || eventName;
}
//end extension
return eventName;
}
function getCacheForID(id) {
return cache[id] = cache[id] || { };
}
function getWrappersForEventName(id, eventName) {
var c = getCacheForID(id);
return c[eventName] = c[eventName] || [];
}
function createWrapper(element, eventName, handler) {
var id = getEventID(element);
var c = getWrappersForEventName(id, eventName);
if (c.pluck("handler").include(handler)) return false;
var wrapper = function(event) {
if (!Event || !Event.extend ||
(event.eventName && event.eventName != eventName))
return false;
Event.extend(event);
handler.call(element, event);
};
//begin extension
if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){
wrapper = wrapper.wrap(function(proceed,event) {
var rel = event.relatedTarget;
var cur = event.currentTarget;
if(rel && rel.nodeType == Node.TEXT_NODE)
rel = rel.parentNode;
if(rel && rel != cur && !rel.descendantOf(cur))
return proceed(event);
});
}
//end extension
wrapper.handler = handler;
c.push(wrapper);
return wrapper;
}
function findWrapper(id, eventName, handler) {
var c = getWrappersForEventName(id, eventName);
return c.find(function(wrapper) { return wrapper.handler == handler });
}
function destroyWrapper(id, eventName, handler) {
var c = getCacheForID(id);
if (!c[eventName]) return false;
c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
}
function destroyCache() {
for (var id in cache)
for (var eventName in cache[id])
cache[id][eventName] = null;
}
if (window.attachEvent) {
window.attachEvent("onunload", destroyCache);
}
return {
observe: function(element, eventName, handler) {
element = $(element);
var name = getDOMEventName(eventName);
var wrapper = createWrapper(element, eventName, handler);
if (!wrapper) return element;
if (element.addEventListener) {
element.addEventListener(name, wrapper, false);
} else {
element.attachEvent("on" + name, wrapper);
}
return element;
},
stopObserving: function(element, eventName, handler) {
element = $(element);
var id = getEventID(element), name = getDOMEventName(eventName);
if (!handler && eventName) {
getWrappersForEventName(id, eventName).each(function(wrapper) {
element.stopObserving(eventName, wrapper.handler);
});
return element;
} else if (!eventName) {
Object.keys(getCacheForID(id)).each(function(eventName) {
element.stopObserving(eventName);
});
return element;
}
var wrapper = findWrapper(id, eventName, handler);
if (!wrapper) return element;
if (element.removeEventListener) {
element.removeEventListener(name, wrapper, false);
} else {
element.detachEvent("on" + name, wrapper);
}
destroyWrapper(id, eventName, handler);
return element;
},
fire: function(element, eventName, memo) {
element = $(element);
if (element == document && document.createEvent && !element.dispatchEvent)
element = document.documentElement;
var event;
if (document.createEvent) {
event = document.createEvent("HTMLEvents");
event.initEvent("dataavailable", true, true);
} else {
event = document.createEventObject();
event.eventType = "ondataavailable";
}
event.eventName = eventName;
event.memo = memo || { };
if (document.createEvent) {
element.dispatchEvent(event);
} else {
element.fireEvent(event.eventType, event);
}
return Event.extend(event);
}
};
})());
Object.extend(Event, Event.Methods);
Element.addMethods({
fire: Event.fire,
observe: Event.observe,
stopObserving: Event.stopObserving
});
Object.extend(document, {
fire: Element.Methods.fire.methodize(),
observe: Element.Methods.observe.methodize(),
stopObserving: Element.Methods.stopObserving.methodize()
});
//mouse:wheel
(function(){
function wheel(event){
var delta;
// normalize the delta
if(event.wheelDelta) // IE & Opera
delta = event.wheelDelta / 120;
else if (event.detail) // W3C
delta =- event.detail / 3;
if(!delta)
return;
var custom_event = event.element().fire('mouse:wheel',{
delta: delta
});
if(custom_event.stopped){
event.stop();
return false;
}
}
document.observe('mousewheel',wheel);
document.observe('DOMMouseScroll',wheel);
})();
/* End Core Extensions */
//from PrototypeUI
var IframeShim = Class.create({
initialize: function() {
this.element = new Element('iframe',{
style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
src: 'javascript:void(0);',
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
}).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;
}
});

4320
lib/static/prototype.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Двоичные данные
lib/static/q_mark.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.2 KiB

929
lib/static/window.js Normal file
Просмотреть файл

@ -0,0 +1,929 @@
/**
* @author Ryan Johnson <http://saucytiger.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', '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, //wether 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.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){
Resizables.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"></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,
styles: {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: 9998
},
ieStyles: {
position: 'absolute',
top: 0,
left: 0,
zIndex: 9998
},
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.ieStyles);
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.styles);
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 || {}));
}
});
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.overlayFinishedOpening = false;
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(){
if(!this.overlayFinishedOpening){
Control.Overlay.observeOnce('afterShow',function(){
this.overlayFinishedOpening = true;
this.open();
}.bind(this));
Control.Overlay.show(this.options.overlayOpacity,this.options.fade ? this.options.fadeDuration : false);
throw $break;
}else
Control.Window.windows.without(this).invoke('close');
},
afterOpen: function(){
Control.Modal.current = this;
},
afterClose: function(){
Control.Overlay.hide(this.options.fade ? this.options.fadeDuration : false);
Control.Modal.current = false;
this.overlayFinishedOpening = 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;
}
}
});

37
rubycas-server.gemspec Normal file
Просмотреть файл

@ -0,0 +1,37 @@
Gem::Specification.new do |s|
s.name = %q{rubycas-server}
s.version = "0.6.99.336"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Matt Zukowski"]
s.date = %q{2008-10-14}
s.description = %q{Provides single sign-on authentication for web applications using the CAS protocol.}
s.email = ["matt@zukowski.ca"]
s.executables = ["rubycas-server", "rubycas-server-ctl"]
s.extra_rdoc_files = ["CHANGELOG.txt", "History.txt", "LICENSE.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "website/index.txt"]
s.files = ["CHANGELOG.txt", "History.txt", "LICENSE.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "Rakefile", "bin/rubycas-server", "bin/rubycas-server-ctl", "casserver.db", "casserver.log", "casserver_db.log", "config.example.yml", "config/hoe.rb", "config/requirements.rb", "custom_views.example.rb", "lib/casserver.rb", "lib/casserver/authenticators/active_directory_ldap.rb", "lib/casserver/authenticators/base.rb", "lib/casserver/authenticators/client_certificate.rb", "lib/casserver/authenticators/ldap.rb", "lib/casserver/authenticators/ntlm.rb", "lib/casserver/authenticators/open_id.rb", "lib/casserver/authenticators/sql.rb", "lib/casserver/authenticators/sql_encrypted.rb", "lib/casserver/authenticators/sql_md5.rb", "lib/casserver/authenticators/test.rb", "lib/casserver/cas.rb", "lib/casserver/conf.rb", "lib/casserver/controllers.rb", "lib/casserver/environment.rb", "lib/casserver/models.rb", "lib/casserver/postambles.rb", "lib/casserver/utils.rb", "lib/casserver/version.rb", "lib/casserver/views.rb", "lib/rubycas-server.rb", "lib/rubycas-server/version.rb", "lib/themes/cas.css", "lib/themes/notice.png", "lib/themes/ok.png", "lib/themes/simple/bg.png", "lib/themes/simple/login_box_bg.png", "lib/themes/simple/logo.png", "lib/themes/simple/theme.css", "lib/themes/urbacon/bg.png", "lib/themes/urbacon/login_box_bg.png", "lib/themes/urbacon/logo.png", "lib/themes/urbacon/theme.css", "lib/themes/warning.png", "misc/basic_cas_single_signon_mechanism_diagram.png", "misc/basic_cas_single_signon_mechanism_diagram.svg", "resources/init.d.sh", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "tasks/deployment.rake", "tasks/environment.rake", "tasks/website.rake", "vendor/isaac_0.9.1/LICENSE", "vendor/isaac_0.9.1/README", "vendor/isaac_0.9.1/TODO", "vendor/isaac_0.9.1/VERSIONS", "vendor/isaac_0.9.1/crypt/ISAAC.rb", "vendor/isaac_0.9.1/isaac.gemspec", "vendor/isaac_0.9.1/setup.rb", "vendor/isaac_0.9.1/test/TC_ISAAC.rb", "website/index.html", "website/index.txt", "website/javascripts/rounded_corners_lite.inc.js", "website/stylesheets/screen.css", "website/template.html.erb"]
s.has_rdoc = true
s.homepage = %q{http://rubycas-server.rubyforge.org}
s.post_install_message = %q{
For more information on RubyCAS-Server, see http://code.google.com/p/rubycas-server
}
s.rdoc_options = ["--main", "README.txt"]
s.require_paths = ["lib"]
s.rubyforge_project = %q{rubycas-server}
s.rubygems_version = %q{1.2.0}
s.summary = %q{Provides single sign-on authentication for web applications using the CAS protocol.}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
if current_version >= 3 then
s.add_development_dependency(%q<hoe>, [">= 1.7.0"])
else
s.add_dependency(%q<hoe>, [">= 1.7.0"])
end
else
s.add_dependency(%q<hoe>, [">= 1.7.0"])
end
end