vmail 0.0.7 → 0.0.8
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/.gitignore +3 -0
- data/NOTES +7 -2
- data/README.markdown +310 -72
- data/lib/vmail.rb +8 -0
- data/lib/vmail.vim +53 -21
- data/lib/vmail/imap_client.rb +19 -4
- data/lib/vmail/message_formatter.rb +32 -11
- data/lib/vmail/options.rb +14 -13
- data/lib/vmail/version.rb +1 -1
- data/test/fixtures/rfc_part.eml +306 -0
- data/test/message_formatter_test.rb +12 -1
- data/vmail.gemspec +3 -3
- data/website/.gitignore +1 -0
- data/website/bottom.markdown +20 -0
- data/website/gen.rb +22 -0
- data/website/images-vmail/1-small.png +0 -0
- data/website/images-vmail/1.png +0 -0
- data/website/images-vmail/attach-small.png +0 -0
- data/website/images-vmail/attach.png +0 -0
- data/website/images-vmail/autocomplete-small.png +0 -0
- data/website/images-vmail/autocomplete.png +0 -0
- data/website/lightbox2/css/lightbox.css +27 -0
- data/website/lightbox2/images/bullet.gif +0 -0
- data/website/lightbox2/images/close.gif +0 -0
- data/website/lightbox2/images/closelabel.gif +0 -0
- data/website/lightbox2/images/donate-button.gif +0 -0
- data/website/lightbox2/images/download-icon.gif +0 -0
- data/website/lightbox2/images/image-1.jpg +0 -0
- data/website/lightbox2/images/loading.gif +0 -0
- data/website/lightbox2/images/nextlabel.gif +0 -0
- data/website/lightbox2/images/prevlabel.gif +0 -0
- data/website/lightbox2/images/thumb-1.jpg +0 -0
- data/website/lightbox2/index.html +63 -0
- data/website/lightbox2/js/builder.js +136 -0
- data/website/lightbox2/js/effects.js +1122 -0
- data/website/lightbox2/js/lightbox.js +498 -0
- data/website/lightbox2/js/prototype.js +4221 -0
- data/website/lightbox2/js/scriptaculous.js +58 -0
- data/website/stylesheets-vmail/960.css +1 -0
- data/website/stylesheets-vmail/reset.css +1 -0
- data/website/stylesheets-vmail/site.css +59 -0
- data/website/stylesheets-vmail/syntax-colors.css +33 -0
- data/website/stylesheets-vmail/text.css +1 -0
- data/website/top.markdown +9 -0
- data/website/vmail-template.html +50 -0
- data/website/vmail.html +438 -0
- metadata +48 -10
- data/gmail.vim +0 -180
- data/wrapper.rb +0 -8
@@ -78,8 +78,19 @@ describe Vmail::MessageFormatter do
|
|
78
78
|
assert_equal 2, attachments.size
|
79
79
|
assert_equal ['image/png', 'image/gif'], attachments.map(&:mime_type)
|
80
80
|
end
|
81
|
-
|
82
81
|
end
|
83
82
|
|
83
|
+
describe 'message with message/rfc822 part' do
|
84
|
+
before do
|
85
|
+
@raw = read_fixture('rfc_part.eml')
|
86
|
+
@mail = Mail.new(@raw)
|
87
|
+
@formatter = Vmail::MessageFormatter.new(@mail)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should extract the message/rfc822 part' do
|
91
|
+
assert_match /I hope everyone is having a great holiday season/,
|
92
|
+
@formatter.process_body
|
93
|
+
end
|
94
|
+
end
|
84
95
|
end
|
85
96
|
|
data/vmail.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Daniel Choi"]
|
10
10
|
s.email = ["dhchoi@gmail.com"]
|
11
|
-
s.homepage = "http://
|
11
|
+
s.homepage = "http://danielchoi.com/software/vmail.html"
|
12
12
|
s.summary = %q{A Vim interface to Gmail}
|
13
13
|
s.description = %q{Manage your email with Vim}
|
14
14
|
|
@@ -19,6 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency 'mail'
|
23
|
-
s.add_dependency 'highline'
|
22
|
+
s.add_dependency 'mail', '>= 2.2.12'
|
23
|
+
s.add_dependency 'highline', '>= 1.6.1'
|
24
24
|
end
|
data/website/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
images-original/
|
@@ -0,0 +1,20 @@
|
|
1
|
+
## How to support the vmail project
|
2
|
+
|
3
|
+
If you find vmail very useful, feel free to drop me a note to say so. If you have
|
4
|
+
a bug to report or a good feature to suggest, please file it on the [issue tracker][1].
|
5
|
+
Few things make this software developer happier than knowing that people find my
|
6
|
+
software useful.
|
7
|
+
|
8
|
+
[1]:https://github.com/danchoi/vmail/issues
|
9
|
+
|
10
|
+
Please do not feel obligated to donate money simply because you use vmail. But if you
|
11
|
+
want to donate some money to support the independent software developer behind
|
12
|
+
vmail, use this PayPal button:
|
13
|
+
|
14
|
+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
15
|
+
<input type="hidden" name="cmd" value="_s-xclick">
|
16
|
+
<input type="hidden" name="hosted_button_id" value="YC3S3D5RFMJSC">
|
17
|
+
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
|
18
|
+
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
|
19
|
+
</form>
|
20
|
+
|
data/website/gen.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
require 'rdiscount'
|
3
|
+
|
4
|
+
top = RDiscount.new(File.read("top.markdown")).to_html
|
5
|
+
|
6
|
+
readme = File.expand_path("../../README.markdown", __FILE__)
|
7
|
+
|
8
|
+
raise "no README" unless File.size?(readme)
|
9
|
+
|
10
|
+
middle_markdown = File.read(readme).split(/^\s*$/)
|
11
|
+
|
12
|
+
middle_markdown = middle_markdown[2..-1].join("\n\n")
|
13
|
+
|
14
|
+
middle = RDiscount.new(middle_markdown).to_html
|
15
|
+
|
16
|
+
bottom = RDiscount.new(File.read("bottom.markdown")).to_html
|
17
|
+
|
18
|
+
content = [top, middle, bottom].join("\n\n")
|
19
|
+
|
20
|
+
template = File.read("vmail-template.html")
|
21
|
+
out = Liquid::Template.parse(template).render 'content' => content, 'timestamp' => Time.now.to_i
|
22
|
+
puts out
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
|
2
|
+
#lightbox img{ width: auto; height: auto;}
|
3
|
+
#lightbox a img{ border: none; }
|
4
|
+
|
5
|
+
#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; }
|
6
|
+
#imageContainer{ padding: 10px; }
|
7
|
+
|
8
|
+
#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; }
|
9
|
+
#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; }
|
10
|
+
#imageContainer>#hoverNav{ left: 0;}
|
11
|
+
#hoverNav a{ outline: none;}
|
12
|
+
|
13
|
+
#prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
|
14
|
+
#prevLink { left: 0; float: left;}
|
15
|
+
#nextLink { right: 0; float: right;}
|
16
|
+
#prevLink:hover, #prevLink:visited:hover { background: url(../images/prevlabel.gif) left 15% no-repeat; }
|
17
|
+
#nextLink:hover, #nextLink:visited:hover { background: url(../images/nextlabel.gif) right 15% no-repeat; }
|
18
|
+
|
19
|
+
#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
|
20
|
+
|
21
|
+
#imageData{ padding:0 10px; color: #666; }
|
22
|
+
#imageData #imageDetails{ width: 70%; float: left; text-align: left; }
|
23
|
+
#imageData #caption{ font-weight: bold; }
|
24
|
+
#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
|
25
|
+
#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;}
|
26
|
+
|
27
|
+
#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; }
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
4
|
+
<head>
|
5
|
+
|
6
|
+
<title>Lightbox JS v2.0 | Test Page</title>
|
7
|
+
|
8
|
+
<link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />
|
9
|
+
|
10
|
+
<script src="js/prototype.js" type="text/javascript"></script>
|
11
|
+
<script src="js/scriptaculous.js?load=effects,builder" type="text/javascript"></script>
|
12
|
+
<script src="js/lightbox.js" type="text/javascript"></script>
|
13
|
+
|
14
|
+
<style type="text/css">
|
15
|
+
body{ color: #333; font: 13px 'Lucida Grande', Verdana, sans-serif; }
|
16
|
+
</style>
|
17
|
+
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
|
21
|
+
|
22
|
+
<h1><a href="http://www.lokeshdhakar.com/projects/lightbox2/">Lightbox JS <em>v2.04</em></a></h1>
|
23
|
+
<p><a href="http://www.lokeshdhakar.com">by Lokesh Dhakar</a></p>
|
24
|
+
|
25
|
+
<h2>Example</h2>
|
26
|
+
|
27
|
+
<a href="images/image-1.jpg" rel="lightbox"><img src="images/thumb-1.jpg" width="100" height="40" alt="" /></a>
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
<h2>How to Use:</h2>
|
33
|
+
<h3>Part 1 - Setup</h3>
|
34
|
+
<ol>
|
35
|
+
<li>Lightbox v2.0 uses the Prototype Framework and Scriptaculous Effects Library. You will need to include these three Javascript files in your header.
|
36
|
+
<pre><code><script type="text/javascript" src="js/prototype.js"></script>
|
37
|
+
<script type="text/javascript" src="js/scriptaculous.js?load=effects,builder"></script>
|
38
|
+
<script type="text/javascript" src="js/lightbox.js"></script>
|
39
|
+
</code></pre>
|
40
|
+
</li>
|
41
|
+
<li>Include the Lightbox CSS file (or append your active stylesheet with the Lightbox styles).
|
42
|
+
<pre><code><link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />
|
43
|
+
</code></pre>
|
44
|
+
</li>
|
45
|
+
<li>Check the CSS and make sure the referenced <code>prevlabel.gif</code> and <code>nextlabel.gif</code> files are in the right location. Also, make sure the <code>loading.gif</code> and <code>closelabel.gif</code> files as referenced near the top of the <code>lightbox.js</code> file are in the right location.</li>
|
46
|
+
</ol>
|
47
|
+
<h3>Part 2 - Activate</h3>
|
48
|
+
<ol>
|
49
|
+
<li>Add a <code>rel="lightbox"</code> attribute to any link tag to activate the lightbox. For example:
|
50
|
+
<pre><code><a href="images/image-1.jpg" rel="lightbox" title="my caption">image #1</a>
|
51
|
+
</code></pre>
|
52
|
+
<em>Optional: </em>Use the <code>title</code> attribute if you want to show a caption. </li>
|
53
|
+
<li>If you have a set of related images that you would like to group, follow step one but additionally include a group name between square brackets in the rel attribute. For example:
|
54
|
+
<pre><code><a href="images/image-1.jpg" rel="lightbox[roadtrip]">image #1</a>
|
55
|
+
<a href="images/image-2.jpg" rel="lightbox[roadtrip]">image #2</a>
|
56
|
+
<a href="images/image-3.jpg" rel="lightbox[roadtrip]">image #3</a>
|
57
|
+
</code></pre>
|
58
|
+
No limits to the number of image sets per page or how many images are allowed in each set. Go nuts!</li>
|
59
|
+
</ol>
|
60
|
+
|
61
|
+
|
62
|
+
</body>
|
63
|
+
</html>
|
@@ -0,0 +1,136 @@
|
|
1
|
+
// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
|
2
|
+
|
3
|
+
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4
|
+
//
|
5
|
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
6
|
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
7
|
+
|
8
|
+
var Builder = {
|
9
|
+
NODEMAP: {
|
10
|
+
AREA: 'map',
|
11
|
+
CAPTION: 'table',
|
12
|
+
COL: 'table',
|
13
|
+
COLGROUP: 'table',
|
14
|
+
LEGEND: 'fieldset',
|
15
|
+
OPTGROUP: 'select',
|
16
|
+
OPTION: 'select',
|
17
|
+
PARAM: 'object',
|
18
|
+
TBODY: 'table',
|
19
|
+
TD: 'table',
|
20
|
+
TFOOT: 'table',
|
21
|
+
TH: 'table',
|
22
|
+
THEAD: 'table',
|
23
|
+
TR: 'table'
|
24
|
+
},
|
25
|
+
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
|
26
|
+
// due to a Firefox bug
|
27
|
+
node: function(elementName) {
|
28
|
+
elementName = elementName.toUpperCase();
|
29
|
+
|
30
|
+
// try innerHTML approach
|
31
|
+
var parentTag = this.NODEMAP[elementName] || 'div';
|
32
|
+
var parentElement = document.createElement(parentTag);
|
33
|
+
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
34
|
+
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
|
35
|
+
} catch(e) {}
|
36
|
+
var element = parentElement.firstChild || null;
|
37
|
+
|
38
|
+
// see if browser added wrapping tags
|
39
|
+
if(element && (element.tagName.toUpperCase() != elementName))
|
40
|
+
element = element.getElementsByTagName(elementName)[0];
|
41
|
+
|
42
|
+
// fallback to createElement approach
|
43
|
+
if(!element) element = document.createElement(elementName);
|
44
|
+
|
45
|
+
// abort if nothing could be created
|
46
|
+
if(!element) return;
|
47
|
+
|
48
|
+
// attributes (or text)
|
49
|
+
if(arguments[1])
|
50
|
+
if(this._isStringOrNumber(arguments[1]) ||
|
51
|
+
(arguments[1] instanceof Array) ||
|
52
|
+
arguments[1].tagName) {
|
53
|
+
this._children(element, arguments[1]);
|
54
|
+
} else {
|
55
|
+
var attrs = this._attributes(arguments[1]);
|
56
|
+
if(attrs.length) {
|
57
|
+
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
58
|
+
parentElement.innerHTML = "<" +elementName + " " +
|
59
|
+
attrs + "></" + elementName + ">";
|
60
|
+
} catch(e) {}
|
61
|
+
element = parentElement.firstChild || null;
|
62
|
+
// workaround firefox 1.0.X bug
|
63
|
+
if(!element) {
|
64
|
+
element = document.createElement(elementName);
|
65
|
+
for(attr in arguments[1])
|
66
|
+
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
|
67
|
+
}
|
68
|
+
if(element.tagName.toUpperCase() != elementName)
|
69
|
+
element = parentElement.getElementsByTagName(elementName)[0];
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
// text, or array of children
|
74
|
+
if(arguments[2])
|
75
|
+
this._children(element, arguments[2]);
|
76
|
+
|
77
|
+
return element;
|
78
|
+
},
|
79
|
+
_text: function(text) {
|
80
|
+
return document.createTextNode(text);
|
81
|
+
},
|
82
|
+
|
83
|
+
ATTR_MAP: {
|
84
|
+
'className': 'class',
|
85
|
+
'htmlFor': 'for'
|
86
|
+
},
|
87
|
+
|
88
|
+
_attributes: function(attributes) {
|
89
|
+
var attrs = [];
|
90
|
+
for(attribute in attributes)
|
91
|
+
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
|
92
|
+
'="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"');
|
93
|
+
return attrs.join(" ");
|
94
|
+
},
|
95
|
+
_children: function(element, children) {
|
96
|
+
if(children.tagName) {
|
97
|
+
element.appendChild(children);
|
98
|
+
return;
|
99
|
+
}
|
100
|
+
if(typeof children=='object') { // array can hold nodes and text
|
101
|
+
children.flatten().each( function(e) {
|
102
|
+
if(typeof e=='object')
|
103
|
+
element.appendChild(e)
|
104
|
+
else
|
105
|
+
if(Builder._isStringOrNumber(e))
|
106
|
+
element.appendChild(Builder._text(e));
|
107
|
+
});
|
108
|
+
} else
|
109
|
+
if(Builder._isStringOrNumber(children))
|
110
|
+
element.appendChild(Builder._text(children));
|
111
|
+
},
|
112
|
+
_isStringOrNumber: function(param) {
|
113
|
+
return(typeof param=='string' || typeof param=='number');
|
114
|
+
},
|
115
|
+
build: function(html) {
|
116
|
+
var element = this.node('div');
|
117
|
+
$(element).update(html.strip());
|
118
|
+
return element.down();
|
119
|
+
},
|
120
|
+
dump: function(scope) {
|
121
|
+
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
|
122
|
+
|
123
|
+
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
|
124
|
+
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
|
125
|
+
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
|
126
|
+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
|
127
|
+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
|
128
|
+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
|
129
|
+
|
130
|
+
tags.each( function(tag){
|
131
|
+
scope[tag] = function() {
|
132
|
+
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
|
133
|
+
}
|
134
|
+
});
|
135
|
+
}
|
136
|
+
}
|
@@ -0,0 +1,1122 @@
|
|
1
|
+
// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
|
2
|
+
|
3
|
+
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4
|
+
// Contributors:
|
5
|
+
// Justin Palmer (http://encytemedia.com/)
|
6
|
+
// Mark Pilgrim (http://diveintomark.org/)
|
7
|
+
// Martin Bialasinki
|
8
|
+
//
|
9
|
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
10
|
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
11
|
+
|
12
|
+
// converts rgb() and #xxx to #xxxxxx format,
|
13
|
+
// returns self (or first argument) if not convertable
|
14
|
+
String.prototype.parseColor = function() {
|
15
|
+
var color = '#';
|
16
|
+
if (this.slice(0,4) == 'rgb(') {
|
17
|
+
var cols = this.slice(4,this.length-1).split(',');
|
18
|
+
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
|
19
|
+
} else {
|
20
|
+
if (this.slice(0,1) == '#') {
|
21
|
+
if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
|
22
|
+
if (this.length==7) color = this.toLowerCase();
|
23
|
+
}
|
24
|
+
}
|
25
|
+
return (color.length==7 ? color : (arguments[0] || this));
|
26
|
+
};
|
27
|
+
|
28
|
+
/*--------------------------------------------------------------------------*/
|
29
|
+
|
30
|
+
Element.collectTextNodes = function(element) {
|
31
|
+
return $A($(element).childNodes).collect( function(node) {
|
32
|
+
return (node.nodeType==3 ? node.nodeValue :
|
33
|
+
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
|
34
|
+
}).flatten().join('');
|
35
|
+
};
|
36
|
+
|
37
|
+
Element.collectTextNodesIgnoreClass = function(element, className) {
|
38
|
+
return $A($(element).childNodes).collect( function(node) {
|
39
|
+
return (node.nodeType==3 ? node.nodeValue :
|
40
|
+
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
|
41
|
+
Element.collectTextNodesIgnoreClass(node, className) : ''));
|
42
|
+
}).flatten().join('');
|
43
|
+
};
|
44
|
+
|
45
|
+
Element.setContentZoom = function(element, percent) {
|
46
|
+
element = $(element);
|
47
|
+
element.setStyle({fontSize: (percent/100) + 'em'});
|
48
|
+
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
|
49
|
+
return element;
|
50
|
+
};
|
51
|
+
|
52
|
+
Element.getInlineOpacity = function(element){
|
53
|
+
return $(element).style.opacity || '';
|
54
|
+
};
|
55
|
+
|
56
|
+
Element.forceRerendering = function(element) {
|
57
|
+
try {
|
58
|
+
element = $(element);
|
59
|
+
var n = document.createTextNode(' ');
|
60
|
+
element.appendChild(n);
|
61
|
+
element.removeChild(n);
|
62
|
+
} catch(e) { }
|
63
|
+
};
|
64
|
+
|
65
|
+
/*--------------------------------------------------------------------------*/
|
66
|
+
|
67
|
+
var Effect = {
|
68
|
+
_elementDoesNotExistError: {
|
69
|
+
name: 'ElementDoesNotExistError',
|
70
|
+
message: 'The specified DOM element does not exist, but is required for this effect to operate'
|
71
|
+
},
|
72
|
+
Transitions: {
|
73
|
+
linear: Prototype.K,
|
74
|
+
sinoidal: function(pos) {
|
75
|
+
return (-Math.cos(pos*Math.PI)/2) + 0.5;
|
76
|
+
},
|
77
|
+
reverse: function(pos) {
|
78
|
+
return 1-pos;
|
79
|
+
},
|
80
|
+
flicker: function(pos) {
|
81
|
+
var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
|
82
|
+
return pos > 1 ? 1 : pos;
|
83
|
+
},
|
84
|
+
wobble: function(pos) {
|
85
|
+
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
|
86
|
+
},
|
87
|
+
pulse: function(pos, pulses) {
|
88
|
+
pulses = pulses || 5;
|
89
|
+
return (
|
90
|
+
((pos % (1/pulses)) * pulses).round() == 0 ?
|
91
|
+
((pos * pulses * 2) - (pos * pulses * 2).floor()) :
|
92
|
+
1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
|
93
|
+
);
|
94
|
+
},
|
95
|
+
spring: function(pos) {
|
96
|
+
return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
|
97
|
+
},
|
98
|
+
none: function(pos) {
|
99
|
+
return 0;
|
100
|
+
},
|
101
|
+
full: function(pos) {
|
102
|
+
return 1;
|
103
|
+
}
|
104
|
+
},
|
105
|
+
DefaultOptions: {
|
106
|
+
duration: 1.0, // seconds
|
107
|
+
fps: 100, // 100= assume 66fps max.
|
108
|
+
sync: false, // true for combining
|
109
|
+
from: 0.0,
|
110
|
+
to: 1.0,
|
111
|
+
delay: 0.0,
|
112
|
+
queue: 'parallel'
|
113
|
+
},
|
114
|
+
tagifyText: function(element) {
|
115
|
+
var tagifyStyle = 'position:relative';
|
116
|
+
if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
|
117
|
+
|
118
|
+
element = $(element);
|
119
|
+
$A(element.childNodes).each( function(child) {
|
120
|
+
if (child.nodeType==3) {
|
121
|
+
child.nodeValue.toArray().each( function(character) {
|
122
|
+
element.insertBefore(
|
123
|
+
new Element('span', {style: tagifyStyle}).update(
|
124
|
+
character == ' ' ? String.fromCharCode(160) : character),
|
125
|
+
child);
|
126
|
+
});
|
127
|
+
Element.remove(child);
|
128
|
+
}
|
129
|
+
});
|
130
|
+
},
|
131
|
+
multiple: function(element, effect) {
|
132
|
+
var elements;
|
133
|
+
if (((typeof element == 'object') ||
|
134
|
+
Object.isFunction(element)) &&
|
135
|
+
(element.length))
|
136
|
+
elements = element;
|
137
|
+
else
|
138
|
+
elements = $(element).childNodes;
|
139
|
+
|
140
|
+
var options = Object.extend({
|
141
|
+
speed: 0.1,
|
142
|
+
delay: 0.0
|
143
|
+
}, arguments[2] || { });
|
144
|
+
var masterDelay = options.delay;
|
145
|
+
|
146
|
+
$A(elements).each( function(element, index) {
|
147
|
+
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
|
148
|
+
});
|
149
|
+
},
|
150
|
+
PAIRS: {
|
151
|
+
'slide': ['SlideDown','SlideUp'],
|
152
|
+
'blind': ['BlindDown','BlindUp'],
|
153
|
+
'appear': ['Appear','Fade']
|
154
|
+
},
|
155
|
+
toggle: function(element, effect) {
|
156
|
+
element = $(element);
|
157
|
+
effect = (effect || 'appear').toLowerCase();
|
158
|
+
var options = Object.extend({
|
159
|
+
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
|
160
|
+
}, arguments[2] || { });
|
161
|
+
Effect[element.visible() ?
|
162
|
+
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
|
167
|
+
|
168
|
+
/* ------------- core effects ------------- */
|
169
|
+
|
170
|
+
Effect.ScopedQueue = Class.create(Enumerable, {
|
171
|
+
initialize: function() {
|
172
|
+
this.effects = [];
|
173
|
+
this.interval = null;
|
174
|
+
},
|
175
|
+
_each: function(iterator) {
|
176
|
+
this.effects._each(iterator);
|
177
|
+
},
|
178
|
+
add: function(effect) {
|
179
|
+
var timestamp = new Date().getTime();
|
180
|
+
|
181
|
+
var position = Object.isString(effect.options.queue) ?
|
182
|
+
effect.options.queue : effect.options.queue.position;
|
183
|
+
|
184
|
+
switch(position) {
|
185
|
+
case 'front':
|
186
|
+
// move unstarted effects after this effect
|
187
|
+
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
|
188
|
+
e.startOn += effect.finishOn;
|
189
|
+
e.finishOn += effect.finishOn;
|
190
|
+
});
|
191
|
+
break;
|
192
|
+
case 'with-last':
|
193
|
+
timestamp = this.effects.pluck('startOn').max() || timestamp;
|
194
|
+
break;
|
195
|
+
case 'end':
|
196
|
+
// start effect after last queued effect has finished
|
197
|
+
timestamp = this.effects.pluck('finishOn').max() || timestamp;
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
|
201
|
+
effect.startOn += timestamp;
|
202
|
+
effect.finishOn += timestamp;
|
203
|
+
|
204
|
+
if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
|
205
|
+
this.effects.push(effect);
|
206
|
+
|
207
|
+
if (!this.interval)
|
208
|
+
this.interval = setInterval(this.loop.bind(this), 15);
|
209
|
+
},
|
210
|
+
remove: function(effect) {
|
211
|
+
this.effects = this.effects.reject(function(e) { return e==effect });
|
212
|
+
if (this.effects.length == 0) {
|
213
|
+
clearInterval(this.interval);
|
214
|
+
this.interval = null;
|
215
|
+
}
|
216
|
+
},
|
217
|
+
loop: function() {
|
218
|
+
var timePos = new Date().getTime();
|
219
|
+
for(var i=0, len=this.effects.length;i<len;i++)
|
220
|
+
this.effects[i] && this.effects[i].loop(timePos);
|
221
|
+
}
|
222
|
+
});
|
223
|
+
|
224
|
+
Effect.Queues = {
|
225
|
+
instances: $H(),
|
226
|
+
get: function(queueName) {
|
227
|
+
if (!Object.isString(queueName)) return queueName;
|
228
|
+
|
229
|
+
return this.instances.get(queueName) ||
|
230
|
+
this.instances.set(queueName, new Effect.ScopedQueue());
|
231
|
+
}
|
232
|
+
};
|
233
|
+
Effect.Queue = Effect.Queues.get('global');
|
234
|
+
|
235
|
+
Effect.Base = Class.create({
|
236
|
+
position: null,
|
237
|
+
start: function(options) {
|
238
|
+
function codeForEvent(options,eventName){
|
239
|
+
return (
|
240
|
+
(options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
|
241
|
+
(options[eventName] ? 'this.options.'+eventName+'(this);' : '')
|
242
|
+
);
|
243
|
+
}
|
244
|
+
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
|
245
|
+
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
|
246
|
+
this.currentFrame = 0;
|
247
|
+
this.state = 'idle';
|
248
|
+
this.startOn = this.options.delay*1000;
|
249
|
+
this.finishOn = this.startOn+(this.options.duration*1000);
|
250
|
+
this.fromToDelta = this.options.to-this.options.from;
|
251
|
+
this.totalTime = this.finishOn-this.startOn;
|
252
|
+
this.totalFrames = this.options.fps*this.options.duration;
|
253
|
+
|
254
|
+
eval('this.render = function(pos){ '+
|
255
|
+
'if (this.state=="idle"){this.state="running";'+
|
256
|
+
codeForEvent(this.options,'beforeSetup')+
|
257
|
+
(this.setup ? 'this.setup();':'')+
|
258
|
+
codeForEvent(this.options,'afterSetup')+
|
259
|
+
'};if (this.state=="running"){'+
|
260
|
+
'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
|
261
|
+
'this.position=pos;'+
|
262
|
+
codeForEvent(this.options,'beforeUpdate')+
|
263
|
+
(this.update ? 'this.update(pos);':'')+
|
264
|
+
codeForEvent(this.options,'afterUpdate')+
|
265
|
+
'}}');
|
266
|
+
|
267
|
+
this.event('beforeStart');
|
268
|
+
if (!this.options.sync)
|
269
|
+
Effect.Queues.get(Object.isString(this.options.queue) ?
|
270
|
+
'global' : this.options.queue.scope).add(this);
|
271
|
+
},
|
272
|
+
loop: function(timePos) {
|
273
|
+
if (timePos >= this.startOn) {
|
274
|
+
if (timePos >= this.finishOn) {
|
275
|
+
this.render(1.0);
|
276
|
+
this.cancel();
|
277
|
+
this.event('beforeFinish');
|
278
|
+
if (this.finish) this.finish();
|
279
|
+
this.event('afterFinish');
|
280
|
+
return;
|
281
|
+
}
|
282
|
+
var pos = (timePos - this.startOn) / this.totalTime,
|
283
|
+
frame = (pos * this.totalFrames).round();
|
284
|
+
if (frame > this.currentFrame) {
|
285
|
+
this.render(pos);
|
286
|
+
this.currentFrame = frame;
|
287
|
+
}
|
288
|
+
}
|
289
|
+
},
|
290
|
+
cancel: function() {
|
291
|
+
if (!this.options.sync)
|
292
|
+
Effect.Queues.get(Object.isString(this.options.queue) ?
|
293
|
+
'global' : this.options.queue.scope).remove(this);
|
294
|
+
this.state = 'finished';
|
295
|
+
},
|
296
|
+
event: function(eventName) {
|
297
|
+
if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
|
298
|
+
if (this.options[eventName]) this.options[eventName](this);
|
299
|
+
},
|
300
|
+
inspect: function() {
|
301
|
+
var data = $H();
|
302
|
+
for(property in this)
|
303
|
+
if (!Object.isFunction(this[property])) data.set(property, this[property]);
|
304
|
+
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
|
305
|
+
}
|
306
|
+
});
|
307
|
+
|
308
|
+
Effect.Parallel = Class.create(Effect.Base, {
|
309
|
+
initialize: function(effects) {
|
310
|
+
this.effects = effects || [];
|
311
|
+
this.start(arguments[1]);
|
312
|
+
},
|
313
|
+
update: function(position) {
|
314
|
+
this.effects.invoke('render', position);
|
315
|
+
},
|
316
|
+
finish: function(position) {
|
317
|
+
this.effects.each( function(effect) {
|
318
|
+
effect.render(1.0);
|
319
|
+
effect.cancel();
|
320
|
+
effect.event('beforeFinish');
|
321
|
+
if (effect.finish) effect.finish(position);
|
322
|
+
effect.event('afterFinish');
|
323
|
+
});
|
324
|
+
}
|
325
|
+
});
|
326
|
+
|
327
|
+
Effect.Tween = Class.create(Effect.Base, {
|
328
|
+
initialize: function(object, from, to) {
|
329
|
+
object = Object.isString(object) ? $(object) : object;
|
330
|
+
var args = $A(arguments), method = args.last(),
|
331
|
+
options = args.length == 5 ? args[3] : null;
|
332
|
+
this.method = Object.isFunction(method) ? method.bind(object) :
|
333
|
+
Object.isFunction(object[method]) ? object[method].bind(object) :
|
334
|
+
function(value) { object[method] = value };
|
335
|
+
this.start(Object.extend({ from: from, to: to }, options || { }));
|
336
|
+
},
|
337
|
+
update: function(position) {
|
338
|
+
this.method(position);
|
339
|
+
}
|
340
|
+
});
|
341
|
+
|
342
|
+
Effect.Event = Class.create(Effect.Base, {
|
343
|
+
initialize: function() {
|
344
|
+
this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
|
345
|
+
},
|
346
|
+
update: Prototype.emptyFunction
|
347
|
+
});
|
348
|
+
|
349
|
+
Effect.Opacity = Class.create(Effect.Base, {
|
350
|
+
initialize: function(element) {
|
351
|
+
this.element = $(element);
|
352
|
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
353
|
+
// make this work on IE on elements without 'layout'
|
354
|
+
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
355
|
+
this.element.setStyle({zoom: 1});
|
356
|
+
var options = Object.extend({
|
357
|
+
from: this.element.getOpacity() || 0.0,
|
358
|
+
to: 1.0
|
359
|
+
}, arguments[1] || { });
|
360
|
+
this.start(options);
|
361
|
+
},
|
362
|
+
update: function(position) {
|
363
|
+
this.element.setOpacity(position);
|
364
|
+
}
|
365
|
+
});
|
366
|
+
|
367
|
+
Effect.Move = Class.create(Effect.Base, {
|
368
|
+
initialize: function(element) {
|
369
|
+
this.element = $(element);
|
370
|
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
371
|
+
var options = Object.extend({
|
372
|
+
x: 0,
|
373
|
+
y: 0,
|
374
|
+
mode: 'relative'
|
375
|
+
}, arguments[1] || { });
|
376
|
+
this.start(options);
|
377
|
+
},
|
378
|
+
setup: function() {
|
379
|
+
this.element.makePositioned();
|
380
|
+
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
|
381
|
+
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
|
382
|
+
if (this.options.mode == 'absolute') {
|
383
|
+
this.options.x = this.options.x - this.originalLeft;
|
384
|
+
this.options.y = this.options.y - this.originalTop;
|
385
|
+
}
|
386
|
+
},
|
387
|
+
update: function(position) {
|
388
|
+
this.element.setStyle({
|
389
|
+
left: (this.options.x * position + this.originalLeft).round() + 'px',
|
390
|
+
top: (this.options.y * position + this.originalTop).round() + 'px'
|
391
|
+
});
|
392
|
+
}
|
393
|
+
});
|
394
|
+
|
395
|
+
// for backwards compatibility
|
396
|
+
Effect.MoveBy = function(element, toTop, toLeft) {
|
397
|
+
return new Effect.Move(element,
|
398
|
+
Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
|
399
|
+
};
|
400
|
+
|
401
|
+
Effect.Scale = Class.create(Effect.Base, {
|
402
|
+
initialize: function(element, percent) {
|
403
|
+
this.element = $(element);
|
404
|
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
405
|
+
var options = Object.extend({
|
406
|
+
scaleX: true,
|
407
|
+
scaleY: true,
|
408
|
+
scaleContent: true,
|
409
|
+
scaleFromCenter: false,
|
410
|
+
scaleMode: 'box', // 'box' or 'contents' or { } with provided values
|
411
|
+
scaleFrom: 100.0,
|
412
|
+
scaleTo: percent
|
413
|
+
}, arguments[2] || { });
|
414
|
+
this.start(options);
|
415
|
+
},
|
416
|
+
setup: function() {
|
417
|
+
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
|
418
|
+
this.elementPositioning = this.element.getStyle('position');
|
419
|
+
|
420
|
+
this.originalStyle = { };
|
421
|
+
['top','left','width','height','fontSize'].each( function(k) {
|
422
|
+
this.originalStyle[k] = this.element.style[k];
|
423
|
+
}.bind(this));
|
424
|
+
|
425
|
+
this.originalTop = this.element.offsetTop;
|
426
|
+
this.originalLeft = this.element.offsetLeft;
|
427
|
+
|
428
|
+
var fontSize = this.element.getStyle('font-size') || '100%';
|
429
|
+
['em','px','%','pt'].each( function(fontSizeType) {
|
430
|
+
if (fontSize.indexOf(fontSizeType)>0) {
|
431
|
+
this.fontSize = parseFloat(fontSize);
|
432
|
+
this.fontSizeType = fontSizeType;
|
433
|
+
}
|
434
|
+
}.bind(this));
|
435
|
+
|
436
|
+
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
|
437
|
+
|
438
|
+
this.dims = null;
|
439
|
+
if (this.options.scaleMode=='box')
|
440
|
+
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
|
441
|
+
if (/^content/.test(this.options.scaleMode))
|
442
|
+
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
|
443
|
+
if (!this.dims)
|
444
|
+
this.dims = [this.options.scaleMode.originalHeight,
|
445
|
+
this.options.scaleMode.originalWidth];
|
446
|
+
},
|
447
|
+
update: function(position) {
|
448
|
+
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
|
449
|
+
if (this.options.scaleContent && this.fontSize)
|
450
|
+
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
|
451
|
+
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
|
452
|
+
},
|
453
|
+
finish: function(position) {
|
454
|
+
if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
|
455
|
+
},
|
456
|
+
setDimensions: function(height, width) {
|
457
|
+
var d = { };
|
458
|
+
if (this.options.scaleX) d.width = width.round() + 'px';
|
459
|
+
if (this.options.scaleY) d.height = height.round() + 'px';
|
460
|
+
if (this.options.scaleFromCenter) {
|
461
|
+
var topd = (height - this.dims[0])/2;
|
462
|
+
var leftd = (width - this.dims[1])/2;
|
463
|
+
if (this.elementPositioning == 'absolute') {
|
464
|
+
if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
|
465
|
+
if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
|
466
|
+
} else {
|
467
|
+
if (this.options.scaleY) d.top = -topd + 'px';
|
468
|
+
if (this.options.scaleX) d.left = -leftd + 'px';
|
469
|
+
}
|
470
|
+
}
|
471
|
+
this.element.setStyle(d);
|
472
|
+
}
|
473
|
+
});
|
474
|
+
|
475
|
+
Effect.Highlight = Class.create(Effect.Base, {
|
476
|
+
initialize: function(element) {
|
477
|
+
this.element = $(element);
|
478
|
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
479
|
+
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
|
480
|
+
this.start(options);
|
481
|
+
},
|
482
|
+
setup: function() {
|
483
|
+
// Prevent executing on elements not in the layout flow
|
484
|
+
if (this.element.getStyle('display')=='none') { this.cancel(); return; }
|
485
|
+
// Disable background image during the effect
|
486
|
+
this.oldStyle = { };
|
487
|
+
if (!this.options.keepBackgroundImage) {
|
488
|
+
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
|
489
|
+
this.element.setStyle({backgroundImage: 'none'});
|
490
|
+
}
|
491
|
+
if (!this.options.endcolor)
|
492
|
+
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
|
493
|
+
if (!this.options.restorecolor)
|
494
|
+
this.options.restorecolor = this.element.getStyle('background-color');
|
495
|
+
// init color calculations
|
496
|
+
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
|
497
|
+
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
|
498
|
+
},
|
499
|
+
update: function(position) {
|
500
|
+
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
|
501
|
+
return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
|
502
|
+
},
|
503
|
+
finish: function() {
|
504
|
+
this.element.setStyle(Object.extend(this.oldStyle, {
|
505
|
+
backgroundColor: this.options.restorecolor
|
506
|
+
}));
|
507
|
+
}
|
508
|
+
});
|
509
|
+
|
510
|
+
Effect.ScrollTo = function(element) {
|
511
|
+
var options = arguments[1] || { },
|
512
|
+
scrollOffsets = document.viewport.getScrollOffsets(),
|
513
|
+
elementOffsets = $(element).cumulativeOffset(),
|
514
|
+
max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
|
515
|
+
|
516
|
+
if (options.offset) elementOffsets[1] += options.offset;
|
517
|
+
|
518
|
+
return new Effect.Tween(null,
|
519
|
+
scrollOffsets.top,
|
520
|
+
elementOffsets[1] > max ? max : elementOffsets[1],
|
521
|
+
options,
|
522
|
+
function(p){ scrollTo(scrollOffsets.left, p.round()) }
|
523
|
+
);
|
524
|
+
};
|
525
|
+
|
526
|
+
/* ------------- combination effects ------------- */
|
527
|
+
|
528
|
+
Effect.Fade = function(element) {
|
529
|
+
element = $(element);
|
530
|
+
var oldOpacity = element.getInlineOpacity();
|
531
|
+
var options = Object.extend({
|
532
|
+
from: element.getOpacity() || 1.0,
|
533
|
+
to: 0.0,
|
534
|
+
afterFinishInternal: function(effect) {
|
535
|
+
if (effect.options.to!=0) return;
|
536
|
+
effect.element.hide().setStyle({opacity: oldOpacity});
|
537
|
+
}
|
538
|
+
}, arguments[1] || { });
|
539
|
+
return new Effect.Opacity(element,options);
|
540
|
+
};
|
541
|
+
|
542
|
+
Effect.Appear = function(element) {
|
543
|
+
element = $(element);
|
544
|
+
var options = Object.extend({
|
545
|
+
from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
|
546
|
+
to: 1.0,
|
547
|
+
// force Safari to render floated elements properly
|
548
|
+
afterFinishInternal: function(effect) {
|
549
|
+
effect.element.forceRerendering();
|
550
|
+
},
|
551
|
+
beforeSetup: function(effect) {
|
552
|
+
effect.element.setOpacity(effect.options.from).show();
|
553
|
+
}}, arguments[1] || { });
|
554
|
+
return new Effect.Opacity(element,options);
|
555
|
+
};
|
556
|
+
|
557
|
+
Effect.Puff = function(element) {
|
558
|
+
element = $(element);
|
559
|
+
var oldStyle = {
|
560
|
+
opacity: element.getInlineOpacity(),
|
561
|
+
position: element.getStyle('position'),
|
562
|
+
top: element.style.top,
|
563
|
+
left: element.style.left,
|
564
|
+
width: element.style.width,
|
565
|
+
height: element.style.height
|
566
|
+
};
|
567
|
+
return new Effect.Parallel(
|
568
|
+
[ new Effect.Scale(element, 200,
|
569
|
+
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
|
570
|
+
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
|
571
|
+
Object.extend({ duration: 1.0,
|
572
|
+
beforeSetupInternal: function(effect) {
|
573
|
+
Position.absolutize(effect.effects[0].element)
|
574
|
+
},
|
575
|
+
afterFinishInternal: function(effect) {
|
576
|
+
effect.effects[0].element.hide().setStyle(oldStyle); }
|
577
|
+
}, arguments[1] || { })
|
578
|
+
);
|
579
|
+
};
|
580
|
+
|
581
|
+
Effect.BlindUp = function(element) {
|
582
|
+
element = $(element);
|
583
|
+
element.makeClipping();
|
584
|
+
return new Effect.Scale(element, 0,
|
585
|
+
Object.extend({ scaleContent: false,
|
586
|
+
scaleX: false,
|
587
|
+
restoreAfterFinish: true,
|
588
|
+
afterFinishInternal: function(effect) {
|
589
|
+
effect.element.hide().undoClipping();
|
590
|
+
}
|
591
|
+
}, arguments[1] || { })
|
592
|
+
);
|
593
|
+
};
|
594
|
+
|
595
|
+
Effect.BlindDown = function(element) {
|
596
|
+
element = $(element);
|
597
|
+
var elementDimensions = element.getDimensions();
|
598
|
+
return new Effect.Scale(element, 100, Object.extend({
|
599
|
+
scaleContent: false,
|
600
|
+
scaleX: false,
|
601
|
+
scaleFrom: 0,
|
602
|
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
603
|
+
restoreAfterFinish: true,
|
604
|
+
afterSetup: function(effect) {
|
605
|
+
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
606
|
+
},
|
607
|
+
afterFinishInternal: function(effect) {
|
608
|
+
effect.element.undoClipping();
|
609
|
+
}
|
610
|
+
}, arguments[1] || { }));
|
611
|
+
};
|
612
|
+
|
613
|
+
Effect.SwitchOff = function(element) {
|
614
|
+
element = $(element);
|
615
|
+
var oldOpacity = element.getInlineOpacity();
|
616
|
+
return new Effect.Appear(element, Object.extend({
|
617
|
+
duration: 0.4,
|
618
|
+
from: 0,
|
619
|
+
transition: Effect.Transitions.flicker,
|
620
|
+
afterFinishInternal: function(effect) {
|
621
|
+
new Effect.Scale(effect.element, 1, {
|
622
|
+
duration: 0.3, scaleFromCenter: true,
|
623
|
+
scaleX: false, scaleContent: false, restoreAfterFinish: true,
|
624
|
+
beforeSetup: function(effect) {
|
625
|
+
effect.element.makePositioned().makeClipping();
|
626
|
+
},
|
627
|
+
afterFinishInternal: function(effect) {
|
628
|
+
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
|
629
|
+
}
|
630
|
+
})
|
631
|
+
}
|
632
|
+
}, arguments[1] || { }));
|
633
|
+
};
|
634
|
+
|
635
|
+
Effect.DropOut = function(element) {
|
636
|
+
element = $(element);
|
637
|
+
var oldStyle = {
|
638
|
+
top: element.getStyle('top'),
|
639
|
+
left: element.getStyle('left'),
|
640
|
+
opacity: element.getInlineOpacity() };
|
641
|
+
return new Effect.Parallel(
|
642
|
+
[ new Effect.Move(element, {x: 0, y: 100, sync: true }),
|
643
|
+
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
|
644
|
+
Object.extend(
|
645
|
+
{ duration: 0.5,
|
646
|
+
beforeSetup: function(effect) {
|
647
|
+
effect.effects[0].element.makePositioned();
|
648
|
+
},
|
649
|
+
afterFinishInternal: function(effect) {
|
650
|
+
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
|
651
|
+
}
|
652
|
+
}, arguments[1] || { }));
|
653
|
+
};
|
654
|
+
|
655
|
+
Effect.Shake = function(element) {
|
656
|
+
element = $(element);
|
657
|
+
var options = Object.extend({
|
658
|
+
distance: 20,
|
659
|
+
duration: 0.5
|
660
|
+
}, arguments[1] || {});
|
661
|
+
var distance = parseFloat(options.distance);
|
662
|
+
var split = parseFloat(options.duration) / 10.0;
|
663
|
+
var oldStyle = {
|
664
|
+
top: element.getStyle('top'),
|
665
|
+
left: element.getStyle('left') };
|
666
|
+
return new Effect.Move(element,
|
667
|
+
{ x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
|
668
|
+
new Effect.Move(effect.element,
|
669
|
+
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
670
|
+
new Effect.Move(effect.element,
|
671
|
+
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
672
|
+
new Effect.Move(effect.element,
|
673
|
+
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
674
|
+
new Effect.Move(effect.element,
|
675
|
+
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
676
|
+
new Effect.Move(effect.element,
|
677
|
+
{ x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
|
678
|
+
effect.element.undoPositioned().setStyle(oldStyle);
|
679
|
+
}}) }}) }}) }}) }}) }});
|
680
|
+
};
|
681
|
+
|
682
|
+
Effect.SlideDown = function(element) {
|
683
|
+
element = $(element).cleanWhitespace();
|
684
|
+
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
|
685
|
+
var oldInnerBottom = element.down().getStyle('bottom');
|
686
|
+
var elementDimensions = element.getDimensions();
|
687
|
+
return new Effect.Scale(element, 100, Object.extend({
|
688
|
+
scaleContent: false,
|
689
|
+
scaleX: false,
|
690
|
+
scaleFrom: window.opera ? 0 : 1,
|
691
|
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
692
|
+
restoreAfterFinish: true,
|
693
|
+
afterSetup: function(effect) {
|
694
|
+
effect.element.makePositioned();
|
695
|
+
effect.element.down().makePositioned();
|
696
|
+
if (window.opera) effect.element.setStyle({top: ''});
|
697
|
+
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
698
|
+
},
|
699
|
+
afterUpdateInternal: function(effect) {
|
700
|
+
effect.element.down().setStyle({bottom:
|
701
|
+
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
702
|
+
},
|
703
|
+
afterFinishInternal: function(effect) {
|
704
|
+
effect.element.undoClipping().undoPositioned();
|
705
|
+
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
|
706
|
+
}, arguments[1] || { })
|
707
|
+
);
|
708
|
+
};
|
709
|
+
|
710
|
+
Effect.SlideUp = function(element) {
|
711
|
+
element = $(element).cleanWhitespace();
|
712
|
+
var oldInnerBottom = element.down().getStyle('bottom');
|
713
|
+
var elementDimensions = element.getDimensions();
|
714
|
+
return new Effect.Scale(element, window.opera ? 0 : 1,
|
715
|
+
Object.extend({ scaleContent: false,
|
716
|
+
scaleX: false,
|
717
|
+
scaleMode: 'box',
|
718
|
+
scaleFrom: 100,
|
719
|
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
720
|
+
restoreAfterFinish: true,
|
721
|
+
afterSetup: function(effect) {
|
722
|
+
effect.element.makePositioned();
|
723
|
+
effect.element.down().makePositioned();
|
724
|
+
if (window.opera) effect.element.setStyle({top: ''});
|
725
|
+
effect.element.makeClipping().show();
|
726
|
+
},
|
727
|
+
afterUpdateInternal: function(effect) {
|
728
|
+
effect.element.down().setStyle({bottom:
|
729
|
+
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
730
|
+
},
|
731
|
+
afterFinishInternal: function(effect) {
|
732
|
+
effect.element.hide().undoClipping().undoPositioned();
|
733
|
+
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
|
734
|
+
}
|
735
|
+
}, arguments[1] || { })
|
736
|
+
);
|
737
|
+
};
|
738
|
+
|
739
|
+
// Bug in opera makes the TD containing this element expand for a instance after finish
|
740
|
+
Effect.Squish = function(element) {
|
741
|
+
return new Effect.Scale(element, window.opera ? 1 : 0, {
|
742
|
+
restoreAfterFinish: true,
|
743
|
+
beforeSetup: function(effect) {
|
744
|
+
effect.element.makeClipping();
|
745
|
+
},
|
746
|
+
afterFinishInternal: function(effect) {
|
747
|
+
effect.element.hide().undoClipping();
|
748
|
+
}
|
749
|
+
});
|
750
|
+
};
|
751
|
+
|
752
|
+
Effect.Grow = function(element) {
|
753
|
+
element = $(element);
|
754
|
+
var options = Object.extend({
|
755
|
+
direction: 'center',
|
756
|
+
moveTransition: Effect.Transitions.sinoidal,
|
757
|
+
scaleTransition: Effect.Transitions.sinoidal,
|
758
|
+
opacityTransition: Effect.Transitions.full
|
759
|
+
}, arguments[1] || { });
|
760
|
+
var oldStyle = {
|
761
|
+
top: element.style.top,
|
762
|
+
left: element.style.left,
|
763
|
+
height: element.style.height,
|
764
|
+
width: element.style.width,
|
765
|
+
opacity: element.getInlineOpacity() };
|
766
|
+
|
767
|
+
var dims = element.getDimensions();
|
768
|
+
var initialMoveX, initialMoveY;
|
769
|
+
var moveX, moveY;
|
770
|
+
|
771
|
+
switch (options.direction) {
|
772
|
+
case 'top-left':
|
773
|
+
initialMoveX = initialMoveY = moveX = moveY = 0;
|
774
|
+
break;
|
775
|
+
case 'top-right':
|
776
|
+
initialMoveX = dims.width;
|
777
|
+
initialMoveY = moveY = 0;
|
778
|
+
moveX = -dims.width;
|
779
|
+
break;
|
780
|
+
case 'bottom-left':
|
781
|
+
initialMoveX = moveX = 0;
|
782
|
+
initialMoveY = dims.height;
|
783
|
+
moveY = -dims.height;
|
784
|
+
break;
|
785
|
+
case 'bottom-right':
|
786
|
+
initialMoveX = dims.width;
|
787
|
+
initialMoveY = dims.height;
|
788
|
+
moveX = -dims.width;
|
789
|
+
moveY = -dims.height;
|
790
|
+
break;
|
791
|
+
case 'center':
|
792
|
+
initialMoveX = dims.width / 2;
|
793
|
+
initialMoveY = dims.height / 2;
|
794
|
+
moveX = -dims.width / 2;
|
795
|
+
moveY = -dims.height / 2;
|
796
|
+
break;
|
797
|
+
}
|
798
|
+
|
799
|
+
return new Effect.Move(element, {
|
800
|
+
x: initialMoveX,
|
801
|
+
y: initialMoveY,
|
802
|
+
duration: 0.01,
|
803
|
+
beforeSetup: function(effect) {
|
804
|
+
effect.element.hide().makeClipping().makePositioned();
|
805
|
+
},
|
806
|
+
afterFinishInternal: function(effect) {
|
807
|
+
new Effect.Parallel(
|
808
|
+
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
|
809
|
+
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
|
810
|
+
new Effect.Scale(effect.element, 100, {
|
811
|
+
scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
|
812
|
+
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
|
813
|
+
], Object.extend({
|
814
|
+
beforeSetup: function(effect) {
|
815
|
+
effect.effects[0].element.setStyle({height: '0px'}).show();
|
816
|
+
},
|
817
|
+
afterFinishInternal: function(effect) {
|
818
|
+
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
|
819
|
+
}
|
820
|
+
}, options)
|
821
|
+
)
|
822
|
+
}
|
823
|
+
});
|
824
|
+
};
|
825
|
+
|
826
|
+
Effect.Shrink = function(element) {
|
827
|
+
element = $(element);
|
828
|
+
var options = Object.extend({
|
829
|
+
direction: 'center',
|
830
|
+
moveTransition: Effect.Transitions.sinoidal,
|
831
|
+
scaleTransition: Effect.Transitions.sinoidal,
|
832
|
+
opacityTransition: Effect.Transitions.none
|
833
|
+
}, arguments[1] || { });
|
834
|
+
var oldStyle = {
|
835
|
+
top: element.style.top,
|
836
|
+
left: element.style.left,
|
837
|
+
height: element.style.height,
|
838
|
+
width: element.style.width,
|
839
|
+
opacity: element.getInlineOpacity() };
|
840
|
+
|
841
|
+
var dims = element.getDimensions();
|
842
|
+
var moveX, moveY;
|
843
|
+
|
844
|
+
switch (options.direction) {
|
845
|
+
case 'top-left':
|
846
|
+
moveX = moveY = 0;
|
847
|
+
break;
|
848
|
+
case 'top-right':
|
849
|
+
moveX = dims.width;
|
850
|
+
moveY = 0;
|
851
|
+
break;
|
852
|
+
case 'bottom-left':
|
853
|
+
moveX = 0;
|
854
|
+
moveY = dims.height;
|
855
|
+
break;
|
856
|
+
case 'bottom-right':
|
857
|
+
moveX = dims.width;
|
858
|
+
moveY = dims.height;
|
859
|
+
break;
|
860
|
+
case 'center':
|
861
|
+
moveX = dims.width / 2;
|
862
|
+
moveY = dims.height / 2;
|
863
|
+
break;
|
864
|
+
}
|
865
|
+
|
866
|
+
return new Effect.Parallel(
|
867
|
+
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
|
868
|
+
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
|
869
|
+
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
|
870
|
+
], Object.extend({
|
871
|
+
beforeStartInternal: function(effect) {
|
872
|
+
effect.effects[0].element.makePositioned().makeClipping();
|
873
|
+
},
|
874
|
+
afterFinishInternal: function(effect) {
|
875
|
+
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
|
876
|
+
}, options)
|
877
|
+
);
|
878
|
+
};
|
879
|
+
|
880
|
+
Effect.Pulsate = function(element) {
|
881
|
+
element = $(element);
|
882
|
+
var options = arguments[1] || { };
|
883
|
+
var oldOpacity = element.getInlineOpacity();
|
884
|
+
var transition = options.transition || Effect.Transitions.sinoidal;
|
885
|
+
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
|
886
|
+
reverser.bind(transition);
|
887
|
+
return new Effect.Opacity(element,
|
888
|
+
Object.extend(Object.extend({ duration: 2.0, from: 0,
|
889
|
+
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
|
890
|
+
}, options), {transition: reverser}));
|
891
|
+
};
|
892
|
+
|
893
|
+
Effect.Fold = function(element) {
|
894
|
+
element = $(element);
|
895
|
+
var oldStyle = {
|
896
|
+
top: element.style.top,
|
897
|
+
left: element.style.left,
|
898
|
+
width: element.style.width,
|
899
|
+
height: element.style.height };
|
900
|
+
element.makeClipping();
|
901
|
+
return new Effect.Scale(element, 5, Object.extend({
|
902
|
+
scaleContent: false,
|
903
|
+
scaleX: false,
|
904
|
+
afterFinishInternal: function(effect) {
|
905
|
+
new Effect.Scale(element, 1, {
|
906
|
+
scaleContent: false,
|
907
|
+
scaleY: false,
|
908
|
+
afterFinishInternal: function(effect) {
|
909
|
+
effect.element.hide().undoClipping().setStyle(oldStyle);
|
910
|
+
} });
|
911
|
+
}}, arguments[1] || { }));
|
912
|
+
};
|
913
|
+
|
914
|
+
Effect.Morph = Class.create(Effect.Base, {
|
915
|
+
initialize: function(element) {
|
916
|
+
this.element = $(element);
|
917
|
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
918
|
+
var options = Object.extend({
|
919
|
+
style: { }
|
920
|
+
}, arguments[1] || { });
|
921
|
+
|
922
|
+
if (!Object.isString(options.style)) this.style = $H(options.style);
|
923
|
+
else {
|
924
|
+
if (options.style.include(':'))
|
925
|
+
this.style = options.style.parseStyle();
|
926
|
+
else {
|
927
|
+
this.element.addClassName(options.style);
|
928
|
+
this.style = $H(this.element.getStyles());
|
929
|
+
this.element.removeClassName(options.style);
|
930
|
+
var css = this.element.getStyles();
|
931
|
+
this.style = this.style.reject(function(style) {
|
932
|
+
return style.value == css[style.key];
|
933
|
+
});
|
934
|
+
options.afterFinishInternal = function(effect) {
|
935
|
+
effect.element.addClassName(effect.options.style);
|
936
|
+
effect.transforms.each(function(transform) {
|
937
|
+
effect.element.style[transform.style] = '';
|
938
|
+
});
|
939
|
+
}
|
940
|
+
}
|
941
|
+
}
|
942
|
+
this.start(options);
|
943
|
+
},
|
944
|
+
|
945
|
+
setup: function(){
|
946
|
+
function parseColor(color){
|
947
|
+
if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
|
948
|
+
color = color.parseColor();
|
949
|
+
return $R(0,2).map(function(i){
|
950
|
+
return parseInt( color.slice(i*2+1,i*2+3), 16 )
|
951
|
+
});
|
952
|
+
}
|
953
|
+
this.transforms = this.style.map(function(pair){
|
954
|
+
var property = pair[0], value = pair[1], unit = null;
|
955
|
+
|
956
|
+
if (value.parseColor('#zzzzzz') != '#zzzzzz') {
|
957
|
+
value = value.parseColor();
|
958
|
+
unit = 'color';
|
959
|
+
} else if (property == 'opacity') {
|
960
|
+
value = parseFloat(value);
|
961
|
+
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
962
|
+
this.element.setStyle({zoom: 1});
|
963
|
+
} else if (Element.CSS_LENGTH.test(value)) {
|
964
|
+
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
|
965
|
+
value = parseFloat(components[1]);
|
966
|
+
unit = (components.length == 3) ? components[2] : null;
|
967
|
+
}
|
968
|
+
|
969
|
+
var originalValue = this.element.getStyle(property);
|
970
|
+
return {
|
971
|
+
style: property.camelize(),
|
972
|
+
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
|
973
|
+
targetValue: unit=='color' ? parseColor(value) : value,
|
974
|
+
unit: unit
|
975
|
+
};
|
976
|
+
}.bind(this)).reject(function(transform){
|
977
|
+
return (
|
978
|
+
(transform.originalValue == transform.targetValue) ||
|
979
|
+
(
|
980
|
+
transform.unit != 'color' &&
|
981
|
+
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
|
982
|
+
)
|
983
|
+
)
|
984
|
+
});
|
985
|
+
},
|
986
|
+
update: function(position) {
|
987
|
+
var style = { }, transform, i = this.transforms.length;
|
988
|
+
while(i--)
|
989
|
+
style[(transform = this.transforms[i]).style] =
|
990
|
+
transform.unit=='color' ? '#'+
|
991
|
+
(Math.round(transform.originalValue[0]+
|
992
|
+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
|
993
|
+
(Math.round(transform.originalValue[1]+
|
994
|
+
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
|
995
|
+
(Math.round(transform.originalValue[2]+
|
996
|
+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
|
997
|
+
(transform.originalValue +
|
998
|
+
(transform.targetValue - transform.originalValue) * position).toFixed(3) +
|
999
|
+
(transform.unit === null ? '' : transform.unit);
|
1000
|
+
this.element.setStyle(style, true);
|
1001
|
+
}
|
1002
|
+
});
|
1003
|
+
|
1004
|
+
Effect.Transform = Class.create({
|
1005
|
+
initialize: function(tracks){
|
1006
|
+
this.tracks = [];
|
1007
|
+
this.options = arguments[1] || { };
|
1008
|
+
this.addTracks(tracks);
|
1009
|
+
},
|
1010
|
+
addTracks: function(tracks){
|
1011
|
+
tracks.each(function(track){
|
1012
|
+
track = $H(track);
|
1013
|
+
var data = track.values().first();
|
1014
|
+
this.tracks.push($H({
|
1015
|
+
ids: track.keys().first(),
|
1016
|
+
effect: Effect.Morph,
|
1017
|
+
options: { style: data }
|
1018
|
+
}));
|
1019
|
+
}.bind(this));
|
1020
|
+
return this;
|
1021
|
+
},
|
1022
|
+
play: function(){
|
1023
|
+
return new Effect.Parallel(
|
1024
|
+
this.tracks.map(function(track){
|
1025
|
+
var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
|
1026
|
+
var elements = [$(ids) || $$(ids)].flatten();
|
1027
|
+
return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
|
1028
|
+
}).flatten(),
|
1029
|
+
this.options
|
1030
|
+
);
|
1031
|
+
}
|
1032
|
+
});
|
1033
|
+
|
1034
|
+
Element.CSS_PROPERTIES = $w(
|
1035
|
+
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
|
1036
|
+
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
|
1037
|
+
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
|
1038
|
+
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
|
1039
|
+
'fontSize fontWeight height left letterSpacing lineHeight ' +
|
1040
|
+
'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
|
1041
|
+
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
|
1042
|
+
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
|
1043
|
+
'right textIndent top width wordSpacing zIndex');
|
1044
|
+
|
1045
|
+
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
|
1046
|
+
|
1047
|
+
String.__parseStyleElement = document.createElement('div');
|
1048
|
+
String.prototype.parseStyle = function(){
|
1049
|
+
var style, styleRules = $H();
|
1050
|
+
if (Prototype.Browser.WebKit)
|
1051
|
+
style = new Element('div',{style:this}).style;
|
1052
|
+
else {
|
1053
|
+
String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
|
1054
|
+
style = String.__parseStyleElement.childNodes[0].style;
|
1055
|
+
}
|
1056
|
+
|
1057
|
+
Element.CSS_PROPERTIES.each(function(property){
|
1058
|
+
if (style[property]) styleRules.set(property, style[property]);
|
1059
|
+
});
|
1060
|
+
|
1061
|
+
if (Prototype.Browser.IE && this.include('opacity'))
|
1062
|
+
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
|
1063
|
+
|
1064
|
+
return styleRules;
|
1065
|
+
};
|
1066
|
+
|
1067
|
+
if (document.defaultView && document.defaultView.getComputedStyle) {
|
1068
|
+
Element.getStyles = function(element) {
|
1069
|
+
var css = document.defaultView.getComputedStyle($(element), null);
|
1070
|
+
return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
|
1071
|
+
styles[property] = css[property];
|
1072
|
+
return styles;
|
1073
|
+
});
|
1074
|
+
};
|
1075
|
+
} else {
|
1076
|
+
Element.getStyles = function(element) {
|
1077
|
+
element = $(element);
|
1078
|
+
var css = element.currentStyle, styles;
|
1079
|
+
styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
|
1080
|
+
results[property] = css[property];
|
1081
|
+
return results;
|
1082
|
+
});
|
1083
|
+
if (!styles.opacity) styles.opacity = element.getOpacity();
|
1084
|
+
return styles;
|
1085
|
+
};
|
1086
|
+
};
|
1087
|
+
|
1088
|
+
Effect.Methods = {
|
1089
|
+
morph: function(element, style) {
|
1090
|
+
element = $(element);
|
1091
|
+
new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
|
1092
|
+
return element;
|
1093
|
+
},
|
1094
|
+
visualEffect: function(element, effect, options) {
|
1095
|
+
element = $(element)
|
1096
|
+
var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
|
1097
|
+
new Effect[klass](element, options);
|
1098
|
+
return element;
|
1099
|
+
},
|
1100
|
+
highlight: function(element, options) {
|
1101
|
+
element = $(element);
|
1102
|
+
new Effect.Highlight(element, options);
|
1103
|
+
return element;
|
1104
|
+
}
|
1105
|
+
};
|
1106
|
+
|
1107
|
+
$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
|
1108
|
+
'pulsate shake puff squish switchOff dropOut').each(
|
1109
|
+
function(effect) {
|
1110
|
+
Effect.Methods[effect] = function(element, options){
|
1111
|
+
element = $(element);
|
1112
|
+
Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
|
1113
|
+
return element;
|
1114
|
+
}
|
1115
|
+
}
|
1116
|
+
);
|
1117
|
+
|
1118
|
+
$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
|
1119
|
+
function(f) { Effect.Methods[f] = Element[f]; }
|
1120
|
+
);
|
1121
|
+
|
1122
|
+
Element.addMethods(Effect.Methods);
|