merged in wmernagh's fork
This commit is contained in:
Коммит
b4b08e42aa
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
});
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 9.2 KiB |
|
@ -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;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче