magic_multi_connections 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +0 -0
- data/History.txt +3 -0
- data/Manifest.txt +32 -0
- data/README.txt +3 -0
- data/Rakefile +103 -0
- data/lib/ext_active_record/connection_specification.rb +24 -0
- data/lib/magic_multi_connections/connected.rb +29 -0
- data/lib/magic_multi_connections/module.rb +26 -0
- data/lib/magic_multi_connections/version.rb +9 -0
- data/lib/magic_multi_connections.rb +21 -0
- data/scripts/txt2html +67 -0
- data/scripts/txt2js +59 -0
- data/setup.rb +1585 -0
- data/test/connections/native_postgresql/connection.rb +20 -0
- data/test/fixtures/contact_repository.rb +3 -0
- data/test/fixtures/db_definitions/postgresql.sql +7 -0
- data/test/fixtures/people.yml +5 -0
- data/test/fixtures/person.rb +2 -0
- data/test/test_helper.rb +71 -0
- data/test/test_magic_multi_connections.rb +26 -0
- data/test/test_parent_module.rb +18 -0
- data/test/test_preexisting_module.rb +39 -0
- data/website/index.html +340 -0
- data/website/index.txt +223 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.js +3 -0
- data/website/template.rhtml +53 -0
- data/website/version-raw.js +3 -0
- data/website/version-raw.txt +2 -0
- data/website/version.js +4 -0
- data/website/version.txt +3 -0
- metadata +80 -0
data/website/index.txt
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
h1. Magic Multi-Connections
|
2
|
+
|
3
|
+
h1. → Ruby on Rails
|
4
|
+
|
5
|
+
h1. → ActiveRecords
|
6
|
+
|
7
|
+
h2. What
|
8
|
+
|
9
|
+
ActiveRecord models are allowed one connection to a database at a time, per class. Ruby on Rails sets up the default connection based on your database.yml configuration to automatically select *development*, *test* or *production*.
|
10
|
+
|
11
|
+
But, what if you want to access two or more databases - have 2+ connections open - at the same time. ActiveRecord requires that you subclass <code>ActiveRecord::Base</code>.
|
12
|
+
|
13
|
+
That prevents you doing migrations from one database to another. It prevents you using one set of model classes on two or more databases with the same schema.
|
14
|
+
|
15
|
+
Magic Multi-Connections allows you to write your models once, and use them for multiple database Rails databases at the same time. How? Using magical namespacing.
|
16
|
+
|
17
|
+
<pre syntax="ruby">class Person < ActiveRecord::Base; end
|
18
|
+
ActiveRecord::Base.establish_connection :production
|
19
|
+
Person.connection # => production
|
20
|
+
|
21
|
+
module ContactRepository
|
22
|
+
establish_connection :contact_repo
|
23
|
+
end
|
24
|
+
ContactRepository::Person.connection # => contact_repo
|
25
|
+
|
26
|
+
old_person = ContactRepository::Person.find_by_email(email)
|
27
|
+
person = old_person.create_as(Person)
|
28
|
+
</pre>
|
29
|
+
|
30
|
+
You do not have to redefine your models for the multi-connection module <code>ContactRepository</code>, they are automatically picked up for you. Magically.
|
31
|
+
|
32
|
+
h2. Installing
|
33
|
+
|
34
|
+
<pre syntax="ruby">sudo gem install magic_multi_connections</pre>
|
35
|
+
|
36
|
+
Rails: Add the following to the bottom of your <code>environment.rb</code> file
|
37
|
+
|
38
|
+
<pre syntax="ruby">require 'magic_multi_connections'</pre>
|
39
|
+
|
40
|
+
Ruby scripts: Add the following to the top of your script
|
41
|
+
|
42
|
+
<pre syntax="ruby">require 'rubygems'
|
43
|
+
require 'magic_multi_connections'</pre>
|
44
|
+
|
45
|
+
|
46
|
+
h2. Demonstration with Rails
|
47
|
+
|
48
|
+
A quick demonstration within Rails to provide a parallel "private" database for an application.
|
49
|
+
|
50
|
+
h3. 1. Create rails app
|
51
|
+
|
52
|
+
Using sqlite3 here, but use your preferred db:
|
53
|
+
|
54
|
+
<pre>> rails privacy -d sqlite3
|
55
|
+
> cd privacy
|
56
|
+
> ruby script/generate model Person
|
57
|
+
> cp config/environments/development.rb config/environments/private.rb
|
58
|
+
</pre>
|
59
|
+
|
60
|
+
The last line allows us to play with our *private* database within the console and rake tasks.
|
61
|
+
|
62
|
+
h3. 2. Edit *config/database.yml* and add our private database:
|
63
|
+
|
64
|
+
Add the following to the bottom of *config/database.yml*
|
65
|
+
|
66
|
+
<pre syntax="yaml">
|
67
|
+
private:
|
68
|
+
adapter: sqlite3
|
69
|
+
database: db/private.sqlite3
|
70
|
+
</pre>
|
71
|
+
|
72
|
+
h3. 3. Create a database schema
|
73
|
+
|
74
|
+
Edit *db/migrate/001_create_people.rb*
|
75
|
+
|
76
|
+
<pre syntax="ruby">class CreatePeople < ActiveRecord::Migration
|
77
|
+
def self.up
|
78
|
+
create_table :people do |t|
|
79
|
+
t.column :name, :string
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.down
|
84
|
+
drop_table :people
|
85
|
+
end
|
86
|
+
end
|
87
|
+
</pre>
|
88
|
+
|
89
|
+
From the command line, migrate this to our *development* and *private* databases:
|
90
|
+
|
91
|
+
<pre>> rake db:migrate
|
92
|
+
> rake db:migrate RAILS_ENV=private</pre>
|
93
|
+
|
94
|
+
h3. 4. Add some data to databases
|
95
|
+
|
96
|
+
<pre syntax="ruby">> ruby script/console development
|
97
|
+
>> Person.create(:name => 'Nic')
|
98
|
+
>> Person.create(:name => 'Banjo')
|
99
|
+
>> exit
|
100
|
+
> ruby script/console private
|
101
|
+
>> Person.create(:name => 'Super Magical Nic')
|
102
|
+
>> exit</pre>
|
103
|
+
|
104
|
+
Now it should be obvious which database our app is accessing.
|
105
|
+
|
106
|
+
h3. 5. Update environment.rb
|
107
|
+
|
108
|
+
Edit *config/environment.rb* to include the library and create the *Private* module.
|
109
|
+
|
110
|
+
Add the following to the end of the file.
|
111
|
+
|
112
|
+
<pre syntax="ruby">
|
113
|
+
require "magic_multi_connections"
|
114
|
+
|
115
|
+
module Private
|
116
|
+
establish_connection :private
|
117
|
+
end
|
118
|
+
</pre>
|
119
|
+
|
120
|
+
This tells the *Private* module that any model class that is requested will be assigned a connection to the *private* database, as defined in the *config/database.yml* specification.
|
121
|
+
|
122
|
+
h3. 6. Setup a controller
|
123
|
+
|
124
|
+
Create a *people* controller with a *index* action
|
125
|
+
|
126
|
+
<pre>> ruby script/generate controller people index</pre>
|
127
|
+
|
128
|
+
Edit your controller *app/controllers/people_controller.rb*
|
129
|
+
|
130
|
+
<pre syntax="ruby">class PeopleController < ApplicationController
|
131
|
+
|
132
|
+
before_filter :check_private
|
133
|
+
|
134
|
+
def index
|
135
|
+
@people = @mod::Person.find(:all)
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
def check_private
|
140
|
+
@mod = params[:private] ? Private : Object
|
141
|
+
end
|
142
|
+
end
|
143
|
+
</pre>
|
144
|
+
|
145
|
+
The *check_private* action is a hack to demonstrate one method for selecting the database. In reality, a stupid one for hiding a "private" database, but you get the point.
|
146
|
+
|
147
|
+
After *check_private* is called, *@mod* is either the *Object* (default) module or the *Private* module. The *Person* class is accessible through either of them.
|
148
|
+
|
149
|
+
Yes, <code>@mod::Person</code> is uglier than just <code>Person</code>. Sorry.
|
150
|
+
|
151
|
+
h3. 7. Setup the index.rhtml view
|
152
|
+
|
153
|
+
Edit *app/views/people/index.rhtml*
|
154
|
+
|
155
|
+
<pre syntax="html"><h1><%= @mod::Person %></h1>
|
156
|
+
<h2><%= @mod::Person.active_connection_name %></h2>
|
157
|
+
|
158
|
+
<ol>
|
159
|
+
<% @people.each do |person| -%>
|
160
|
+
<li><%= "#{person.name} - #{person.class}" %></li>
|
161
|
+
<% end -%>
|
162
|
+
</ol>
|
163
|
+
</pre>
|
164
|
+
|
165
|
+
h3. 8. Test our multi-connection Rails app
|
166
|
+
|
167
|
+
Launch the app
|
168
|
+
|
169
|
+
<pre>> mongrel_rails start</pre>
|
170
|
+
|
171
|
+
In your browser, go to "http://localhost:3000/people":http://localhost:3000/people and see the list of people: Nic and Banjo.
|
172
|
+
|
173
|
+
Now, to see the private database, go to "http://localhost:3000/people?private=1":http://localhost:3000/people?private=1 and see the private list. Its so private, I won't show it here.
|
174
|
+
|
175
|
+
Note: you may need to refresh the private url to see the results. Perhaps Rails is caching the SQL even though its a different connection to a different database. If you know what's happening here, please "email me":mailto:drnicwilliams@gmail.com?subject=MMC+caching+problem or the "forum":mailto:magicmodels@googlegroups.com?subject=MMC+caching+problem. Thanks.
|
176
|
+
|
177
|
+
h3. 9. End
|
178
|
+
|
179
|
+
There ends our example of a Rails application using one model class to access multiple databases cleanly.
|
180
|
+
|
181
|
+
h2. Pre-existing modules
|
182
|
+
|
183
|
+
In Rails, model files are placed in the *app/models* folder. If you place them in a subfolder, say *app/models/admin*, then those model classes are access via module namespaces.
|
184
|
+
|
185
|
+
So, *app/models/admin/page.rb* represents the <code>Admin::Page</code> class.
|
186
|
+
|
187
|
+
Magic Multi-Connections works for these model classes as well.
|
188
|
+
|
189
|
+
<pre syntax="ruby">Admin.establish_connection :admin_dev
|
190
|
+
Admin::Page.active_connection_name # => "Admin::Page"
|
191
|
+
</pre>
|
192
|
+
|
193
|
+
h2. Other tricks
|
194
|
+
|
195
|
+
The Magic Multi-Connections includes <code>diff</code> and <code>diff?</code> methods extracted from the "Riff plugin":http://tfletcher.com/svn/rails-plugins/riff/README by "Tim Fletcher":http://tfletcher.com/, so that <code>id</code> values are ignored when comparing objects from different connections/namespaces.
|
196
|
+
|
197
|
+
<pre syntax="ruby"># Detect differences between two activerecords, e.g.
|
198
|
+
new_person = Person.find_by_username('drnic')
|
199
|
+
old_person = ContactRepository::Person.find_by_username('drnic')
|
200
|
+
|
201
|
+
new_person.diff?(old_person) # => true
|
202
|
+
|
203
|
+
new_person.diff(old_person) # => { :name => ['Dr Nic', 'Nic'], :age => [32, 20] }
|
204
|
+
</pre>
|
205
|
+
|
206
|
+
h2. Dr Nic's Blog
|
207
|
+
|
208
|
+
"http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and
|
209
|
+
other stories and things.
|
210
|
+
|
211
|
+
h2. Forum
|
212
|
+
|
213
|
+
Discussion about the Magic Multi-Connections is on the Magic Models forum:
|
214
|
+
|
215
|
+
"http://groups.google.com/group/magicmodels":http://groups.google.com/group/magicmodels
|
216
|
+
|
217
|
+
h2. Licence
|
218
|
+
|
219
|
+
This code is free to use under the terms of the MIT licence.
|
220
|
+
|
221
|
+
h2. Contact
|
222
|
+
|
223
|
+
Comments are welcome. Send an email to "Dr Nic Williams":mailto:drnicwilliams@gmail.com.
|
@@ -0,0 +1,285 @@
|
|
1
|
+
|
2
|
+
/****************************************************************
|
3
|
+
* *
|
4
|
+
* curvyCorners *
|
5
|
+
* ------------ *
|
6
|
+
* *
|
7
|
+
* This script generates rounded corners for your divs. *
|
8
|
+
* *
|
9
|
+
* Version 1.2.9 *
|
10
|
+
* Copyright (c) 2006 Cameron Cooke *
|
11
|
+
* By: Cameron Cooke and Tim Hutchison. *
|
12
|
+
* *
|
13
|
+
* *
|
14
|
+
* Website: http://www.curvycorners.net *
|
15
|
+
* Email: info@totalinfinity.com *
|
16
|
+
* Forum: http://www.curvycorners.net/forum/ *
|
17
|
+
* *
|
18
|
+
* *
|
19
|
+
* This library is free software; you can redistribute *
|
20
|
+
* it and/or modify it under the terms of the GNU *
|
21
|
+
* Lesser General Public License as published by the *
|
22
|
+
* Free Software Foundation; either version 2.1 of the *
|
23
|
+
* License, or (at your option) any later version. *
|
24
|
+
* *
|
25
|
+
* This library is distributed in the hope that it will *
|
26
|
+
* be useful, but WITHOUT ANY WARRANTY; without even the *
|
27
|
+
* implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
28
|
+
* PARTICULAR PURPOSE. See the GNU Lesser General Public *
|
29
|
+
* License for more details. *
|
30
|
+
* *
|
31
|
+
* You should have received a copy of the GNU Lesser *
|
32
|
+
* General Public License along with this library; *
|
33
|
+
* Inc., 59 Temple Place, Suite 330, Boston, *
|
34
|
+
* MA 02111-1307 USA *
|
35
|
+
* *
|
36
|
+
****************************************************************/
|
37
|
+
|
38
|
+
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
|
39
|
+
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
|
40
|
+
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
|
41
|
+
else
|
42
|
+
{ var startIndex = 1; var boxCol = arguments;}
|
43
|
+
var curvyCornersCol = new Array(); if(arguments[0].validTags)
|
44
|
+
var validElements = arguments[0].validTags; else
|
45
|
+
var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
|
46
|
+
{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
|
47
|
+
{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
|
48
|
+
}
|
49
|
+
this.objects = curvyCornersCol; this.applyCornersToAll = function()
|
50
|
+
{ for(var x = 0, k = this.objects.length; x < k; x++)
|
51
|
+
{ this.objects[x].applyCorners();}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
function curvyObject()
|
55
|
+
{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
|
56
|
+
this.box.innerHTML = ""; this.applyCorners = function()
|
57
|
+
{ for(var t = 0; t < 2; t++)
|
58
|
+
{ switch(t)
|
59
|
+
{ case 0:
|
60
|
+
if(this.settings.tl || this.settings.tr)
|
61
|
+
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
|
62
|
+
break; case 1:
|
63
|
+
if(this.settings.bl || this.settings.br)
|
64
|
+
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
|
65
|
+
break;}
|
66
|
+
}
|
67
|
+
if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
|
68
|
+
{ if(i > -1 < 4)
|
69
|
+
{ var cc = corners[i]; if(!this.settings[cc])
|
70
|
+
{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
|
71
|
+
{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
|
72
|
+
newCorner.style.backgroundColor = this.boxColour; else
|
73
|
+
newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
|
74
|
+
{ case "tl":
|
75
|
+
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
|
76
|
+
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
|
77
|
+
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
|
78
|
+
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
|
79
|
+
newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
else
|
83
|
+
{ if(this.masterCorners[this.settings[cc].radius])
|
84
|
+
{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
|
85
|
+
else
|
86
|
+
{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
|
87
|
+
{ if((intx +1) >= borderRadius)
|
88
|
+
var y1 = -1; else
|
89
|
+
var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
|
90
|
+
{ if((intx) >= borderRadius)
|
91
|
+
var y2 = -1; else
|
92
|
+
var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
|
93
|
+
var y3 = -1; else
|
94
|
+
var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
|
95
|
+
if((intx) >= j)
|
96
|
+
var y4 = -1; else
|
97
|
+
var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
|
98
|
+
{ for(var inty = (y1 + 1); inty < y2; inty++)
|
99
|
+
{ if(this.settings.antiAlias)
|
100
|
+
{ if(this.backgroundImage != "")
|
101
|
+
{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
|
102
|
+
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
|
103
|
+
else
|
104
|
+
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
|
105
|
+
}
|
106
|
+
else
|
107
|
+
{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
if(this.settings.antiAlias)
|
111
|
+
{ if(y3 >= y2)
|
112
|
+
{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
|
113
|
+
}
|
114
|
+
else
|
115
|
+
{ if(y3 >= y1)
|
116
|
+
{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
|
117
|
+
}
|
118
|
+
var outsideColour = this.borderColour;}
|
119
|
+
else
|
120
|
+
{ var outsideColour = this.boxColour; var y3 = y1;}
|
121
|
+
if(this.settings.antiAlias)
|
122
|
+
{ for(var inty = (y3 + 1); inty < y4; inty++)
|
123
|
+
{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
|
127
|
+
if(cc != "br")
|
128
|
+
{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
|
129
|
+
{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
|
130
|
+
if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
|
131
|
+
switch(cc)
|
132
|
+
{ case "tr":
|
133
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
|
134
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
|
135
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
if(newCorner)
|
140
|
+
{ switch(cc)
|
141
|
+
{ case "tl":
|
142
|
+
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
|
143
|
+
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
|
144
|
+
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
|
145
|
+
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
|
150
|
+
radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
|
151
|
+
{ if(z == "t" || z == "b")
|
152
|
+
{ if(radiusDiff[z])
|
153
|
+
{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
|
154
|
+
newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
|
155
|
+
{ case "tl":
|
156
|
+
newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
|
157
|
+
newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
|
158
|
+
newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
|
159
|
+
newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
|
160
|
+
}
|
161
|
+
var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
|
162
|
+
{ case "t":
|
163
|
+
if(this.topContainer)
|
164
|
+
{ if(this.settings.tl.radius && this.settings.tr.radius)
|
165
|
+
{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
|
166
|
+
newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
|
167
|
+
this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
|
168
|
+
break; case "b":
|
169
|
+
if(this.bottomContainer)
|
170
|
+
{ if(this.settings.bl.radius && this.settings.br.radius)
|
171
|
+
{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
|
172
|
+
newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
|
173
|
+
}
|
174
|
+
break;}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
if(this.settings.autoPad == true && this.boxPadding > 0)
|
178
|
+
{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
|
179
|
+
contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
|
180
|
+
contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
|
181
|
+
}
|
182
|
+
this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
|
183
|
+
{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
|
184
|
+
{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
|
185
|
+
else
|
186
|
+
{ pixel.style.backgroundColor = colour;}
|
187
|
+
if (transAmount != 100)
|
188
|
+
setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
|
189
|
+
}
|
190
|
+
function insertAfter(parent, node, referenceNode)
|
191
|
+
{ parent.insertBefore(node, referenceNode.nextSibling);}
|
192
|
+
function BlendColour(Col1, Col2, Col1Fraction)
|
193
|
+
{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
|
194
|
+
function IntToHex(strNum)
|
195
|
+
{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
|
196
|
+
function MakeHex(x)
|
197
|
+
{ if((x >= 0) && (x <= 9))
|
198
|
+
{ return x;}
|
199
|
+
else
|
200
|
+
{ switch(x)
|
201
|
+
{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
function pixelFraction(x, y, r)
|
205
|
+
{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
|
206
|
+
{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
|
207
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
|
208
|
+
{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
|
209
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
|
210
|
+
{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
|
211
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
|
212
|
+
{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
|
213
|
+
switch (whatsides)
|
214
|
+
{ case "LeftRight":
|
215
|
+
pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
|
216
|
+
pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
|
217
|
+
pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
|
218
|
+
pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
|
219
|
+
pixelfraction = 1;}
|
220
|
+
return pixelfraction;}
|
221
|
+
function rgb2Hex(rgbColour)
|
222
|
+
{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
|
223
|
+
catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
|
224
|
+
return hexColour;}
|
225
|
+
function rgb2Array(rgbColour)
|
226
|
+
{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
|
227
|
+
function setOpacity(obj, opacity)
|
228
|
+
{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
|
229
|
+
{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
|
230
|
+
else if(typeof(obj.style.opacity) != "undefined")
|
231
|
+
{ obj.style.opacity = opacity/100;}
|
232
|
+
else if(typeof(obj.style.MozOpacity) != "undefined")
|
233
|
+
{ obj.style.MozOpacity = opacity/100;}
|
234
|
+
else if(typeof(obj.style.filter) != "undefined")
|
235
|
+
{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
|
236
|
+
else if(typeof(obj.style.KHTMLOpacity) != "undefined")
|
237
|
+
{ obj.style.KHTMLOpacity = opacity/100;}
|
238
|
+
}
|
239
|
+
function inArray(array, value)
|
240
|
+
{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
|
241
|
+
return false;}
|
242
|
+
function inArrayKey(array, value)
|
243
|
+
{ for(key in array){ if(key === value) return true;}
|
244
|
+
return false;}
|
245
|
+
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
|
246
|
+
else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
|
247
|
+
else { elm['on' + evType] = fn;}
|
248
|
+
}
|
249
|
+
function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
|
250
|
+
}
|
251
|
+
function format_colour(colour)
|
252
|
+
{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
|
253
|
+
{ if(colour.substr(0, 3) == "rgb")
|
254
|
+
{ returnColour = rgb2Hex(colour);}
|
255
|
+
else if(colour.length == 4)
|
256
|
+
{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
|
257
|
+
else
|
258
|
+
{ returnColour = colour;}
|
259
|
+
}
|
260
|
+
return returnColour;}
|
261
|
+
function get_style(obj, property, propertyNS)
|
262
|
+
{ try
|
263
|
+
{ if(obj.currentStyle)
|
264
|
+
{ var returnVal = eval("obj.currentStyle." + property);}
|
265
|
+
else
|
266
|
+
{ if(isSafari && obj.style.display == "none")
|
267
|
+
{ obj.style.display = ""; var wasHidden = true;}
|
268
|
+
var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
|
269
|
+
{ obj.style.display = "none";}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
catch(e)
|
273
|
+
{ }
|
274
|
+
return returnVal;}
|
275
|
+
function getElementsByClass(searchClass, node, tag)
|
276
|
+
{ var classElements = new Array(); if(node == null)
|
277
|
+
node = document; if(tag == null)
|
278
|
+
tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
|
279
|
+
{ if(pattern.test(els[i].className))
|
280
|
+
{ classElements[j] = els[i]; j++;}
|
281
|
+
}
|
282
|
+
return classElements;}
|
283
|
+
function newCurvyError(errorMessage)
|
284
|
+
{ return new Error("curvyCorners Error:\n" + errorMessage)
|
285
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
body {
|
2
|
+
background-color: #4D2E67;
|
3
|
+
font-family: "Georgia", sans-serif;
|
4
|
+
font-size: 16px;
|
5
|
+
line-height: 1.6em;
|
6
|
+
padding: 1.6em 0 0 0;
|
7
|
+
color: #eee;
|
8
|
+
}
|
9
|
+
h1, h2, h3, h4, h5, h6 {
|
10
|
+
color: #A79712;
|
11
|
+
}
|
12
|
+
h1 {
|
13
|
+
font-family: sans-serif;
|
14
|
+
font-weight: normal;
|
15
|
+
font-size: 4em;
|
16
|
+
line-height: 0.8em;
|
17
|
+
letter-spacing: -0.1ex;
|
18
|
+
margin: 5px;
|
19
|
+
color: #FFEDFA;
|
20
|
+
}
|
21
|
+
h1.primary {
|
22
|
+
color: #A79712;
|
23
|
+
}
|
24
|
+
|
25
|
+
li {
|
26
|
+
padding: 0;
|
27
|
+
margin: 0;
|
28
|
+
list-style-type: square;
|
29
|
+
}
|
30
|
+
a {
|
31
|
+
color: #A79712;
|
32
|
+
font-weight: normal;
|
33
|
+
text-decoration: underline;
|
34
|
+
}
|
35
|
+
blockquote {
|
36
|
+
font-size: 90%;
|
37
|
+
font-style: italic;
|
38
|
+
border-left: 1px solid #eee;
|
39
|
+
padding-left: 1em;
|
40
|
+
}
|
41
|
+
.caps {
|
42
|
+
font-size: 80%;
|
43
|
+
}
|
44
|
+
|
45
|
+
strong {
|
46
|
+
background-color: #D09FDC;
|
47
|
+
color: #1B1B1A;
|
48
|
+
font-weight: normal;
|
49
|
+
}
|
50
|
+
|
51
|
+
#main {
|
52
|
+
width: 45em;
|
53
|
+
padding: 0;
|
54
|
+
margin: 0 auto;
|
55
|
+
}
|
56
|
+
.coda {
|
57
|
+
text-align: right;
|
58
|
+
color: #77f;
|
59
|
+
font-size: smaller;
|
60
|
+
}
|
61
|
+
|
62
|
+
table {
|
63
|
+
font-size: 90%;
|
64
|
+
line-height: 1.4em;
|
65
|
+
color: #ff8;
|
66
|
+
background-color: #111;
|
67
|
+
padding: 2px 10px 2px 10px;
|
68
|
+
border-style: dashed;
|
69
|
+
}
|
70
|
+
|
71
|
+
th {
|
72
|
+
color: #fff;
|
73
|
+
}
|
74
|
+
|
75
|
+
td {
|
76
|
+
padding: 2px 10px 2px 10px;
|
77
|
+
}
|
78
|
+
|
79
|
+
.success {
|
80
|
+
color: #0CC52B;
|
81
|
+
}
|
82
|
+
|
83
|
+
.failed {
|
84
|
+
color: #E90A1B;
|
85
|
+
}
|
86
|
+
|
87
|
+
.unknown {
|
88
|
+
color: #995000;
|
89
|
+
}
|
90
|
+
pre, code {
|
91
|
+
font-family: monospace;
|
92
|
+
font-size: 90%;
|
93
|
+
line-height: 1.4em;
|
94
|
+
color: #ff8;
|
95
|
+
background-color: #111;
|
96
|
+
padding: 2px 10px 2px 10px;
|
97
|
+
}
|
98
|
+
.comment { color: #aaa; font-style: italic; }
|
99
|
+
.keyword { color: #eff; font-weight: bold; }
|
100
|
+
.punct { color: #eee; font-weight: bold; }
|
101
|
+
.symbol { color: #0bb; }
|
102
|
+
.string { color: #6b4; }
|
103
|
+
.ident { color: #ff8; }
|
104
|
+
.constant { color: #66f; }
|
105
|
+
.regex { color: #ec6; }
|
106
|
+
.number { color: #F99; }
|
107
|
+
.expr { color: #227; }
|
108
|
+
|
109
|
+
#version {
|
110
|
+
float: right;
|
111
|
+
text-align: right;
|
112
|
+
font-family: sans-serif;
|
113
|
+
font-weight: normal;
|
114
|
+
color: #FFEDFA;
|
115
|
+
background-color: #A79712;
|
116
|
+
padding: 15px 20px 10px 20px;
|
117
|
+
margin: 0 auto;
|
118
|
+
margin-top: 15px;
|
119
|
+
border: 3px solid #FFEDFA;
|
120
|
+
}
|
121
|
+
|
122
|
+
#version .numbers {
|
123
|
+
display: block;
|
124
|
+
font-size: 4em;
|
125
|
+
line-height: 0.8em;
|
126
|
+
letter-spacing: -0.1ex;
|
127
|
+
}
|
128
|
+
|
129
|
+
#version a {
|
130
|
+
text-decoration: none;
|
131
|
+
color: #FFEDFA;
|
132
|
+
}
|
133
|
+
|
134
|
+
.clickable {
|
135
|
+
cursor: pointer;
|
136
|
+
cursor: hand;
|
137
|
+
}
|
138
|
+
|
data/website/template.js
ADDED