Description:
more updated rails
git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@360 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r163:74e3afe899a3 - - The requested commit is too big and content was truncated. 5 files changed. Show full diff
@@ -1,109 +1,110 | |||||
|
1 | # Don't change this file! |
|
1 | # Don't change this file! |
|
2 | # Configure your app in config/environment.rb and config/environments/*.rb |
|
2 | # Configure your app in config/environment.rb and config/environments/*.rb |
|
3 |
|
3 | ||
|
4 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) |
|
4 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) |
|
5 |
|
5 | ||
|
6 | module Rails |
|
6 | module Rails |
|
7 | class << self |
|
7 | class << self |
|
8 | def boot! |
|
8 | def boot! |
|
9 | unless booted? |
|
9 | unless booted? |
|
10 | preinitialize |
|
10 | preinitialize |
|
11 | pick_boot.run |
|
11 | pick_boot.run |
|
12 | end |
|
12 | end |
|
13 | end |
|
13 | end |
|
14 |
|
14 | ||
|
15 | def booted? |
|
15 | def booted? |
|
16 | defined? Rails::Initializer |
|
16 | defined? Rails::Initializer |
|
17 | end |
|
17 | end |
|
18 |
|
18 | ||
|
19 | def pick_boot |
|
19 | def pick_boot |
|
20 | (vendor_rails? ? VendorBoot : GemBoot).new |
|
20 | (vendor_rails? ? VendorBoot : GemBoot).new |
|
21 | end |
|
21 | end |
|
22 |
|
22 | ||
|
23 | def vendor_rails? |
|
23 | def vendor_rails? |
|
24 | File.exist?("#{RAILS_ROOT}/vendor/rails") |
|
24 | File.exist?("#{RAILS_ROOT}/vendor/rails") |
|
25 | end |
|
25 | end |
|
26 |
|
26 | ||
|
27 | def preinitialize |
|
27 | def preinitialize |
|
28 | load(preinitializer_path) if File.exist?(preinitializer_path) |
|
28 | load(preinitializer_path) if File.exist?(preinitializer_path) |
|
29 | end |
|
29 | end |
|
30 |
|
30 | ||
|
31 | def preinitializer_path |
|
31 | def preinitializer_path |
|
32 | "#{RAILS_ROOT}/config/preinitializer.rb" |
|
32 | "#{RAILS_ROOT}/config/preinitializer.rb" |
|
33 | end |
|
33 | end |
|
34 | end |
|
34 | end |
|
35 |
|
35 | ||
|
36 | class Boot |
|
36 | class Boot |
|
37 | def run |
|
37 | def run |
|
38 | load_initializer |
|
38 | load_initializer |
|
39 | Rails::Initializer.run(:set_load_path) |
|
39 | Rails::Initializer.run(:set_load_path) |
|
40 | end |
|
40 | end |
|
41 | end |
|
41 | end |
|
42 |
|
42 | ||
|
43 | class VendorBoot < Boot |
|
43 | class VendorBoot < Boot |
|
44 | def load_initializer |
|
44 | def load_initializer |
|
45 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" |
|
45 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" |
|
46 | Rails::Initializer.run(:install_gem_spec_stubs) |
|
46 | Rails::Initializer.run(:install_gem_spec_stubs) |
|
|
47 | + Rails::GemDependency.add_frozen_gem_path | ||
|
47 | end |
|
48 | end |
|
48 | end |
|
49 | end |
|
49 |
|
50 | ||
|
50 | class GemBoot < Boot |
|
51 | class GemBoot < Boot |
|
51 | def load_initializer |
|
52 | def load_initializer |
|
52 | self.class.load_rubygems |
|
53 | self.class.load_rubygems |
|
53 | load_rails_gem |
|
54 | load_rails_gem |
|
54 | require 'initializer' |
|
55 | require 'initializer' |
|
55 | end |
|
56 | end |
|
56 |
|
57 | ||
|
57 | def load_rails_gem |
|
58 | def load_rails_gem |
|
58 | if version = self.class.gem_version |
|
59 | if version = self.class.gem_version |
|
59 | gem 'rails', version |
|
60 | gem 'rails', version |
|
60 | else |
|
61 | else |
|
61 | gem 'rails' |
|
62 | gem 'rails' |
|
62 | end |
|
63 | end |
|
63 | rescue Gem::LoadError => load_error |
|
64 | rescue Gem::LoadError => load_error |
|
64 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) |
|
65 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) |
|
65 | exit 1 |
|
66 | exit 1 |
|
66 | end |
|
67 | end |
|
67 |
|
68 | ||
|
68 | class << self |
|
69 | class << self |
|
69 | def rubygems_version |
|
70 | def rubygems_version |
|
70 |
- Gem::RubyGemsVersion |
|
71 | + Gem::RubyGemsVersion rescue nil |
|
71 | end |
|
72 | end |
|
72 |
|
73 | ||
|
73 | def gem_version |
|
74 | def gem_version |
|
74 | if defined? RAILS_GEM_VERSION |
|
75 | if defined? RAILS_GEM_VERSION |
|
75 | RAILS_GEM_VERSION |
|
76 | RAILS_GEM_VERSION |
|
76 | elsif ENV.include?('RAILS_GEM_VERSION') |
|
77 | elsif ENV.include?('RAILS_GEM_VERSION') |
|
77 | ENV['RAILS_GEM_VERSION'] |
|
78 | ENV['RAILS_GEM_VERSION'] |
|
78 | else |
|
79 | else |
|
79 | parse_gem_version(read_environment_rb) |
|
80 | parse_gem_version(read_environment_rb) |
|
80 | end |
|
81 | end |
|
81 | end |
|
82 | end |
|
82 |
|
83 | ||
|
83 | def load_rubygems |
|
84 | def load_rubygems |
|
84 | require 'rubygems' |
|
85 | require 'rubygems' |
|
85 |
- min_version = '1. |
|
86 | + min_version = '1.3.1' |
|
86 | unless rubygems_version >= min_version |
|
87 | unless rubygems_version >= min_version |
|
87 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) |
|
88 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) |
|
88 | exit 1 |
|
89 | exit 1 |
|
89 | end |
|
90 | end |
|
90 |
|
91 | ||
|
91 | rescue LoadError |
|
92 | rescue LoadError |
|
92 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) |
|
93 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) |
|
93 | exit 1 |
|
94 | exit 1 |
|
94 | end |
|
95 | end |
|
95 |
|
96 | ||
|
96 | def parse_gem_version(text) |
|
97 | def parse_gem_version(text) |
|
97 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ |
|
98 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ |
|
98 | end |
|
99 | end |
|
99 |
|
100 | ||
|
100 | private |
|
101 | private |
|
101 | def read_environment_rb |
|
102 | def read_environment_rb |
|
102 | File.read("#{RAILS_ROOT}/config/environment.rb") |
|
103 | File.read("#{RAILS_ROOT}/config/environment.rb") |
|
103 | end |
|
104 | end |
|
104 | end |
|
105 | end |
|
105 | end |
|
106 | end |
|
106 | end |
|
107 | end |
|
107 |
|
108 | ||
|
108 | # All that for this: |
|
109 | # All that for this: |
|
109 | Rails.boot! |
|
110 | Rails.boot! |
@@ -1,963 +1,963 | |||||
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
2 |
- // (c) 2005-200 |
|
2 | + // (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) |
|
3 |
- // (c) 2005-200 |
|
3 | + // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) |
|
4 | // Contributors: |
|
4 | // Contributors: |
|
5 | // Richard Livsey |
|
5 | // Richard Livsey |
|
6 | // Rahul Bhargava |
|
6 | // Rahul Bhargava |
|
7 | // Rob Wills |
|
7 | // Rob Wills |
|
8 |
// |
|
8 | // |
|
9 | // script.aculo.us is freely distributable under the terms of an MIT-style license. |
|
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/ |
|
10 | // For details, see the script.aculo.us web site: http://script.aculo.us/ |
|
11 |
|
11 | ||
|
12 |
// Autocompleter.Base handles all the autocompletion functionality |
|
12 | // Autocompleter.Base handles all the autocompletion functionality |
|
13 | // that's independent of the data source for autocompletion. This |
|
13 | // that's independent of the data source for autocompletion. This |
|
14 | // includes drawing the autocompletion menu, observing keyboard |
|
14 | // includes drawing the autocompletion menu, observing keyboard |
|
15 | // and mouse events, and similar. |
|
15 | // and mouse events, and similar. |
|
16 | // |
|
16 | // |
|
17 |
// Specific autocompleters need to provide, at the very least, |
|
17 | // Specific autocompleters need to provide, at the very least, |
|
18 | // a getUpdatedChoices function that will be invoked every time |
|
18 | // a getUpdatedChoices function that will be invoked every time |
|
19 |
// the text inside the monitored textbox changes. This method |
|
19 | // the text inside the monitored textbox changes. This method |
|
20 | // should get the text for which to provide autocompletion by |
|
20 | // should get the text for which to provide autocompletion by |
|
21 | // invoking this.getToken(), NOT by directly accessing |
|
21 | // invoking this.getToken(), NOT by directly accessing |
|
22 | // this.element.value. This is to allow incremental tokenized |
|
22 | // this.element.value. This is to allow incremental tokenized |
|
23 | // autocompletion. Specific auto-completion logic (AJAX, etc) |
|
23 | // autocompletion. Specific auto-completion logic (AJAX, etc) |
|
24 | // belongs in getUpdatedChoices. |
|
24 | // belongs in getUpdatedChoices. |
|
25 | // |
|
25 | // |
|
26 | // Tokenized incremental autocompletion is enabled automatically |
|
26 | // Tokenized incremental autocompletion is enabled automatically |
|
27 | // when an autocompleter is instantiated with the 'tokens' option |
|
27 | // when an autocompleter is instantiated with the 'tokens' option |
|
28 | // in the options parameter, e.g.: |
|
28 | // in the options parameter, e.g.: |
|
29 | // new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); |
|
29 | // new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); |
|
30 | // will incrementally autocomplete with a comma as the token. |
|
30 | // will incrementally autocomplete with a comma as the token. |
|
31 | // Additionally, ',' in the above example can be replaced with |
|
31 | // Additionally, ',' in the above example can be replaced with |
|
32 | // a token array, e.g. { tokens: [',', '\n'] } which |
|
32 | // a token array, e.g. { tokens: [',', '\n'] } which |
|
33 |
// enables autocompletion on multiple tokens. This is most |
|
33 | // enables autocompletion on multiple tokens. This is most |
|
34 |
// useful when one of the tokens is \n (a newline), as it |
|
34 | // useful when one of the tokens is \n (a newline), as it |
|
35 | // allows smart autocompletion after linebreaks. |
|
35 | // allows smart autocompletion after linebreaks. |
|
36 |
|
36 | ||
|
37 | if(typeof Effect == 'undefined') |
|
37 | if(typeof Effect == 'undefined') |
|
38 | throw("controls.js requires including script.aculo.us' effects.js library"); |
|
38 | throw("controls.js requires including script.aculo.us' effects.js library"); |
|
39 |
|
39 | ||
|
40 | - var Autocompleter = { } |
|
40 | + var Autocompleter = { }; |
|
41 | Autocompleter.Base = Class.create({ |
|
41 | Autocompleter.Base = Class.create({ |
|
42 | baseInitialize: function(element, update, options) { |
|
42 | baseInitialize: function(element, update, options) { |
|
43 | - element = $(element) |
|
43 | + element = $(element); |
|
44 |
this.element = element; |
|
44 | this.element = element; |
|
45 |
this.update = $(update); |
|
45 | this.update = $(update); |
|
46 |
this.hasFocus = false; |
|
46 | this.hasFocus = false; |
|
47 |
this.changed = false; |
|
47 | this.changed = false; |
|
48 |
this.active = false; |
|
48 | this.active = false; |
|
49 |
this.index = 0; |
|
49 | this.index = 0; |
|
50 | this.entryCount = 0; |
|
50 | this.entryCount = 0; |
|
51 | this.oldElementValue = this.element.value; |
|
51 | this.oldElementValue = this.element.value; |
|
52 |
|
52 | ||
|
53 | if(this.setOptions) |
|
53 | if(this.setOptions) |
|
54 | this.setOptions(options); |
|
54 | this.setOptions(options); |
|
55 | else |
|
55 | else |
|
56 | this.options = options || { }; |
|
56 | this.options = options || { }; |
|
57 |
|
57 | ||
|
58 | this.options.paramName = this.options.paramName || this.element.name; |
|
58 | this.options.paramName = this.options.paramName || this.element.name; |
|
59 | this.options.tokens = this.options.tokens || []; |
|
59 | this.options.tokens = this.options.tokens || []; |
|
60 | this.options.frequency = this.options.frequency || 0.4; |
|
60 | this.options.frequency = this.options.frequency || 0.4; |
|
61 | this.options.minChars = this.options.minChars || 1; |
|
61 | this.options.minChars = this.options.minChars || 1; |
|
62 |
this.options.onShow = this.options.onShow || |
|
62 | this.options.onShow = this.options.onShow || |
|
63 |
function(element, update){ |
|
63 | function(element, update){ |
|
64 | if(!update.style.position || update.style.position=='absolute') { |
|
64 | if(!update.style.position || update.style.position=='absolute') { |
|
65 | update.style.position = 'absolute'; |
|
65 | update.style.position = 'absolute'; |
|
66 | Position.clone(element, update, { |
|
66 | Position.clone(element, update, { |
|
67 |
setHeight: false, |
|
67 | setHeight: false, |
|
68 | offsetTop: element.offsetHeight |
|
68 | offsetTop: element.offsetHeight |
|
69 | }); |
|
69 | }); |
|
70 | } |
|
70 | } |
|
71 | Effect.Appear(update,{duration:0.15}); |
|
71 | Effect.Appear(update,{duration:0.15}); |
|
72 | }; |
|
72 | }; |
|
73 |
this.options.onHide = this.options.onHide || |
|
73 | this.options.onHide = this.options.onHide || |
|
74 | function(element, update){ new Effect.Fade(update,{duration:0.15}) }; |
|
74 | function(element, update){ new Effect.Fade(update,{duration:0.15}) }; |
|
75 |
|
75 | ||
|
76 |
if(typeof(this.options.tokens) == 'string') |
|
76 | if(typeof(this.options.tokens) == 'string') |
|
77 | this.options.tokens = new Array(this.options.tokens); |
|
77 | this.options.tokens = new Array(this.options.tokens); |
|
78 | // Force carriage returns as token delimiters anyway |
|
78 | // Force carriage returns as token delimiters anyway |
|
79 | if (!this.options.tokens.include('\n')) |
|
79 | if (!this.options.tokens.include('\n')) |
|
80 | this.options.tokens.push('\n'); |
|
80 | this.options.tokens.push('\n'); |
|
81 |
|
81 | ||
|
82 | this.observer = null; |
|
82 | this.observer = null; |
|
83 |
|
83 | ||
|
84 | this.element.setAttribute('autocomplete','off'); |
|
84 | this.element.setAttribute('autocomplete','off'); |
|
85 |
|
85 | ||
|
86 | Element.hide(this.update); |
|
86 | Element.hide(this.update); |
|
87 |
|
87 | ||
|
88 | Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); |
|
88 | Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); |
|
89 | Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); |
|
89 | Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); |
|
90 | }, |
|
90 | }, |
|
91 |
|
91 | ||
|
92 | show: function() { |
|
92 | show: function() { |
|
93 | if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); |
|
93 | if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); |
|
94 |
if(!this.iefix && |
|
94 | if(!this.iefix && |
|
95 | (Prototype.Browser.IE) && |
|
95 | (Prototype.Browser.IE) && |
|
96 | (Element.getStyle(this.update, 'position')=='absolute')) { |
|
96 | (Element.getStyle(this.update, 'position')=='absolute')) { |
|
97 |
new Insertion.After(this.update, |
|
97 | new Insertion.After(this.update, |
|
98 | '<iframe id="' + this.update.id + '_iefix" '+ |
|
98 | '<iframe id="' + this.update.id + '_iefix" '+ |
|
99 | 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + |
|
99 | 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + |
|
100 | 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); |
|
100 | 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); |
|
101 | this.iefix = $(this.update.id+'_iefix'); |
|
101 | this.iefix = $(this.update.id+'_iefix'); |
|
102 | } |
|
102 | } |
|
103 | if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); |
|
103 | if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); |
|
104 | }, |
|
104 | }, |
|
105 |
|
105 | ||
|
106 | fixIEOverlapping: function() { |
|
106 | fixIEOverlapping: function() { |
|
107 | Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); |
|
107 | Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); |
|
108 | this.iefix.style.zIndex = 1; |
|
108 | this.iefix.style.zIndex = 1; |
|
109 | this.update.style.zIndex = 2; |
|
109 | this.update.style.zIndex = 2; |
|
110 | Element.show(this.iefix); |
|
110 | Element.show(this.iefix); |
|
111 | }, |
|
111 | }, |
|
112 |
|
112 | ||
|
113 | hide: function() { |
|
113 | hide: function() { |
|
114 | this.stopIndicator(); |
|
114 | this.stopIndicator(); |
|
115 | if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); |
|
115 | if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); |
|
116 | if(this.iefix) Element.hide(this.iefix); |
|
116 | if(this.iefix) Element.hide(this.iefix); |
|
117 | }, |
|
117 | }, |
|
118 |
|
118 | ||
|
119 | startIndicator: function() { |
|
119 | startIndicator: function() { |
|
120 | if(this.options.indicator) Element.show(this.options.indicator); |
|
120 | if(this.options.indicator) Element.show(this.options.indicator); |
|
121 | }, |
|
121 | }, |
|
122 |
|
122 | ||
|
123 | stopIndicator: function() { |
|
123 | stopIndicator: function() { |
|
124 | if(this.options.indicator) Element.hide(this.options.indicator); |
|
124 | if(this.options.indicator) Element.hide(this.options.indicator); |
|
125 | }, |
|
125 | }, |
|
126 |
|
126 | ||
|
127 | onKeyPress: function(event) { |
|
127 | onKeyPress: function(event) { |
|
128 | if(this.active) |
|
128 | if(this.active) |
|
129 | switch(event.keyCode) { |
|
129 | switch(event.keyCode) { |
|
130 | case Event.KEY_TAB: |
|
130 | case Event.KEY_TAB: |
|
131 | case Event.KEY_RETURN: |
|
131 | case Event.KEY_RETURN: |
|
132 | this.selectEntry(); |
|
132 | this.selectEntry(); |
|
133 | Event.stop(event); |
|
133 | Event.stop(event); |
|
134 | case Event.KEY_ESC: |
|
134 | case Event.KEY_ESC: |
|
135 | this.hide(); |
|
135 | this.hide(); |
|
136 | this.active = false; |
|
136 | this.active = false; |
|
137 | Event.stop(event); |
|
137 | Event.stop(event); |
|
138 | return; |
|
138 | return; |
|
139 | case Event.KEY_LEFT: |
|
139 | case Event.KEY_LEFT: |
|
140 | case Event.KEY_RIGHT: |
|
140 | case Event.KEY_RIGHT: |
|
141 | return; |
|
141 | return; |
|
142 | case Event.KEY_UP: |
|
142 | case Event.KEY_UP: |
|
143 | this.markPrevious(); |
|
143 | this.markPrevious(); |
|
144 | this.render(); |
|
144 | this.render(); |
|
145 | Event.stop(event); |
|
145 | Event.stop(event); |
|
146 | return; |
|
146 | return; |
|
147 | case Event.KEY_DOWN: |
|
147 | case Event.KEY_DOWN: |
|
148 | this.markNext(); |
|
148 | this.markNext(); |
|
149 | this.render(); |
|
149 | this.render(); |
|
150 | Event.stop(event); |
|
150 | Event.stop(event); |
|
151 | return; |
|
151 | return; |
|
152 | } |
|
152 | } |
|
153 |
else |
|
153 | else |
|
154 |
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || |
|
154 | if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || |
|
155 | (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; |
|
155 | (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; |
|
156 |
|
156 | ||
|
157 | this.changed = true; |
|
157 | this.changed = true; |
|
158 | this.hasFocus = true; |
|
158 | this.hasFocus = true; |
|
159 |
|
159 | ||
|
160 | if(this.observer) clearTimeout(this.observer); |
|
160 | if(this.observer) clearTimeout(this.observer); |
|
161 |
this.observer = |
|
161 | this.observer = |
|
162 | setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); |
|
162 | setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); |
|
163 | }, |
|
163 | }, |
|
164 |
|
164 | ||
|
165 | activate: function() { |
|
165 | activate: function() { |
|
166 | this.changed = false; |
|
166 | this.changed = false; |
|
167 | this.hasFocus = true; |
|
167 | this.hasFocus = true; |
|
168 | this.getUpdatedChoices(); |
|
168 | this.getUpdatedChoices(); |
|
169 | }, |
|
169 | }, |
|
170 |
|
170 | ||
|
171 | onHover: function(event) { |
|
171 | onHover: function(event) { |
|
172 | var element = Event.findElement(event, 'LI'); |
|
172 | var element = Event.findElement(event, 'LI'); |
|
173 |
if(this.index != element.autocompleteIndex) |
|
173 | if(this.index != element.autocompleteIndex) |
|
174 | { |
|
174 | { |
|
175 | this.index = element.autocompleteIndex; |
|
175 | this.index = element.autocompleteIndex; |
|
176 | this.render(); |
|
176 | this.render(); |
|
177 | } |
|
177 | } |
|
178 | Event.stop(event); |
|
178 | Event.stop(event); |
|
179 | }, |
|
179 | }, |
|
180 |
|
180 | ||
|
181 | onClick: function(event) { |
|
181 | onClick: function(event) { |
|
182 | var element = Event.findElement(event, 'LI'); |
|
182 | var element = Event.findElement(event, 'LI'); |
|
183 | this.index = element.autocompleteIndex; |
|
183 | this.index = element.autocompleteIndex; |
|
184 | this.selectEntry(); |
|
184 | this.selectEntry(); |
|
185 | this.hide(); |
|
185 | this.hide(); |
|
186 | }, |
|
186 | }, |
|
187 |
|
187 | ||
|
188 | onBlur: function(event) { |
|
188 | onBlur: function(event) { |
|
189 | // needed to make click events working |
|
189 | // needed to make click events working |
|
190 | setTimeout(this.hide.bind(this), 250); |
|
190 | setTimeout(this.hide.bind(this), 250); |
|
191 | this.hasFocus = false; |
|
191 | this.hasFocus = false; |
|
192 |
this.active = false; |
|
192 | this.active = false; |
|
193 |
}, |
|
193 | }, |
|
194 |
|
194 | ||
|
195 | render: function() { |
|
195 | render: function() { |
|
196 | if(this.entryCount > 0) { |
|
196 | if(this.entryCount > 0) { |
|
197 | for (var i = 0; i < this.entryCount; i++) |
|
197 | for (var i = 0; i < this.entryCount; i++) |
|
198 |
this.index==i ? |
|
198 | this.index==i ? |
|
199 |
Element.addClassName(this.getEntry(i),"selected") : |
|
199 | Element.addClassName(this.getEntry(i),"selected") : |
|
200 | Element.removeClassName(this.getEntry(i),"selected"); |
|
200 | Element.removeClassName(this.getEntry(i),"selected"); |
|
201 |
if(this.hasFocus) { |
|
201 | if(this.hasFocus) { |
|
202 | this.show(); |
|
202 | this.show(); |
|
203 | this.active = true; |
|
203 | this.active = true; |
|
204 | } |
|
204 | } |
|
205 | } else { |
|
205 | } else { |
|
206 | this.active = false; |
|
206 | this.active = false; |
|
207 | this.hide(); |
|
207 | this.hide(); |
|
208 | } |
|
208 | } |
|
209 | }, |
|
209 | }, |
|
210 |
|
210 | ||
|
211 | markPrevious: function() { |
|
211 | markPrevious: function() { |
|
212 | - if(this.index > 0) this.index-- |
|
212 | + if(this.index > 0) this.index--; |
|
213 | else this.index = this.entryCount-1; |
|
213 | else this.index = this.entryCount-1; |
|
214 | this.getEntry(this.index).scrollIntoView(true); |
|
214 | this.getEntry(this.index).scrollIntoView(true); |
|
215 | }, |
|
215 | }, |
|
216 |
|
216 | ||
|
217 | markNext: function() { |
|
217 | markNext: function() { |
|
218 | - if(this.index < this.entryCount-1) this.index++ |
|
218 | + if(this.index < this.entryCount-1) this.index++; |
|
219 | else this.index = 0; |
|
219 | else this.index = 0; |
|
220 | this.getEntry(this.index).scrollIntoView(false); |
|
220 | this.getEntry(this.index).scrollIntoView(false); |
|
221 | }, |
|
221 | }, |
|
222 |
|
222 | ||
|
223 | getEntry: function(index) { |
|
223 | getEntry: function(index) { |
|
224 | return this.update.firstChild.childNodes[index]; |
|
224 | return this.update.firstChild.childNodes[index]; |
|
225 | }, |
|
225 | }, |
|
226 |
|
226 | ||
|
227 | getCurrentEntry: function() { |
|
227 | getCurrentEntry: function() { |
|
228 | return this.getEntry(this.index); |
|
228 | return this.getEntry(this.index); |
|
229 | }, |
|
229 | }, |
|
230 |
|
230 | ||
|
231 | selectEntry: function() { |
|
231 | selectEntry: function() { |
|
232 | this.active = false; |
|
232 | this.active = false; |
|
233 | this.updateElement(this.getCurrentEntry()); |
|
233 | this.updateElement(this.getCurrentEntry()); |
|
234 | }, |
|
234 | }, |
|
235 |
|
235 | ||
|
236 | updateElement: function(selectedElement) { |
|
236 | updateElement: function(selectedElement) { |
|
237 | if (this.options.updateElement) { |
|
237 | if (this.options.updateElement) { |
|
238 | this.options.updateElement(selectedElement); |
|
238 | this.options.updateElement(selectedElement); |
|
239 | return; |
|
239 | return; |
|
240 | } |
|
240 | } |
|
241 | var value = ''; |
|
241 | var value = ''; |
|
242 | if (this.options.select) { |
|
242 | if (this.options.select) { |
|
243 | var nodes = $(selectedElement).select('.' + this.options.select) || []; |
|
243 | var nodes = $(selectedElement).select('.' + this.options.select) || []; |
|
244 | if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); |
|
244 | if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); |
|
245 | } else |
|
245 | } else |
|
246 | value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); |
|
246 | value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); |
|
247 |
|
247 | ||
|
248 | var bounds = this.getTokenBounds(); |
|
248 | var bounds = this.getTokenBounds(); |
|
249 | if (bounds[0] != -1) { |
|
249 | if (bounds[0] != -1) { |
|
250 | var newValue = this.element.value.substr(0, bounds[0]); |
|
250 | var newValue = this.element.value.substr(0, bounds[0]); |
|
251 | var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); |
|
251 | var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); |
|
252 | if (whitespace) |
|
252 | if (whitespace) |
|
253 | newValue += whitespace[0]; |
|
253 | newValue += whitespace[0]; |
|
254 | this.element.value = newValue + value + this.element.value.substr(bounds[1]); |
|
254 | this.element.value = newValue + value + this.element.value.substr(bounds[1]); |
|
255 | } else { |
|
255 | } else { |
|
256 | this.element.value = value; |
|
256 | this.element.value = value; |
|
257 | } |
|
257 | } |
|
258 | this.oldElementValue = this.element.value; |
|
258 | this.oldElementValue = this.element.value; |
|
259 | this.element.focus(); |
|
259 | this.element.focus(); |
|
260 |
|
260 | ||
|
261 | if (this.options.afterUpdateElement) |
|
261 | if (this.options.afterUpdateElement) |
|
262 | this.options.afterUpdateElement(this.element, selectedElement); |
|
262 | this.options.afterUpdateElement(this.element, selectedElement); |
|
263 | }, |
|
263 | }, |
|
264 |
|
264 | ||
|
265 | updateChoices: function(choices) { |
|
265 | updateChoices: function(choices) { |
|
266 | if(!this.changed && this.hasFocus) { |
|
266 | if(!this.changed && this.hasFocus) { |
|
267 | this.update.innerHTML = choices; |
|
267 | this.update.innerHTML = choices; |
|
268 | Element.cleanWhitespace(this.update); |
|
268 | Element.cleanWhitespace(this.update); |
|
269 | Element.cleanWhitespace(this.update.down()); |
|
269 | Element.cleanWhitespace(this.update.down()); |
|
270 |
|
270 | ||
|
271 | if(this.update.firstChild && this.update.down().childNodes) { |
|
271 | if(this.update.firstChild && this.update.down().childNodes) { |
|
272 |
this.entryCount = |
|
272 | this.entryCount = |
|
273 | this.update.down().childNodes.length; |
|
273 | this.update.down().childNodes.length; |
|
274 | for (var i = 0; i < this.entryCount; i++) { |
|
274 | for (var i = 0; i < this.entryCount; i++) { |
|
275 | var entry = this.getEntry(i); |
|
275 | var entry = this.getEntry(i); |
|
276 | entry.autocompleteIndex = i; |
|
276 | entry.autocompleteIndex = i; |
|
277 | this.addObservers(entry); |
|
277 | this.addObservers(entry); |
|
278 | } |
|
278 | } |
|
279 |
} else { |
|
279 | } else { |
|
280 | this.entryCount = 0; |
|
280 | this.entryCount = 0; |
|
281 | } |
|
281 | } |
|
282 |
|
282 | ||
|
283 | this.stopIndicator(); |
|
283 | this.stopIndicator(); |
|
284 | this.index = 0; |
|
284 | this.index = 0; |
|
285 |
|
285 | ||
|
286 | if(this.entryCount==1 && this.options.autoSelect) { |
|
286 | if(this.entryCount==1 && this.options.autoSelect) { |
|
287 | this.selectEntry(); |
|
287 | this.selectEntry(); |
|
288 | this.hide(); |
|
288 | this.hide(); |
|
289 | } else { |
|
289 | } else { |
|
290 | this.render(); |
|
290 | this.render(); |
|
291 | } |
|
291 | } |
|
292 | } |
|
292 | } |
|
293 | }, |
|
293 | }, |
|
294 |
|
294 | ||
|
295 | addObservers: function(element) { |
|
295 | addObservers: function(element) { |
|
296 | Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); |
|
296 | Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); |
|
297 | Event.observe(element, "click", this.onClick.bindAsEventListener(this)); |
|
297 | Event.observe(element, "click", this.onClick.bindAsEventListener(this)); |
|
298 | }, |
|
298 | }, |
|
299 |
|
299 | ||
|
300 | onObserverEvent: function() { |
|
300 | onObserverEvent: function() { |
|
301 |
this.changed = false; |
|
301 | this.changed = false; |
|
302 | this.tokenBounds = null; |
|
302 | this.tokenBounds = null; |
|
303 | if(this.getToken().length>=this.options.minChars) { |
|
303 | if(this.getToken().length>=this.options.minChars) { |
|
304 | this.getUpdatedChoices(); |
|
304 | this.getUpdatedChoices(); |
|
305 | } else { |
|
305 | } else { |
|
306 | this.active = false; |
|
306 | this.active = false; |
|
307 | this.hide(); |
|
307 | this.hide(); |
|
308 | } |
|
308 | } |
|
309 | this.oldElementValue = this.element.value; |
|
309 | this.oldElementValue = this.element.value; |
|
310 | }, |
|
310 | }, |
|
311 |
|
311 | ||
|
312 | getToken: function() { |
|
312 | getToken: function() { |
|
313 | var bounds = this.getTokenBounds(); |
|
313 | var bounds = this.getTokenBounds(); |
|
314 | return this.element.value.substring(bounds[0], bounds[1]).strip(); |
|
314 | return this.element.value.substring(bounds[0], bounds[1]).strip(); |
|
315 | }, |
|
315 | }, |
|
316 |
|
316 | ||
|
317 | getTokenBounds: function() { |
|
317 | getTokenBounds: function() { |
|
318 | if (null != this.tokenBounds) return this.tokenBounds; |
|
318 | if (null != this.tokenBounds) return this.tokenBounds; |
|
319 | var value = this.element.value; |
|
319 | var value = this.element.value; |
|
320 | if (value.strip().empty()) return [-1, 0]; |
|
320 | if (value.strip().empty()) return [-1, 0]; |
|
321 | var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); |
|
321 | var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); |
|
322 | var offset = (diff == this.oldElementValue.length ? 1 : 0); |
|
322 | var offset = (diff == this.oldElementValue.length ? 1 : 0); |
|
323 | var prevTokenPos = -1, nextTokenPos = value.length; |
|
323 | var prevTokenPos = -1, nextTokenPos = value.length; |
|
324 | var tp; |
|
324 | var tp; |
|
325 | for (var index = 0, l = this.options.tokens.length; index < l; ++index) { |
|
325 | for (var index = 0, l = this.options.tokens.length; index < l; ++index) { |
|
326 | tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); |
|
326 | tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); |
|
327 | if (tp > prevTokenPos) prevTokenPos = tp; |
|
327 | if (tp > prevTokenPos) prevTokenPos = tp; |
|
328 | tp = value.indexOf(this.options.tokens[index], diff + offset); |
|
328 | tp = value.indexOf(this.options.tokens[index], diff + offset); |
|
329 | if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; |
|
329 | if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; |
|
330 | } |
|
330 | } |
|
331 | return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); |
|
331 | return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); |
|
332 | } |
|
332 | } |
|
333 | }); |
|
333 | }); |
|
334 |
|
334 | ||
|
335 | Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { |
|
335 | Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { |
|
336 | var boundary = Math.min(newS.length, oldS.length); |
|
336 | var boundary = Math.min(newS.length, oldS.length); |
|
337 | for (var index = 0; index < boundary; ++index) |
|
337 | for (var index = 0; index < boundary; ++index) |
|
338 | if (newS[index] != oldS[index]) |
|
338 | if (newS[index] != oldS[index]) |
|
339 | return index; |
|
339 | return index; |
|
340 | return boundary; |
|
340 | return boundary; |
|
341 | }; |
|
341 | }; |
|
342 |
|
342 | ||
|
343 | Ajax.Autocompleter = Class.create(Autocompleter.Base, { |
|
343 | Ajax.Autocompleter = Class.create(Autocompleter.Base, { |
|
344 | initialize: function(element, update, url, options) { |
|
344 | initialize: function(element, update, url, options) { |
|
345 | this.baseInitialize(element, update, options); |
|
345 | this.baseInitialize(element, update, options); |
|
346 | this.options.asynchronous = true; |
|
346 | this.options.asynchronous = true; |
|
347 | this.options.onComplete = this.onComplete.bind(this); |
|
347 | this.options.onComplete = this.onComplete.bind(this); |
|
348 | this.options.defaultParams = this.options.parameters || null; |
|
348 | this.options.defaultParams = this.options.parameters || null; |
|
349 | this.url = url; |
|
349 | this.url = url; |
|
350 | }, |
|
350 | }, |
|
351 |
|
351 | ||
|
352 | getUpdatedChoices: function() { |
|
352 | getUpdatedChoices: function() { |
|
353 | this.startIndicator(); |
|
353 | this.startIndicator(); |
|
354 |
|
354 | ||
|
355 |
var entry = encodeURIComponent(this.options.paramName) + '=' + |
|
355 | var entry = encodeURIComponent(this.options.paramName) + '=' + |
|
356 | encodeURIComponent(this.getToken()); |
|
356 | encodeURIComponent(this.getToken()); |
|
357 |
|
357 | ||
|
358 | this.options.parameters = this.options.callback ? |
|
358 | this.options.parameters = this.options.callback ? |
|
359 | this.options.callback(this.element, entry) : entry; |
|
359 | this.options.callback(this.element, entry) : entry; |
|
360 |
|
360 | ||
|
361 |
if(this.options.defaultParams) |
|
361 | if(this.options.defaultParams) |
|
362 | this.options.parameters += '&' + this.options.defaultParams; |
|
362 | this.options.parameters += '&' + this.options.defaultParams; |
|
363 |
|
363 | ||
|
364 | new Ajax.Request(this.url, this.options); |
|
364 | new Ajax.Request(this.url, this.options); |
|
365 | }, |
|
365 | }, |
|
366 |
|
366 | ||
|
367 | onComplete: function(request) { |
|
367 | onComplete: function(request) { |
|
368 | this.updateChoices(request.responseText); |
|
368 | this.updateChoices(request.responseText); |
|
369 | } |
|
369 | } |
|
370 | }); |
|
370 | }); |
|
371 |
|
371 | ||
|
372 | // The local array autocompleter. Used when you'd prefer to |
|
372 | // The local array autocompleter. Used when you'd prefer to |
|
373 | // inject an array of autocompletion options into the page, rather |
|
373 | // inject an array of autocompletion options into the page, rather |
|
374 | // than sending out Ajax queries, which can be quite slow sometimes. |
|
374 | // than sending out Ajax queries, which can be quite slow sometimes. |
|
375 | // |
|
375 | // |
|
376 | // The constructor takes four parameters. The first two are, as usual, |
|
376 | // The constructor takes four parameters. The first two are, as usual, |
|
377 | // the id of the monitored textbox, and id of the autocompletion menu. |
|
377 | // the id of the monitored textbox, and id of the autocompletion menu. |
|
378 | // The third is the array you want to autocomplete from, and the fourth |
|
378 | // The third is the array you want to autocomplete from, and the fourth |
|
379 | // is the options block. |
|
379 | // is the options block. |
|
380 | // |
|
380 | // |
|
381 | // Extra local autocompletion options: |
|
381 | // Extra local autocompletion options: |
|
382 | // - choices - How many autocompletion choices to offer |
|
382 | // - choices - How many autocompletion choices to offer |
|
383 | // |
|
383 | // |
|
384 | // - partialSearch - If false, the autocompleter will match entered |
|
384 | // - partialSearch - If false, the autocompleter will match entered |
|
385 |
// text only at the beginning of strings in the |
|
385 | // text only at the beginning of strings in the |
|
386 | // autocomplete array. Defaults to true, which will |
|
386 | // autocomplete array. Defaults to true, which will |
|
387 | // match text at the beginning of any *word* in the |
|
387 | // match text at the beginning of any *word* in the |
|
388 | // strings in the autocomplete array. If you want to |
|
388 | // strings in the autocomplete array. If you want to |
|
389 | // search anywhere in the string, additionally set |
|
389 | // search anywhere in the string, additionally set |
|
390 | // the option fullSearch to true (default: off). |
|
390 | // the option fullSearch to true (default: off). |
|
391 | // |
|
391 | // |
|
392 | // - fullSsearch - Search anywhere in autocomplete array strings. |
|
392 | // - fullSsearch - Search anywhere in autocomplete array strings. |
|
393 | // |
|
393 | // |
|
394 | // - partialChars - How many characters to enter before triggering |
|
394 | // - partialChars - How many characters to enter before triggering |
|
395 | // a partial match (unlike minChars, which defines |
|
395 | // a partial match (unlike minChars, which defines |
|
396 | // how many characters are required to do any match |
|
396 | // how many characters are required to do any match |
|
397 | // at all). Defaults to 2. |
|
397 | // at all). Defaults to 2. |
|
398 | // |
|
398 | // |
|
399 | // - ignoreCase - Whether to ignore case when autocompleting. |
|
399 | // - ignoreCase - Whether to ignore case when autocompleting. |
|
400 | // Defaults to true. |
|
400 | // Defaults to true. |
|
401 | // |
|
401 | // |
|
402 |
// It's possible to pass in a custom function as the 'selector' |
|
402 | // It's possible to pass in a custom function as the 'selector' |
|
403 | // option, if you prefer to write your own autocompletion logic. |
|
403 | // option, if you prefer to write your own autocompletion logic. |
|
404 | // In that case, the other options above will not apply unless |
|
404 | // In that case, the other options above will not apply unless |
|
405 | // you support them. |
|
405 | // you support them. |
|
406 |
|
406 | ||
|
407 | Autocompleter.Local = Class.create(Autocompleter.Base, { |
|
407 | Autocompleter.Local = Class.create(Autocompleter.Base, { |
|
408 | initialize: function(element, update, array, options) { |
|
408 | initialize: function(element, update, array, options) { |
|
409 | this.baseInitialize(element, update, options); |
|
409 | this.baseInitialize(element, update, options); |
|
410 | this.options.array = array; |
|
410 | this.options.array = array; |
|
411 | }, |
|
411 | }, |
|
412 |
|
412 | ||
|
413 | getUpdatedChoices: function() { |
|
413 | getUpdatedChoices: function() { |
|
414 | this.updateChoices(this.options.selector(this)); |
|
414 | this.updateChoices(this.options.selector(this)); |
|
415 | }, |
|
415 | }, |
|
416 |
|
416 | ||
|
417 | setOptions: function(options) { |
|
417 | setOptions: function(options) { |
|
418 | this.options = Object.extend({ |
|
418 | this.options = Object.extend({ |
|
419 | choices: 10, |
|
419 | choices: 10, |
|
420 | partialSearch: true, |
|
420 | partialSearch: true, |
|
421 | partialChars: 2, |
|
421 | partialChars: 2, |
|
422 | ignoreCase: true, |
|
422 | ignoreCase: true, |
|
423 | fullSearch: false, |
|
423 | fullSearch: false, |
|
424 | selector: function(instance) { |
|
424 | selector: function(instance) { |
|
425 | var ret = []; // Beginning matches |
|
425 | var ret = []; // Beginning matches |
|
426 | var partial = []; // Inside matches |
|
426 | var partial = []; // Inside matches |
|
427 | var entry = instance.getToken(); |
|
427 | var entry = instance.getToken(); |
|
428 | var count = 0; |
|
428 | var count = 0; |
|
429 |
|
429 | ||
|
430 |
for (var i = 0; i < instance.options.array.length && |
|
430 | for (var i = 0; i < instance.options.array.length && |
|
431 |
ret.length < instance.options.choices ; i++) { |
|
431 | ret.length < instance.options.choices ; i++) { |
|
432 |
|
432 | ||
|
433 | var elem = instance.options.array[i]; |
|
433 | var elem = instance.options.array[i]; |
|
434 |
var foundPos = instance.options.ignoreCase ? |
|
434 | var foundPos = instance.options.ignoreCase ? |
|
435 |
elem.toLowerCase().indexOf(entry.toLowerCase()) : |
|
435 | elem.toLowerCase().indexOf(entry.toLowerCase()) : |
|
436 | elem.indexOf(entry); |
|
436 | elem.indexOf(entry); |
|
437 |
|
437 | ||
|
438 | while (foundPos != -1) { |
|
438 | while (foundPos != -1) { |
|
439 |
if (foundPos == 0 && elem.length != entry.length) { |
|
439 | if (foundPos == 0 && elem.length != entry.length) { |
|
440 |
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + |
|
440 | ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + |
|
441 | elem.substr(entry.length) + "</li>"); |
|
441 | elem.substr(entry.length) + "</li>"); |
|
442 | break; |
|
442 | break; |
|
443 |
} else if (entry.length >= instance.options.partialChars && |
|
443 | } else if (entry.length >= instance.options.partialChars && |
|
444 | instance.options.partialSearch && foundPos != -1) { |
|
444 | instance.options.partialSearch && foundPos != -1) { |
|
445 | if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { |
|
445 | if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { |
|
446 | partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + |
|
446 | partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + |
|
447 | elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( |
|
447 | elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( |
|
448 | foundPos + entry.length) + "</li>"); |
|
448 | foundPos + entry.length) + "</li>"); |
|
449 | break; |
|
449 | break; |
|
450 | } |
|
450 | } |
|
451 | } |
|
451 | } |
|
452 |
|
452 | ||
|
453 |
foundPos = instance.options.ignoreCase ? |
|
453 | foundPos = instance.options.ignoreCase ? |
|
454 |
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : |
|
454 | elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : |
|
455 | elem.indexOf(entry, foundPos + 1); |
|
455 | elem.indexOf(entry, foundPos + 1); |
|
456 |
|
456 | ||
|
457 | } |
|
457 | } |
|
458 | } |
|
458 | } |
|
459 | if (partial.length) |
|
459 | if (partial.length) |
|
460 | - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) |
|
460 | + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); |
|
461 | return "<ul>" + ret.join('') + "</ul>"; |
|
461 | return "<ul>" + ret.join('') + "</ul>"; |
|
462 | } |
|
462 | } |
|
463 | }, options || { }); |
|
463 | }, options || { }); |
|
464 | } |
|
464 | } |
|
465 | }); |
|
465 | }); |
|
466 |
|
466 | ||
|
467 | // AJAX in-place editor and collection editor |
|
467 | // AJAX in-place editor and collection editor |
|
468 | // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007). |
|
468 | // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007). |
|
469 |
|
469 | ||
|
470 | // Use this if you notice weird scrolling problems on some browsers, |
|
470 | // Use this if you notice weird scrolling problems on some browsers, |
|
471 | // the DOM might be a bit confused when this gets called so do this |
|
471 | // the DOM might be a bit confused when this gets called so do this |
|
472 | // waits 1 ms (with setTimeout) until it does the activation |
|
472 | // waits 1 ms (with setTimeout) until it does the activation |
|
473 | Field.scrollFreeActivate = function(field) { |
|
473 | Field.scrollFreeActivate = function(field) { |
|
474 | setTimeout(function() { |
|
474 | setTimeout(function() { |
|
475 | Field.activate(field); |
|
475 | Field.activate(field); |
|
476 | }, 1); |
|
476 | }, 1); |
|
477 | - } |
|
477 | + }; |
|
478 |
|
478 | ||
|
479 | Ajax.InPlaceEditor = Class.create({ |
|
479 | Ajax.InPlaceEditor = Class.create({ |
|
480 | initialize: function(element, url, options) { |
|
480 | initialize: function(element, url, options) { |
|
481 | this.url = url; |
|
481 | this.url = url; |
|
482 | this.element = element = $(element); |
|
482 | this.element = element = $(element); |
|
483 | this.prepareOptions(); |
|
483 | this.prepareOptions(); |
|
484 | this._controls = { }; |
|
484 | this._controls = { }; |
|
485 | arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! |
|
485 | arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! |
|
486 | Object.extend(this.options, options || { }); |
|
486 | Object.extend(this.options, options || { }); |
|
487 | if (!this.options.formId && this.element.id) { |
|
487 | if (!this.options.formId && this.element.id) { |
|
488 | this.options.formId = this.element.id + '-inplaceeditor'; |
|
488 | this.options.formId = this.element.id + '-inplaceeditor'; |
|
489 | if ($(this.options.formId)) |
|
489 | if ($(this.options.formId)) |
|
490 | this.options.formId = ''; |
|
490 | this.options.formId = ''; |
|
491 | } |
|
491 | } |
|
492 | if (this.options.externalControl) |
|
492 | if (this.options.externalControl) |
|
493 | this.options.externalControl = $(this.options.externalControl); |
|
493 | this.options.externalControl = $(this.options.externalControl); |
|
494 | if (!this.options.externalControl) |
|
494 | if (!this.options.externalControl) |
|
495 | this.options.externalControlOnly = false; |
|
495 | this.options.externalControlOnly = false; |
|
496 | this._originalBackground = this.element.getStyle('background-color') || 'transparent'; |
|
496 | this._originalBackground = this.element.getStyle('background-color') || 'transparent'; |
|
497 | this.element.title = this.options.clickToEditText; |
|
497 | this.element.title = this.options.clickToEditText; |
|
498 | this._boundCancelHandler = this.handleFormCancellation.bind(this); |
|
498 | this._boundCancelHandler = this.handleFormCancellation.bind(this); |
|
499 | this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); |
|
499 | this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); |
|
500 | this._boundFailureHandler = this.handleAJAXFailure.bind(this); |
|
500 | this._boundFailureHandler = this.handleAJAXFailure.bind(this); |
|
501 | this._boundSubmitHandler = this.handleFormSubmission.bind(this); |
|
501 | this._boundSubmitHandler = this.handleFormSubmission.bind(this); |
|
502 | this._boundWrapperHandler = this.wrapUp.bind(this); |
|
502 | this._boundWrapperHandler = this.wrapUp.bind(this); |
|
503 | this.registerListeners(); |
|
503 | this.registerListeners(); |
|
504 | }, |
|
504 | }, |
|
505 | checkForEscapeOrReturn: function(e) { |
|
505 | checkForEscapeOrReturn: function(e) { |
|
506 | if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; |
|
506 | if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; |
|
507 | if (Event.KEY_ESC == e.keyCode) |
|
507 | if (Event.KEY_ESC == e.keyCode) |
|
508 | this.handleFormCancellation(e); |
|
508 | this.handleFormCancellation(e); |
|
509 | else if (Event.KEY_RETURN == e.keyCode) |
|
509 | else if (Event.KEY_RETURN == e.keyCode) |
|
510 | this.handleFormSubmission(e); |
|
510 | this.handleFormSubmission(e); |
|
511 | }, |
|
511 | }, |
|
512 | createControl: function(mode, handler, extraClasses) { |
|
512 | createControl: function(mode, handler, extraClasses) { |
|
513 | var control = this.options[mode + 'Control']; |
|
513 | var control = this.options[mode + 'Control']; |
|
514 | var text = this.options[mode + 'Text']; |
|
514 | var text = this.options[mode + 'Text']; |
|
515 | if ('button' == control) { |
|
515 | if ('button' == control) { |
|
516 | var btn = document.createElement('input'); |
|
516 | var btn = document.createElement('input'); |
|
517 | btn.type = 'submit'; |
|
517 | btn.type = 'submit'; |
|
518 | btn.value = text; |
|
518 | btn.value = text; |
|
519 | btn.className = 'editor_' + mode + '_button'; |
|
519 | btn.className = 'editor_' + mode + '_button'; |
|
520 | if ('cancel' == mode) |
|
520 | if ('cancel' == mode) |
|
521 | btn.onclick = this._boundCancelHandler; |
|
521 | btn.onclick = this._boundCancelHandler; |
|
522 | this._form.appendChild(btn); |
|
522 | this._form.appendChild(btn); |
|
523 | this._controls[mode] = btn; |
|
523 | this._controls[mode] = btn; |
|
524 | } else if ('link' == control) { |
|
524 | } else if ('link' == control) { |
|
525 | var link = document.createElement('a'); |
|
525 | var link = document.createElement('a'); |
|
526 | link.href = '#'; |
|
526 | link.href = '#'; |
|
527 | link.appendChild(document.createTextNode(text)); |
|
527 | link.appendChild(document.createTextNode(text)); |
|
528 | link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; |
|
528 | link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; |
|
529 | link.className = 'editor_' + mode + '_link'; |
|
529 | link.className = 'editor_' + mode + '_link'; |
|
530 | if (extraClasses) |
|
530 | if (extraClasses) |
|
531 | link.className += ' ' + extraClasses; |
|
531 | link.className += ' ' + extraClasses; |
|
532 | this._form.appendChild(link); |
|
532 | this._form.appendChild(link); |
|
533 | this._controls[mode] = link; |
|
533 | this._controls[mode] = link; |
|
534 | } |
|
534 | } |
|
535 | }, |
|
535 | }, |
|
536 | createEditField: function() { |
|
536 | createEditField: function() { |
|
537 | var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); |
|
537 | var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); |
|
538 | var fld; |
|
538 | var fld; |
|
539 | if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { |
|
539 | if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { |
|
540 | fld = document.createElement('input'); |
|
540 | fld = document.createElement('input'); |
|
541 | fld.type = 'text'; |
|
541 | fld.type = 'text'; |
|
542 | var size = this.options.size || this.options.cols || 0; |
|
542 | var size = this.options.size || this.options.cols || 0; |
|
543 | if (0 < size) fld.size = size; |
|
543 | if (0 < size) fld.size = size; |
|
544 | } else { |
|
544 | } else { |
|
545 | fld = document.createElement('textarea'); |
|
545 | fld = document.createElement('textarea'); |
|
546 | fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); |
|
546 | fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); |
|
547 | fld.cols = this.options.cols || 40; |
|
547 | fld.cols = this.options.cols || 40; |
|
548 | } |
|
548 | } |
|
549 | fld.name = this.options.paramName; |
|
549 | fld.name = this.options.paramName; |
|
550 | fld.value = text; // No HTML breaks conversion anymore |
|
550 | fld.value = text; // No HTML breaks conversion anymore |
|
551 | fld.className = 'editor_field'; |
|
551 | fld.className = 'editor_field'; |
|
552 | if (this.options.submitOnBlur) |
|
552 | if (this.options.submitOnBlur) |
|
553 | fld.onblur = this._boundSubmitHandler; |
|
553 | fld.onblur = this._boundSubmitHandler; |
|
554 | this._controls.editor = fld; |
|
554 | this._controls.editor = fld; |
|
555 | if (this.options.loadTextURL) |
|
555 | if (this.options.loadTextURL) |
|
556 | this.loadExternalText(); |
|
556 | this.loadExternalText(); |
|
557 | this._form.appendChild(this._controls.editor); |
|
557 | this._form.appendChild(this._controls.editor); |
|
558 | }, |
|
558 | }, |
|
559 | createForm: function() { |
|
559 | createForm: function() { |
|
560 | var ipe = this; |
|
560 | var ipe = this; |
|
561 | function addText(mode, condition) { |
|
561 | function addText(mode, condition) { |
|
562 | var text = ipe.options['text' + mode + 'Controls']; |
|
562 | var text = ipe.options['text' + mode + 'Controls']; |
|
563 | if (!text || condition === false) return; |
|
563 | if (!text || condition === false) return; |
|
564 | ipe._form.appendChild(document.createTextNode(text)); |
|
564 | ipe._form.appendChild(document.createTextNode(text)); |
|
565 | }; |
|
565 | }; |
|
566 | this._form = $(document.createElement('form')); |
|
566 | this._form = $(document.createElement('form')); |
|
567 | this._form.id = this.options.formId; |
|
567 | this._form.id = this.options.formId; |
|
568 | this._form.addClassName(this.options.formClassName); |
|
568 | this._form.addClassName(this.options.formClassName); |
|
569 | this._form.onsubmit = this._boundSubmitHandler; |
|
569 | this._form.onsubmit = this._boundSubmitHandler; |
|
570 | this.createEditField(); |
|
570 | this.createEditField(); |
|
571 | if ('textarea' == this._controls.editor.tagName.toLowerCase()) |
|
571 | if ('textarea' == this._controls.editor.tagName.toLowerCase()) |
|
572 | this._form.appendChild(document.createElement('br')); |
|
572 | this._form.appendChild(document.createElement('br')); |
|
573 | if (this.options.onFormCustomization) |
|
573 | if (this.options.onFormCustomization) |
|
574 | this.options.onFormCustomization(this, this._form); |
|
574 | this.options.onFormCustomization(this, this._form); |
|
575 | addText('Before', this.options.okControl || this.options.cancelControl); |
|
575 | addText('Before', this.options.okControl || this.options.cancelControl); |
|
576 | this.createControl('ok', this._boundSubmitHandler); |
|
576 | this.createControl('ok', this._boundSubmitHandler); |
|
577 | addText('Between', this.options.okControl && this.options.cancelControl); |
|
577 | addText('Between', this.options.okControl && this.options.cancelControl); |
|
578 | this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); |
|
578 | this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); |
|
579 | addText('After', this.options.okControl || this.options.cancelControl); |
|
579 | addText('After', this.options.okControl || this.options.cancelControl); |
|
580 | }, |
|
580 | }, |
|
581 | destroy: function() { |
|
581 | destroy: function() { |
|
582 | if (this._oldInnerHTML) |
|
582 | if (this._oldInnerHTML) |
|
583 | this.element.innerHTML = this._oldInnerHTML; |
|
583 | this.element.innerHTML = this._oldInnerHTML; |
|
584 | this.leaveEditMode(); |
|
584 | this.leaveEditMode(); |
|
585 | this.unregisterListeners(); |
|
585 | this.unregisterListeners(); |
|
586 | }, |
|
586 | }, |
|
587 | enterEditMode: function(e) { |
|
587 | enterEditMode: function(e) { |
|
588 | if (this._saving || this._editing) return; |
|
588 | if (this._saving || this._editing) return; |
|
589 | this._editing = true; |
|
589 | this._editing = true; |
|
590 | this.triggerCallback('onEnterEditMode'); |
|
590 | this.triggerCallback('onEnterEditMode'); |
|
591 | if (this.options.externalControl) |
|
591 | if (this.options.externalControl) |
|
592 | this.options.externalControl.hide(); |
|
592 | this.options.externalControl.hide(); |
|
593 | this.element.hide(); |
|
593 | this.element.hide(); |
|
594 | this.createForm(); |
|
594 | this.createForm(); |
|
595 | this.element.parentNode.insertBefore(this._form, this.element); |
|
595 | this.element.parentNode.insertBefore(this._form, this.element); |
|
596 | if (!this.options.loadTextURL) |
|
596 | if (!this.options.loadTextURL) |
|
597 | this.postProcessEditField(); |
|
597 | this.postProcessEditField(); |
|
598 | if (e) Event.stop(e); |
|
598 | if (e) Event.stop(e); |
|
599 | }, |
|
599 | }, |
|
600 | enterHover: function(e) { |
|
600 | enterHover: function(e) { |
|
601 | if (this.options.hoverClassName) |
|
601 | if (this.options.hoverClassName) |
|
602 | this.element.addClassName(this.options.hoverClassName); |
|
602 | this.element.addClassName(this.options.hoverClassName); |
|
603 | if (this._saving) return; |
|
603 | if (this._saving) return; |
|
604 | this.triggerCallback('onEnterHover'); |
|
604 | this.triggerCallback('onEnterHover'); |
|
605 | }, |
|
605 | }, |
|
606 | getText: function() { |
|
606 | getText: function() { |
|
607 | - return this.element.innerHTML; |
|
607 | + return this.element.innerHTML.unescapeHTML(); |
|
608 | }, |
|
608 | }, |
|
609 | handleAJAXFailure: function(transport) { |
|
609 | handleAJAXFailure: function(transport) { |
|
610 | this.triggerCallback('onFailure', transport); |
|
610 | this.triggerCallback('onFailure', transport); |
|
611 | if (this._oldInnerHTML) { |
|
611 | if (this._oldInnerHTML) { |
|
612 | this.element.innerHTML = this._oldInnerHTML; |
|
612 | this.element.innerHTML = this._oldInnerHTML; |
|
613 | this._oldInnerHTML = null; |
|
613 | this._oldInnerHTML = null; |
|
614 | } |
|
614 | } |
|
615 | }, |
|
615 | }, |
|
616 | handleFormCancellation: function(e) { |
|
616 | handleFormCancellation: function(e) { |
|
617 | this.wrapUp(); |
|
617 | this.wrapUp(); |
|
618 | if (e) Event.stop(e); |
|
618 | if (e) Event.stop(e); |
|
619 | }, |
|
619 | }, |
|
620 | handleFormSubmission: function(e) { |
|
620 | handleFormSubmission: function(e) { |
|
621 | var form = this._form; |
|
621 | var form = this._form; |
|
622 | var value = $F(this._controls.editor); |
|
622 | var value = $F(this._controls.editor); |
|
623 | this.prepareSubmission(); |
|
623 | this.prepareSubmission(); |
|
624 | var params = this.options.callback(form, value) || ''; |
|
624 | var params = this.options.callback(form, value) || ''; |
|
625 | if (Object.isString(params)) |
|
625 | if (Object.isString(params)) |
|
626 | params = params.toQueryParams(); |
|
626 | params = params.toQueryParams(); |
|
627 | params.editorId = this.element.id; |
|
627 | params.editorId = this.element.id; |
|
628 | if (this.options.htmlResponse) { |
|
628 | if (this.options.htmlResponse) { |
|
629 | var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); |
|
629 | var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); |
|
630 | Object.extend(options, { |
|
630 | Object.extend(options, { |
|
631 | parameters: params, |
|
631 | parameters: params, |
|
632 | onComplete: this._boundWrapperHandler, |
|
632 | onComplete: this._boundWrapperHandler, |
|
633 | onFailure: this._boundFailureHandler |
|
633 | onFailure: this._boundFailureHandler |
|
634 | }); |
|
634 | }); |
|
635 | new Ajax.Updater({ success: this.element }, this.url, options); |
|
635 | new Ajax.Updater({ success: this.element }, this.url, options); |
|
636 | } else { |
|
636 | } else { |
|
637 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
637 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
638 | Object.extend(options, { |
|
638 | Object.extend(options, { |
|
639 | parameters: params, |
|
639 | parameters: params, |
|
640 | onComplete: this._boundWrapperHandler, |
|
640 | onComplete: this._boundWrapperHandler, |
|
641 | onFailure: this._boundFailureHandler |
|
641 | onFailure: this._boundFailureHandler |
|
642 | }); |
|
642 | }); |
|
643 | new Ajax.Request(this.url, options); |
|
643 | new Ajax.Request(this.url, options); |
|
644 | } |
|
644 | } |
|
645 | if (e) Event.stop(e); |
|
645 | if (e) Event.stop(e); |
|
646 | }, |
|
646 | }, |
|
647 | leaveEditMode: function() { |
|
647 | leaveEditMode: function() { |
|
648 | this.element.removeClassName(this.options.savingClassName); |
|
648 | this.element.removeClassName(this.options.savingClassName); |
|
649 | this.removeForm(); |
|
649 | this.removeForm(); |
|
650 | this.leaveHover(); |
|
650 | this.leaveHover(); |
|
651 | this.element.style.backgroundColor = this._originalBackground; |
|
651 | this.element.style.backgroundColor = this._originalBackground; |
|
652 | this.element.show(); |
|
652 | this.element.show(); |
|
653 | if (this.options.externalControl) |
|
653 | if (this.options.externalControl) |
|
654 | this.options.externalControl.show(); |
|
654 | this.options.externalControl.show(); |
|
655 | this._saving = false; |
|
655 | this._saving = false; |
|
656 | this._editing = false; |
|
656 | this._editing = false; |
|
657 | this._oldInnerHTML = null; |
|
657 | this._oldInnerHTML = null; |
|
658 | this.triggerCallback('onLeaveEditMode'); |
|
658 | this.triggerCallback('onLeaveEditMode'); |
|
659 | }, |
|
659 | }, |
|
660 | leaveHover: function(e) { |
|
660 | leaveHover: function(e) { |
|
661 | if (this.options.hoverClassName) |
|
661 | if (this.options.hoverClassName) |
|
662 | this.element.removeClassName(this.options.hoverClassName); |
|
662 | this.element.removeClassName(this.options.hoverClassName); |
|
663 | if (this._saving) return; |
|
663 | if (this._saving) return; |
|
664 | this.triggerCallback('onLeaveHover'); |
|
664 | this.triggerCallback('onLeaveHover'); |
|
665 | }, |
|
665 | }, |
|
666 | loadExternalText: function() { |
|
666 | loadExternalText: function() { |
|
667 | this._form.addClassName(this.options.loadingClassName); |
|
667 | this._form.addClassName(this.options.loadingClassName); |
|
668 | this._controls.editor.disabled = true; |
|
668 | this._controls.editor.disabled = true; |
|
669 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
669 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
670 | Object.extend(options, { |
|
670 | Object.extend(options, { |
|
671 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
671 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
672 | onComplete: Prototype.emptyFunction, |
|
672 | onComplete: Prototype.emptyFunction, |
|
673 | onSuccess: function(transport) { |
|
673 | onSuccess: function(transport) { |
|
674 | this._form.removeClassName(this.options.loadingClassName); |
|
674 | this._form.removeClassName(this.options.loadingClassName); |
|
675 | var text = transport.responseText; |
|
675 | var text = transport.responseText; |
|
676 | if (this.options.stripLoadedTextTags) |
|
676 | if (this.options.stripLoadedTextTags) |
|
677 | text = text.stripTags(); |
|
677 | text = text.stripTags(); |
|
678 | this._controls.editor.value = text; |
|
678 | this._controls.editor.value = text; |
|
679 | this._controls.editor.disabled = false; |
|
679 | this._controls.editor.disabled = false; |
|
680 | this.postProcessEditField(); |
|
680 | this.postProcessEditField(); |
|
681 | }.bind(this), |
|
681 | }.bind(this), |
|
682 | onFailure: this._boundFailureHandler |
|
682 | onFailure: this._boundFailureHandler |
|
683 | }); |
|
683 | }); |
|
684 | new Ajax.Request(this.options.loadTextURL, options); |
|
684 | new Ajax.Request(this.options.loadTextURL, options); |
|
685 | }, |
|
685 | }, |
|
686 | postProcessEditField: function() { |
|
686 | postProcessEditField: function() { |
|
687 | var fpc = this.options.fieldPostCreation; |
|
687 | var fpc = this.options.fieldPostCreation; |
|
688 | if (fpc) |
|
688 | if (fpc) |
|
689 | $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); |
|
689 | $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); |
|
690 | }, |
|
690 | }, |
|
691 | prepareOptions: function() { |
|
691 | prepareOptions: function() { |
|
692 | this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); |
|
692 | this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); |
|
693 | Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); |
|
693 | Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); |
|
694 | [this._extraDefaultOptions].flatten().compact().each(function(defs) { |
|
694 | [this._extraDefaultOptions].flatten().compact().each(function(defs) { |
|
695 | Object.extend(this.options, defs); |
|
695 | Object.extend(this.options, defs); |
|
696 | }.bind(this)); |
|
696 | }.bind(this)); |
|
697 | }, |
|
697 | }, |
|
698 | prepareSubmission: function() { |
|
698 | prepareSubmission: function() { |
|
699 | this._saving = true; |
|
699 | this._saving = true; |
|
700 | this.removeForm(); |
|
700 | this.removeForm(); |
|
701 | this.leaveHover(); |
|
701 | this.leaveHover(); |
|
702 | this.showSaving(); |
|
702 | this.showSaving(); |
|
703 | }, |
|
703 | }, |
|
704 | registerListeners: function() { |
|
704 | registerListeners: function() { |
|
705 | this._listeners = { }; |
|
705 | this._listeners = { }; |
|
706 | var listener; |
|
706 | var listener; |
|
707 | $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { |
|
707 | $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { |
|
708 | listener = this[pair.value].bind(this); |
|
708 | listener = this[pair.value].bind(this); |
|
709 | this._listeners[pair.key] = listener; |
|
709 | this._listeners[pair.key] = listener; |
|
710 | if (!this.options.externalControlOnly) |
|
710 | if (!this.options.externalControlOnly) |
|
711 | this.element.observe(pair.key, listener); |
|
711 | this.element.observe(pair.key, listener); |
|
712 | if (this.options.externalControl) |
|
712 | if (this.options.externalControl) |
|
713 | this.options.externalControl.observe(pair.key, listener); |
|
713 | this.options.externalControl.observe(pair.key, listener); |
|
714 | }.bind(this)); |
|
714 | }.bind(this)); |
|
715 | }, |
|
715 | }, |
|
716 | removeForm: function() { |
|
716 | removeForm: function() { |
|
717 | if (!this._form) return; |
|
717 | if (!this._form) return; |
|
718 | this._form.remove(); |
|
718 | this._form.remove(); |
|
719 | this._form = null; |
|
719 | this._form = null; |
|
720 | this._controls = { }; |
|
720 | this._controls = { }; |
|
721 | }, |
|
721 | }, |
|
722 | showSaving: function() { |
|
722 | showSaving: function() { |
|
723 | this._oldInnerHTML = this.element.innerHTML; |
|
723 | this._oldInnerHTML = this.element.innerHTML; |
|
724 | this.element.innerHTML = this.options.savingText; |
|
724 | this.element.innerHTML = this.options.savingText; |
|
725 | this.element.addClassName(this.options.savingClassName); |
|
725 | this.element.addClassName(this.options.savingClassName); |
|
726 | this.element.style.backgroundColor = this._originalBackground; |
|
726 | this.element.style.backgroundColor = this._originalBackground; |
|
727 | this.element.show(); |
|
727 | this.element.show(); |
|
728 | }, |
|
728 | }, |
|
729 | triggerCallback: function(cbName, arg) { |
|
729 | triggerCallback: function(cbName, arg) { |
|
730 | if ('function' == typeof this.options[cbName]) { |
|
730 | if ('function' == typeof this.options[cbName]) { |
|
731 | this.options[cbName](this, arg); |
|
731 | this.options[cbName](this, arg); |
|
732 | } |
|
732 | } |
|
733 | }, |
|
733 | }, |
|
734 | unregisterListeners: function() { |
|
734 | unregisterListeners: function() { |
|
735 | $H(this._listeners).each(function(pair) { |
|
735 | $H(this._listeners).each(function(pair) { |
|
736 | if (!this.options.externalControlOnly) |
|
736 | if (!this.options.externalControlOnly) |
|
737 | this.element.stopObserving(pair.key, pair.value); |
|
737 | this.element.stopObserving(pair.key, pair.value); |
|
738 | if (this.options.externalControl) |
|
738 | if (this.options.externalControl) |
|
739 | this.options.externalControl.stopObserving(pair.key, pair.value); |
|
739 | this.options.externalControl.stopObserving(pair.key, pair.value); |
|
740 | }.bind(this)); |
|
740 | }.bind(this)); |
|
741 | }, |
|
741 | }, |
|
742 | wrapUp: function(transport) { |
|
742 | wrapUp: function(transport) { |
|
743 | this.leaveEditMode(); |
|
743 | this.leaveEditMode(); |
|
744 | // Can't use triggerCallback due to backward compatibility: requires |
|
744 | // Can't use triggerCallback due to backward compatibility: requires |
|
745 | // binding + direct element |
|
745 | // binding + direct element |
|
746 | this._boundComplete(transport, this.element); |
|
746 | this._boundComplete(transport, this.element); |
|
747 | } |
|
747 | } |
|
748 | }); |
|
748 | }); |
|
749 |
|
749 | ||
|
750 | Object.extend(Ajax.InPlaceEditor.prototype, { |
|
750 | Object.extend(Ajax.InPlaceEditor.prototype, { |
|
751 | dispose: Ajax.InPlaceEditor.prototype.destroy |
|
751 | dispose: Ajax.InPlaceEditor.prototype.destroy |
|
752 | }); |
|
752 | }); |
|
753 |
|
753 | ||
|
754 | Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { |
|
754 | Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { |
|
755 | initialize: function($super, element, url, options) { |
|
755 | initialize: function($super, element, url, options) { |
|
756 | this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; |
|
756 | this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; |
|
757 | $super(element, url, options); |
|
757 | $super(element, url, options); |
|
758 | }, |
|
758 | }, |
|
759 |
|
759 | ||
|
760 | createEditField: function() { |
|
760 | createEditField: function() { |
|
761 | var list = document.createElement('select'); |
|
761 | var list = document.createElement('select'); |
|
762 | list.name = this.options.paramName; |
|
762 | list.name = this.options.paramName; |
|
763 | list.size = 1; |
|
763 | list.size = 1; |
|
764 | this._controls.editor = list; |
|
764 | this._controls.editor = list; |
|
765 | this._collection = this.options.collection || []; |
|
765 | this._collection = this.options.collection || []; |
|
766 | if (this.options.loadCollectionURL) |
|
766 | if (this.options.loadCollectionURL) |
|
767 | this.loadCollection(); |
|
767 | this.loadCollection(); |
|
768 | else |
|
768 | else |
|
769 | this.checkForExternalText(); |
|
769 | this.checkForExternalText(); |
|
770 | this._form.appendChild(this._controls.editor); |
|
770 | this._form.appendChild(this._controls.editor); |
|
771 | }, |
|
771 | }, |
|
772 |
|
772 | ||
|
773 | loadCollection: function() { |
|
773 | loadCollection: function() { |
|
774 | this._form.addClassName(this.options.loadingClassName); |
|
774 | this._form.addClassName(this.options.loadingClassName); |
|
775 | this.showLoadingText(this.options.loadingCollectionText); |
|
775 | this.showLoadingText(this.options.loadingCollectionText); |
|
776 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
776 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
777 | Object.extend(options, { |
|
777 | Object.extend(options, { |
|
778 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
778 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
779 | onComplete: Prototype.emptyFunction, |
|
779 | onComplete: Prototype.emptyFunction, |
|
780 | onSuccess: function(transport) { |
|
780 | onSuccess: function(transport) { |
|
781 | var js = transport.responseText.strip(); |
|
781 | var js = transport.responseText.strip(); |
|
782 | if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check |
|
782 | if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check |
|
783 |
- throw |
|
783 | + throw('Server returned an invalid collection representation.'); |
|
784 | this._collection = eval(js); |
|
784 | this._collection = eval(js); |
|
785 | this.checkForExternalText(); |
|
785 | this.checkForExternalText(); |
|
786 | }.bind(this), |
|
786 | }.bind(this), |
|
787 | onFailure: this.onFailure |
|
787 | onFailure: this.onFailure |
|
788 | }); |
|
788 | }); |
|
789 | new Ajax.Request(this.options.loadCollectionURL, options); |
|
789 | new Ajax.Request(this.options.loadCollectionURL, options); |
|
790 | }, |
|
790 | }, |
|
791 |
|
791 | ||
|
792 | showLoadingText: function(text) { |
|
792 | showLoadingText: function(text) { |
|
793 | this._controls.editor.disabled = true; |
|
793 | this._controls.editor.disabled = true; |
|
794 | var tempOption = this._controls.editor.firstChild; |
|
794 | var tempOption = this._controls.editor.firstChild; |
|
795 | if (!tempOption) { |
|
795 | if (!tempOption) { |
|
796 | tempOption = document.createElement('option'); |
|
796 | tempOption = document.createElement('option'); |
|
797 | tempOption.value = ''; |
|
797 | tempOption.value = ''; |
|
798 | this._controls.editor.appendChild(tempOption); |
|
798 | this._controls.editor.appendChild(tempOption); |
|
799 | tempOption.selected = true; |
|
799 | tempOption.selected = true; |
|
800 | } |
|
800 | } |
|
801 | tempOption.update((text || '').stripScripts().stripTags()); |
|
801 | tempOption.update((text || '').stripScripts().stripTags()); |
|
802 | }, |
|
802 | }, |
|
803 |
|
803 | ||
|
804 | checkForExternalText: function() { |
|
804 | checkForExternalText: function() { |
|
805 | this._text = this.getText(); |
|
805 | this._text = this.getText(); |
|
806 | if (this.options.loadTextURL) |
|
806 | if (this.options.loadTextURL) |
|
807 | this.loadExternalText(); |
|
807 | this.loadExternalText(); |
|
808 | else |
|
808 | else |
|
809 | this.buildOptionList(); |
|
809 | this.buildOptionList(); |
|
810 | }, |
|
810 | }, |
|
811 |
|
811 | ||
|
812 | loadExternalText: function() { |
|
812 | loadExternalText: function() { |
|
813 | this.showLoadingText(this.options.loadingText); |
|
813 | this.showLoadingText(this.options.loadingText); |
|
814 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
814 | var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); |
|
815 | Object.extend(options, { |
|
815 | Object.extend(options, { |
|
816 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
816 | parameters: 'editorId=' + encodeURIComponent(this.element.id), |
|
817 | onComplete: Prototype.emptyFunction, |
|
817 | onComplete: Prototype.emptyFunction, |
|
818 | onSuccess: function(transport) { |
|
818 | onSuccess: function(transport) { |
|
819 | this._text = transport.responseText.strip(); |
|
819 | this._text = transport.responseText.strip(); |
|
820 | this.buildOptionList(); |
|
820 | this.buildOptionList(); |
|
821 | }.bind(this), |
|
821 | }.bind(this), |
|
822 | onFailure: this.onFailure |
|
822 | onFailure: this.onFailure |
|
823 | }); |
|
823 | }); |
|
824 | new Ajax.Request(this.options.loadTextURL, options); |
|
824 | new Ajax.Request(this.options.loadTextURL, options); |
|
825 | }, |
|
825 | }, |
|
826 |
|
826 | ||
|
827 | buildOptionList: function() { |
|
827 | buildOptionList: function() { |
|
828 | this._form.removeClassName(this.options.loadingClassName); |
|
828 | this._form.removeClassName(this.options.loadingClassName); |
|
829 | this._collection = this._collection.map(function(entry) { |
|
829 | this._collection = this._collection.map(function(entry) { |
|
830 | return 2 === entry.length ? entry : [entry, entry].flatten(); |
|
830 | return 2 === entry.length ? entry : [entry, entry].flatten(); |
|
831 | }); |
|
831 | }); |
|
832 | var marker = ('value' in this.options) ? this.options.value : this._text; |
|
832 | var marker = ('value' in this.options) ? this.options.value : this._text; |
|
833 | var textFound = this._collection.any(function(entry) { |
|
833 | var textFound = this._collection.any(function(entry) { |
|
834 | return entry[0] == marker; |
|
834 | return entry[0] == marker; |
|
835 | }.bind(this)); |
|
835 | }.bind(this)); |
|
836 | this._controls.editor.update(''); |
|
836 | this._controls.editor.update(''); |
|
837 | var option; |
|
837 | var option; |
|
838 | this._collection.each(function(entry, index) { |
|
838 | this._collection.each(function(entry, index) { |
|
839 | option = document.createElement('option'); |
|
839 | option = document.createElement('option'); |
|
840 | option.value = entry[0]; |
|
840 | option.value = entry[0]; |
|
841 | option.selected = textFound ? entry[0] == marker : 0 == index; |
|
841 | option.selected = textFound ? entry[0] == marker : 0 == index; |
|
842 | option.appendChild(document.createTextNode(entry[1])); |
|
842 | option.appendChild(document.createTextNode(entry[1])); |
|
843 | this._controls.editor.appendChild(option); |
|
843 | this._controls.editor.appendChild(option); |
|
844 | }.bind(this)); |
|
844 | }.bind(this)); |
|
845 | this._controls.editor.disabled = false; |
|
845 | this._controls.editor.disabled = false; |
|
846 | Field.scrollFreeActivate(this._controls.editor); |
|
846 | Field.scrollFreeActivate(this._controls.editor); |
|
847 | } |
|
847 | } |
|
848 | }); |
|
848 | }); |
|
849 |
|
849 | ||
|
850 | //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** |
|
850 | //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** |
|
851 | //**** This only exists for a while, in order to let **** |
|
851 | //**** This only exists for a while, in order to let **** |
|
852 | //**** users adapt to the new API. Read up on the new **** |
|
852 | //**** users adapt to the new API. Read up on the new **** |
|
853 | //**** API and convert your code to it ASAP! **** |
|
853 | //**** API and convert your code to it ASAP! **** |
|
854 |
|
854 | ||
|
855 | Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { |
|
855 | Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { |
|
856 | if (!options) return; |
|
856 | if (!options) return; |
|
857 | function fallback(name, expr) { |
|
857 | function fallback(name, expr) { |
|
858 | if (name in options || expr === undefined) return; |
|
858 | if (name in options || expr === undefined) return; |
|
859 | options[name] = expr; |
|
859 | options[name] = expr; |
|
860 | }; |
|
860 | }; |
|
861 | fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : |
|
861 | fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : |
|
862 | options.cancelLink == options.cancelButton == false ? false : undefined))); |
|
862 | options.cancelLink == options.cancelButton == false ? false : undefined))); |
|
863 | fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : |
|
863 | fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : |
|
864 | options.okLink == options.okButton == false ? false : undefined))); |
|
864 | options.okLink == options.okButton == false ? false : undefined))); |
|
865 | fallback('highlightColor', options.highlightcolor); |
|
865 | fallback('highlightColor', options.highlightcolor); |
|
866 | fallback('highlightEndColor', options.highlightendcolor); |
|
866 | fallback('highlightEndColor', options.highlightendcolor); |
|
867 | }; |
|
867 | }; |
|
868 |
|
868 | ||
|
869 | Object.extend(Ajax.InPlaceEditor, { |
|
869 | Object.extend(Ajax.InPlaceEditor, { |
|
870 | DefaultOptions: { |
|
870 | DefaultOptions: { |
|
871 | ajaxOptions: { }, |
|
871 | ajaxOptions: { }, |
|
872 | autoRows: 3, // Use when multi-line w/ rows == 1 |
|
872 | autoRows: 3, // Use when multi-line w/ rows == 1 |
|
873 | cancelControl: 'link', // 'link'|'button'|false |
|
873 | cancelControl: 'link', // 'link'|'button'|false |
|
874 | cancelText: 'cancel', |
|
874 | cancelText: 'cancel', |
|
875 | clickToEditText: 'Click to edit', |
|
875 | clickToEditText: 'Click to edit', |
|
876 | externalControl: null, // id|elt |
|
876 | externalControl: null, // id|elt |
|
877 | externalControlOnly: false, |
|
877 | externalControlOnly: false, |
|
878 | fieldPostCreation: 'activate', // 'activate'|'focus'|false |
|
878 | fieldPostCreation: 'activate', // 'activate'|'focus'|false |
|
879 | formClassName: 'inplaceeditor-form', |
|
879 | formClassName: 'inplaceeditor-form', |
|
880 | formId: null, // id|elt |
|
880 | formId: null, // id|elt |
|
881 | highlightColor: '#ffff99', |
|
881 | highlightColor: '#ffff99', |
|
882 | highlightEndColor: '#ffffff', |
|
882 | highlightEndColor: '#ffffff', |
|
883 | hoverClassName: '', |
|
883 | hoverClassName: '', |
|
884 | htmlResponse: true, |
|
884 | htmlResponse: true, |
|
885 | loadingClassName: 'inplaceeditor-loading', |
|
885 | loadingClassName: 'inplaceeditor-loading', |
|
886 | loadingText: 'Loading...', |
|
886 | loadingText: 'Loading...', |
|
887 | okControl: 'button', // 'link'|'button'|false |
|
887 | okControl: 'button', // 'link'|'button'|false |
|
888 | okText: 'ok', |
|
888 | okText: 'ok', |
|
889 | paramName: 'value', |
|
889 | paramName: 'value', |
|
890 | rows: 1, // If 1 and multi-line, uses autoRows |
|
890 | rows: 1, // If 1 and multi-line, uses autoRows |
|
891 | savingClassName: 'inplaceeditor-saving', |
|
891 | savingClassName: 'inplaceeditor-saving', |
|
892 | savingText: 'Saving...', |
|
892 | savingText: 'Saving...', |
|
893 | size: 0, |
|
893 | size: 0, |
|
894 | stripLoadedTextTags: false, |
|
894 | stripLoadedTextTags: false, |
|
895 | submitOnBlur: false, |
|
895 | submitOnBlur: false, |
|
896 | textAfterControls: '', |
|
896 | textAfterControls: '', |
|
897 | textBeforeControls: '', |
|
897 | textBeforeControls: '', |
|
898 | textBetweenControls: '' |
|
898 | textBetweenControls: '' |
|
899 | }, |
|
899 | }, |
|
900 | DefaultCallbacks: { |
|
900 | DefaultCallbacks: { |
|
901 | callback: function(form) { |
|
901 | callback: function(form) { |
|
902 | return Form.serialize(form); |
|
902 | return Form.serialize(form); |
|
903 | }, |
|
903 | }, |
|
904 | onComplete: function(transport, element) { |
|
904 | onComplete: function(transport, element) { |
|
905 | // For backward compatibility, this one is bound to the IPE, and passes |
|
905 | // For backward compatibility, this one is bound to the IPE, and passes |
|
906 | // the element directly. It was too often customized, so we don't break it. |
|
906 | // the element directly. It was too often customized, so we don't break it. |
|
907 | new Effect.Highlight(element, { |
|
907 | new Effect.Highlight(element, { |
|
908 | startcolor: this.options.highlightColor, keepBackgroundImage: true }); |
|
908 | startcolor: this.options.highlightColor, keepBackgroundImage: true }); |
|
909 | }, |
|
909 | }, |
|
910 | onEnterEditMode: null, |
|
910 | onEnterEditMode: null, |
|
911 | onEnterHover: function(ipe) { |
|
911 | onEnterHover: function(ipe) { |
|
912 | ipe.element.style.backgroundColor = ipe.options.highlightColor; |
|
912 | ipe.element.style.backgroundColor = ipe.options.highlightColor; |
|
913 | if (ipe._effect) |
|
913 | if (ipe._effect) |
|
914 | ipe._effect.cancel(); |
|
914 | ipe._effect.cancel(); |
|
915 | }, |
|
915 | }, |
|
916 | onFailure: function(transport, ipe) { |
|
916 | onFailure: function(transport, ipe) { |
|
917 | alert('Error communication with the server: ' + transport.responseText.stripTags()); |
|
917 | alert('Error communication with the server: ' + transport.responseText.stripTags()); |
|
918 | }, |
|
918 | }, |
|
919 | onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. |
|
919 | onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. |
|
920 | onLeaveEditMode: null, |
|
920 | onLeaveEditMode: null, |
|
921 | onLeaveHover: function(ipe) { |
|
921 | onLeaveHover: function(ipe) { |
|
922 | ipe._effect = new Effect.Highlight(ipe.element, { |
|
922 | ipe._effect = new Effect.Highlight(ipe.element, { |
|
923 | startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, |
|
923 | startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, |
|
924 | restorecolor: ipe._originalBackground, keepBackgroundImage: true |
|
924 | restorecolor: ipe._originalBackground, keepBackgroundImage: true |
|
925 | }); |
|
925 | }); |
|
926 | } |
|
926 | } |
|
927 | }, |
|
927 | }, |
|
928 | Listeners: { |
|
928 | Listeners: { |
|
929 | click: 'enterEditMode', |
|
929 | click: 'enterEditMode', |
|
930 | keydown: 'checkForEscapeOrReturn', |
|
930 | keydown: 'checkForEscapeOrReturn', |
|
931 | mouseover: 'enterHover', |
|
931 | mouseover: 'enterHover', |
|
932 | mouseout: 'leaveHover' |
|
932 | mouseout: 'leaveHover' |
|
933 | } |
|
933 | } |
|
934 | }); |
|
934 | }); |
|
935 |
|
935 | ||
|
936 | Ajax.InPlaceCollectionEditor.DefaultOptions = { |
|
936 | Ajax.InPlaceCollectionEditor.DefaultOptions = { |
|
937 | loadingCollectionText: 'Loading options...' |
|
937 | loadingCollectionText: 'Loading options...' |
|
938 | }; |
|
938 | }; |
|
939 |
|
939 | ||
|
940 |
// Delayed observer, like Form.Element.Observer, |
|
940 | // Delayed observer, like Form.Element.Observer, |
|
941 | // but waits for delay after last key input |
|
941 | // but waits for delay after last key input |
|
942 | // Ideal for live-search fields |
|
942 | // Ideal for live-search fields |
|
943 |
|
943 | ||
|
944 | Form.Element.DelayedObserver = Class.create({ |
|
944 | Form.Element.DelayedObserver = Class.create({ |
|
945 | initialize: function(element, delay, callback) { |
|
945 | initialize: function(element, delay, callback) { |
|
946 | this.delay = delay || 0.5; |
|
946 | this.delay = delay || 0.5; |
|
947 | this.element = $(element); |
|
947 | this.element = $(element); |
|
948 | this.callback = callback; |
|
948 | this.callback = callback; |
|
949 | this.timer = null; |
|
949 | this.timer = null; |
|
950 |
this.lastValue = $F(this.element); |
|
950 | this.lastValue = $F(this.element); |
|
951 | Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); |
|
951 | Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); |
|
952 | }, |
|
952 | }, |
|
953 | delayedListener: function(event) { |
|
953 | delayedListener: function(event) { |
|
954 | if(this.lastValue == $F(this.element)) return; |
|
954 | if(this.lastValue == $F(this.element)) return; |
|
955 | if(this.timer) clearTimeout(this.timer); |
|
955 | if(this.timer) clearTimeout(this.timer); |
|
956 | this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); |
|
956 | this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); |
|
957 | this.lastValue = $F(this.element); |
|
957 | this.lastValue = $F(this.element); |
|
958 | }, |
|
958 | }, |
|
959 | onTimerEvent: function() { |
|
959 | onTimerEvent: function() { |
|
960 | this.timer = null; |
|
960 | this.timer = null; |
|
961 | this.callback(this.element, $F(this.element)); |
|
961 | this.callback(this.element, $F(this.element)); |
|
962 | } |
|
962 | } |
|
963 |
- }); |
|
963 | + }); No newline at end of file |
@@ -1,972 +1,973 | |||||
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
2 |
- // (c) 2005-200 |
|
2 | + // (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) |
|
3 |
// |
|
3 | // |
|
4 | // script.aculo.us is freely distributable under the terms of an MIT-style license. |
|
4 | // script.aculo.us is freely distributable under the terms of an MIT-style license. |
|
5 | // For details, see the script.aculo.us web site: http://script.aculo.us/ |
|
5 | // For details, see the script.aculo.us web site: http://script.aculo.us/ |
|
6 |
|
6 | ||
|
7 | if(Object.isUndefined(Effect)) |
|
7 | if(Object.isUndefined(Effect)) |
|
8 | throw("dragdrop.js requires including script.aculo.us' effects.js library"); |
|
8 | throw("dragdrop.js requires including script.aculo.us' effects.js library"); |
|
9 |
|
9 | ||
|
10 | var Droppables = { |
|
10 | var Droppables = { |
|
11 | drops: [], |
|
11 | drops: [], |
|
12 |
|
12 | ||
|
13 | remove: function(element) { |
|
13 | remove: function(element) { |
|
14 | this.drops = this.drops.reject(function(d) { return d.element==$(element) }); |
|
14 | this.drops = this.drops.reject(function(d) { return d.element==$(element) }); |
|
15 | }, |
|
15 | }, |
|
16 |
|
16 | ||
|
17 | add: function(element) { |
|
17 | add: function(element) { |
|
18 | element = $(element); |
|
18 | element = $(element); |
|
19 | var options = Object.extend({ |
|
19 | var options = Object.extend({ |
|
20 | greedy: true, |
|
20 | greedy: true, |
|
21 | hoverclass: null, |
|
21 | hoverclass: null, |
|
22 | tree: false |
|
22 | tree: false |
|
23 | }, arguments[1] || { }); |
|
23 | }, arguments[1] || { }); |
|
24 |
|
24 | ||
|
25 | // cache containers |
|
25 | // cache containers |
|
26 | if(options.containment) { |
|
26 | if(options.containment) { |
|
27 | options._containers = []; |
|
27 | options._containers = []; |
|
28 | var containment = options.containment; |
|
28 | var containment = options.containment; |
|
29 | if(Object.isArray(containment)) { |
|
29 | if(Object.isArray(containment)) { |
|
30 | containment.each( function(c) { options._containers.push($(c)) }); |
|
30 | containment.each( function(c) { options._containers.push($(c)) }); |
|
31 | } else { |
|
31 | } else { |
|
32 | options._containers.push($(containment)); |
|
32 | options._containers.push($(containment)); |
|
33 | } |
|
33 | } |
|
34 | } |
|
34 | } |
|
35 |
|
35 | ||
|
36 | if(options.accept) options.accept = [options.accept].flatten(); |
|
36 | if(options.accept) options.accept = [options.accept].flatten(); |
|
37 |
|
37 | ||
|
38 | Element.makePositioned(element); // fix IE |
|
38 | Element.makePositioned(element); // fix IE |
|
39 | options.element = element; |
|
39 | options.element = element; |
|
40 |
|
40 | ||
|
41 | this.drops.push(options); |
|
41 | this.drops.push(options); |
|
42 | }, |
|
42 | }, |
|
43 |
|
43 | ||
|
44 | findDeepestChild: function(drops) { |
|
44 | findDeepestChild: function(drops) { |
|
45 | deepest = drops[0]; |
|
45 | deepest = drops[0]; |
|
46 |
|
46 | ||
|
47 | for (i = 1; i < drops.length; ++i) |
|
47 | for (i = 1; i < drops.length; ++i) |
|
48 | if (Element.isParent(drops[i].element, deepest.element)) |
|
48 | if (Element.isParent(drops[i].element, deepest.element)) |
|
49 | deepest = drops[i]; |
|
49 | deepest = drops[i]; |
|
50 |
|
50 | ||
|
51 | return deepest; |
|
51 | return deepest; |
|
52 | }, |
|
52 | }, |
|
53 |
|
53 | ||
|
54 | isContained: function(element, drop) { |
|
54 | isContained: function(element, drop) { |
|
55 | var containmentNode; |
|
55 | var containmentNode; |
|
56 | if(drop.tree) { |
|
56 | if(drop.tree) { |
|
57 |
containmentNode = element.treeNode; |
|
57 | containmentNode = element.treeNode; |
|
58 | } else { |
|
58 | } else { |
|
59 | containmentNode = element.parentNode; |
|
59 | containmentNode = element.parentNode; |
|
60 | } |
|
60 | } |
|
61 | return drop._containers.detect(function(c) { return containmentNode == c }); |
|
61 | return drop._containers.detect(function(c) { return containmentNode == c }); |
|
62 | }, |
|
62 | }, |
|
63 |
|
63 | ||
|
64 | isAffected: function(point, element, drop) { |
|
64 | isAffected: function(point, element, drop) { |
|
65 | return ( |
|
65 | return ( |
|
66 | (drop.element!=element) && |
|
66 | (drop.element!=element) && |
|
67 | ((!drop._containers) || |
|
67 | ((!drop._containers) || |
|
68 | this.isContained(element, drop)) && |
|
68 | this.isContained(element, drop)) && |
|
69 | ((!drop.accept) || |
|
69 | ((!drop.accept) || |
|
70 |
(Element.classNames(element).detect( |
|
70 | (Element.classNames(element).detect( |
|
71 | function(v) { return drop.accept.include(v) } ) )) && |
|
71 | function(v) { return drop.accept.include(v) } ) )) && |
|
72 | Position.within(drop.element, point[0], point[1]) ); |
|
72 | Position.within(drop.element, point[0], point[1]) ); |
|
73 | }, |
|
73 | }, |
|
74 |
|
74 | ||
|
75 | deactivate: function(drop) { |
|
75 | deactivate: function(drop) { |
|
76 | if(drop.hoverclass) |
|
76 | if(drop.hoverclass) |
|
77 | Element.removeClassName(drop.element, drop.hoverclass); |
|
77 | Element.removeClassName(drop.element, drop.hoverclass); |
|
78 | this.last_active = null; |
|
78 | this.last_active = null; |
|
79 | }, |
|
79 | }, |
|
80 |
|
80 | ||
|
81 | activate: function(drop) { |
|
81 | activate: function(drop) { |
|
82 | if(drop.hoverclass) |
|
82 | if(drop.hoverclass) |
|
83 | Element.addClassName(drop.element, drop.hoverclass); |
|
83 | Element.addClassName(drop.element, drop.hoverclass); |
|
84 | this.last_active = drop; |
|
84 | this.last_active = drop; |
|
85 | }, |
|
85 | }, |
|
86 |
|
86 | ||
|
87 | show: function(point, element) { |
|
87 | show: function(point, element) { |
|
88 | if(!this.drops.length) return; |
|
88 | if(!this.drops.length) return; |
|
89 | var drop, affected = []; |
|
89 | var drop, affected = []; |
|
90 |
|
90 | ||
|
91 | this.drops.each( function(drop) { |
|
91 | this.drops.each( function(drop) { |
|
92 | if(Droppables.isAffected(point, element, drop)) |
|
92 | if(Droppables.isAffected(point, element, drop)) |
|
93 | affected.push(drop); |
|
93 | affected.push(drop); |
|
94 | }); |
|
94 | }); |
|
95 |
|
95 | ||
|
96 | if(affected.length>0) |
|
96 | if(affected.length>0) |
|
97 | drop = Droppables.findDeepestChild(affected); |
|
97 | drop = Droppables.findDeepestChild(affected); |
|
98 |
|
98 | ||
|
99 | if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); |
|
99 | if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); |
|
100 | if (drop) { |
|
100 | if (drop) { |
|
101 | Position.within(drop.element, point[0], point[1]); |
|
101 | Position.within(drop.element, point[0], point[1]); |
|
102 | if(drop.onHover) |
|
102 | if(drop.onHover) |
|
103 | drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); |
|
103 | drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); |
|
104 |
|
104 | ||
|
105 | if (drop != this.last_active) Droppables.activate(drop); |
|
105 | if (drop != this.last_active) Droppables.activate(drop); |
|
106 | } |
|
106 | } |
|
107 | }, |
|
107 | }, |
|
108 |
|
108 | ||
|
109 | fire: function(event, element) { |
|
109 | fire: function(event, element) { |
|
110 | if(!this.last_active) return; |
|
110 | if(!this.last_active) return; |
|
111 | Position.prepare(); |
|
111 | Position.prepare(); |
|
112 |
|
112 | ||
|
113 | if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) |
|
113 | if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) |
|
114 | if (this.last_active.onDrop) { |
|
114 | if (this.last_active.onDrop) { |
|
115 |
this.last_active.onDrop(element, this.last_active.element, event); |
|
115 | this.last_active.onDrop(element, this.last_active.element, event); |
|
116 |
return true; |
|
116 | return true; |
|
117 | } |
|
117 | } |
|
118 | }, |
|
118 | }, |
|
119 |
|
119 | ||
|
120 | reset: function() { |
|
120 | reset: function() { |
|
121 | if(this.last_active) |
|
121 | if(this.last_active) |
|
122 | this.deactivate(this.last_active); |
|
122 | this.deactivate(this.last_active); |
|
123 | } |
|
123 | } |
|
124 | - } |
|
124 | + }; |
|
125 |
|
125 | ||
|
126 | var Draggables = { |
|
126 | var Draggables = { |
|
127 | drags: [], |
|
127 | drags: [], |
|
128 | observers: [], |
|
128 | observers: [], |
|
129 |
|
129 | ||
|
130 | register: function(draggable) { |
|
130 | register: function(draggable) { |
|
131 | if(this.drags.length == 0) { |
|
131 | if(this.drags.length == 0) { |
|
132 | this.eventMouseUp = this.endDrag.bindAsEventListener(this); |
|
132 | this.eventMouseUp = this.endDrag.bindAsEventListener(this); |
|
133 | this.eventMouseMove = this.updateDrag.bindAsEventListener(this); |
|
133 | this.eventMouseMove = this.updateDrag.bindAsEventListener(this); |
|
134 | this.eventKeypress = this.keyPress.bindAsEventListener(this); |
|
134 | this.eventKeypress = this.keyPress.bindAsEventListener(this); |
|
135 |
|
135 | ||
|
136 | Event.observe(document, "mouseup", this.eventMouseUp); |
|
136 | Event.observe(document, "mouseup", this.eventMouseUp); |
|
137 | Event.observe(document, "mousemove", this.eventMouseMove); |
|
137 | Event.observe(document, "mousemove", this.eventMouseMove); |
|
138 | Event.observe(document, "keypress", this.eventKeypress); |
|
138 | Event.observe(document, "keypress", this.eventKeypress); |
|
139 | } |
|
139 | } |
|
140 | this.drags.push(draggable); |
|
140 | this.drags.push(draggable); |
|
141 | }, |
|
141 | }, |
|
142 |
|
142 | ||
|
143 | unregister: function(draggable) { |
|
143 | unregister: function(draggable) { |
|
144 | this.drags = this.drags.reject(function(d) { return d==draggable }); |
|
144 | this.drags = this.drags.reject(function(d) { return d==draggable }); |
|
145 | if(this.drags.length == 0) { |
|
145 | if(this.drags.length == 0) { |
|
146 | Event.stopObserving(document, "mouseup", this.eventMouseUp); |
|
146 | Event.stopObserving(document, "mouseup", this.eventMouseUp); |
|
147 | Event.stopObserving(document, "mousemove", this.eventMouseMove); |
|
147 | Event.stopObserving(document, "mousemove", this.eventMouseMove); |
|
148 | Event.stopObserving(document, "keypress", this.eventKeypress); |
|
148 | Event.stopObserving(document, "keypress", this.eventKeypress); |
|
149 | } |
|
149 | } |
|
150 | }, |
|
150 | }, |
|
151 |
|
151 | ||
|
152 | activate: function(draggable) { |
|
152 | activate: function(draggable) { |
|
153 |
if(draggable.options.delay) { |
|
153 | if(draggable.options.delay) { |
|
154 |
this._timeout = setTimeout(function() { |
|
154 | this._timeout = setTimeout(function() { |
|
155 |
Draggables._timeout = null; |
|
155 | Draggables._timeout = null; |
|
156 |
window.focus(); |
|
156 | window.focus(); |
|
157 |
Draggables.activeDraggable = draggable; |
|
157 | Draggables.activeDraggable = draggable; |
|
158 |
}.bind(this), draggable.options.delay); |
|
158 | }.bind(this), draggable.options.delay); |
|
159 | } else { |
|
159 | } else { |
|
160 | window.focus(); // allows keypress events if window isn't currently focused, fails for Safari |
|
160 | window.focus(); // allows keypress events if window isn't currently focused, fails for Safari |
|
161 | this.activeDraggable = draggable; |
|
161 | this.activeDraggable = draggable; |
|
162 | } |
|
162 | } |
|
163 | }, |
|
163 | }, |
|
164 |
|
164 | ||
|
165 | deactivate: function() { |
|
165 | deactivate: function() { |
|
166 | this.activeDraggable = null; |
|
166 | this.activeDraggable = null; |
|
167 | }, |
|
167 | }, |
|
168 |
|
168 | ||
|
169 | updateDrag: function(event) { |
|
169 | updateDrag: function(event) { |
|
170 | if(!this.activeDraggable) return; |
|
170 | if(!this.activeDraggable) return; |
|
171 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
171 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
172 | // Mozilla-based browsers fire successive mousemove events with |
|
172 | // Mozilla-based browsers fire successive mousemove events with |
|
173 | // the same coordinates, prevent needless redrawing (moz bug?) |
|
173 | // the same coordinates, prevent needless redrawing (moz bug?) |
|
174 | if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; |
|
174 | if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; |
|
175 | this._lastPointer = pointer; |
|
175 | this._lastPointer = pointer; |
|
176 |
|
176 | ||
|
177 | this.activeDraggable.updateDrag(event, pointer); |
|
177 | this.activeDraggable.updateDrag(event, pointer); |
|
178 | }, |
|
178 | }, |
|
179 |
|
179 | ||
|
180 | endDrag: function(event) { |
|
180 | endDrag: function(event) { |
|
181 |
if(this._timeout) { |
|
181 | if(this._timeout) { |
|
182 |
clearTimeout(this._timeout); |
|
182 | clearTimeout(this._timeout); |
|
183 |
this._timeout = null; |
|
183 | this._timeout = null; |
|
184 | } |
|
184 | } |
|
185 | if(!this.activeDraggable) return; |
|
185 | if(!this.activeDraggable) return; |
|
186 | this._lastPointer = null; |
|
186 | this._lastPointer = null; |
|
187 | this.activeDraggable.endDrag(event); |
|
187 | this.activeDraggable.endDrag(event); |
|
188 | this.activeDraggable = null; |
|
188 | this.activeDraggable = null; |
|
189 | }, |
|
189 | }, |
|
190 |
|
190 | ||
|
191 | keyPress: function(event) { |
|
191 | keyPress: function(event) { |
|
192 | if(this.activeDraggable) |
|
192 | if(this.activeDraggable) |
|
193 | this.activeDraggable.keyPress(event); |
|
193 | this.activeDraggable.keyPress(event); |
|
194 | }, |
|
194 | }, |
|
195 |
|
195 | ||
|
196 | addObserver: function(observer) { |
|
196 | addObserver: function(observer) { |
|
197 | this.observers.push(observer); |
|
197 | this.observers.push(observer); |
|
198 | this._cacheObserverCallbacks(); |
|
198 | this._cacheObserverCallbacks(); |
|
199 | }, |
|
199 | }, |
|
200 |
|
200 | ||
|
201 | removeObserver: function(element) { // element instead of observer fixes mem leaks |
|
201 | removeObserver: function(element) { // element instead of observer fixes mem leaks |
|
202 | this.observers = this.observers.reject( function(o) { return o.element==element }); |
|
202 | this.observers = this.observers.reject( function(o) { return o.element==element }); |
|
203 | this._cacheObserverCallbacks(); |
|
203 | this._cacheObserverCallbacks(); |
|
204 | }, |
|
204 | }, |
|
205 |
|
205 | ||
|
206 | notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' |
|
206 | notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' |
|
207 | if(this[eventName+'Count'] > 0) |
|
207 | if(this[eventName+'Count'] > 0) |
|
208 | this.observers.each( function(o) { |
|
208 | this.observers.each( function(o) { |
|
209 | if(o[eventName]) o[eventName](eventName, draggable, event); |
|
209 | if(o[eventName]) o[eventName](eventName, draggable, event); |
|
210 | }); |
|
210 | }); |
|
211 | if(draggable.options[eventName]) draggable.options[eventName](draggable, event); |
|
211 | if(draggable.options[eventName]) draggable.options[eventName](draggable, event); |
|
212 | }, |
|
212 | }, |
|
213 |
|
213 | ||
|
214 | _cacheObserverCallbacks: function() { |
|
214 | _cacheObserverCallbacks: function() { |
|
215 | ['onStart','onEnd','onDrag'].each( function(eventName) { |
|
215 | ['onStart','onEnd','onDrag'].each( function(eventName) { |
|
216 | Draggables[eventName+'Count'] = Draggables.observers.select( |
|
216 | Draggables[eventName+'Count'] = Draggables.observers.select( |
|
217 | function(o) { return o[eventName]; } |
|
217 | function(o) { return o[eventName]; } |
|
218 | ).length; |
|
218 | ).length; |
|
219 | }); |
|
219 | }); |
|
220 | } |
|
220 | } |
|
221 | - } |
|
221 | + }; |
|
222 |
|
222 | ||
|
223 |
|
|
223 | /*--------------------------------------------------------------------------*/ |
|
224 |
|
224 | ||
|
225 | var Draggable = Class.create({ |
|
225 | var Draggable = Class.create({ |
|
226 | initialize: function(element) { |
|
226 | initialize: function(element) { |
|
227 | var defaults = { |
|
227 | var defaults = { |
|
228 | handle: false, |
|
228 | handle: false, |
|
229 | reverteffect: function(element, top_offset, left_offset) { |
|
229 | reverteffect: function(element, top_offset, left_offset) { |
|
230 | var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; |
|
230 | var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; |
|
231 | new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, |
|
231 | new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, |
|
232 | queue: {scope:'_draggable', position:'end'} |
|
232 | queue: {scope:'_draggable', position:'end'} |
|
233 | }); |
|
233 | }); |
|
234 | }, |
|
234 | }, |
|
235 | endeffect: function(element) { |
|
235 | endeffect: function(element) { |
|
236 | var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; |
|
236 | var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; |
|
237 |
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, |
|
237 | new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, |
|
238 | queue: {scope:'_draggable', position:'end'}, |
|
238 | queue: {scope:'_draggable', position:'end'}, |
|
239 |
afterFinish: function(){ |
|
239 | afterFinish: function(){ |
|
240 |
Draggable._dragging[element] = false |
|
240 | Draggable._dragging[element] = false |
|
241 | } |
|
241 | } |
|
242 |
}); |
|
242 | }); |
|
243 | }, |
|
243 | }, |
|
244 | zindex: 1000, |
|
244 | zindex: 1000, |
|
245 | revert: false, |
|
245 | revert: false, |
|
246 | quiet: false, |
|
246 | quiet: false, |
|
247 | scroll: false, |
|
247 | scroll: false, |
|
248 | scrollSensitivity: 20, |
|
248 | scrollSensitivity: 20, |
|
249 | scrollSpeed: 15, |
|
249 | scrollSpeed: 15, |
|
250 | snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } |
|
250 | snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } |
|
251 | delay: 0 |
|
251 | delay: 0 |
|
252 | }; |
|
252 | }; |
|
253 |
|
253 | ||
|
254 | if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) |
|
254 | if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) |
|
255 | Object.extend(defaults, { |
|
255 | Object.extend(defaults, { |
|
256 | starteffect: function(element) { |
|
256 | starteffect: function(element) { |
|
257 | element._opacity = Element.getOpacity(element); |
|
257 | element._opacity = Element.getOpacity(element); |
|
258 | Draggable._dragging[element] = true; |
|
258 | Draggable._dragging[element] = true; |
|
259 |
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); |
|
259 | new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); |
|
260 | } |
|
260 | } |
|
261 | }); |
|
261 | }); |
|
262 |
|
262 | ||
|
263 | var options = Object.extend(defaults, arguments[1] || { }); |
|
263 | var options = Object.extend(defaults, arguments[1] || { }); |
|
264 |
|
264 | ||
|
265 | this.element = $(element); |
|
265 | this.element = $(element); |
|
266 |
|
266 | ||
|
267 | if(options.handle && Object.isString(options.handle)) |
|
267 | if(options.handle && Object.isString(options.handle)) |
|
268 | this.handle = this.element.down('.'+options.handle, 0); |
|
268 | this.handle = this.element.down('.'+options.handle, 0); |
|
269 |
|
269 | ||
|
270 | if(!this.handle) this.handle = $(options.handle); |
|
270 | if(!this.handle) this.handle = $(options.handle); |
|
271 | if(!this.handle) this.handle = this.element; |
|
271 | if(!this.handle) this.handle = this.element; |
|
272 |
|
272 | ||
|
273 | if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { |
|
273 | if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { |
|
274 | options.scroll = $(options.scroll); |
|
274 | options.scroll = $(options.scroll); |
|
275 | this._isScrollChild = Element.childOf(this.element, options.scroll); |
|
275 | this._isScrollChild = Element.childOf(this.element, options.scroll); |
|
276 | } |
|
276 | } |
|
277 |
|
277 | ||
|
278 |
Element.makePositioned(this.element); // fix IE |
|
278 | Element.makePositioned(this.element); // fix IE |
|
279 |
|
279 | ||
|
280 | this.options = options; |
|
280 | this.options = options; |
|
281 |
this.dragging = false; |
|
281 | this.dragging = false; |
|
282 |
|
282 | ||
|
283 | this.eventMouseDown = this.initDrag.bindAsEventListener(this); |
|
283 | this.eventMouseDown = this.initDrag.bindAsEventListener(this); |
|
284 | Event.observe(this.handle, "mousedown", this.eventMouseDown); |
|
284 | Event.observe(this.handle, "mousedown", this.eventMouseDown); |
|
285 |
|
285 | ||
|
286 | Draggables.register(this); |
|
286 | Draggables.register(this); |
|
287 | }, |
|
287 | }, |
|
288 |
|
288 | ||
|
289 | destroy: function() { |
|
289 | destroy: function() { |
|
290 | Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); |
|
290 | Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); |
|
291 | Draggables.unregister(this); |
|
291 | Draggables.unregister(this); |
|
292 | }, |
|
292 | }, |
|
293 |
|
293 | ||
|
294 | currentDelta: function() { |
|
294 | currentDelta: function() { |
|
295 | return([ |
|
295 | return([ |
|
296 | parseInt(Element.getStyle(this.element,'left') || '0'), |
|
296 | parseInt(Element.getStyle(this.element,'left') || '0'), |
|
297 | parseInt(Element.getStyle(this.element,'top') || '0')]); |
|
297 | parseInt(Element.getStyle(this.element,'top') || '0')]); |
|
298 | }, |
|
298 | }, |
|
299 |
|
299 | ||
|
300 | initDrag: function(event) { |
|
300 | initDrag: function(event) { |
|
301 | if(!Object.isUndefined(Draggable._dragging[this.element]) && |
|
301 | if(!Object.isUndefined(Draggable._dragging[this.element]) && |
|
302 | Draggable._dragging[this.element]) return; |
|
302 | Draggable._dragging[this.element]) return; |
|
303 |
if(Event.isLeftClick(event)) { |
|
303 | if(Event.isLeftClick(event)) { |
|
304 | // abort on form elements, fixes a Firefox issue |
|
304 | // abort on form elements, fixes a Firefox issue |
|
305 | var src = Event.element(event); |
|
305 | var src = Event.element(event); |
|
306 | if((tag_name = src.tagName.toUpperCase()) && ( |
|
306 | if((tag_name = src.tagName.toUpperCase()) && ( |
|
307 | tag_name=='INPUT' || |
|
307 | tag_name=='INPUT' || |
|
308 | tag_name=='SELECT' || |
|
308 | tag_name=='SELECT' || |
|
309 | tag_name=='OPTION' || |
|
309 | tag_name=='OPTION' || |
|
310 | tag_name=='BUTTON' || |
|
310 | tag_name=='BUTTON' || |
|
311 | tag_name=='TEXTAREA')) return; |
|
311 | tag_name=='TEXTAREA')) return; |
|
312 |
|
312 | ||
|
313 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
313 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
314 | var pos = Position.cumulativeOffset(this.element); |
|
314 | var pos = Position.cumulativeOffset(this.element); |
|
315 | this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); |
|
315 | this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); |
|
316 |
|
316 | ||
|
317 | Draggables.activate(this); |
|
317 | Draggables.activate(this); |
|
318 | Event.stop(event); |
|
318 | Event.stop(event); |
|
319 | } |
|
319 | } |
|
320 | }, |
|
320 | }, |
|
321 |
|
321 | ||
|
322 | startDrag: function(event) { |
|
322 | startDrag: function(event) { |
|
323 | this.dragging = true; |
|
323 | this.dragging = true; |
|
324 | if(!this.delta) |
|
324 | if(!this.delta) |
|
325 | this.delta = this.currentDelta(); |
|
325 | this.delta = this.currentDelta(); |
|
326 |
|
326 | ||
|
327 | if(this.options.zindex) { |
|
327 | if(this.options.zindex) { |
|
328 | this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); |
|
328 | this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); |
|
329 | this.element.style.zIndex = this.options.zindex; |
|
329 | this.element.style.zIndex = this.options.zindex; |
|
330 | } |
|
330 | } |
|
331 |
|
331 | ||
|
332 | if(this.options.ghosting) { |
|
332 | if(this.options.ghosting) { |
|
333 | this._clone = this.element.cloneNode(true); |
|
333 | this._clone = this.element.cloneNode(true); |
|
334 |
- this |
|
334 | + this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); |
|
335 |
- if (!this. |
|
335 | + if (!this._originallyAbsolute) |
|
336 | Position.absolutize(this.element); |
|
336 | Position.absolutize(this.element); |
|
337 | this.element.parentNode.insertBefore(this._clone, this.element); |
|
337 | this.element.parentNode.insertBefore(this._clone, this.element); |
|
338 | } |
|
338 | } |
|
339 |
|
339 | ||
|
340 | if(this.options.scroll) { |
|
340 | if(this.options.scroll) { |
|
341 | if (this.options.scroll == window) { |
|
341 | if (this.options.scroll == window) { |
|
342 | var where = this._getWindowScroll(this.options.scroll); |
|
342 | var where = this._getWindowScroll(this.options.scroll); |
|
343 | this.originalScrollLeft = where.left; |
|
343 | this.originalScrollLeft = where.left; |
|
344 | this.originalScrollTop = where.top; |
|
344 | this.originalScrollTop = where.top; |
|
345 | } else { |
|
345 | } else { |
|
346 | this.originalScrollLeft = this.options.scroll.scrollLeft; |
|
346 | this.originalScrollLeft = this.options.scroll.scrollLeft; |
|
347 | this.originalScrollTop = this.options.scroll.scrollTop; |
|
347 | this.originalScrollTop = this.options.scroll.scrollTop; |
|
348 | } |
|
348 | } |
|
349 | } |
|
349 | } |
|
350 |
|
350 | ||
|
351 | Draggables.notify('onStart', this, event); |
|
351 | Draggables.notify('onStart', this, event); |
|
352 |
|
352 | ||
|
353 | if(this.options.starteffect) this.options.starteffect(this.element); |
|
353 | if(this.options.starteffect) this.options.starteffect(this.element); |
|
354 | }, |
|
354 | }, |
|
355 |
|
355 | ||
|
356 | updateDrag: function(event, pointer) { |
|
356 | updateDrag: function(event, pointer) { |
|
357 | if(!this.dragging) this.startDrag(event); |
|
357 | if(!this.dragging) this.startDrag(event); |
|
358 |
|
358 | ||
|
359 | if(!this.options.quiet){ |
|
359 | if(!this.options.quiet){ |
|
360 | Position.prepare(); |
|
360 | Position.prepare(); |
|
361 | Droppables.show(pointer, this.element); |
|
361 | Droppables.show(pointer, this.element); |
|
362 | } |
|
362 | } |
|
363 |
|
363 | ||
|
364 | Draggables.notify('onDrag', this, event); |
|
364 | Draggables.notify('onDrag', this, event); |
|
365 |
|
365 | ||
|
366 | this.draw(pointer); |
|
366 | this.draw(pointer); |
|
367 | if(this.options.change) this.options.change(this); |
|
367 | if(this.options.change) this.options.change(this); |
|
368 |
|
368 | ||
|
369 | if(this.options.scroll) { |
|
369 | if(this.options.scroll) { |
|
370 | this.stopScrolling(); |
|
370 | this.stopScrolling(); |
|
371 |
|
371 | ||
|
372 | var p; |
|
372 | var p; |
|
373 | if (this.options.scroll == window) { |
|
373 | if (this.options.scroll == window) { |
|
374 | with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } |
|
374 | with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } |
|
375 | } else { |
|
375 | } else { |
|
376 | p = Position.page(this.options.scroll); |
|
376 | p = Position.page(this.options.scroll); |
|
377 | p[0] += this.options.scroll.scrollLeft + Position.deltaX; |
|
377 | p[0] += this.options.scroll.scrollLeft + Position.deltaX; |
|
378 | p[1] += this.options.scroll.scrollTop + Position.deltaY; |
|
378 | p[1] += this.options.scroll.scrollTop + Position.deltaY; |
|
379 | p.push(p[0]+this.options.scroll.offsetWidth); |
|
379 | p.push(p[0]+this.options.scroll.offsetWidth); |
|
380 | p.push(p[1]+this.options.scroll.offsetHeight); |
|
380 | p.push(p[1]+this.options.scroll.offsetHeight); |
|
381 | } |
|
381 | } |
|
382 | var speed = [0,0]; |
|
382 | var speed = [0,0]; |
|
383 | if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); |
|
383 | if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); |
|
384 | if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); |
|
384 | if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); |
|
385 | if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); |
|
385 | if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); |
|
386 | if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); |
|
386 | if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); |
|
387 | this.startScrolling(speed); |
|
387 | this.startScrolling(speed); |
|
388 | } |
|
388 | } |
|
389 |
|
389 | ||
|
390 | // fix AppleWebKit rendering |
|
390 | // fix AppleWebKit rendering |
|
391 | if(Prototype.Browser.WebKit) window.scrollBy(0,0); |
|
391 | if(Prototype.Browser.WebKit) window.scrollBy(0,0); |
|
392 |
|
392 | ||
|
393 | Event.stop(event); |
|
393 | Event.stop(event); |
|
394 | }, |
|
394 | }, |
|
395 |
|
395 | ||
|
396 | finishDrag: function(event, success) { |
|
396 | finishDrag: function(event, success) { |
|
397 | this.dragging = false; |
|
397 | this.dragging = false; |
|
398 |
|
398 | ||
|
399 | if(this.options.quiet){ |
|
399 | if(this.options.quiet){ |
|
400 | Position.prepare(); |
|
400 | Position.prepare(); |
|
401 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
401 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
|
402 | Droppables.show(pointer, this.element); |
|
402 | Droppables.show(pointer, this.element); |
|
403 | } |
|
403 | } |
|
404 |
|
404 | ||
|
405 | if(this.options.ghosting) { |
|
405 | if(this.options.ghosting) { |
|
406 |
- if (!this. |
|
406 | + if (!this._originallyAbsolute) |
|
407 | Position.relativize(this.element); |
|
407 | Position.relativize(this.element); |
|
408 |
- delete this. |
|
408 | + delete this._originallyAbsolute; |
|
409 | Element.remove(this._clone); |
|
409 | Element.remove(this._clone); |
|
410 | this._clone = null; |
|
410 | this._clone = null; |
|
411 | } |
|
411 | } |
|
412 |
|
412 | ||
|
413 |
var dropped = false; |
|
413 | var dropped = false; |
|
414 |
if(success) { |
|
414 | if(success) { |
|
415 |
dropped = Droppables.fire(event, this.element); |
|
415 | dropped = Droppables.fire(event, this.element); |
|
416 |
if (!dropped) dropped = false; |
|
416 | if (!dropped) dropped = false; |
|
417 | } |
|
417 | } |
|
418 | if(dropped && this.options.onDropped) this.options.onDropped(this.element); |
|
418 | if(dropped && this.options.onDropped) this.options.onDropped(this.element); |
|
419 | Draggables.notify('onEnd', this, event); |
|
419 | Draggables.notify('onEnd', this, event); |
|
420 |
|
420 | ||
|
421 | var revert = this.options.revert; |
|
421 | var revert = this.options.revert; |
|
422 | if(revert && Object.isFunction(revert)) revert = revert(this.element); |
|
422 | if(revert && Object.isFunction(revert)) revert = revert(this.element); |
|
423 |
|
423 | ||
|
424 | var d = this.currentDelta(); |
|
424 | var d = this.currentDelta(); |
|
425 | if(revert && this.options.reverteffect) { |
|
425 | if(revert && this.options.reverteffect) { |
|
426 | if (dropped == 0 || revert != 'failure') |
|
426 | if (dropped == 0 || revert != 'failure') |
|
427 | this.options.reverteffect(this.element, |
|
427 | this.options.reverteffect(this.element, |
|
428 | d[1]-this.delta[1], d[0]-this.delta[0]); |
|
428 | d[1]-this.delta[1], d[0]-this.delta[0]); |
|
429 | } else { |
|
429 | } else { |
|
430 | this.delta = d; |
|
430 | this.delta = d; |
|
431 | } |
|
431 | } |
|
432 |
|
432 | ||
|
433 | if(this.options.zindex) |
|
433 | if(this.options.zindex) |
|
434 | this.element.style.zIndex = this.originalZ; |
|
434 | this.element.style.zIndex = this.originalZ; |
|
435 |
|
435 | ||
|
436 |
if(this.options.endeffect) |
|
436 | if(this.options.endeffect) |
|
437 | this.options.endeffect(this.element); |
|
437 | this.options.endeffect(this.element); |
|
438 |
|
438 | ||
|
439 | Draggables.deactivate(this); |
|
439 | Draggables.deactivate(this); |
|
440 | Droppables.reset(); |
|
440 | Droppables.reset(); |
|
441 | }, |
|
441 | }, |
|
442 |
|
442 | ||
|
443 | keyPress: function(event) { |
|
443 | keyPress: function(event) { |
|
444 | if(event.keyCode!=Event.KEY_ESC) return; |
|
444 | if(event.keyCode!=Event.KEY_ESC) return; |
|
445 | this.finishDrag(event, false); |
|
445 | this.finishDrag(event, false); |
|
446 | Event.stop(event); |
|
446 | Event.stop(event); |
|
447 | }, |
|
447 | }, |
|
448 |
|
448 | ||
|
449 | endDrag: function(event) { |
|
449 | endDrag: function(event) { |
|
450 | if(!this.dragging) return; |
|
450 | if(!this.dragging) return; |
|
451 | this.stopScrolling(); |
|
451 | this.stopScrolling(); |
|
452 | this.finishDrag(event, true); |
|
452 | this.finishDrag(event, true); |
|
453 | Event.stop(event); |
|
453 | Event.stop(event); |
|
454 | }, |
|
454 | }, |
|
455 |
|
455 | ||
|
456 | draw: function(point) { |
|
456 | draw: function(point) { |
|
457 | var pos = Position.cumulativeOffset(this.element); |
|
457 | var pos = Position.cumulativeOffset(this.element); |
|
458 | if(this.options.ghosting) { |
|
458 | if(this.options.ghosting) { |
|
459 | var r = Position.realOffset(this.element); |
|
459 | var r = Position.realOffset(this.element); |
|
460 | pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; |
|
460 | pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; |
|
461 | } |
|
461 | } |
|
462 |
|
462 | ||
|
463 | var d = this.currentDelta(); |
|
463 | var d = this.currentDelta(); |
|
464 | pos[0] -= d[0]; pos[1] -= d[1]; |
|
464 | pos[0] -= d[0]; pos[1] -= d[1]; |
|
465 |
|
465 | ||
|
466 | if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { |
|
466 | if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { |
|
467 | pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; |
|
467 | pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; |
|
468 | pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; |
|
468 | pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; |
|
469 | } |
|
469 | } |
|
470 |
|
470 | ||
|
471 |
var p = [0,1].map(function(i){ |
|
471 | var p = [0,1].map(function(i){ |
|
472 |
return (point[i]-pos[i]-this.offset[i]) |
|
472 | return (point[i]-pos[i]-this.offset[i]) |
|
473 | }.bind(this)); |
|
473 | }.bind(this)); |
|
474 |
|
474 | ||
|
475 | if(this.options.snap) { |
|
475 | if(this.options.snap) { |
|
476 | if(Object.isFunction(this.options.snap)) { |
|
476 | if(Object.isFunction(this.options.snap)) { |
|
477 | p = this.options.snap(p[0],p[1],this); |
|
477 | p = this.options.snap(p[0],p[1],this); |
|
478 | } else { |
|
478 | } else { |
|
479 | if(Object.isArray(this.options.snap)) { |
|
479 | if(Object.isArray(this.options.snap)) { |
|
480 | p = p.map( function(v, i) { |
|
480 | p = p.map( function(v, i) { |
|
481 | - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)) |
|
481 | + return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); |
|
482 | } else { |
|
482 | } else { |
|
483 | p = p.map( function(v) { |
|
483 | p = p.map( function(v) { |
|
484 | - return (v/this.options.snap).round()*this.options.snap }.bind(this)) |
|
484 | + return (v/this.options.snap).round()*this.options.snap }.bind(this)); |
|
485 | } |
|
485 | } |
|
486 | }} |
|
486 | }} |
|
487 |
|
487 | ||
|
488 | var style = this.element.style; |
|
488 | var style = this.element.style; |
|
489 | if((!this.options.constraint) || (this.options.constraint=='horizontal')) |
|
489 | if((!this.options.constraint) || (this.options.constraint=='horizontal')) |
|
490 | style.left = p[0] + "px"; |
|
490 | style.left = p[0] + "px"; |
|
491 | if((!this.options.constraint) || (this.options.constraint=='vertical')) |
|
491 | if((!this.options.constraint) || (this.options.constraint=='vertical')) |
|
492 | style.top = p[1] + "px"; |
|
492 | style.top = p[1] + "px"; |
|
493 |
|
493 | ||
|
494 | if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering |
|
494 | if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering |
|
495 | }, |
|
495 | }, |
|
496 |
|
496 | ||
|
497 | stopScrolling: function() { |
|
497 | stopScrolling: function() { |
|
498 | if(this.scrollInterval) { |
|
498 | if(this.scrollInterval) { |
|
499 | clearInterval(this.scrollInterval); |
|
499 | clearInterval(this.scrollInterval); |
|
500 | this.scrollInterval = null; |
|
500 | this.scrollInterval = null; |
|
501 | Draggables._lastScrollPointer = null; |
|
501 | Draggables._lastScrollPointer = null; |
|
502 | } |
|
502 | } |
|
503 | }, |
|
503 | }, |
|
504 |
|
504 | ||
|
505 | startScrolling: function(speed) { |
|
505 | startScrolling: function(speed) { |
|
506 | if(!(speed[0] || speed[1])) return; |
|
506 | if(!(speed[0] || speed[1])) return; |
|
507 | this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; |
|
507 | this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; |
|
508 | this.lastScrolled = new Date(); |
|
508 | this.lastScrolled = new Date(); |
|
509 | this.scrollInterval = setInterval(this.scroll.bind(this), 10); |
|
509 | this.scrollInterval = setInterval(this.scroll.bind(this), 10); |
|
510 | }, |
|
510 | }, |
|
511 |
|
511 | ||
|
512 | scroll: function() { |
|
512 | scroll: function() { |
|
513 | var current = new Date(); |
|
513 | var current = new Date(); |
|
514 | var delta = current - this.lastScrolled; |
|
514 | var delta = current - this.lastScrolled; |
|
515 | this.lastScrolled = current; |
|
515 | this.lastScrolled = current; |
|
516 | if(this.options.scroll == window) { |
|
516 | if(this.options.scroll == window) { |
|
517 | with (this._getWindowScroll(this.options.scroll)) { |
|
517 | with (this._getWindowScroll(this.options.scroll)) { |
|
518 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { |
|
518 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { |
|
519 | var d = delta / 1000; |
|
519 | var d = delta / 1000; |
|
520 | this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); |
|
520 | this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); |
|
521 | } |
|
521 | } |
|
522 | } |
|
522 | } |
|
523 | } else { |
|
523 | } else { |
|
524 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; |
|
524 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; |
|
525 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; |
|
525 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; |
|
526 | } |
|
526 | } |
|
527 |
|
527 | ||
|
528 | Position.prepare(); |
|
528 | Position.prepare(); |
|
529 | Droppables.show(Draggables._lastPointer, this.element); |
|
529 | Droppables.show(Draggables._lastPointer, this.element); |
|
530 | Draggables.notify('onDrag', this); |
|
530 | Draggables.notify('onDrag', this); |
|
531 | if (this._isScrollChild) { |
|
531 | if (this._isScrollChild) { |
|
532 | Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); |
|
532 | Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); |
|
533 | Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; |
|
533 | Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; |
|
534 | Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; |
|
534 | Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; |
|
535 | if (Draggables._lastScrollPointer[0] < 0) |
|
535 | if (Draggables._lastScrollPointer[0] < 0) |
|
536 | Draggables._lastScrollPointer[0] = 0; |
|
536 | Draggables._lastScrollPointer[0] = 0; |
|
537 | if (Draggables._lastScrollPointer[1] < 0) |
|
537 | if (Draggables._lastScrollPointer[1] < 0) |
|
538 | Draggables._lastScrollPointer[1] = 0; |
|
538 | Draggables._lastScrollPointer[1] = 0; |
|
539 | this.draw(Draggables._lastScrollPointer); |
|
539 | this.draw(Draggables._lastScrollPointer); |
|
540 | } |
|
540 | } |
|
541 |
|
541 | ||
|
542 | if(this.options.change) this.options.change(this); |
|
542 | if(this.options.change) this.options.change(this); |
|
543 | }, |
|
543 | }, |
|
544 |
|
544 | ||
|
545 | _getWindowScroll: function(w) { |
|
545 | _getWindowScroll: function(w) { |
|
546 | var T, L, W, H; |
|
546 | var T, L, W, H; |
|
547 | with (w.document) { |
|
547 | with (w.document) { |
|
548 | if (w.document.documentElement && documentElement.scrollTop) { |
|
548 | if (w.document.documentElement && documentElement.scrollTop) { |
|
549 | T = documentElement.scrollTop; |
|
549 | T = documentElement.scrollTop; |
|
550 | L = documentElement.scrollLeft; |
|
550 | L = documentElement.scrollLeft; |
|
551 | } else if (w.document.body) { |
|
551 | } else if (w.document.body) { |
|
552 | T = body.scrollTop; |
|
552 | T = body.scrollTop; |
|
553 | L = body.scrollLeft; |
|
553 | L = body.scrollLeft; |
|
554 | } |
|
554 | } |
|
555 | if (w.innerWidth) { |
|
555 | if (w.innerWidth) { |
|
556 | W = w.innerWidth; |
|
556 | W = w.innerWidth; |
|
557 | H = w.innerHeight; |
|
557 | H = w.innerHeight; |
|
558 | } else if (w.document.documentElement && documentElement.clientWidth) { |
|
558 | } else if (w.document.documentElement && documentElement.clientWidth) { |
|
559 | W = documentElement.clientWidth; |
|
559 | W = documentElement.clientWidth; |
|
560 | H = documentElement.clientHeight; |
|
560 | H = documentElement.clientHeight; |
|
561 | } else { |
|
561 | } else { |
|
562 | W = body.offsetWidth; |
|
562 | W = body.offsetWidth; |
|
563 | - H = body.offsetHeight |
|
563 | + H = body.offsetHeight; |
|
564 | } |
|
564 | } |
|
565 | } |
|
565 | } |
|
566 | return { top: T, left: L, width: W, height: H }; |
|
566 | return { top: T, left: L, width: W, height: H }; |
|
567 | } |
|
567 | } |
|
568 | }); |
|
568 | }); |
|
569 |
|
569 | ||
|
570 | Draggable._dragging = { }; |
|
570 | Draggable._dragging = { }; |
|
571 |
|
571 | ||
|
572 | /*--------------------------------------------------------------------------*/ |
|
572 | /*--------------------------------------------------------------------------*/ |
|
573 |
|
573 | ||
|
574 | var SortableObserver = Class.create({ |
|
574 | var SortableObserver = Class.create({ |
|
575 | initialize: function(element, observer) { |
|
575 | initialize: function(element, observer) { |
|
576 | this.element = $(element); |
|
576 | this.element = $(element); |
|
577 | this.observer = observer; |
|
577 | this.observer = observer; |
|
578 | this.lastValue = Sortable.serialize(this.element); |
|
578 | this.lastValue = Sortable.serialize(this.element); |
|
579 | }, |
|
579 | }, |
|
580 |
|
580 | ||
|
581 | onStart: function() { |
|
581 | onStart: function() { |
|
582 | this.lastValue = Sortable.serialize(this.element); |
|
582 | this.lastValue = Sortable.serialize(this.element); |
|
583 | }, |
|
583 | }, |
|
584 |
|
584 | ||
|
585 | onEnd: function() { |
|
585 | onEnd: function() { |
|
586 | Sortable.unmark(); |
|
586 | Sortable.unmark(); |
|
587 | if(this.lastValue != Sortable.serialize(this.element)) |
|
587 | if(this.lastValue != Sortable.serialize(this.element)) |
|
588 | this.observer(this.element) |
|
588 | this.observer(this.element) |
|
589 | } |
|
589 | } |
|
590 | }); |
|
590 | }); |
|
591 |
|
591 | ||
|
592 | var Sortable = { |
|
592 | var Sortable = { |
|
593 | SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, |
|
593 | SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, |
|
594 |
|
594 | ||
|
595 | sortables: { }, |
|
595 | sortables: { }, |
|
596 |
|
596 | ||
|
597 | _findRootElement: function(element) { |
|
597 | _findRootElement: function(element) { |
|
598 |
while (element.tagName.toUpperCase() != "BODY") { |
|
598 | while (element.tagName.toUpperCase() != "BODY") { |
|
599 | if(element.id && Sortable.sortables[element.id]) return element; |
|
599 | if(element.id && Sortable.sortables[element.id]) return element; |
|
600 | element = element.parentNode; |
|
600 | element = element.parentNode; |
|
601 | } |
|
601 | } |
|
602 | }, |
|
602 | }, |
|
603 |
|
603 | ||
|
604 | options: function(element) { |
|
604 | options: function(element) { |
|
605 | element = Sortable._findRootElement($(element)); |
|
605 | element = Sortable._findRootElement($(element)); |
|
606 | if(!element) return; |
|
606 | if(!element) return; |
|
607 | return Sortable.sortables[element.id]; |
|
607 | return Sortable.sortables[element.id]; |
|
608 | }, |
|
608 | }, |
|
609 |
|
609 | ||
|
610 | destroy: function(element){ |
|
610 | destroy: function(element){ |
|
611 | - var s = Sortable.options(element); |
|
611 | + element = $(element); |
|
|
612 | + var s = Sortable.sortables[element.id]; | ||
|
612 |
|
613 | ||
|
613 | if(s) { |
|
614 | if(s) { |
|
614 | Draggables.removeObserver(s.element); |
|
615 | Draggables.removeObserver(s.element); |
|
615 | s.droppables.each(function(d){ Droppables.remove(d) }); |
|
616 | s.droppables.each(function(d){ Droppables.remove(d) }); |
|
616 | s.draggables.invoke('destroy'); |
|
617 | s.draggables.invoke('destroy'); |
|
617 |
|
618 | ||
|
618 | delete Sortable.sortables[s.element.id]; |
|
619 | delete Sortable.sortables[s.element.id]; |
|
619 | } |
|
620 | } |
|
620 | }, |
|
621 | }, |
|
621 |
|
622 | ||
|
622 | create: function(element) { |
|
623 | create: function(element) { |
|
623 | element = $(element); |
|
624 | element = $(element); |
|
624 |
var options = Object.extend({ |
|
625 | var options = Object.extend({ |
|
625 | element: element, |
|
626 | element: element, |
|
626 | tag: 'li', // assumes li children, override with tag: 'tagname' |
|
627 | tag: 'li', // assumes li children, override with tag: 'tagname' |
|
627 | dropOnEmpty: false, |
|
628 | dropOnEmpty: false, |
|
628 | tree: false, |
|
629 | tree: false, |
|
629 | treeTag: 'ul', |
|
630 | treeTag: 'ul', |
|
630 | overlap: 'vertical', // one of 'vertical', 'horizontal' |
|
631 | overlap: 'vertical', // one of 'vertical', 'horizontal' |
|
631 | constraint: 'vertical', // one of 'vertical', 'horizontal', false |
|
632 | constraint: 'vertical', // one of 'vertical', 'horizontal', false |
|
632 | containment: element, // also takes array of elements (or id's); or false |
|
633 | containment: element, // also takes array of elements (or id's); or false |
|
633 | handle: false, // or a CSS class |
|
634 | handle: false, // or a CSS class |
|
634 | only: false, |
|
635 | only: false, |
|
635 | delay: 0, |
|
636 | delay: 0, |
|
636 | hoverclass: null, |
|
637 | hoverclass: null, |
|
637 | ghosting: false, |
|
638 | ghosting: false, |
|
638 |
quiet: false, |
|
639 | quiet: false, |
|
639 | scroll: false, |
|
640 | scroll: false, |
|
640 | scrollSensitivity: 20, |
|
641 | scrollSensitivity: 20, |
|
641 | scrollSpeed: 15, |
|
642 | scrollSpeed: 15, |
|
642 | format: this.SERIALIZE_RULE, |
|
643 | format: this.SERIALIZE_RULE, |
|
643 |
|
644 | ||
|
644 |
// these take arrays of elements or ids and can be |
|
645 | // these take arrays of elements or ids and can be |
|
645 | // used for better initialization performance |
|
646 | // used for better initialization performance |
|
646 | elements: false, |
|
647 | elements: false, |
|
647 | handles: false, |
|
648 | handles: false, |
|
648 |
|
649 | ||
|
649 | onChange: Prototype.emptyFunction, |
|
650 | onChange: Prototype.emptyFunction, |
|
650 | onUpdate: Prototype.emptyFunction |
|
651 | onUpdate: Prototype.emptyFunction |
|
651 | }, arguments[1] || { }); |
|
652 | }, arguments[1] || { }); |
|
652 |
|
653 | ||
|
653 | // clear any old sortable with same element |
|
654 | // clear any old sortable with same element |
|
654 | this.destroy(element); |
|
655 | this.destroy(element); |
|
655 |
|
656 | ||
|
656 | // build options for the draggables |
|
657 | // build options for the draggables |
|
657 | var options_for_draggable = { |
|
658 | var options_for_draggable = { |
|
658 | revert: true, |
|
659 | revert: true, |
|
659 | quiet: options.quiet, |
|
660 | quiet: options.quiet, |
|
660 | scroll: options.scroll, |
|
661 | scroll: options.scroll, |
|
661 | scrollSpeed: options.scrollSpeed, |
|
662 | scrollSpeed: options.scrollSpeed, |
|
662 | scrollSensitivity: options.scrollSensitivity, |
|
663 | scrollSensitivity: options.scrollSensitivity, |
|
663 | delay: options.delay, |
|
664 | delay: options.delay, |
|
664 | ghosting: options.ghosting, |
|
665 | ghosting: options.ghosting, |
|
665 | constraint: options.constraint, |
|
666 | constraint: options.constraint, |
|
666 | handle: options.handle }; |
|
667 | handle: options.handle }; |
|
667 |
|
668 | ||
|
668 | if(options.starteffect) |
|
669 | if(options.starteffect) |
|
669 | options_for_draggable.starteffect = options.starteffect; |
|
670 | options_for_draggable.starteffect = options.starteffect; |
|
670 |
|
671 | ||
|
671 | if(options.reverteffect) |
|
672 | if(options.reverteffect) |
|
672 | options_for_draggable.reverteffect = options.reverteffect; |
|
673 | options_for_draggable.reverteffect = options.reverteffect; |
|
673 | else |
|
674 | else |
|
674 | if(options.ghosting) options_for_draggable.reverteffect = function(element) { |
|
675 | if(options.ghosting) options_for_draggable.reverteffect = function(element) { |
|
675 | element.style.top = 0; |
|
676 | element.style.top = 0; |
|
676 | element.style.left = 0; |
|
677 | element.style.left = 0; |
|
677 | }; |
|
678 | }; |
|
678 |
|
679 | ||
|
679 | if(options.endeffect) |
|
680 | if(options.endeffect) |
|
680 | options_for_draggable.endeffect = options.endeffect; |
|
681 | options_for_draggable.endeffect = options.endeffect; |
|
681 |
|
682 | ||
|
682 | if(options.zindex) |
|
683 | if(options.zindex) |
|
683 | options_for_draggable.zindex = options.zindex; |
|
684 | options_for_draggable.zindex = options.zindex; |
|
684 |
|
685 | ||
|
685 |
// build options for the droppables |
|
686 | // build options for the droppables |
|
686 | var options_for_droppable = { |
|
687 | var options_for_droppable = { |
|
687 | overlap: options.overlap, |
|
688 | overlap: options.overlap, |
|
688 | containment: options.containment, |
|
689 | containment: options.containment, |
|
689 | tree: options.tree, |
|
690 | tree: options.tree, |
|
690 | hoverclass: options.hoverclass, |
|
691 | hoverclass: options.hoverclass, |
|
691 | onHover: Sortable.onHover |
|
692 | onHover: Sortable.onHover |
|
692 | - } |
|
693 | + }; |
|
693 |
|
694 | ||
|
694 | var options_for_tree = { |
|
695 | var options_for_tree = { |
|
695 | onHover: Sortable.onEmptyHover, |
|
696 | onHover: Sortable.onEmptyHover, |
|
696 | overlap: options.overlap, |
|
697 | overlap: options.overlap, |
|
697 | containment: options.containment, |
|
698 | containment: options.containment, |
|
698 | hoverclass: options.hoverclass |
|
699 | hoverclass: options.hoverclass |
|
699 | - } |
|
700 | + }; |
|
700 |
|
701 | ||
|
701 | // fix for gecko engine |
|
702 | // fix for gecko engine |
|
702 |
|
|
703 | Element.cleanWhitespace(element); |
|
703 |
|
704 | ||
|
704 | options.draggables = []; |
|
705 | options.draggables = []; |
|
705 | options.droppables = []; |
|
706 | options.droppables = []; |
|
706 |
|
707 | ||
|
707 | // drop on empty handling |
|
708 | // drop on empty handling |
|
708 | if(options.dropOnEmpty || options.tree) { |
|
709 | if(options.dropOnEmpty || options.tree) { |
|
709 | Droppables.add(element, options_for_tree); |
|
710 | Droppables.add(element, options_for_tree); |
|
710 | options.droppables.push(element); |
|
711 | options.droppables.push(element); |
|
711 | } |
|
712 | } |
|
712 |
|
713 | ||
|
713 | (options.elements || this.findElements(element, options) || []).each( function(e,i) { |
|
714 | (options.elements || this.findElements(element, options) || []).each( function(e,i) { |
|
714 | var handle = options.handles ? $(options.handles[i]) : |
|
715 | var handle = options.handles ? $(options.handles[i]) : |
|
715 |
(options.handle ? $(e).select('.' + options.handle)[0] : e); |
|
716 | (options.handle ? $(e).select('.' + options.handle)[0] : e); |
|
716 | options.draggables.push( |
|
717 | options.draggables.push( |
|
717 | new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); |
|
718 | new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); |
|
718 | Droppables.add(e, options_for_droppable); |
|
719 | Droppables.add(e, options_for_droppable); |
|
719 | if(options.tree) e.treeNode = element; |
|
720 | if(options.tree) e.treeNode = element; |
|
720 |
options.droppables.push(e); |
|
721 | options.droppables.push(e); |
|
721 | }); |
|
722 | }); |
|
722 |
|
723 | ||
|
723 | if(options.tree) { |
|
724 | if(options.tree) { |
|
724 | (Sortable.findTreeElements(element, options) || []).each( function(e) { |
|
725 | (Sortable.findTreeElements(element, options) || []).each( function(e) { |
|
725 | Droppables.add(e, options_for_tree); |
|
726 | Droppables.add(e, options_for_tree); |
|
726 | e.treeNode = element; |
|
727 | e.treeNode = element; |
|
727 | options.droppables.push(e); |
|
728 | options.droppables.push(e); |
|
728 | }); |
|
729 | }); |
|
729 | } |
|
730 | } |
|
730 |
|
731 | ||
|
731 | // keep reference |
|
732 | // keep reference |
|
732 | this.sortables[element.id] = options; |
|
733 | this.sortables[element.id] = options; |
|
733 |
|
734 | ||
|
734 | // for onupdate |
|
735 | // for onupdate |
|
735 | Draggables.addObserver(new SortableObserver(element, options.onUpdate)); |
|
736 | Draggables.addObserver(new SortableObserver(element, options.onUpdate)); |
|
736 |
|
737 | ||
|
737 | }, |
|
738 | }, |
|
738 |
|
739 | ||
|
739 | // return all suitable-for-sortable elements in a guaranteed order |
|
740 | // return all suitable-for-sortable elements in a guaranteed order |
|
740 | findElements: function(element, options) { |
|
741 | findElements: function(element, options) { |
|
741 | return Element.findChildren( |
|
742 | return Element.findChildren( |
|
742 | element, options.only, options.tree ? true : false, options.tag); |
|
743 | element, options.only, options.tree ? true : false, options.tag); |
|
743 | }, |
|
744 | }, |
|
744 |
|
745 | ||
|
745 | findTreeElements: function(element, options) { |
|
746 | findTreeElements: function(element, options) { |
|
746 | return Element.findChildren( |
|
747 | return Element.findChildren( |
|
747 | element, options.only, options.tree ? true : false, options.treeTag); |
|
748 | element, options.only, options.tree ? true : false, options.treeTag); |
|
748 | }, |
|
749 | }, |
|
749 |
|
750 | ||
|
750 | onHover: function(element, dropon, overlap) { |
|
751 | onHover: function(element, dropon, overlap) { |
|
751 | if(Element.isParent(dropon, element)) return; |
|
752 | if(Element.isParent(dropon, element)) return; |
|
752 |
|
753 | ||
|
753 | if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { |
|
754 | if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { |
|
754 | return; |
|
755 | return; |
|
755 | } else if(overlap>0.5) { |
|
756 | } else if(overlap>0.5) { |
|
756 | Sortable.mark(dropon, 'before'); |
|
757 | Sortable.mark(dropon, 'before'); |
|
757 | if(dropon.previousSibling != element) { |
|
758 | if(dropon.previousSibling != element) { |
|
758 | var oldParentNode = element.parentNode; |
|
759 | var oldParentNode = element.parentNode; |
|
759 | element.style.visibility = "hidden"; // fix gecko rendering |
|
760 | element.style.visibility = "hidden"; // fix gecko rendering |
|
760 | dropon.parentNode.insertBefore(element, dropon); |
|
761 | dropon.parentNode.insertBefore(element, dropon); |
|
761 |
if(dropon.parentNode!=oldParentNode) |
|
762 | if(dropon.parentNode!=oldParentNode) |
|
762 | Sortable.options(oldParentNode).onChange(element); |
|
763 | Sortable.options(oldParentNode).onChange(element); |
|
763 | Sortable.options(dropon.parentNode).onChange(element); |
|
764 | Sortable.options(dropon.parentNode).onChange(element); |
|
764 | } |
|
765 | } |
|
765 | } else { |
|
766 | } else { |
|
766 | Sortable.mark(dropon, 'after'); |
|
767 | Sortable.mark(dropon, 'after'); |
|
767 | var nextElement = dropon.nextSibling || null; |
|
768 | var nextElement = dropon.nextSibling || null; |
|
768 | if(nextElement != element) { |
|
769 | if(nextElement != element) { |
|
769 | var oldParentNode = element.parentNode; |
|
770 | var oldParentNode = element.parentNode; |
|
770 | element.style.visibility = "hidden"; // fix gecko rendering |
|
771 | element.style.visibility = "hidden"; // fix gecko rendering |
|
771 | dropon.parentNode.insertBefore(element, nextElement); |
|
772 | dropon.parentNode.insertBefore(element, nextElement); |
|
772 |
if(dropon.parentNode!=oldParentNode) |
|
773 | if(dropon.parentNode!=oldParentNode) |
|
773 | Sortable.options(oldParentNode).onChange(element); |
|
774 | Sortable.options(oldParentNode).onChange(element); |
|
774 | Sortable.options(dropon.parentNode).onChange(element); |
|
775 | Sortable.options(dropon.parentNode).onChange(element); |
|
775 | } |
|
776 | } |
|
776 | } |
|
777 | } |
|
777 | }, |
|
778 | }, |
|
778 |
|
779 | ||
|
779 | onEmptyHover: function(element, dropon, overlap) { |
|
780 | onEmptyHover: function(element, dropon, overlap) { |
|
780 | var oldParentNode = element.parentNode; |
|
781 | var oldParentNode = element.parentNode; |
|
781 | var droponOptions = Sortable.options(dropon); |
|
782 | var droponOptions = Sortable.options(dropon); |
|
782 |
|
783 | ||
|
783 | if(!Element.isParent(dropon, element)) { |
|
784 | if(!Element.isParent(dropon, element)) { |
|
784 | var index; |
|
785 | var index; |
|
785 |
|
786 | ||
|
786 | var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); |
|
787 | var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); |
|
787 | var child = null; |
|
788 | var child = null; |
|
788 |
|
789 | ||
|
789 | if(children) { |
|
790 | if(children) { |
|
790 | var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); |
|
791 | var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); |
|
791 |
|
792 | ||
|
792 | for (index = 0; index < children.length; index += 1) { |
|
793 | for (index = 0; index < children.length; index += 1) { |
|
793 | if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { |
|
794 | if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { |
|
794 | offset -= Element.offsetSize (children[index], droponOptions.overlap); |
|
795 | offset -= Element.offsetSize (children[index], droponOptions.overlap); |
|
795 | } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { |
|
796 | } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { |
|
796 | child = index + 1 < children.length ? children[index + 1] : null; |
|
797 | child = index + 1 < children.length ? children[index + 1] : null; |
|
797 | break; |
|
798 | break; |
|
798 | } else { |
|
799 | } else { |
|
799 | child = children[index]; |
|
800 | child = children[index]; |
|
800 | break; |
|
801 | break; |
|
801 | } |
|
802 | } |
|
802 | } |
|
803 | } |
|
803 | } |
|
804 | } |
|
804 |
|
805 | ||
|
805 | dropon.insertBefore(element, child); |
|
806 | dropon.insertBefore(element, child); |
|
806 |
|
807 | ||
|
807 | Sortable.options(oldParentNode).onChange(element); |
|
808 | Sortable.options(oldParentNode).onChange(element); |
|
808 | droponOptions.onChange(element); |
|
809 | droponOptions.onChange(element); |
|
809 | } |
|
810 | } |
|
810 | }, |
|
811 | }, |
|
811 |
|
812 | ||
|
812 | unmark: function() { |
|
813 | unmark: function() { |
|
813 | if(Sortable._marker) Sortable._marker.hide(); |
|
814 | if(Sortable._marker) Sortable._marker.hide(); |
|
814 | }, |
|
815 | }, |
|
815 |
|
816 | ||
|
816 | mark: function(dropon, position) { |
|
817 | mark: function(dropon, position) { |
|
817 | // mark on ghosting only |
|
818 | // mark on ghosting only |
|
818 | var sortable = Sortable.options(dropon.parentNode); |
|
819 | var sortable = Sortable.options(dropon.parentNode); |
|
819 |
if(sortable && !sortable.ghosting) return; |
|
820 | if(sortable && !sortable.ghosting) return; |
|
820 |
|
821 | ||
|
821 | if(!Sortable._marker) { |
|
822 | if(!Sortable._marker) { |
|
822 |
Sortable._marker = |
|
823 | Sortable._marker = |
|
823 | ($('dropmarker') || Element.extend(document.createElement('DIV'))). |
|
824 | ($('dropmarker') || Element.extend(document.createElement('DIV'))). |
|
824 | hide().addClassName('dropmarker').setStyle({position:'absolute'}); |
|
825 | hide().addClassName('dropmarker').setStyle({position:'absolute'}); |
|
825 | document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); |
|
826 | document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); |
|
826 |
} |
|
827 | } |
|
827 | var offsets = Position.cumulativeOffset(dropon); |
|
828 | var offsets = Position.cumulativeOffset(dropon); |
|
828 | Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); |
|
829 | Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); |
|
829 |
|
830 | ||
|
830 | if(position=='after') |
|
831 | if(position=='after') |
|
831 |
if(sortable.overlap == 'horizontal') |
|
832 | if(sortable.overlap == 'horizontal') |
|
832 | Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); |
|
833 | Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); |
|
833 | else |
|
834 | else |
|
834 | Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); |
|
835 | Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); |
|
835 |
|
836 | ||
|
836 | Sortable._marker.show(); |
|
837 | Sortable._marker.show(); |
|
837 | }, |
|
838 | }, |
|
838 |
|
839 | ||
|
839 | _tree: function(element, options, parent) { |
|
840 | _tree: function(element, options, parent) { |
|
840 | var children = Sortable.findElements(element, options) || []; |
|
841 | var children = Sortable.findElements(element, options) || []; |
|
841 |
|
842 | ||
|
842 | for (var i = 0; i < children.length; ++i) { |
|
843 | for (var i = 0; i < children.length; ++i) { |
|
843 | var match = children[i].id.match(options.format); |
|
844 | var match = children[i].id.match(options.format); |
|
844 |
|
845 | ||
|
845 | if (!match) continue; |
|
846 | if (!match) continue; |
|
846 |
|
847 | ||
|
847 | var child = { |
|
848 | var child = { |
|
848 | id: encodeURIComponent(match ? match[1] : null), |
|
849 | id: encodeURIComponent(match ? match[1] : null), |
|
849 | element: element, |
|
850 | element: element, |
|
850 | parent: parent, |
|
851 | parent: parent, |
|
851 | children: [], |
|
852 | children: [], |
|
852 | position: parent.children.length, |
|
853 | position: parent.children.length, |
|
853 | container: $(children[i]).down(options.treeTag) |
|
854 | container: $(children[i]).down(options.treeTag) |
|
854 | - } |
|
855 | + }; |
|
855 |
|
856 | ||
|
856 | /* Get the element containing the children and recurse over it */ |
|
857 | /* Get the element containing the children and recurse over it */ |
|
857 | if (child.container) |
|
858 | if (child.container) |
|
858 | - this._tree(child.container, options, child) |
|
859 | + this._tree(child.container, options, child); |
|
859 |
|
860 | ||
|
860 | parent.children.push (child); |
|
861 | parent.children.push (child); |
|
861 | } |
|
862 | } |
|
862 |
|
863 | ||
|
863 |
return parent; |
|
864 | return parent; |
|
864 | }, |
|
865 | }, |
|
865 |
|
866 | ||
|
866 | tree: function(element) { |
|
867 | tree: function(element) { |
|
867 | element = $(element); |
|
868 | element = $(element); |
|
868 | var sortableOptions = this.options(element); |
|
869 | var sortableOptions = this.options(element); |
|
869 | var options = Object.extend({ |
|
870 | var options = Object.extend({ |
|
870 | tag: sortableOptions.tag, |
|
871 | tag: sortableOptions.tag, |
|
871 | treeTag: sortableOptions.treeTag, |
|
872 | treeTag: sortableOptions.treeTag, |
|
872 | only: sortableOptions.only, |
|
873 | only: sortableOptions.only, |
|
873 | name: element.id, |
|
874 | name: element.id, |
|
874 | format: sortableOptions.format |
|
875 | format: sortableOptions.format |
|
875 | }, arguments[1] || { }); |
|
876 | }, arguments[1] || { }); |
|
876 |
|
877 | ||
|
877 | var root = { |
|
878 | var root = { |
|
878 | id: null, |
|
879 | id: null, |
|
879 | parent: null, |
|
880 | parent: null, |
|
880 | children: [], |
|
881 | children: [], |
|
881 | container: element, |
|
882 | container: element, |
|
882 | position: 0 |
|
883 | position: 0 |
|
883 | - } |
|
884 | + }; |
|
884 |
|
885 | ||
|
885 | return Sortable._tree(element, options, root); |
|
886 | return Sortable._tree(element, options, root); |
|
886 | }, |
|
887 | }, |
|
887 |
|
888 | ||
|
888 | /* Construct a [i] index for a particular node */ |
|
889 | /* Construct a [i] index for a particular node */ |
|
889 | _constructIndex: function(node) { |
|
890 | _constructIndex: function(node) { |
|
890 | var index = ''; |
|
891 | var index = ''; |
|
891 | do { |
|
892 | do { |
|
892 | if (node.id) index = '[' + node.position + ']' + index; |
|
893 | if (node.id) index = '[' + node.position + ']' + index; |
|
893 | } while ((node = node.parent) != null); |
|
894 | } while ((node = node.parent) != null); |
|
894 | return index; |
|
895 | return index; |
|
895 | }, |
|
896 | }, |
|
896 |
|
897 | ||
|
897 | sequence: function(element) { |
|
898 | sequence: function(element) { |
|
898 | element = $(element); |
|
899 | element = $(element); |
|
899 | var options = Object.extend(this.options(element), arguments[1] || { }); |
|
900 | var options = Object.extend(this.options(element), arguments[1] || { }); |
|
900 |
|
901 | ||
|
901 | return $(this.findElements(element, options) || []).map( function(item) { |
|
902 | return $(this.findElements(element, options) || []).map( function(item) { |
|
902 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; |
|
903 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; |
|
903 | }); |
|
904 | }); |
|
904 | }, |
|
905 | }, |
|
905 |
|
906 | ||
|
906 | setSequence: function(element, new_sequence) { |
|
907 | setSequence: function(element, new_sequence) { |
|
907 | element = $(element); |
|
908 | element = $(element); |
|
908 | var options = Object.extend(this.options(element), arguments[2] || { }); |
|
909 | var options = Object.extend(this.options(element), arguments[2] || { }); |
|
909 |
|
910 | ||
|
910 | var nodeMap = { }; |
|
911 | var nodeMap = { }; |
|
911 | this.findElements(element, options).each( function(n) { |
|
912 | this.findElements(element, options).each( function(n) { |
|
912 | if (n.id.match(options.format)) |
|
913 | if (n.id.match(options.format)) |
|
913 | nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; |
|
914 | nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; |
|
914 | n.parentNode.removeChild(n); |
|
915 | n.parentNode.removeChild(n); |
|
915 | }); |
|
916 | }); |
|
916 |
|
917 | ||
|
917 | new_sequence.each(function(ident) { |
|
918 | new_sequence.each(function(ident) { |
|
918 | var n = nodeMap[ident]; |
|
919 | var n = nodeMap[ident]; |
|
919 | if (n) { |
|
920 | if (n) { |
|
920 | n[1].appendChild(n[0]); |
|
921 | n[1].appendChild(n[0]); |
|
921 | delete nodeMap[ident]; |
|
922 | delete nodeMap[ident]; |
|
922 | } |
|
923 | } |
|
923 | }); |
|
924 | }); |
|
924 | }, |
|
925 | }, |
|
925 |
|
926 | ||
|
926 | serialize: function(element) { |
|
927 | serialize: function(element) { |
|
927 | element = $(element); |
|
928 | element = $(element); |
|
928 | var options = Object.extend(Sortable.options(element), arguments[1] || { }); |
|
929 | var options = Object.extend(Sortable.options(element), arguments[1] || { }); |
|
929 | var name = encodeURIComponent( |
|
930 | var name = encodeURIComponent( |
|
930 | (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); |
|
931 | (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); |
|
931 |
|
932 | ||
|
932 | if (options.tree) { |
|
933 | if (options.tree) { |
|
933 | return Sortable.tree(element, arguments[1]).children.map( function (item) { |
|
934 | return Sortable.tree(element, arguments[1]).children.map( function (item) { |
|
934 |
return [name + Sortable._constructIndex(item) + "[id]=" + |
|
935 | return [name + Sortable._constructIndex(item) + "[id]=" + |
|
935 | encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); |
|
936 | encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); |
|
936 | }).flatten().join('&'); |
|
937 | }).flatten().join('&'); |
|
937 | } else { |
|
938 | } else { |
|
938 | return Sortable.sequence(element, arguments[1]).map( function(item) { |
|
939 | return Sortable.sequence(element, arguments[1]).map( function(item) { |
|
939 | return name + "[]=" + encodeURIComponent(item); |
|
940 | return name + "[]=" + encodeURIComponent(item); |
|
940 | }).join('&'); |
|
941 | }).join('&'); |
|
941 | } |
|
942 | } |
|
942 | } |
|
943 | } |
|
943 | - } |
|
944 | + }; |
|
944 |
|
945 | ||
|
945 |
|
|
946 | // Returns true if child is contained within element |
|
946 | Element.isParent = function(child, element) { |
|
947 | Element.isParent = function(child, element) { |
|
947 | if (!child.parentNode || child == element) return false; |
|
948 | if (!child.parentNode || child == element) return false; |
|
948 | if (child.parentNode == element) return true; |
|
949 | if (child.parentNode == element) return true; |
|
949 | return Element.isParent(child.parentNode, element); |
|
950 | return Element.isParent(child.parentNode, element); |
|
950 | - } |
|
951 | + }; |
|
951 |
|
952 | ||
|
952 |
Element.findChildren = function(element, only, recursive, tagName) { |
|
953 | Element.findChildren = function(element, only, recursive, tagName) { |
|
953 | if(!element.hasChildNodes()) return null; |
|
954 | if(!element.hasChildNodes()) return null; |
|
954 | tagName = tagName.toUpperCase(); |
|
955 | tagName = tagName.toUpperCase(); |
|
955 | if(only) only = [only].flatten(); |
|
956 | if(only) only = [only].flatten(); |
|
956 | var elements = []; |
|
957 | var elements = []; |
|
957 | $A(element.childNodes).each( function(e) { |
|
958 | $A(element.childNodes).each( function(e) { |
|
958 | if(e.tagName && e.tagName.toUpperCase()==tagName && |
|
959 | if(e.tagName && e.tagName.toUpperCase()==tagName && |
|
959 | (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) |
|
960 | (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) |
|
960 | elements.push(e); |
|
961 | elements.push(e); |
|
961 | if(recursive) { |
|
962 | if(recursive) { |
|
962 | var grandchildren = Element.findChildren(e, only, recursive, tagName); |
|
963 | var grandchildren = Element.findChildren(e, only, recursive, tagName); |
|
963 | if(grandchildren) elements.push(grandchildren); |
|
964 | if(grandchildren) elements.push(grandchildren); |
|
964 | } |
|
965 | } |
|
965 | }); |
|
966 | }); |
|
966 |
|
967 | ||
|
967 | return (elements.length>0 ? elements.flatten() : []); |
|
968 | return (elements.length>0 ? elements.flatten() : []); |
|
968 | - } |
|
969 | + }; |
|
969 |
|
970 | ||
|
970 | Element.offsetSize = function (element, type) { |
|
971 | Element.offsetSize = function (element, type) { |
|
971 | return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; |
|
972 | return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; |
|
972 | - } |
|
973 | + }; No newline at end of file |
@@ -1,1120 +1,1128 | |||||
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
1 | // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|
2 | // Contributors: |
|
2 | // Contributors: |
|
3 | // Justin Palmer (http://encytemedia.com/) |
|
3 | // Justin Palmer (http://encytemedia.com/) |
|
4 | // Mark Pilgrim (http://diveintomark.org/) |
|
4 | // Mark Pilgrim (http://diveintomark.org/) |
|
5 | // Martin Bialasinki |
|
5 | // Martin Bialasinki |
|
6 |
// |
|
6 | // |
|
7 | // script.aculo.us is freely distributable under the terms of an MIT-style license. |
|
7 | // script.aculo.us is freely distributable under the terms of an MIT-style license. |
|
8 |
// For details, see the script.aculo.us web site: http://script.aculo.us/ |
|
8 | // For details, see the script.aculo.us web site: http://script.aculo.us/ |
|
9 |
|
9 | ||
|
10 |
// converts rgb() and #xxx to #xxxxxx format, |
|
10 | // converts rgb() and #xxx to #xxxxxx format, |
|
11 |
// returns self (or first argument) if not convertable |
|
11 | // returns self (or first argument) if not convertable |
|
12 |
String.prototype.parseColor = function() { |
|
12 | String.prototype.parseColor = function() { |
|
13 | var color = '#'; |
|
13 | var color = '#'; |
|
14 |
if (this.slice(0,4) == 'rgb(') { |
|
14 | if (this.slice(0,4) == 'rgb(') { |
|
15 |
var cols = this.slice(4,this.length-1).split(','); |
|
15 | var cols = this.slice(4,this.length-1).split(','); |
|
16 |
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); |
|
16 | var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); |
|
17 |
} else { |
|
17 | } else { |
|
18 |
if (this.slice(0,1) == '#') { |
|
18 | if (this.slice(0,1) == '#') { |
|
19 |
if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); |
|
19 | if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); |
|
20 |
if (this.length==7) color = this.toLowerCase(); |
|
20 | if (this.length==7) color = this.toLowerCase(); |
|
21 |
} |
|
21 | } |
|
22 |
} |
|
22 | } |
|
23 |
return (color.length==7 ? color : (arguments[0] || this)); |
|
23 | return (color.length==7 ? color : (arguments[0] || this)); |
|
24 | }; |
|
24 | }; |
|
25 |
|
25 | ||
|
26 | /*--------------------------------------------------------------------------*/ |
|
26 | /*--------------------------------------------------------------------------*/ |
|
27 |
|
27 | ||
|
28 |
Element.collectTextNodes = function(element) { |
|
28 | Element.collectTextNodes = function(element) { |
|
29 | return $A($(element).childNodes).collect( function(node) { |
|
29 | return $A($(element).childNodes).collect( function(node) { |
|
30 |
return (node.nodeType==3 ? node.nodeValue : |
|
30 | return (node.nodeType==3 ? node.nodeValue : |
|
31 | (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); |
|
31 | (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); |
|
32 | }).flatten().join(''); |
|
32 | }).flatten().join(''); |
|
33 | }; |
|
33 | }; |
|
34 |
|
34 | ||
|
35 |
Element.collectTextNodesIgnoreClass = function(element, className) { |
|
35 | Element.collectTextNodesIgnoreClass = function(element, className) { |
|
36 | return $A($(element).childNodes).collect( function(node) { |
|
36 | return $A($(element).childNodes).collect( function(node) { |
|
37 |
return (node.nodeType==3 ? node.nodeValue : |
|
37 | return (node.nodeType==3 ? node.nodeValue : |
|
38 |
((node.hasChildNodes() && !Element.hasClassName(node,className)) ? |
|
38 | ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? |
|
39 | Element.collectTextNodesIgnoreClass(node, className) : '')); |
|
39 | Element.collectTextNodesIgnoreClass(node, className) : '')); |
|
40 | }).flatten().join(''); |
|
40 | }).flatten().join(''); |
|
41 | }; |
|
41 | }; |
|
42 |
|
42 | ||
|
43 | Element.setContentZoom = function(element, percent) { |
|
43 | Element.setContentZoom = function(element, percent) { |
|
44 |
element = $(element); |
|
44 | element = $(element); |
|
45 |
element.setStyle({fontSize: (percent/100) + 'em'}); |
|
45 | element.setStyle({fontSize: (percent/100) + 'em'}); |
|
46 | if (Prototype.Browser.WebKit) window.scrollBy(0,0); |
|
46 | if (Prototype.Browser.WebKit) window.scrollBy(0,0); |
|
47 | return element; |
|
47 | return element; |
|
48 | }; |
|
48 | }; |
|
49 |
|
49 | ||
|
50 | Element.getInlineOpacity = function(element){ |
|
50 | Element.getInlineOpacity = function(element){ |
|
51 | return $(element).style.opacity || ''; |
|
51 | return $(element).style.opacity || ''; |
|
52 | }; |
|
52 | }; |
|
53 |
|
53 | ||
|
54 | Element.forceRerendering = function(element) { |
|
54 | Element.forceRerendering = function(element) { |
|
55 | try { |
|
55 | try { |
|
56 | element = $(element); |
|
56 | element = $(element); |
|
57 | var n = document.createTextNode(' '); |
|
57 | var n = document.createTextNode(' '); |
|
58 | element.appendChild(n); |
|
58 | element.appendChild(n); |
|
59 | element.removeChild(n); |
|
59 | element.removeChild(n); |
|
60 | } catch(e) { } |
|
60 | } catch(e) { } |
|
61 | }; |
|
61 | }; |
|
62 |
|
62 | ||
|
63 | /*--------------------------------------------------------------------------*/ |
|
63 | /*--------------------------------------------------------------------------*/ |
|
64 |
|
64 | ||
|
65 | var Effect = { |
|
65 | var Effect = { |
|
66 | _elementDoesNotExistError: { |
|
66 | _elementDoesNotExistError: { |
|
67 | name: 'ElementDoesNotExistError', |
|
67 | name: 'ElementDoesNotExistError', |
|
68 | message: 'The specified DOM element does not exist, but is required for this effect to operate' |
|
68 | message: 'The specified DOM element does not exist, but is required for this effect to operate' |
|
69 | }, |
|
69 | }, |
|
70 | Transitions: { |
|
70 | Transitions: { |
|
71 | linear: Prototype.K, |
|
71 | linear: Prototype.K, |
|
72 | sinoidal: function(pos) { |
|
72 | sinoidal: function(pos) { |
|
73 |
- return (-Math.cos(pos*Math.PI)/2) + |
|
73 | + return (-Math.cos(pos*Math.PI)/2) + .5; |
|
74 | }, |
|
74 | }, |
|
75 | reverse: function(pos) { |
|
75 | reverse: function(pos) { |
|
76 | return 1-pos; |
|
76 | return 1-pos; |
|
77 | }, |
|
77 | }, |
|
78 | flicker: function(pos) { |
|
78 | flicker: function(pos) { |
|
79 |
- var pos = ((-Math.cos(pos*Math.PI)/4) + |
|
79 | + var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; |
|
80 | return pos > 1 ? 1 : pos; |
|
80 | return pos > 1 ? 1 : pos; |
|
81 | }, |
|
81 | }, |
|
82 | wobble: function(pos) { |
|
82 | wobble: function(pos) { |
|
83 |
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + |
|
83 | + return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; |
|
84 | }, |
|
84 | }, |
|
85 |
pulse: function(pos, pulses) { |
|
85 | pulse: function(pos, pulses) { |
|
86 | - pulses = pulses || 5; |
|
86 | + return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; |
|
87 | - return ( |
|
||
|
88 | - ((pos % (1/pulses)) * pulses).round() == 0 ? |
|
||
|
89 | - ((pos * pulses * 2) - (pos * pulses * 2).floor()) : |
|
||
|
90 | - 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) |
|
||
|
91 | - ); |
|
||
|
92 | }, |
|
87 | }, |
|
93 |
spring: function(pos) { |
|
88 | spring: function(pos) { |
|
94 |
return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); |
|
89 | return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); |
|
95 | }, |
|
90 | }, |
|
96 | none: function(pos) { |
|
91 | none: function(pos) { |
|
97 | return 0; |
|
92 | return 0; |
|
98 | }, |
|
93 | }, |
|
99 | full: function(pos) { |
|
94 | full: function(pos) { |
|
100 | return 1; |
|
95 | return 1; |
|
101 | } |
|
96 | } |
|
102 | }, |
|
97 | }, |
|
103 | DefaultOptions: { |
|
98 | DefaultOptions: { |
|
104 | duration: 1.0, // seconds |
|
99 | duration: 1.0, // seconds |
|
105 | fps: 100, // 100= assume 66fps max. |
|
100 | fps: 100, // 100= assume 66fps max. |
|
106 | sync: false, // true for combining |
|
101 | sync: false, // true for combining |
|
107 | from: 0.0, |
|
102 | from: 0.0, |
|
108 | to: 1.0, |
|
103 | to: 1.0, |
|
109 | delay: 0.0, |
|
104 | delay: 0.0, |
|
110 | queue: 'parallel' |
|
105 | queue: 'parallel' |
|
111 | }, |
|
106 | }, |
|
112 | tagifyText: function(element) { |
|
107 | tagifyText: function(element) { |
|
113 | var tagifyStyle = 'position:relative'; |
|
108 | var tagifyStyle = 'position:relative'; |
|
114 | if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; |
|
109 | if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; |
|
115 |
|
110 | ||
|
116 | element = $(element); |
|
111 | element = $(element); |
|
117 | $A(element.childNodes).each( function(child) { |
|
112 | $A(element.childNodes).each( function(child) { |
|
118 | if (child.nodeType==3) { |
|
113 | if (child.nodeType==3) { |
|
119 | child.nodeValue.toArray().each( function(character) { |
|
114 | child.nodeValue.toArray().each( function(character) { |
|
120 | element.insertBefore( |
|
115 | element.insertBefore( |
|
121 | new Element('span', {style: tagifyStyle}).update( |
|
116 | new Element('span', {style: tagifyStyle}).update( |
|
122 |
character == ' ' ? String.fromCharCode(160) : character), |
|
117 | character == ' ' ? String.fromCharCode(160) : character), |
|
123 | child); |
|
118 | child); |
|
124 | }); |
|
119 | }); |
|
125 | Element.remove(child); |
|
120 | Element.remove(child); |
|
126 | } |
|
121 | } |
|
127 | }); |
|
122 | }); |
|
128 | }, |
|
123 | }, |
|
129 | multiple: function(element, effect) { |
|
124 | multiple: function(element, effect) { |
|
130 | var elements; |
|
125 | var elements; |
|
131 |
if (((typeof element == 'object') || |
|
126 | if (((typeof element == 'object') || |
|
132 |
Object.isFunction(element)) && |
|
127 | Object.isFunction(element)) && |
|
133 | (element.length)) |
|
128 | (element.length)) |
|
134 | elements = element; |
|
129 | elements = element; |
|
135 | else |
|
130 | else |
|
136 | elements = $(element).childNodes; |
|
131 | elements = $(element).childNodes; |
|
137 |
|
132 | ||
|
138 | var options = Object.extend({ |
|
133 | var options = Object.extend({ |
|
139 | speed: 0.1, |
|
134 | speed: 0.1, |
|
140 | delay: 0.0 |
|
135 | delay: 0.0 |
|
141 | }, arguments[2] || { }); |
|
136 | }, arguments[2] || { }); |
|
142 | var masterDelay = options.delay; |
|
137 | var masterDelay = options.delay; |
|
143 |
|
138 | ||
|
144 | $A(elements).each( function(element, index) { |
|
139 | $A(elements).each( function(element, index) { |
|
145 | new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); |
|
140 | new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); |
|
146 | }); |
|
141 | }); |
|
147 | }, |
|
142 | }, |
|
148 | PAIRS: { |
|
143 | PAIRS: { |
|
149 | 'slide': ['SlideDown','SlideUp'], |
|
144 | 'slide': ['SlideDown','SlideUp'], |
|
150 | 'blind': ['BlindDown','BlindUp'], |
|
145 | 'blind': ['BlindDown','BlindUp'], |
|
151 | 'appear': ['Appear','Fade'] |
|
146 | 'appear': ['Appear','Fade'] |
|
152 | }, |
|
147 | }, |
|
153 | toggle: function(element, effect) { |
|
148 | toggle: function(element, effect) { |
|
154 | element = $(element); |
|
149 | element = $(element); |
|
155 | effect = (effect || 'appear').toLowerCase(); |
|
150 | effect = (effect || 'appear').toLowerCase(); |
|
156 | var options = Object.extend({ |
|
151 | var options = Object.extend({ |
|
157 | queue: { position:'end', scope:(element.id || 'global'), limit: 1 } |
|
152 | queue: { position:'end', scope:(element.id || 'global'), limit: 1 } |
|
158 | }, arguments[2] || { }); |
|
153 | }, arguments[2] || { }); |
|
159 |
Effect[element.visible() ? |
|
154 | Effect[element.visible() ? |
|
160 | Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); |
|
155 | Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); |
|
161 | } |
|
156 | } |
|
162 | }; |
|
157 | }; |
|
163 |
|
158 | ||
|
164 | Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; |
|
159 | Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; |
|
165 |
|
160 | ||
|
166 | /* ------------- core effects ------------- */ |
|
161 | /* ------------- core effects ------------- */ |
|
167 |
|
162 | ||
|
168 | Effect.ScopedQueue = Class.create(Enumerable, { |
|
163 | Effect.ScopedQueue = Class.create(Enumerable, { |
|
169 | initialize: function() { |
|
164 | initialize: function() { |
|
170 | this.effects = []; |
|
165 | this.effects = []; |
|
171 |
this.interval = null; |
|
166 | this.interval = null; |
|
172 | }, |
|
167 | }, |
|
173 | _each: function(iterator) { |
|
168 | _each: function(iterator) { |
|
174 | this.effects._each(iterator); |
|
169 | this.effects._each(iterator); |
|
175 | }, |
|
170 | }, |
|
176 | add: function(effect) { |
|
171 | add: function(effect) { |
|
177 | var timestamp = new Date().getTime(); |
|
172 | var timestamp = new Date().getTime(); |
|
178 |
|
173 | ||
|
179 |
var position = Object.isString(effect.options.queue) ? |
|
174 | var position = Object.isString(effect.options.queue) ? |
|
180 | effect.options.queue : effect.options.queue.position; |
|
175 | effect.options.queue : effect.options.queue.position; |
|
181 |
|
176 | ||
|
182 | switch(position) { |
|
177 | switch(position) { |
|
183 | case 'front': |
|
178 | case 'front': |
|
184 |
// move unstarted effects after this effect |
|
179 | // move unstarted effects after this effect |
|
185 | this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { |
|
180 | this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { |
|
186 | e.startOn += effect.finishOn; |
|
181 | e.startOn += effect.finishOn; |
|
187 | e.finishOn += effect.finishOn; |
|
182 | e.finishOn += effect.finishOn; |
|
188 | }); |
|
183 | }); |
|
189 | break; |
|
184 | break; |
|
190 | case 'with-last': |
|
185 | case 'with-last': |
|
191 | timestamp = this.effects.pluck('startOn').max() || timestamp; |
|
186 | timestamp = this.effects.pluck('startOn').max() || timestamp; |
|
192 | break; |
|
187 | break; |
|
193 | case 'end': |
|
188 | case 'end': |
|
194 | // start effect after last queued effect has finished |
|
189 | // start effect after last queued effect has finished |
|
195 | timestamp = this.effects.pluck('finishOn').max() || timestamp; |
|
190 | timestamp = this.effects.pluck('finishOn').max() || timestamp; |
|
196 | break; |
|
191 | break; |
|
197 | } |
|
192 | } |
|
198 |
|
193 | ||
|
199 | effect.startOn += timestamp; |
|
194 | effect.startOn += timestamp; |
|
200 | effect.finishOn += timestamp; |
|
195 | effect.finishOn += timestamp; |
|
201 |
|
196 | ||
|
202 | if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) |
|
197 | if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) |
|
203 | this.effects.push(effect); |
|
198 | this.effects.push(effect); |
|
204 |
|
199 | ||
|
205 | if (!this.interval) |
|
200 | if (!this.interval) |
|
206 | this.interval = setInterval(this.loop.bind(this), 15); |
|
201 | this.interval = setInterval(this.loop.bind(this), 15); |
|
207 | }, |
|
202 | }, |
|
208 | remove: function(effect) { |
|
203 | remove: function(effect) { |
|
209 | this.effects = this.effects.reject(function(e) { return e==effect }); |
|
204 | this.effects = this.effects.reject(function(e) { return e==effect }); |
|
210 | if (this.effects.length == 0) { |
|
205 | if (this.effects.length == 0) { |
|
211 | clearInterval(this.interval); |
|
206 | clearInterval(this.interval); |
|
212 | this.interval = null; |
|
207 | this.interval = null; |
|
213 | } |
|
208 | } |
|
214 | }, |
|
209 | }, |
|
215 | loop: function() { |
|
210 | loop: function() { |
|
216 | var timePos = new Date().getTime(); |
|
211 | var timePos = new Date().getTime(); |
|
217 |
for(var i=0, len=this.effects.length;i<len;i++) |
|
212 | for(var i=0, len=this.effects.length;i<len;i++) |
|
218 | this.effects[i] && this.effects[i].loop(timePos); |
|
213 | this.effects[i] && this.effects[i].loop(timePos); |
|
219 | } |
|
214 | } |
|
220 | }); |
|
215 | }); |
|
221 |
|
216 | ||
|
222 | Effect.Queues = { |
|
217 | Effect.Queues = { |
|
223 | instances: $H(), |
|
218 | instances: $H(), |
|
224 | get: function(queueName) { |
|
219 | get: function(queueName) { |
|
225 | if (!Object.isString(queueName)) return queueName; |
|
220 | if (!Object.isString(queueName)) return queueName; |
|
226 |
|
221 | ||
|
227 | return this.instances.get(queueName) || |
|
222 | return this.instances.get(queueName) || |
|
228 | this.instances.set(queueName, new Effect.ScopedQueue()); |
|
223 | this.instances.set(queueName, new Effect.ScopedQueue()); |
|
229 | } |
|
224 | } |
|
230 | }; |
|
225 | }; |
|
231 | Effect.Queue = Effect.Queues.get('global'); |
|
226 | Effect.Queue = Effect.Queues.get('global'); |
|
232 |
|
227 | ||
|
233 | Effect.Base = Class.create({ |
|
228 | Effect.Base = Class.create({ |
|
234 | position: null, |
|
229 | position: null, |
|
235 | start: function(options) { |
|
230 | start: function(options) { |
|
236 | function codeForEvent(options,eventName){ |
|
231 | function codeForEvent(options,eventName){ |
|
237 | return ( |
|
232 | return ( |
|
238 | (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + |
|
233 | (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + |
|
239 | (options[eventName] ? 'this.options.'+eventName+'(this);' : '') |
|
234 | (options[eventName] ? 'this.options.'+eventName+'(this);' : '') |
|
240 | ); |
|
235 | ); |
|
241 | } |
|
236 | } |
|
242 | if (options && options.transition === false) options.transition = Effect.Transitions.linear; |
|
237 | if (options && options.transition === false) options.transition = Effect.Transitions.linear; |
|
243 | this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); |
|
238 | this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); |
|
244 | this.currentFrame = 0; |
|
239 | this.currentFrame = 0; |
|
245 | this.state = 'idle'; |
|
240 | this.state = 'idle'; |
|
246 | this.startOn = this.options.delay*1000; |
|
241 | this.startOn = this.options.delay*1000; |
|
247 | this.finishOn = this.startOn+(this.options.duration*1000); |
|
242 | this.finishOn = this.startOn+(this.options.duration*1000); |
|
248 | this.fromToDelta = this.options.to-this.options.from; |
|
243 | this.fromToDelta = this.options.to-this.options.from; |
|
249 | this.totalTime = this.finishOn-this.startOn; |
|
244 | this.totalTime = this.finishOn-this.startOn; |
|
250 | this.totalFrames = this.options.fps*this.options.duration; |
|
245 | this.totalFrames = this.options.fps*this.options.duration; |
|
251 |
|
246 | ||
|
252 |
- |
|
247 | + this.render = (function() { |
|
253 | - 'if (this.state=="idle"){this.state="running";'+ |
|
248 | + function dispatch(effect, eventName) { |
|
254 | - codeForEvent(this.options,'beforeSetup')+ |
|
249 | + if (effect.options[eventName + 'Internal']) |
|
255 | - (this.setup ? 'this.setup();':'')+ |
|
250 | + effect.options[eventName + 'Internal'](effect); |
|
256 | - codeForEvent(this.options,'afterSetup')+ |
|
251 | + if (effect.options[eventName]) |
|
257 | - '};if (this.state=="running"){'+ |
|
252 | + effect.options[eventName](effect); |
|
258 | - 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ |
|
253 | + } |
|
259 | - 'this.position=pos;'+ |
|
254 | + |
|
260 | - codeForEvent(this.options,'beforeUpdate')+ |
|
255 | + return function(pos) { |
|
261 | - (this.update ? 'this.update(pos);':'')+ |
|
256 | + if (this.state === "idle") { |
|
262 | - codeForEvent(this.options,'afterUpdate')+ |
|
257 | + this.state = "running"; |
|
263 | - '}}'); |
|
258 | + dispatch(this, 'beforeSetup'); |
|
|
259 | + if (this.setup) this.setup(); | ||
|
|
260 | + dispatch(this, 'afterSetup'); | ||
|
|
261 | + } | ||
|
|
262 | + if (this.state === "running") { | ||
|
|
263 | + pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; | ||
|
|
264 | + this.position = pos; | ||
|
|
265 | + dispatch(this, 'beforeUpdate'); | ||
|
|
266 | + if (this.update) this.update(pos); | ||
|
|
267 | + dispatch(this, 'afterUpdate'); | ||
|
|
268 | + } | ||
|
|
269 | + }; | ||
|
|
270 | + })(); | ||
|
264 |
|
271 | ||
|
265 | this.event('beforeStart'); |
|
272 | this.event('beforeStart'); |
|
266 | if (!this.options.sync) |
|
273 | if (!this.options.sync) |
|
267 |
Effect.Queues.get(Object.isString(this.options.queue) ? |
|
274 | Effect.Queues.get(Object.isString(this.options.queue) ? |
|
268 | 'global' : this.options.queue.scope).add(this); |
|
275 | 'global' : this.options.queue.scope).add(this); |
|
269 | }, |
|
276 | }, |
|
270 | loop: function(timePos) { |
|
277 | loop: function(timePos) { |
|
271 | if (timePos >= this.startOn) { |
|
278 | if (timePos >= this.startOn) { |
|
272 | if (timePos >= this.finishOn) { |
|
279 | if (timePos >= this.finishOn) { |
|
273 | this.render(1.0); |
|
280 | this.render(1.0); |
|
274 | this.cancel(); |
|
281 | this.cancel(); |
|
275 | this.event('beforeFinish'); |
|
282 | this.event('beforeFinish'); |
|
276 |
if (this.finish) this.finish(); |
|
283 | if (this.finish) this.finish(); |
|
277 | this.event('afterFinish'); |
|
284 | this.event('afterFinish'); |
|
278 |
return; |
|
285 | return; |
|
279 | } |
|
286 | } |
|
280 | var pos = (timePos - this.startOn) / this.totalTime, |
|
287 | var pos = (timePos - this.startOn) / this.totalTime, |
|
281 | frame = (pos * this.totalFrames).round(); |
|
288 | frame = (pos * this.totalFrames).round(); |
|
282 | if (frame > this.currentFrame) { |
|
289 | if (frame > this.currentFrame) { |
|
283 | this.render(pos); |
|
290 | this.render(pos); |
|
284 | this.currentFrame = frame; |
|
291 | this.currentFrame = frame; |
|
285 | } |
|
292 | } |
|
286 | } |
|
293 | } |
|
287 | }, |
|
294 | }, |
|
288 | cancel: function() { |
|
295 | cancel: function() { |
|
289 | if (!this.options.sync) |
|
296 | if (!this.options.sync) |
|
290 |
Effect.Queues.get(Object.isString(this.options.queue) ? |
|
297 | Effect.Queues.get(Object.isString(this.options.queue) ? |
|
291 | 'global' : this.options.queue.scope).remove(this); |
|
298 | 'global' : this.options.queue.scope).remove(this); |
|
292 | this.state = 'finished'; |
|
299 | this.state = 'finished'; |
|
293 | }, |
|
300 | }, |
|
294 | event: function(eventName) { |
|
301 | event: function(eventName) { |
|
295 | if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); |
|
302 | if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); |
|
296 | if (this.options[eventName]) this.options[eventName](this); |
|
303 | if (this.options[eventName]) this.options[eventName](this); |
|
297 | }, |
|
304 | }, |
|
298 | inspect: function() { |
|
305 | inspect: function() { |
|
299 | var data = $H(); |
|
306 | var data = $H(); |
|
300 | for(property in this) |
|
307 | for(property in this) |
|
301 | if (!Object.isFunction(this[property])) data.set(property, this[property]); |
|
308 | if (!Object.isFunction(this[property])) data.set(property, this[property]); |
|
302 | return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; |
|
309 | return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; |
|
303 | } |
|
310 | } |
|
304 | }); |
|
311 | }); |
|
305 |
|
312 | ||
|
306 | Effect.Parallel = Class.create(Effect.Base, { |
|
313 | Effect.Parallel = Class.create(Effect.Base, { |
|
307 | initialize: function(effects) { |
|
314 | initialize: function(effects) { |
|
308 | this.effects = effects || []; |
|
315 | this.effects = effects || []; |
|
309 | this.start(arguments[1]); |
|
316 | this.start(arguments[1]); |
|
310 | }, |
|
317 | }, |
|
311 | update: function(position) { |
|
318 | update: function(position) { |
|
312 | this.effects.invoke('render', position); |
|
319 | this.effects.invoke('render', position); |
|
313 | }, |
|
320 | }, |
|
314 | finish: function(position) { |
|
321 | finish: function(position) { |
|
315 | this.effects.each( function(effect) { |
|
322 | this.effects.each( function(effect) { |
|
316 | effect.render(1.0); |
|
323 | effect.render(1.0); |
|
317 | effect.cancel(); |
|
324 | effect.cancel(); |
|
318 | effect.event('beforeFinish'); |
|
325 | effect.event('beforeFinish'); |
|
319 | if (effect.finish) effect.finish(position); |
|
326 | if (effect.finish) effect.finish(position); |
|
320 | effect.event('afterFinish'); |
|
327 | effect.event('afterFinish'); |
|
321 | }); |
|
328 | }); |
|
322 | } |
|
329 | } |
|
323 | }); |
|
330 | }); |
|
324 |
|
331 | ||
|
325 | Effect.Tween = Class.create(Effect.Base, { |
|
332 | Effect.Tween = Class.create(Effect.Base, { |
|
326 | initialize: function(object, from, to) { |
|
333 | initialize: function(object, from, to) { |
|
327 | object = Object.isString(object) ? $(object) : object; |
|
334 | object = Object.isString(object) ? $(object) : object; |
|
328 |
var args = $A(arguments), method = args.last(), |
|
335 | var args = $A(arguments), method = args.last(), |
|
329 | options = args.length == 5 ? args[3] : null; |
|
336 | options = args.length == 5 ? args[3] : null; |
|
330 | this.method = Object.isFunction(method) ? method.bind(object) : |
|
337 | this.method = Object.isFunction(method) ? method.bind(object) : |
|
331 |
Object.isFunction(object[method]) ? object[method].bind(object) : |
|
338 | Object.isFunction(object[method]) ? object[method].bind(object) : |
|
332 | function(value) { object[method] = value }; |
|
339 | function(value) { object[method] = value }; |
|
333 | this.start(Object.extend({ from: from, to: to }, options || { })); |
|
340 | this.start(Object.extend({ from: from, to: to }, options || { })); |
|
334 | }, |
|
341 | }, |
|
335 | update: function(position) { |
|
342 | update: function(position) { |
|
336 | this.method(position); |
|
343 | this.method(position); |
|
337 | } |
|
344 | } |
|
338 | }); |
|
345 | }); |
|
339 |
|
346 | ||
|
340 | Effect.Event = Class.create(Effect.Base, { |
|
347 | Effect.Event = Class.create(Effect.Base, { |
|
341 | initialize: function() { |
|
348 | initialize: function() { |
|
342 | this.start(Object.extend({ duration: 0 }, arguments[0] || { })); |
|
349 | this.start(Object.extend({ duration: 0 }, arguments[0] || { })); |
|
343 | }, |
|
350 | }, |
|
344 | update: Prototype.emptyFunction |
|
351 | update: Prototype.emptyFunction |
|
345 | }); |
|
352 | }); |
|
346 |
|
353 | ||
|
347 | Effect.Opacity = Class.create(Effect.Base, { |
|
354 | Effect.Opacity = Class.create(Effect.Base, { |
|
348 | initialize: function(element) { |
|
355 | initialize: function(element) { |
|
349 | this.element = $(element); |
|
356 | this.element = $(element); |
|
350 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
357 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
351 | // make this work on IE on elements without 'layout' |
|
358 | // make this work on IE on elements without 'layout' |
|
352 | if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) |
|
359 | if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) |
|
353 | this.element.setStyle({zoom: 1}); |
|
360 | this.element.setStyle({zoom: 1}); |
|
354 | var options = Object.extend({ |
|
361 | var options = Object.extend({ |
|
355 | from: this.element.getOpacity() || 0.0, |
|
362 | from: this.element.getOpacity() || 0.0, |
|
356 | to: 1.0 |
|
363 | to: 1.0 |
|
357 | }, arguments[1] || { }); |
|
364 | }, arguments[1] || { }); |
|
358 | this.start(options); |
|
365 | this.start(options); |
|
359 | }, |
|
366 | }, |
|
360 | update: function(position) { |
|
367 | update: function(position) { |
|
361 | this.element.setOpacity(position); |
|
368 | this.element.setOpacity(position); |
|
362 | } |
|
369 | } |
|
363 | }); |
|
370 | }); |
|
364 |
|
371 | ||
|
365 | Effect.Move = Class.create(Effect.Base, { |
|
372 | Effect.Move = Class.create(Effect.Base, { |
|
366 | initialize: function(element) { |
|
373 | initialize: function(element) { |
|
367 | this.element = $(element); |
|
374 | this.element = $(element); |
|
368 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
375 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
369 | var options = Object.extend({ |
|
376 | var options = Object.extend({ |
|
370 | x: 0, |
|
377 | x: 0, |
|
371 | y: 0, |
|
378 | y: 0, |
|
372 | mode: 'relative' |
|
379 | mode: 'relative' |
|
373 | }, arguments[1] || { }); |
|
380 | }, arguments[1] || { }); |
|
374 | this.start(options); |
|
381 | this.start(options); |
|
375 | }, |
|
382 | }, |
|
376 | setup: function() { |
|
383 | setup: function() { |
|
377 | this.element.makePositioned(); |
|
384 | this.element.makePositioned(); |
|
378 | this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); |
|
385 | this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); |
|
379 | this.originalTop = parseFloat(this.element.getStyle('top') || '0'); |
|
386 | this.originalTop = parseFloat(this.element.getStyle('top') || '0'); |
|
380 | if (this.options.mode == 'absolute') { |
|
387 | if (this.options.mode == 'absolute') { |
|
381 | this.options.x = this.options.x - this.originalLeft; |
|
388 | this.options.x = this.options.x - this.originalLeft; |
|
382 | this.options.y = this.options.y - this.originalTop; |
|
389 | this.options.y = this.options.y - this.originalTop; |
|
383 | } |
|
390 | } |
|
384 | }, |
|
391 | }, |
|
385 | update: function(position) { |
|
392 | update: function(position) { |
|
386 | this.element.setStyle({ |
|
393 | this.element.setStyle({ |
|
387 | left: (this.options.x * position + this.originalLeft).round() + 'px', |
|
394 | left: (this.options.x * position + this.originalLeft).round() + 'px', |
|
388 | top: (this.options.y * position + this.originalTop).round() + 'px' |
|
395 | top: (this.options.y * position + this.originalTop).round() + 'px' |
|
389 | }); |
|
396 | }); |
|
390 | } |
|
397 | } |
|
391 | }); |
|
398 | }); |
|
392 |
|
399 | ||
|
393 | // for backwards compatibility |
|
400 | // for backwards compatibility |
|
394 | Effect.MoveBy = function(element, toTop, toLeft) { |
|
401 | Effect.MoveBy = function(element, toTop, toLeft) { |
|
395 |
return new Effect.Move(element, |
|
402 | return new Effect.Move(element, |
|
396 | Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); |
|
403 | Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); |
|
397 | }; |
|
404 | }; |
|
398 |
|
405 | ||
|
399 | Effect.Scale = Class.create(Effect.Base, { |
|
406 | Effect.Scale = Class.create(Effect.Base, { |
|
400 | initialize: function(element, percent) { |
|
407 | initialize: function(element, percent) { |
|
401 | this.element = $(element); |
|
408 | this.element = $(element); |
|
402 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
409 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
403 | var options = Object.extend({ |
|
410 | var options = Object.extend({ |
|
404 | scaleX: true, |
|
411 | scaleX: true, |
|
405 | scaleY: true, |
|
412 | scaleY: true, |
|
406 | scaleContent: true, |
|
413 | scaleContent: true, |
|
407 | scaleFromCenter: false, |
|
414 | scaleFromCenter: false, |
|
408 | scaleMode: 'box', // 'box' or 'contents' or { } with provided values |
|
415 | scaleMode: 'box', // 'box' or 'contents' or { } with provided values |
|
409 | scaleFrom: 100.0, |
|
416 | scaleFrom: 100.0, |
|
410 | scaleTo: percent |
|
417 | scaleTo: percent |
|
411 | }, arguments[2] || { }); |
|
418 | }, arguments[2] || { }); |
|
412 | this.start(options); |
|
419 | this.start(options); |
|
413 | }, |
|
420 | }, |
|
414 | setup: function() { |
|
421 | setup: function() { |
|
415 | this.restoreAfterFinish = this.options.restoreAfterFinish || false; |
|
422 | this.restoreAfterFinish = this.options.restoreAfterFinish || false; |
|
416 | this.elementPositioning = this.element.getStyle('position'); |
|
423 | this.elementPositioning = this.element.getStyle('position'); |
|
417 |
|
424 | ||
|
418 | this.originalStyle = { }; |
|
425 | this.originalStyle = { }; |
|
419 | ['top','left','width','height','fontSize'].each( function(k) { |
|
426 | ['top','left','width','height','fontSize'].each( function(k) { |
|
420 | this.originalStyle[k] = this.element.style[k]; |
|
427 | this.originalStyle[k] = this.element.style[k]; |
|
421 | }.bind(this)); |
|
428 | }.bind(this)); |
|
422 |
|
429 | ||
|
423 | this.originalTop = this.element.offsetTop; |
|
430 | this.originalTop = this.element.offsetTop; |
|
424 | this.originalLeft = this.element.offsetLeft; |
|
431 | this.originalLeft = this.element.offsetLeft; |
|
425 |
|
432 | ||
|
426 | var fontSize = this.element.getStyle('font-size') || '100%'; |
|
433 | var fontSize = this.element.getStyle('font-size') || '100%'; |
|
427 | ['em','px','%','pt'].each( function(fontSizeType) { |
|
434 | ['em','px','%','pt'].each( function(fontSizeType) { |
|
428 | if (fontSize.indexOf(fontSizeType)>0) { |
|
435 | if (fontSize.indexOf(fontSizeType)>0) { |
|
429 | this.fontSize = parseFloat(fontSize); |
|
436 | this.fontSize = parseFloat(fontSize); |
|
430 | this.fontSizeType = fontSizeType; |
|
437 | this.fontSizeType = fontSizeType; |
|
431 | } |
|
438 | } |
|
432 | }.bind(this)); |
|
439 | }.bind(this)); |
|
433 |
|
440 | ||
|
434 | this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; |
|
441 | this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; |
|
435 |
|
442 | ||
|
436 | this.dims = null; |
|
443 | this.dims = null; |
|
437 | if (this.options.scaleMode=='box') |
|
444 | if (this.options.scaleMode=='box') |
|
438 | this.dims = [this.element.offsetHeight, this.element.offsetWidth]; |
|
445 | this.dims = [this.element.offsetHeight, this.element.offsetWidth]; |
|
439 | if (/^content/.test(this.options.scaleMode)) |
|
446 | if (/^content/.test(this.options.scaleMode)) |
|
440 | this.dims = [this.element.scrollHeight, this.element.scrollWidth]; |
|
447 | this.dims = [this.element.scrollHeight, this.element.scrollWidth]; |
|
441 | if (!this.dims) |
|
448 | if (!this.dims) |
|
442 | this.dims = [this.options.scaleMode.originalHeight, |
|
449 | this.dims = [this.options.scaleMode.originalHeight, |
|
443 | this.options.scaleMode.originalWidth]; |
|
450 | this.options.scaleMode.originalWidth]; |
|
444 | }, |
|
451 | }, |
|
445 | update: function(position) { |
|
452 | update: function(position) { |
|
446 | var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); |
|
453 | var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); |
|
447 | if (this.options.scaleContent && this.fontSize) |
|
454 | if (this.options.scaleContent && this.fontSize) |
|
448 | this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); |
|
455 | this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); |
|
449 | this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); |
|
456 | this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); |
|
450 | }, |
|
457 | }, |
|
451 | finish: function(position) { |
|
458 | finish: function(position) { |
|
452 | if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); |
|
459 | if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); |
|
453 | }, |
|
460 | }, |
|
454 | setDimensions: function(height, width) { |
|
461 | setDimensions: function(height, width) { |
|
455 | var d = { }; |
|
462 | var d = { }; |
|
456 | if (this.options.scaleX) d.width = width.round() + 'px'; |
|
463 | if (this.options.scaleX) d.width = width.round() + 'px'; |
|
457 | if (this.options.scaleY) d.height = height.round() + 'px'; |
|
464 | if (this.options.scaleY) d.height = height.round() + 'px'; |
|
458 | if (this.options.scaleFromCenter) { |
|
465 | if (this.options.scaleFromCenter) { |
|
459 | var topd = (height - this.dims[0])/2; |
|
466 | var topd = (height - this.dims[0])/2; |
|
460 | var leftd = (width - this.dims[1])/2; |
|
467 | var leftd = (width - this.dims[1])/2; |
|
461 | if (this.elementPositioning == 'absolute') { |
|
468 | if (this.elementPositioning == 'absolute') { |
|
462 | if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; |
|
469 | if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; |
|
463 | if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; |
|
470 | if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; |
|
464 | } else { |
|
471 | } else { |
|
465 | if (this.options.scaleY) d.top = -topd + 'px'; |
|
472 | if (this.options.scaleY) d.top = -topd + 'px'; |
|
466 | if (this.options.scaleX) d.left = -leftd + 'px'; |
|
473 | if (this.options.scaleX) d.left = -leftd + 'px'; |
|
467 | } |
|
474 | } |
|
468 | } |
|
475 | } |
|
469 | this.element.setStyle(d); |
|
476 | this.element.setStyle(d); |
|
470 | } |
|
477 | } |
|
471 | }); |
|
478 | }); |
|
472 |
|
479 | ||
|
473 | Effect.Highlight = Class.create(Effect.Base, { |
|
480 | Effect.Highlight = Class.create(Effect.Base, { |
|
474 | initialize: function(element) { |
|
481 | initialize: function(element) { |
|
475 | this.element = $(element); |
|
482 | this.element = $(element); |
|
476 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
483 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
477 | var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); |
|
484 | var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); |
|
478 | this.start(options); |
|
485 | this.start(options); |
|
479 | }, |
|
486 | }, |
|
480 | setup: function() { |
|
487 | setup: function() { |
|
481 | // Prevent executing on elements not in the layout flow |
|
488 | // Prevent executing on elements not in the layout flow |
|
482 | if (this.element.getStyle('display')=='none') { this.cancel(); return; } |
|
489 | if (this.element.getStyle('display')=='none') { this.cancel(); return; } |
|
483 | // Disable background image during the effect |
|
490 | // Disable background image during the effect |
|
484 | this.oldStyle = { }; |
|
491 | this.oldStyle = { }; |
|
485 | if (!this.options.keepBackgroundImage) { |
|
492 | if (!this.options.keepBackgroundImage) { |
|
486 | this.oldStyle.backgroundImage = this.element.getStyle('background-image'); |
|
493 | this.oldStyle.backgroundImage = this.element.getStyle('background-image'); |
|
487 | this.element.setStyle({backgroundImage: 'none'}); |
|
494 | this.element.setStyle({backgroundImage: 'none'}); |
|
488 | } |
|
495 | } |
|
489 | if (!this.options.endcolor) |
|
496 | if (!this.options.endcolor) |
|
490 | this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); |
|
497 | this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); |
|
491 | if (!this.options.restorecolor) |
|
498 | if (!this.options.restorecolor) |
|
492 | this.options.restorecolor = this.element.getStyle('background-color'); |
|
499 | this.options.restorecolor = this.element.getStyle('background-color'); |
|
493 | // init color calculations |
|
500 | // init color calculations |
|
494 | this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); |
|
501 | this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); |
|
495 | 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)); |
|
502 | 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)); |
|
496 | }, |
|
503 | }, |
|
497 | update: function(position) { |
|
504 | update: function(position) { |
|
498 | this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ |
|
505 | this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ |
|
499 | return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); |
|
506 | return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); |
|
500 | }, |
|
507 | }, |
|
501 | finish: function() { |
|
508 | finish: function() { |
|
502 | this.element.setStyle(Object.extend(this.oldStyle, { |
|
509 | this.element.setStyle(Object.extend(this.oldStyle, { |
|
503 | backgroundColor: this.options.restorecolor |
|
510 | backgroundColor: this.options.restorecolor |
|
504 | })); |
|
511 | })); |
|
505 | } |
|
512 | } |
|
506 | }); |
|
513 | }); |
|
507 |
|
514 | ||
|
508 | Effect.ScrollTo = function(element) { |
|
515 | Effect.ScrollTo = function(element) { |
|
509 | var options = arguments[1] || { }, |
|
516 | var options = arguments[1] || { }, |
|
510 |
|
|
517 | scrollOffsets = document.viewport.getScrollOffsets(), |
|
511 |
- |
|
518 | + elementOffsets = $(element).cumulativeOffset(); |
|
512 | - max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); |
|
||
|
513 |
|
519 | ||
|
514 | if (options.offset) elementOffsets[1] += options.offset; |
|
520 | if (options.offset) elementOffsets[1] += options.offset; |
|
515 |
|
521 | ||
|
516 | return new Effect.Tween(null, |
|
522 | return new Effect.Tween(null, |
|
517 | scrollOffsets.top, |
|
523 | scrollOffsets.top, |
|
518 | - elementOffsets[1] > max ? max : elementOffsets[1], |
|
524 | + elementOffsets[1], |
|
519 | options, |
|
525 | options, |
|
520 | - function(p){ scrollTo(scrollOffsets.left, p.round()) } |
|
526 | + function(p){ scrollTo(scrollOffsets.left, p.round()); } |
|
521 | ); |
|
527 | ); |
|
522 | }; |
|
528 | }; |
|
523 |
|
529 | ||
|
524 | /* ------------- combination effects ------------- */ |
|
530 | /* ------------- combination effects ------------- */ |
|
525 |
|
531 | ||
|
526 | Effect.Fade = function(element) { |
|
532 | Effect.Fade = function(element) { |
|
527 | element = $(element); |
|
533 | element = $(element); |
|
528 | var oldOpacity = element.getInlineOpacity(); |
|
534 | var oldOpacity = element.getInlineOpacity(); |
|
529 | var options = Object.extend({ |
|
535 | var options = Object.extend({ |
|
530 | from: element.getOpacity() || 1.0, |
|
536 | from: element.getOpacity() || 1.0, |
|
531 | to: 0.0, |
|
537 | to: 0.0, |
|
532 |
afterFinishInternal: function(effect) { |
|
538 | afterFinishInternal: function(effect) { |
|
533 | if (effect.options.to!=0) return; |
|
539 | if (effect.options.to!=0) return; |
|
534 |
effect.element.hide().setStyle({opacity: oldOpacity}); |
|
540 | effect.element.hide().setStyle({opacity: oldOpacity}); |
|
535 | } |
|
541 | } |
|
536 | }, arguments[1] || { }); |
|
542 | }, arguments[1] || { }); |
|
537 | return new Effect.Opacity(element,options); |
|
543 | return new Effect.Opacity(element,options); |
|
538 | }; |
|
544 | }; |
|
539 |
|
545 | ||
|
540 | Effect.Appear = function(element) { |
|
546 | Effect.Appear = function(element) { |
|
541 | element = $(element); |
|
547 | element = $(element); |
|
542 | var options = Object.extend({ |
|
548 | var options = Object.extend({ |
|
543 | from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), |
|
549 | from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), |
|
544 | to: 1.0, |
|
550 | to: 1.0, |
|
545 | // force Safari to render floated elements properly |
|
551 | // force Safari to render floated elements properly |
|
546 | afterFinishInternal: function(effect) { |
|
552 | afterFinishInternal: function(effect) { |
|
547 | effect.element.forceRerendering(); |
|
553 | effect.element.forceRerendering(); |
|
548 | }, |
|
554 | }, |
|
549 | beforeSetup: function(effect) { |
|
555 | beforeSetup: function(effect) { |
|
550 |
effect.element.setOpacity(effect.options.from).show(); |
|
556 | effect.element.setOpacity(effect.options.from).show(); |
|
551 | }}, arguments[1] || { }); |
|
557 | }}, arguments[1] || { }); |
|
552 | return new Effect.Opacity(element,options); |
|
558 | return new Effect.Opacity(element,options); |
|
553 | }; |
|
559 | }; |
|
554 |
|
560 | ||
|
555 | Effect.Puff = function(element) { |
|
561 | Effect.Puff = function(element) { |
|
556 | element = $(element); |
|
562 | element = $(element); |
|
557 |
var oldStyle = { |
|
563 | var oldStyle = { |
|
558 |
opacity: element.getInlineOpacity(), |
|
564 | opacity: element.getInlineOpacity(), |
|
559 | position: element.getStyle('position'), |
|
565 | position: element.getStyle('position'), |
|
560 | top: element.style.top, |
|
566 | top: element.style.top, |
|
561 | left: element.style.left, |
|
567 | left: element.style.left, |
|
562 | width: element.style.width, |
|
568 | width: element.style.width, |
|
563 | height: element.style.height |
|
569 | height: element.style.height |
|
564 | }; |
|
570 | }; |
|
565 | return new Effect.Parallel( |
|
571 | return new Effect.Parallel( |
|
566 |
[ new Effect.Scale(element, 200, |
|
572 | [ new Effect.Scale(element, 200, |
|
567 |
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), |
|
573 | { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), |
|
568 |
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], |
|
574 | new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], |
|
569 |
Object.extend({ duration: 1.0, |
|
575 | Object.extend({ duration: 1.0, |
|
570 | beforeSetupInternal: function(effect) { |
|
576 | beforeSetupInternal: function(effect) { |
|
571 | - Position.absolutize(effect.effects[0].element) |
|
577 | + Position.absolutize(effect.effects[0].element); |
|
572 | }, |
|
578 | }, |
|
573 | afterFinishInternal: function(effect) { |
|
579 | afterFinishInternal: function(effect) { |
|
574 | effect.effects[0].element.hide().setStyle(oldStyle); } |
|
580 | effect.effects[0].element.hide().setStyle(oldStyle); } |
|
575 | }, arguments[1] || { }) |
|
581 | }, arguments[1] || { }) |
|
576 | ); |
|
582 | ); |
|
577 | }; |
|
583 | }; |
|
578 |
|
584 | ||
|
579 | Effect.BlindUp = function(element) { |
|
585 | Effect.BlindUp = function(element) { |
|
580 | element = $(element); |
|
586 | element = $(element); |
|
581 | element.makeClipping(); |
|
587 | element.makeClipping(); |
|
582 | return new Effect.Scale(element, 0, |
|
588 | return new Effect.Scale(element, 0, |
|
583 |
Object.extend({ scaleContent: false, |
|
589 | Object.extend({ scaleContent: false, |
|
584 |
scaleX: false, |
|
590 | scaleX: false, |
|
585 | restoreAfterFinish: true, |
|
591 | restoreAfterFinish: true, |
|
586 | afterFinishInternal: function(effect) { |
|
592 | afterFinishInternal: function(effect) { |
|
587 | effect.element.hide().undoClipping(); |
|
593 | effect.element.hide().undoClipping(); |
|
588 |
} |
|
594 | } |
|
589 | }, arguments[1] || { }) |
|
595 | }, arguments[1] || { }) |
|
590 | ); |
|
596 | ); |
|
591 | }; |
|
597 | }; |
|
592 |
|
598 | ||
|
593 | Effect.BlindDown = function(element) { |
|
599 | Effect.BlindDown = function(element) { |
|
594 | element = $(element); |
|
600 | element = $(element); |
|
595 | var elementDimensions = element.getDimensions(); |
|
601 | var elementDimensions = element.getDimensions(); |
|
596 |
return new Effect.Scale(element, 100, Object.extend({ |
|
602 | return new Effect.Scale(element, 100, Object.extend({ |
|
597 |
scaleContent: false, |
|
603 | scaleContent: false, |
|
598 | scaleX: false, |
|
604 | scaleX: false, |
|
599 | scaleFrom: 0, |
|
605 | scaleFrom: 0, |
|
600 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
606 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
601 | restoreAfterFinish: true, |
|
607 | restoreAfterFinish: true, |
|
602 | afterSetup: function(effect) { |
|
608 | afterSetup: function(effect) { |
|
603 |
effect.element.makeClipping().setStyle({height: '0px'}).show(); |
|
609 | effect.element.makeClipping().setStyle({height: '0px'}).show(); |
|
604 |
}, |
|
610 | }, |
|
605 | afterFinishInternal: function(effect) { |
|
611 | afterFinishInternal: function(effect) { |
|
606 | effect.element.undoClipping(); |
|
612 | effect.element.undoClipping(); |
|
607 | } |
|
613 | } |
|
608 | }, arguments[1] || { })); |
|
614 | }, arguments[1] || { })); |
|
609 | }; |
|
615 | }; |
|
610 |
|
616 | ||
|
611 | Effect.SwitchOff = function(element) { |
|
617 | Effect.SwitchOff = function(element) { |
|
612 | element = $(element); |
|
618 | element = $(element); |
|
613 | var oldOpacity = element.getInlineOpacity(); |
|
619 | var oldOpacity = element.getInlineOpacity(); |
|
614 | return new Effect.Appear(element, Object.extend({ |
|
620 | return new Effect.Appear(element, Object.extend({ |
|
615 | duration: 0.4, |
|
621 | duration: 0.4, |
|
616 | from: 0, |
|
622 | from: 0, |
|
617 | transition: Effect.Transitions.flicker, |
|
623 | transition: Effect.Transitions.flicker, |
|
618 | afterFinishInternal: function(effect) { |
|
624 | afterFinishInternal: function(effect) { |
|
619 |
new Effect.Scale(effect.element, 1, { |
|
625 | new Effect.Scale(effect.element, 1, { |
|
620 | duration: 0.3, scaleFromCenter: true, |
|
626 | duration: 0.3, scaleFromCenter: true, |
|
621 | scaleX: false, scaleContent: false, restoreAfterFinish: true, |
|
627 | scaleX: false, scaleContent: false, restoreAfterFinish: true, |
|
622 |
beforeSetup: function(effect) { |
|
628 | beforeSetup: function(effect) { |
|
623 | effect.element.makePositioned().makeClipping(); |
|
629 | effect.element.makePositioned().makeClipping(); |
|
624 | }, |
|
630 | }, |
|
625 | afterFinishInternal: function(effect) { |
|
631 | afterFinishInternal: function(effect) { |
|
626 | effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); |
|
632 | effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); |
|
627 | } |
|
633 | } |
|
628 | - }) |
|
634 | + }); |
|
629 | } |
|
635 | } |
|
630 | }, arguments[1] || { })); |
|
636 | }, arguments[1] || { })); |
|
631 | }; |
|
637 | }; |
|
632 |
|
638 | ||
|
633 | Effect.DropOut = function(element) { |
|
639 | Effect.DropOut = function(element) { |
|
634 | element = $(element); |
|
640 | element = $(element); |
|
635 | var oldStyle = { |
|
641 | var oldStyle = { |
|
636 | top: element.getStyle('top'), |
|
642 | top: element.getStyle('top'), |
|
637 | left: element.getStyle('left'), |
|
643 | left: element.getStyle('left'), |
|
638 | opacity: element.getInlineOpacity() }; |
|
644 | opacity: element.getInlineOpacity() }; |
|
639 | return new Effect.Parallel( |
|
645 | return new Effect.Parallel( |
|
640 |
[ new Effect.Move(element, {x: 0, y: 100, sync: true }), |
|
646 | [ new Effect.Move(element, {x: 0, y: 100, sync: true }), |
|
641 | new Effect.Opacity(element, { sync: true, to: 0.0 }) ], |
|
647 | new Effect.Opacity(element, { sync: true, to: 0.0 }) ], |
|
642 | Object.extend( |
|
648 | Object.extend( |
|
643 | { duration: 0.5, |
|
649 | { duration: 0.5, |
|
644 | beforeSetup: function(effect) { |
|
650 | beforeSetup: function(effect) { |
|
645 |
effect.effects[0].element.makePositioned(); |
|
651 | effect.effects[0].element.makePositioned(); |
|
646 | }, |
|
652 | }, |
|
647 | afterFinishInternal: function(effect) { |
|
653 | afterFinishInternal: function(effect) { |
|
648 | effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); |
|
654 | effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); |
|
649 |
} |
|
655 | } |
|
650 | }, arguments[1] || { })); |
|
656 | }, arguments[1] || { })); |
|
651 | }; |
|
657 | }; |
|
652 |
|
658 | ||
|
653 | Effect.Shake = function(element) { |
|
659 | Effect.Shake = function(element) { |
|
654 | element = $(element); |
|
660 | element = $(element); |
|
655 | var options = Object.extend({ |
|
661 | var options = Object.extend({ |
|
656 | distance: 20, |
|
662 | distance: 20, |
|
657 | duration: 0.5 |
|
663 | duration: 0.5 |
|
658 | }, arguments[1] || {}); |
|
664 | }, arguments[1] || {}); |
|
659 | var distance = parseFloat(options.distance); |
|
665 | var distance = parseFloat(options.distance); |
|
660 | var split = parseFloat(options.duration) / 10.0; |
|
666 | var split = parseFloat(options.duration) / 10.0; |
|
661 | var oldStyle = { |
|
667 | var oldStyle = { |
|
662 | top: element.getStyle('top'), |
|
668 | top: element.getStyle('top'), |
|
663 | left: element.getStyle('left') }; |
|
669 | left: element.getStyle('left') }; |
|
664 | return new Effect.Move(element, |
|
670 | return new Effect.Move(element, |
|
665 | { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { |
|
671 | { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { |
|
666 | new Effect.Move(effect.element, |
|
672 | new Effect.Move(effect.element, |
|
667 | { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
673 | { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
668 | new Effect.Move(effect.element, |
|
674 | new Effect.Move(effect.element, |
|
669 | { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
675 | { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
670 | new Effect.Move(effect.element, |
|
676 | new Effect.Move(effect.element, |
|
671 | { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
677 | { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
672 | new Effect.Move(effect.element, |
|
678 | new Effect.Move(effect.element, |
|
673 | { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
679 | { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { |
|
674 | new Effect.Move(effect.element, |
|
680 | new Effect.Move(effect.element, |
|
675 | { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { |
|
681 | { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { |
|
676 | effect.element.undoPositioned().setStyle(oldStyle); |
|
682 | effect.element.undoPositioned().setStyle(oldStyle); |
|
677 | - }}) }}) }}) }}) }}) }}); |
|
683 | + }}); }}); }}); }}); }}); }}); |
|
678 | }; |
|
684 | }; |
|
679 |
|
685 | ||
|
680 | Effect.SlideDown = function(element) { |
|
686 | Effect.SlideDown = function(element) { |
|
681 | element = $(element).cleanWhitespace(); |
|
687 | element = $(element).cleanWhitespace(); |
|
682 | // SlideDown need to have the content of the element wrapped in a container element with fixed height! |
|
688 | // SlideDown need to have the content of the element wrapped in a container element with fixed height! |
|
683 | var oldInnerBottom = element.down().getStyle('bottom'); |
|
689 | var oldInnerBottom = element.down().getStyle('bottom'); |
|
684 | var elementDimensions = element.getDimensions(); |
|
690 | var elementDimensions = element.getDimensions(); |
|
685 |
return new Effect.Scale(element, 100, Object.extend({ |
|
691 | return new Effect.Scale(element, 100, Object.extend({ |
|
686 |
scaleContent: false, |
|
692 | scaleContent: false, |
|
687 |
scaleX: false, |
|
693 | scaleX: false, |
|
688 | scaleFrom: window.opera ? 0 : 1, |
|
694 | scaleFrom: window.opera ? 0 : 1, |
|
689 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
695 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
690 | restoreAfterFinish: true, |
|
696 | restoreAfterFinish: true, |
|
691 | afterSetup: function(effect) { |
|
697 | afterSetup: function(effect) { |
|
692 | effect.element.makePositioned(); |
|
698 | effect.element.makePositioned(); |
|
693 | effect.element.down().makePositioned(); |
|
699 | effect.element.down().makePositioned(); |
|
694 | if (window.opera) effect.element.setStyle({top: ''}); |
|
700 | if (window.opera) effect.element.setStyle({top: ''}); |
|
695 |
effect.element.makeClipping().setStyle({height: '0px'}).show(); |
|
701 | effect.element.makeClipping().setStyle({height: '0px'}).show(); |
|
696 | }, |
|
702 | }, |
|
697 | afterUpdateInternal: function(effect) { |
|
703 | afterUpdateInternal: function(effect) { |
|
698 | effect.element.down().setStyle({bottom: |
|
704 | effect.element.down().setStyle({bottom: |
|
699 |
(effect.dims[0] - effect.element.clientHeight) + 'px' }); |
|
705 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); |
|
700 | }, |
|
706 | }, |
|
701 | afterFinishInternal: function(effect) { |
|
707 | afterFinishInternal: function(effect) { |
|
702 | effect.element.undoClipping().undoPositioned(); |
|
708 | effect.element.undoClipping().undoPositioned(); |
|
703 | effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } |
|
709 | effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } |
|
704 | }, arguments[1] || { }) |
|
710 | }, arguments[1] || { }) |
|
705 | ); |
|
711 | ); |
|
706 | }; |
|
712 | }; |
|
707 |
|
713 | ||
|
708 | Effect.SlideUp = function(element) { |
|
714 | Effect.SlideUp = function(element) { |
|
709 | element = $(element).cleanWhitespace(); |
|
715 | element = $(element).cleanWhitespace(); |
|
710 | var oldInnerBottom = element.down().getStyle('bottom'); |
|
716 | var oldInnerBottom = element.down().getStyle('bottom'); |
|
711 | var elementDimensions = element.getDimensions(); |
|
717 | var elementDimensions = element.getDimensions(); |
|
712 | return new Effect.Scale(element, window.opera ? 0 : 1, |
|
718 | return new Effect.Scale(element, window.opera ? 0 : 1, |
|
713 |
Object.extend({ scaleContent: false, |
|
719 | Object.extend({ scaleContent: false, |
|
714 |
scaleX: false, |
|
720 | scaleX: false, |
|
715 | scaleMode: 'box', |
|
721 | scaleMode: 'box', |
|
716 | scaleFrom: 100, |
|
722 | scaleFrom: 100, |
|
717 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
723 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, |
|
718 | restoreAfterFinish: true, |
|
724 | restoreAfterFinish: true, |
|
719 | afterSetup: function(effect) { |
|
725 | afterSetup: function(effect) { |
|
720 | effect.element.makePositioned(); |
|
726 | effect.element.makePositioned(); |
|
721 | effect.element.down().makePositioned(); |
|
727 | effect.element.down().makePositioned(); |
|
722 | if (window.opera) effect.element.setStyle({top: ''}); |
|
728 | if (window.opera) effect.element.setStyle({top: ''}); |
|
723 | effect.element.makeClipping().show(); |
|
729 | effect.element.makeClipping().show(); |
|
724 |
}, |
|
730 | }, |
|
725 | afterUpdateInternal: function(effect) { |
|
731 | afterUpdateInternal: function(effect) { |
|
726 | effect.element.down().setStyle({bottom: |
|
732 | effect.element.down().setStyle({bottom: |
|
727 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); |
|
733 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); |
|
728 | }, |
|
734 | }, |
|
729 | afterFinishInternal: function(effect) { |
|
735 | afterFinishInternal: function(effect) { |
|
730 | effect.element.hide().undoClipping().undoPositioned(); |
|
736 | effect.element.hide().undoClipping().undoPositioned(); |
|
731 | effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); |
|
737 | effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); |
|
732 | } |
|
738 | } |
|
733 | }, arguments[1] || { }) |
|
739 | }, arguments[1] || { }) |
|
734 | ); |
|
740 | ); |
|
735 | }; |
|
741 | }; |
|
736 |
|
742 | ||
|
737 |
// Bug in opera makes the TD containing this element expand for a instance after finish |
|
743 | // Bug in opera makes the TD containing this element expand for a instance after finish |
|
738 | Effect.Squish = function(element) { |
|
744 | Effect.Squish = function(element) { |
|
739 |
return new Effect.Scale(element, window.opera ? 1 : 0, { |
|
745 | return new Effect.Scale(element, window.opera ? 1 : 0, { |
|
740 | restoreAfterFinish: true, |
|
746 | restoreAfterFinish: true, |
|
741 | beforeSetup: function(effect) { |
|
747 | beforeSetup: function(effect) { |
|
742 |
effect.element.makeClipping(); |
|
748 | effect.element.makeClipping(); |
|
743 |
}, |
|
749 | }, |
|
744 | afterFinishInternal: function(effect) { |
|
750 | afterFinishInternal: function(effect) { |
|
745 |
effect.element.hide().undoClipping(); |
|
751 | effect.element.hide().undoClipping(); |
|
746 | } |
|
752 | } |
|
747 | }); |
|
753 | }); |
|
748 | }; |
|
754 | }; |
|
749 |
|
755 | ||
|
750 | Effect.Grow = function(element) { |
|
756 | Effect.Grow = function(element) { |
|
751 | element = $(element); |
|
757 | element = $(element); |
|
752 | var options = Object.extend({ |
|
758 | var options = Object.extend({ |
|
753 | direction: 'center', |
|
759 | direction: 'center', |
|
754 | moveTransition: Effect.Transitions.sinoidal, |
|
760 | moveTransition: Effect.Transitions.sinoidal, |
|
755 | scaleTransition: Effect.Transitions.sinoidal, |
|
761 | scaleTransition: Effect.Transitions.sinoidal, |
|
756 | opacityTransition: Effect.Transitions.full |
|
762 | opacityTransition: Effect.Transitions.full |
|
757 | }, arguments[1] || { }); |
|
763 | }, arguments[1] || { }); |
|
758 | var oldStyle = { |
|
764 | var oldStyle = { |
|
759 | top: element.style.top, |
|
765 | top: element.style.top, |
|
760 | left: element.style.left, |
|
766 | left: element.style.left, |
|
761 | height: element.style.height, |
|
767 | height: element.style.height, |
|
762 | width: element.style.width, |
|
768 | width: element.style.width, |
|
763 | opacity: element.getInlineOpacity() }; |
|
769 | opacity: element.getInlineOpacity() }; |
|
764 |
|
770 | ||
|
765 |
var dims = element.getDimensions(); |
|
771 | var dims = element.getDimensions(); |
|
766 | var initialMoveX, initialMoveY; |
|
772 | var initialMoveX, initialMoveY; |
|
767 | var moveX, moveY; |
|
773 | var moveX, moveY; |
|
768 |
|
774 | ||
|
769 | switch (options.direction) { |
|
775 | switch (options.direction) { |
|
770 | case 'top-left': |
|
776 | case 'top-left': |
|
771 |
initialMoveX = initialMoveY = moveX = moveY = 0; |
|
777 | initialMoveX = initialMoveY = moveX = moveY = 0; |
|
772 | break; |
|
778 | break; |
|
773 | case 'top-right': |
|
779 | case 'top-right': |
|
774 | initialMoveX = dims.width; |
|
780 | initialMoveX = dims.width; |
|
775 | initialMoveY = moveY = 0; |
|
781 | initialMoveY = moveY = 0; |
|
776 | moveX = -dims.width; |
|
782 | moveX = -dims.width; |
|
777 | break; |
|
783 | break; |
|
778 | case 'bottom-left': |
|
784 | case 'bottom-left': |
|
779 | initialMoveX = moveX = 0; |
|
785 | initialMoveX = moveX = 0; |
|
780 | initialMoveY = dims.height; |
|
786 | initialMoveY = dims.height; |
|
781 | moveY = -dims.height; |
|
787 | moveY = -dims.height; |
|
782 | break; |
|
788 | break; |
|
783 | case 'bottom-right': |
|
789 | case 'bottom-right': |
|
784 | initialMoveX = dims.width; |
|
790 | initialMoveX = dims.width; |
|
785 | initialMoveY = dims.height; |
|
791 | initialMoveY = dims.height; |
|
786 | moveX = -dims.width; |
|
792 | moveX = -dims.width; |
|
787 | moveY = -dims.height; |
|
793 | moveY = -dims.height; |
|
788 | break; |
|
794 | break; |
|
789 | case 'center': |
|
795 | case 'center': |
|
790 | initialMoveX = dims.width / 2; |
|
796 | initialMoveX = dims.width / 2; |
|
791 | initialMoveY = dims.height / 2; |
|
797 | initialMoveY = dims.height / 2; |
|
792 | moveX = -dims.width / 2; |
|
798 | moveX = -dims.width / 2; |
|
793 | moveY = -dims.height / 2; |
|
799 | moveY = -dims.height / 2; |
|
794 | break; |
|
800 | break; |
|
795 | } |
|
801 | } |
|
796 |
|
802 | ||
|
797 | return new Effect.Move(element, { |
|
803 | return new Effect.Move(element, { |
|
798 | x: initialMoveX, |
|
804 | x: initialMoveX, |
|
799 | y: initialMoveY, |
|
805 | y: initialMoveY, |
|
800 |
duration: 0.01, |
|
806 | duration: 0.01, |
|
801 | beforeSetup: function(effect) { |
|
807 | beforeSetup: function(effect) { |
|
802 | effect.element.hide().makeClipping().makePositioned(); |
|
808 | effect.element.hide().makeClipping().makePositioned(); |
|
803 | }, |
|
809 | }, |
|
804 | afterFinishInternal: function(effect) { |
|
810 | afterFinishInternal: function(effect) { |
|
805 | new Effect.Parallel( |
|
811 | new Effect.Parallel( |
|
806 | [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), |
|
812 | [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), |
|
807 | new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), |
|
813 | new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), |
|
808 | new Effect.Scale(effect.element, 100, { |
|
814 | new Effect.Scale(effect.element, 100, { |
|
809 |
scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, |
|
815 | scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, |
|
810 | sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) |
|
816 | sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) |
|
811 | ], Object.extend({ |
|
817 | ], Object.extend({ |
|
812 | beforeSetup: function(effect) { |
|
818 | beforeSetup: function(effect) { |
|
813 |
effect.effects[0].element.setStyle({height: '0px'}).show(); |
|
819 | effect.effects[0].element.setStyle({height: '0px'}).show(); |
|
814 | }, |
|
820 | }, |
|
815 | afterFinishInternal: function(effect) { |
|
821 | afterFinishInternal: function(effect) { |
|
816 |
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); |
|
822 | effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); |
|
817 | } |
|
823 | } |
|
818 | }, options) |
|
824 | }, options) |
|
819 | - ) |
|
825 | + ); |
|
820 | } |
|
826 | } |
|
821 | }); |
|
827 | }); |
|
822 | }; |
|
828 | }; |
|
823 |
|
829 | ||
|
824 | Effect.Shrink = function(element) { |
|
830 | Effect.Shrink = function(element) { |
|
825 | element = $(element); |
|
831 | element = $(element); |
|
826 | var options = Object.extend({ |
|
832 | var options = Object.extend({ |
|
827 | direction: 'center', |
|
833 | direction: 'center', |
|
828 | moveTransition: Effect.Transitions.sinoidal, |
|
834 | moveTransition: Effect.Transitions.sinoidal, |
|
829 | scaleTransition: Effect.Transitions.sinoidal, |
|
835 | scaleTransition: Effect.Transitions.sinoidal, |
|
830 | opacityTransition: Effect.Transitions.none |
|
836 | opacityTransition: Effect.Transitions.none |
|
831 | }, arguments[1] || { }); |
|
837 | }, arguments[1] || { }); |
|
832 | var oldStyle = { |
|
838 | var oldStyle = { |
|
833 | top: element.style.top, |
|
839 | top: element.style.top, |
|
834 | left: element.style.left, |
|
840 | left: element.style.left, |
|
835 | height: element.style.height, |
|
841 | height: element.style.height, |
|
836 | width: element.style.width, |
|
842 | width: element.style.width, |
|
837 | opacity: element.getInlineOpacity() }; |
|
843 | opacity: element.getInlineOpacity() }; |
|
838 |
|
844 | ||
|
839 | var dims = element.getDimensions(); |
|
845 | var dims = element.getDimensions(); |
|
840 | var moveX, moveY; |
|
846 | var moveX, moveY; |
|
841 |
|
847 | ||
|
842 | switch (options.direction) { |
|
848 | switch (options.direction) { |
|
843 | case 'top-left': |
|
849 | case 'top-left': |
|
844 | moveX = moveY = 0; |
|
850 | moveX = moveY = 0; |
|
845 | break; |
|
851 | break; |
|
846 | case 'top-right': |
|
852 | case 'top-right': |
|
847 | moveX = dims.width; |
|
853 | moveX = dims.width; |
|
848 | moveY = 0; |
|
854 | moveY = 0; |
|
849 | break; |
|
855 | break; |
|
850 | case 'bottom-left': |
|
856 | case 'bottom-left': |
|
851 | moveX = 0; |
|
857 | moveX = 0; |
|
852 | moveY = dims.height; |
|
858 | moveY = dims.height; |
|
853 | break; |
|
859 | break; |
|
854 | case 'bottom-right': |
|
860 | case 'bottom-right': |
|
855 | moveX = dims.width; |
|
861 | moveX = dims.width; |
|
856 | moveY = dims.height; |
|
862 | moveY = dims.height; |
|
857 | break; |
|
863 | break; |
|
858 |
case 'center': |
|
864 | case 'center': |
|
859 | moveX = dims.width / 2; |
|
865 | moveX = dims.width / 2; |
|
860 | moveY = dims.height / 2; |
|
866 | moveY = dims.height / 2; |
|
861 | break; |
|
867 | break; |
|
862 | } |
|
868 | } |
|
863 |
|
869 | ||
|
864 | return new Effect.Parallel( |
|
870 | return new Effect.Parallel( |
|
865 | [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), |
|
871 | [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), |
|
866 | new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), |
|
872 | new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), |
|
867 | new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) |
|
873 | new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) |
|
868 |
], Object.extend({ |
|
874 | ], Object.extend({ |
|
869 | beforeStartInternal: function(effect) { |
|
875 | beforeStartInternal: function(effect) { |
|
870 |
effect.effects[0].element.makePositioned().makeClipping(); |
|
876 | effect.effects[0].element.makePositioned().makeClipping(); |
|
871 | }, |
|
877 | }, |
|
872 | afterFinishInternal: function(effect) { |
|
878 | afterFinishInternal: function(effect) { |
|
873 | effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } |
|
879 | effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } |
|
874 | }, options) |
|
880 | }, options) |
|
875 | ); |
|
881 | ); |
|
876 | }; |
|
882 | }; |
|
877 |
|
883 | ||
|
878 | Effect.Pulsate = function(element) { |
|
884 | Effect.Pulsate = function(element) { |
|
879 | element = $(element); |
|
885 | element = $(element); |
|
880 |
- var options = arguments[1] || { } |
|
886 | + var options = arguments[1] || { }, |
|
881 |
- |
|
887 | + oldOpacity = element.getInlineOpacity(), |
|
882 |
- |
|
888 | + transition = options.transition || Effect.Transitions.linear, |
|
883 | - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; |
|
889 | + reverser = function(pos){ |
|
884 | - reverser.bind(transition); |
|
890 | + return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); |
|
|
891 | + }; | ||
|
|
892 | + | ||
|
885 |
return new Effect.Opacity(element, |
|
893 | return new Effect.Opacity(element, |
|
886 | Object.extend(Object.extend({ duration: 2.0, from: 0, |
|
894 | Object.extend(Object.extend({ duration: 2.0, from: 0, |
|
887 | afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } |
|
895 | afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } |
|
888 | }, options), {transition: reverser})); |
|
896 | }, options), {transition: reverser})); |
|
889 | }; |
|
897 | }; |
|
890 |
|
898 | ||
|
891 | Effect.Fold = function(element) { |
|
899 | Effect.Fold = function(element) { |
|
892 | element = $(element); |
|
900 | element = $(element); |
|
893 | var oldStyle = { |
|
901 | var oldStyle = { |
|
894 | top: element.style.top, |
|
902 | top: element.style.top, |
|
895 | left: element.style.left, |
|
903 | left: element.style.left, |
|
896 | width: element.style.width, |
|
904 | width: element.style.width, |
|
897 | height: element.style.height }; |
|
905 | height: element.style.height }; |
|
898 | element.makeClipping(); |
|
906 | element.makeClipping(); |
|
899 |
return new Effect.Scale(element, 5, Object.extend({ |
|
907 | return new Effect.Scale(element, 5, Object.extend({ |
|
900 | scaleContent: false, |
|
908 | scaleContent: false, |
|
901 | scaleX: false, |
|
909 | scaleX: false, |
|
902 | afterFinishInternal: function(effect) { |
|
910 | afterFinishInternal: function(effect) { |
|
903 |
new Effect.Scale(element, 1, { |
|
911 | new Effect.Scale(element, 1, { |
|
904 |
scaleContent: false, |
|
912 | scaleContent: false, |
|
905 | scaleY: false, |
|
913 | scaleY: false, |
|
906 | afterFinishInternal: function(effect) { |
|
914 | afterFinishInternal: function(effect) { |
|
907 | effect.element.hide().undoClipping().setStyle(oldStyle); |
|
915 | effect.element.hide().undoClipping().setStyle(oldStyle); |
|
908 | } }); |
|
916 | } }); |
|
909 | }}, arguments[1] || { })); |
|
917 | }}, arguments[1] || { })); |
|
910 | }; |
|
918 | }; |
|
911 |
|
919 | ||
|
912 | Effect.Morph = Class.create(Effect.Base, { |
|
920 | Effect.Morph = Class.create(Effect.Base, { |
|
913 | initialize: function(element) { |
|
921 | initialize: function(element) { |
|
914 | this.element = $(element); |
|
922 | this.element = $(element); |
|
915 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
923 | if (!this.element) throw(Effect._elementDoesNotExistError); |
|
916 | var options = Object.extend({ |
|
924 | var options = Object.extend({ |
|
917 | style: { } |
|
925 | style: { } |
|
918 | }, arguments[1] || { }); |
|
926 | }, arguments[1] || { }); |
|
919 |
|
927 | ||
|
920 | if (!Object.isString(options.style)) this.style = $H(options.style); |
|
928 | if (!Object.isString(options.style)) this.style = $H(options.style); |
|
921 | else { |
|
929 | else { |
|
922 | if (options.style.include(':')) |
|
930 | if (options.style.include(':')) |
|
923 | this.style = options.style.parseStyle(); |
|
931 | this.style = options.style.parseStyle(); |
|
924 | else { |
|
932 | else { |
|
925 | this.element.addClassName(options.style); |
|
933 | this.element.addClassName(options.style); |
|
926 | this.style = $H(this.element.getStyles()); |
|
934 | this.style = $H(this.element.getStyles()); |
|
927 | this.element.removeClassName(options.style); |
|
935 | this.element.removeClassName(options.style); |
|
928 | var css = this.element.getStyles(); |
|
936 | var css = this.element.getStyles(); |
|
929 | this.style = this.style.reject(function(style) { |
|
937 | this.style = this.style.reject(function(style) { |
|
930 | return style.value == css[style.key]; |
|
938 | return style.value == css[style.key]; |
|
931 | }); |
|
939 | }); |
|
932 | options.afterFinishInternal = function(effect) { |
|
940 | options.afterFinishInternal = function(effect) { |
|
933 | effect.element.addClassName(effect.options.style); |
|
941 | effect.element.addClassName(effect.options.style); |
|
934 | effect.transforms.each(function(transform) { |
|
942 | effect.transforms.each(function(transform) { |
|
935 | effect.element.style[transform.style] = ''; |
|
943 | effect.element.style[transform.style] = ''; |
|
936 | }); |
|
944 | }); |
|
937 | - } |
|
945 | + }; |
|
938 | } |
|
946 | } |
|
939 | } |
|
947 | } |
|
940 | this.start(options); |
|
948 | this.start(options); |
|
941 | }, |
|
949 | }, |
|
942 |
|
950 | ||
|
943 | setup: function(){ |
|
951 | setup: function(){ |
|
944 | function parseColor(color){ |
|
952 | function parseColor(color){ |
|
945 | if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; |
|
953 | if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; |
|
946 | color = color.parseColor(); |
|
954 | color = color.parseColor(); |
|
947 | return $R(0,2).map(function(i){ |
|
955 | return $R(0,2).map(function(i){ |
|
948 |
- return parseInt( color.slice(i*2+1,i*2+3), 16 ) |
|
956 | + return parseInt( color.slice(i*2+1,i*2+3), 16 ); |
|
949 | }); |
|
957 | }); |
|
950 | } |
|
958 | } |
|
951 | this.transforms = this.style.map(function(pair){ |
|
959 | this.transforms = this.style.map(function(pair){ |
|
952 | var property = pair[0], value = pair[1], unit = null; |
|
960 | var property = pair[0], value = pair[1], unit = null; |
|
953 |
|
961 | ||
|
954 | if (value.parseColor('#zzzzzz') != '#zzzzzz') { |
|
962 | if (value.parseColor('#zzzzzz') != '#zzzzzz') { |
|
955 | value = value.parseColor(); |
|
963 | value = value.parseColor(); |
|
956 | unit = 'color'; |
|
964 | unit = 'color'; |
|
957 | } else if (property == 'opacity') { |
|
965 | } else if (property == 'opacity') { |
|
958 | value = parseFloat(value); |
|
966 | value = parseFloat(value); |
|
959 | if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) |
|
967 | if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) |
|
960 | this.element.setStyle({zoom: 1}); |
|
968 | this.element.setStyle({zoom: 1}); |
|
961 | } else if (Element.CSS_LENGTH.test(value)) { |
|
969 | } else if (Element.CSS_LENGTH.test(value)) { |
|
962 | var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); |
|
970 | var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); |
|
963 | value = parseFloat(components[1]); |
|
971 | value = parseFloat(components[1]); |
|
964 | unit = (components.length == 3) ? components[2] : null; |
|
972 | unit = (components.length == 3) ? components[2] : null; |
|
965 | } |
|
973 | } |
|
966 |
|
974 | ||
|
967 | var originalValue = this.element.getStyle(property); |
|
975 | var originalValue = this.element.getStyle(property); |
|
968 |
return { |
|
976 | return { |
|
969 |
style: property.camelize(), |
|
977 | style: property.camelize(), |
|
970 |
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), |
|
978 | originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), |
|
971 | targetValue: unit=='color' ? parseColor(value) : value, |
|
979 | targetValue: unit=='color' ? parseColor(value) : value, |
|
972 | unit: unit |
|
980 | unit: unit |
|
973 | }; |
|
981 | }; |
|
974 | }.bind(this)).reject(function(transform){ |
|
982 | }.bind(this)).reject(function(transform){ |
|
975 | return ( |
|
983 | return ( |
|
976 | (transform.originalValue == transform.targetValue) || |
|
984 | (transform.originalValue == transform.targetValue) || |
|
977 | ( |
|
985 | ( |
|
978 | transform.unit != 'color' && |
|
986 | transform.unit != 'color' && |
|
979 | (isNaN(transform.originalValue) || isNaN(transform.targetValue)) |
|
987 | (isNaN(transform.originalValue) || isNaN(transform.targetValue)) |
|
980 | ) |
|
988 | ) |
|
981 | - ) |
|
989 | + ); |
|
982 | }); |
|
990 | }); |
|
983 | }, |
|
991 | }, |
|
984 | update: function(position) { |
|
992 | update: function(position) { |
|
985 | var style = { }, transform, i = this.transforms.length; |
|
993 | var style = { }, transform, i = this.transforms.length; |
|
986 | while(i--) |
|
994 | while(i--) |
|
987 |
style[(transform = this.transforms[i]).style] = |
|
995 | style[(transform = this.transforms[i]).style] = |
|
988 | transform.unit=='color' ? '#'+ |
|
996 | transform.unit=='color' ? '#'+ |
|
989 | (Math.round(transform.originalValue[0]+ |
|
997 | (Math.round(transform.originalValue[0]+ |
|
990 | (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + |
|
998 | (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + |
|
991 | (Math.round(transform.originalValue[1]+ |
|
999 | (Math.round(transform.originalValue[1]+ |
|
992 | (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + |
|
1000 | (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + |
|
993 | (Math.round(transform.originalValue[2]+ |
|
1001 | (Math.round(transform.originalValue[2]+ |
|
994 | (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : |
|
1002 | (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : |
|
995 | (transform.originalValue + |
|
1003 | (transform.originalValue + |
|
996 |
(transform.targetValue - transform.originalValue) * position).toFixed(3) + |
|
1004 | (transform.targetValue - transform.originalValue) * position).toFixed(3) + |
|
997 | (transform.unit === null ? '' : transform.unit); |
|
1005 | (transform.unit === null ? '' : transform.unit); |
|
998 | this.element.setStyle(style, true); |
|
1006 | this.element.setStyle(style, true); |
|
999 | } |
|
1007 | } |
|
1000 | }); |
|
1008 | }); |
|
1001 |
|
1009 | ||
|
1002 | Effect.Transform = Class.create({ |
|
1010 | Effect.Transform = Class.create({ |
|
1003 | initialize: function(tracks){ |
|
1011 | initialize: function(tracks){ |
|
1004 | this.tracks = []; |
|
1012 | this.tracks = []; |
|
1005 | this.options = arguments[1] || { }; |
|
1013 | this.options = arguments[1] || { }; |
|
1006 | this.addTracks(tracks); |
|
1014 | this.addTracks(tracks); |
|
1007 | }, |
|
1015 | }, |
|
1008 | addTracks: function(tracks){ |
|
1016 | addTracks: function(tracks){ |
|
1009 | tracks.each(function(track){ |
|
1017 | tracks.each(function(track){ |
|
1010 | track = $H(track); |
|
1018 | track = $H(track); |
|
1011 | var data = track.values().first(); |
|
1019 | var data = track.values().first(); |
|
1012 | this.tracks.push($H({ |
|
1020 | this.tracks.push($H({ |
|
1013 | ids: track.keys().first(), |
|
1021 | ids: track.keys().first(), |
|
1014 | effect: Effect.Morph, |
|
1022 | effect: Effect.Morph, |
|
1015 | options: { style: data } |
|
1023 | options: { style: data } |
|
1016 | })); |
|
1024 | })); |
|
1017 | }.bind(this)); |
|
1025 | }.bind(this)); |
|
1018 | return this; |
|
1026 | return this; |
|
1019 | }, |
|
1027 | }, |
|
1020 | play: function(){ |
|
1028 | play: function(){ |
|
1021 | return new Effect.Parallel( |
|
1029 | return new Effect.Parallel( |
|
1022 | this.tracks.map(function(track){ |
|
1030 | this.tracks.map(function(track){ |
|
1023 | var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); |
|
1031 | var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); |
|
1024 | var elements = [$(ids) || $$(ids)].flatten(); |
|
1032 | var elements = [$(ids) || $$(ids)].flatten(); |
|
1025 | return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); |
|
1033 | return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); |
|
1026 | }).flatten(), |
|
1034 | }).flatten(), |
|
1027 | this.options |
|
1035 | this.options |
|
1028 | ); |
|
1036 | ); |
|
1029 | } |
|
1037 | } |
|
1030 | }); |
|
1038 | }); |
|
1031 |
|
1039 | ||
|
1032 | Element.CSS_PROPERTIES = $w( |
|
1040 | Element.CSS_PROPERTIES = $w( |
|
1033 |
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + |
|
1041 | 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + |
|
1034 | 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + |
|
1042 | 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + |
|
1035 | 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + |
|
1043 | 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + |
|
1036 | 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + |
|
1044 | 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + |
|
1037 | 'fontSize fontWeight height left letterSpacing lineHeight ' + |
|
1045 | 'fontSize fontWeight height left letterSpacing lineHeight ' + |
|
1038 | 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ |
|
1046 | 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ |
|
1039 | 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + |
|
1047 | 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + |
|
1040 | 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + |
|
1048 | 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + |
|
1041 | 'right textIndent top width wordSpacing zIndex'); |
|
1049 | 'right textIndent top width wordSpacing zIndex'); |
|
1042 |
|
1050 | ||
|
1043 | Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; |
|
1051 | Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; |
|
1044 |
|
1052 | ||
|
1045 | String.__parseStyleElement = document.createElement('div'); |
|
1053 | String.__parseStyleElement = document.createElement('div'); |
|
1046 | String.prototype.parseStyle = function(){ |
|
1054 | String.prototype.parseStyle = function(){ |
|
1047 | var style, styleRules = $H(); |
|
1055 | var style, styleRules = $H(); |
|
1048 | if (Prototype.Browser.WebKit) |
|
1056 | if (Prototype.Browser.WebKit) |
|
1049 | style = new Element('div',{style:this}).style; |
|
1057 | style = new Element('div',{style:this}).style; |
|
1050 | else { |
|
1058 | else { |
|
1051 | String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; |
|
1059 | String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; |
|
1052 | style = String.__parseStyleElement.childNodes[0].style; |
|
1060 | style = String.__parseStyleElement.childNodes[0].style; |
|
1053 | } |
|
1061 | } |
|
1054 |
|
1062 | ||
|
1055 | Element.CSS_PROPERTIES.each(function(property){ |
|
1063 | Element.CSS_PROPERTIES.each(function(property){ |
|
1056 |
if (style[property]) styleRules.set(property, style[property]); |
|
1064 | if (style[property]) styleRules.set(property, style[property]); |
|
1057 | }); |
|
1065 | }); |
|
1058 |
|
1066 | ||
|
1059 | if (Prototype.Browser.IE && this.include('opacity')) |
|
1067 | if (Prototype.Browser.IE && this.include('opacity')) |
|
1060 | styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); |
|
1068 | styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); |
|
1061 |
|
1069 | ||
|
1062 | return styleRules; |
|
1070 | return styleRules; |
|
1063 | }; |
|
1071 | }; |
|
1064 |
|
1072 | ||
|
1065 | if (document.defaultView && document.defaultView.getComputedStyle) { |
|
1073 | if (document.defaultView && document.defaultView.getComputedStyle) { |
|
1066 | Element.getStyles = function(element) { |
|
1074 | Element.getStyles = function(element) { |
|
1067 | var css = document.defaultView.getComputedStyle($(element), null); |
|
1075 | var css = document.defaultView.getComputedStyle($(element), null); |
|
1068 | return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { |
|
1076 | return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { |
|
1069 | styles[property] = css[property]; |
|
1077 | styles[property] = css[property]; |
|
1070 | return styles; |
|
1078 | return styles; |
|
1071 | }); |
|
1079 | }); |
|
1072 | }; |
|
1080 | }; |
|
1073 | } else { |
|
1081 | } else { |
|
1074 | Element.getStyles = function(element) { |
|
1082 | Element.getStyles = function(element) { |
|
1075 | element = $(element); |
|
1083 | element = $(element); |
|
1076 | var css = element.currentStyle, styles; |
|
1084 | var css = element.currentStyle, styles; |
|
1077 |
- styles = Element.CSS_PROPERTIES.inject({ }, function( |
|
1085 | + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { |
|
1078 |
- |
|
1086 | + results[property] = css[property]; |
|
1079 |
- return |
|
1087 | + return results; |
|
1080 | }); |
|
1088 | }); |
|
1081 |
- if (!styles.opacity) styles. |
|
1089 | + if (!styles.opacity) styles.opacity = element.getOpacity(); |
|
1082 | return styles; |
|
1090 | return styles; |
|
1083 | }; |
|
1091 | }; |
|
1084 |
- } |
|
1092 | + } |
|
1085 |
|
1093 | ||
|
1086 | Effect.Methods = { |
|
1094 | Effect.Methods = { |
|
1087 | morph: function(element, style) { |
|
1095 | morph: function(element, style) { |
|
1088 | element = $(element); |
|
1096 | element = $(element); |
|
1089 | new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); |
|
1097 | new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); |
|
1090 | return element; |
|
1098 | return element; |
|
1091 | }, |
|
1099 | }, |
|
1092 | visualEffect: function(element, effect, options) { |
|
1100 | visualEffect: function(element, effect, options) { |
|
1093 | - element = $(element) |
|
1101 | + element = $(element); |
|
1094 | var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); |
|
1102 | var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); |
|
1095 | new Effect[klass](element, options); |
|
1103 | new Effect[klass](element, options); |
|
1096 | return element; |
|
1104 | return element; |
|
1097 | }, |
|
1105 | }, |
|
1098 | highlight: function(element, options) { |
|
1106 | highlight: function(element, options) { |
|
1099 | element = $(element); |
|
1107 | element = $(element); |
|
1100 | new Effect.Highlight(element, options); |
|
1108 | new Effect.Highlight(element, options); |
|
1101 | return element; |
|
1109 | return element; |
|
1102 | } |
|
1110 | } |
|
1103 | }; |
|
1111 | }; |
|
1104 |
|
1112 | ||
|
1105 | $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ |
|
1113 | $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ |
|
1106 | 'pulsate shake puff squish switchOff dropOut').each( |
|
1114 | 'pulsate shake puff squish switchOff dropOut').each( |
|
1107 |
function(effect) { |
|
1115 | function(effect) { |
|
1108 | Effect.Methods[effect] = function(element, options){ |
|
1116 | Effect.Methods[effect] = function(element, options){ |
|
1109 | element = $(element); |
|
1117 | element = $(element); |
|
1110 | Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); |
|
1118 | Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); |
|
1111 | return element; |
|
1119 | return element; |
|
1112 | - } |
|
1120 | + }; |
|
1113 | } |
|
1121 | } |
|
1114 | ); |
|
1122 | ); |
|
1115 |
|
1123 | ||
|
1116 |
$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( |
|
1124 | $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( |
|
1117 | function(f) { Effect.Methods[f] = Element[f]; } |
|
1125 | function(f) { Effect.Methods[f] = Element[f]; } |
|
1118 | ); |
|
1126 | ); |
|
1119 |
|
1127 | ||
|
1120 |
- Element.addMethods(Effect.Methods); |
|
1128 | + Element.addMethods(Effect.Methods); No newline at end of file |
modified file |
You need to be logged in to leave comments.
Login now